/****************************************************************************
* gproj.h :
* This header file defines geographic referencing system class
*
* Credit:
* The map projections in this file were implemented originaly by
* EROS Data Center in the package GCTPC.
* (ftp://edcftp.cr.usgs.gov:pub/software/gctpc)
* This file and gproj.cpp merely provide a c++ wrap up of the
* projections. Each projection is implemented in an individual class.
*
* Change Log :
* Nov 23, 1997 Initial version, Liujian Qian
*
* $Id: gproj.h,v 1.23 1999/02/10 21:56:02 qian Exp $
***************************************************************************/
#ifndef _GEOREF_H_
#define _GEOREF_H_
#include "gobject.h"
#define MAXLONG 2147483647.
#define DBLLONG 4.61168601e18
#define EPSLN 1.0e-10
class ostream;
/**
* identification code for the major projections;
* not all projections listed here are supported by GFC.
*/
enum GProjCode {
Geographic = 0, //just plain longitude/latitude
UTM, //60 zones
StatePlane, //a grid coordinate system
Albers, //conical equal area
Lambert, //Lambert comformal conic
Mercator, //true local shapes
Polyconic, //many cones;
LambertAzimuthal, //zenithal equal area
Azimuthal, //true distance & direction in center
Robinson, //or Orthophanic
Polar, //Polar Stereographic
TransverseMercator //
};
/**
* @internal
* GUV is for storing intermediate coordinates during
* projection transformation.
*/
struct GUV
{
double u,v;
};
/**
* Ellipsoid of the Earth
*/
struct GEllipsoid
{
double major, minor; //Hemi-major and minor axis of Earth
};
extern GEllipsoid clarke66;
extern GEllipsoid new_international;
/**
* @short defines basic variables/methods for map projections.
*
* This class defines basic map projection parameters and routines;
* It serves as the base class for all concrete projections.
*/
class GMapProj : public GObject
{
protected:
union
{
GEllipsoid ellip; //treat Earth as an ellipsoid
double radius; //treat Earth as a sphere
};
union {
double lon_center; //central longitude (meridian)
double mer_center; //central meridian
};
union {
double lat_center; //latitude at the center/origin of projection
double lat_origin;
};
double false_easting; //offset (in meters)
double false_northing; //to avoid negative x,y coordinates
GProjCode proj_id; //identification code
enum {MAX_VAL = 4};
// scale_factor and es can be computed from other parameters
// so they will not be part of the stored projection data.
double scale_factor; //determined by what?
double es; //square of eccentricity (1-b^2/a^2)
public :
friend ostream& operator<<(ostream& s, const GMapProj& a);
virtual uint32 getPSize() const;
virtual Result input (const char* );
virtual Result output (char*& ) ;
virtual Result pack (DataPipe& );
virtual Result unpack (DataPipe& );
public:
/**
* default constructor.
*/
NOP GMapProj();
/**
* Forward conversion from (longitude,latitude) to projected coordinates
* in meters.
* @param (lon, lat) MUST be *radians* !!!
*/
virtual Result forward(double lon, double lat, double& x, double& y)=0;
/**
* Inverse conversion from projected coordinates to (longitude, latitude).
* (x,y) must be in meters; and (lon, lat) will be in *radians*.
*/
virtual Result inverse(double x, double y, double& lon, double& lat)=0;
public:
//routines commonly used during projection
/**
* adjust a longitude angle to range from -180 to 180 radians
*/
static double adjustLon(double);
/**
* Function to eliminate roundoff errors in asin
*/
static double asinZ(double x);
/**
* calculate constants e0, e1, e2, e3, which are used in
* calculating true distance along meridian; x is squared eccentricity.
*/
static double e0(double x);
static double e1(double x);
static double e2(double x);
static double e3(double x);
/**
* calculate constant e4 from input of the eccentricity of the spheroid x
*/
static double e4(double);
/**
* Computes the constant small m for Oblique Equal Area.
*/
static double ms(double e, double s, double c);
/**
* compute constant small q which is the radius of a
* parallel of latitude, phi, divided by the semimajor axis
*/
static double qs(double e, double s, double c);
/**
* compute the constant small t for use in the forward
* computations in the Lambert Conformal Conic and the Polar
* Stereographic projections.
*/
static double ts(double e, double phi, double sinphi);
/**
* compute phi1, the latitude for the inverse of the
* Albers Conical Equal-Area projection.
*/
static double phi1z(double e, double qs, Result& res);
/**
* compute the latitude angle, phi2, for the inverse of the
* Lambert Conformal Conic and Polar Stereographic projections.
*/
static double phi2z(double e, double ts, Result& res);
/**
* compute latitude, phi3, for the inverse of the Equidistant
* Conic projection.
*/
static double phi3z(double ml,double e0,double e1,
double e2, double e3, Result& res);
/**
* compute phi4, the latitude for the inverse of the
* Polyconic projection.
*/
static Result phi4z(double, double, double, double, double,
double, double, double*, double*);
/**
* calculate a UTM zone number.
* Longitude should be in degrees!
*/
static int getUTMZone(double lon);
/**
* convert Degree/Minute/Second to decimal degree.
*/
static double DMS2DD(int d, int m, int s);
/**
* convert a Decimal Degree (DD) coordinate into degree/minute/second
*/
static void DD2DMS(double dd, int& d, int& m, int& s);
/**
* calculate the distance along a meridian from
* the Equator to latitude (phi)
*/
double distML(double phi, double e0=0, double e1=0,
double e2=0, double e3=0) const;
/**
* test if the ellipsoid is Clarke66.
*/
bool isClarke66() const;
/**
* test if Earth is treated as a shpere (if eccentricty < c)
*/
bool isSphere(const double c = 0.00001) const;
};
/**
* @short class for UTM projection.
*
* UTM projection divides the Earth between lats. 84N and 80S
* into 60 zones. The scal along central meridian is reduced to 0.9996.
* In the northern Hemisphere, the Equator at the central meridian is
* considered the origin, with an x coordinate of 500,000 m and a y of
* 0. For the southern Hemisphere the same point is the origin, but while
* x remains same 500,000m, the y is 10,000000. IN each case numbers
* increase toward east and north thus to avoid negative values. For each
* point on the Earth, its position is uniquely determined by the (x,y)
* coordinates plus the zone number.
*/
class GProjUTM : public GMapProj
{
double indicator; //sphereical indicator: 1 if sphere
double ml0; //small value m
double _e0, _e1, _e2, _e3, _e, _esp; //eccentricty constants
protected:
int zone; //for southern Hemisphere use negative values
public: // common methods of GObject.
friend ostream& operator<<(ostream& s, const GProjUTM& a);
virtual uint32 getPSize() const;
virtual Result input (const char* );
virtual Result output (char*& ) ;
virtual Result pack (DataPipe& );
virtual Result unpack (DataPipe& );
public:
/**
* Default constructor; must call init() before any conversion.
*/
NOP GProjUTM();
/**
* construct a UTM projection with major/minor axis and zone number.
* If the projection is applied to Southern Hemishpere then the
* value of _zone should be negative (ie -55 instead of 55 for part
* of Australia).
*/
NOP GProjUTM(double r_maj, double r_min, int _zone);
/**
* same as previous constructor; uses a handy form of parameter.
*/
NOP GProjUTM(const GEllipsoid& e, int _zone);
/**
* initialize for the UTM projection. Must be called before
* any foward/inverse conversion can happen.
*/
Result init(double r_maj, double r_min, int _zone);
/**
* Forward conversion from (longitude,latitude) to UTM coordinates
* in meters.
* @param (lon, lat) MUST be *radians* !!!
*/
Result forward(double lon, double lat, double& x, double& y);
/**
* Inverse conversion from UTM coordinates to (longitude, latitude).
* (x,y) must be in meters; and (lon, lat) will be in *radians*.
*/
Result inverse(double x, double y, double& lon, double& lat);
};
/**
* @short Class for Lambert Conformal Conic projection.
*
* A conic conformal projections where parallels are unequally spaced
* arcs of concentric circles, more closely spaced near the center
* of the map. Meridians are equally spaced radii of the same circles,
* thereby cutting parallels at right angles. Scale is true along two
* standard parallels, normally, or along just one. Used for maps of
* countries and regions with predominant east-west expanse.
* -- (J. Snyder, "Map Projections - A working manual").
*/
class GProjLambert : public GMapProj
{
double ns; //ratio of angle between meridian
double f0; //flattening of ellipsoid
double rh; //height above ellipsoid
double e; //eccentricity
protected:
double std_par1, std_par2;
public :
friend ostream& operator<<(ostream& s, const GProjLambert& a);
virtual uint32 getPSize() const;
virtual Result input (const char* );
virtual Result output (char*& ) ;
virtual Result pack (DataPipe& );
virtual Result unpack (DataPipe& );
public:
/**
* Default constructor; must call init() before any conversion.
*/
NOP GProjLambert();
/**
* construct a Lambert (CC) projection.
* @param major/minor axis;
* lat1/lat2 first and second standard parallel; both are radians
* c_lon/c_lat central longitude and latitude; both are radians
* x_false/y_false false easting and northing. both are radians
*/
NOP GProjLambert(double r_maj, double r_min,
double lat1, double lat2,
double c_lon, double c_lat,
double x_false, double y_false);
/**
* initialize for the Lambert projection. Must be called before
* any foward/inverse conversion can happen.
* @param uses same parameter as in second constructor. longitudes/lattitudes
* are all radians.
*/
Result init(double r_maj, double r_min,
double lat1, double lat2,
double c_lon, double c_lat,
double x_false, double y_false);
/**
* Forward conversion from (longitude,latitude) to Lambert coordinates
* in meters.
* @param (lon, lat) MUST be radians!!!
*/
Result forward(double lon, double lat, double& x, double& y);
/**
* Inverse conversion from Lambert coordinates to (longitude, latitude).
* (x,y) must be in meters; and (lon, lat) will be in radians.
*/
Result inverse(double x, double y, double& lon, double& lat);
};
/**
* @short Mercator projection class
*
*/
class GProjMercator : public GMapProj
{
protected:
double e, m1; // small value m
public:
/**
*/
NOP GProjMercator();
/**
* constructor
* @param c_lon/c_lat central longitude/latitude (must be radians).
*/
NOP GProjMercator(double r_maj, double r_min, double c_lon, double c_lat,
double false_east, double false_north);
/**
* initialize for the Mercator projection. Must be called before
* any foward/inverse conversion can happen, if the object is created
* using the constructor with no parameters.
* @param uses same parameter as in second constructor.
*/
Result init(double r_maj, double r_min,
double c_lon, double c_lat,
double x_false, double y_false);
/**
* Forward conversion from (longitude,latitude) to Mercator coordinates
* in meters.
* @param (lon, lat) MUST be radians!!!
*/
Result forward(double lon, double lat, double& x, double& y);
/**
* Inverse conversion from Mercator coordinates to (longitude, latitude).
* (x,y) must be in meters; and (lon, lat) will be in radians.
*/
Result inverse(double x, double y, double& lon, double& lat);
};
/**
* @short Albers Conical equal-area projection class.
* One of the most commonly used projection for maps of theconterminous
* United States. It uses two standard parallels.
*/
class GProjAlbers : public GMapProj
{
double c; //constant c
double e3; //eccentricity
double rh; //height above elipsoid
double ns0; //ratio between meridians
protected:
double std_par1, std_par2;
public:
friend ostream& operator<<(ostream& s, const GProjAlbers& a);
public:
/**
* this constructor has no parameters. You mush call init() before
* any projection can take place using this object.
*/
NOP GProjAlbers();
/**
* create an Albers map projection object with the given parameters.
* @param r_maj, r_min is the major/minor axis of the earth
* lat1/lat2 is the first and second standard parallel (in radians)
* lon0/lat0 is the central longitude and origin latitude (in radians)
* fs_east/fs_north is the false easting/norhting.
*/
NOP GProjAlbers(double r_maj, double r_min,
double lat1, double lat2,
double lon0, double lat0,
double fs_east=0, double fs_north=0);
/**
* setup the parameters for the Albers projection. This is called
* by the constructor with the same set of parameters.
*/
Result init(double r_maj, double r_min,
double lat1, double lat2,
double lon0, double lat0,
double fs_east=0, double fs_north=0);
/**
* Forward conversion from (longitude,latitude) to Albers coordinates
* in meters.
* @param (lon, lat) MUST be radians!!!
*/
Result forward(double lon, double lat, double& x, double& y);
/**
* Inverse conversion from Albers coordinates to (longitude, latitude).
* (x,y) must be in *meters*; and (lon, lat) will be in *radians*.
*/
Result inverse(double x, double y, double& lon, double& lat);
};
#endif
Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999