mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-19 06:05:31 -06:00
397 lines
16 KiB
Text
397 lines
16 KiB
Text
/*! \page osr_tutorial OGR Projections Tutorial
|
|
|
|
\section osr_tutorial_intro Introduction
|
|
|
|
The OGRSpatialReference, and OGRCoordinateTransformation classes provide
|
|
services to represent coordinate systems (projections and datums) and to
|
|
transform between them. These services are loosely modelled on the
|
|
OpenGIS Coordinate Transformations specification, and use the same
|
|
Well Known Text format for describing coordinate systems.
|
|
|
|
Some background on OpenGIS coordinate systems and services can be found
|
|
in the Simple Features for COM, and Spatial Reference Systems Abstract Model
|
|
documents available from the <a href="http://www.opengeospatial.org">Open Geospatial Consortium</a>.
|
|
The <a href="http://www.remotesensing.org/geotiff/proj_list">GeoTIFF Projections Transform List</a>
|
|
may also be of assistance in
|
|
understanding formulations of projections in WKT. The
|
|
<a href="http://www.epsg.org">EPSG</a>
|
|
Geodesy web page is also a useful resource.
|
|
|
|
\section osr_tutorial_cs Defining a Geographic Coordinate System
|
|
|
|
Coordinate systems are encapsulated in the OGRSpatialReference class. There
|
|
are a number of ways of initializing an OGRSpatialReference object to a
|
|
valid coordinate system. There are two primary kinds of coordinate systems.
|
|
The first is geographic (positions are measured in long/lat) and the second
|
|
is projected (such as UTM - positions are measured in meters or feet).
|
|
|
|
A Geographic coordinate system contains information on the datum (which implies
|
|
an spheroid described by a semi-major axis, and inverse flattening), prime
|
|
meridian (normally Greenwich), and an angular units type which is normally
|
|
degrees. The following code initializes a geographic coordinate system
|
|
on supplying all this information along with a user visible name for the
|
|
geographic coordinate system.
|
|
|
|
\code
|
|
OGRSpatialReference oSRS;
|
|
|
|
oSRS.SetGeogCS( "My geographic coordinate system",
|
|
"WGS_1984",
|
|
"My WGS84 Spheroid",
|
|
SRS_WGS84_SEMIMAJOR, SRS_WGS84_INVFLATTENING,
|
|
"Greenwich", 0.0,
|
|
"degree", SRS_UA_DEGREE_CONV );
|
|
\endcode
|
|
|
|
Of these values, the names "My geographic coordinate system", "My WGS84
|
|
Spheroid", "Greenwich" and "degree" are not keys, but are used for display
|
|
to the user. However, the datum name "WGS_1984" is used as a key to identify
|
|
the datum, and there are rules on what values can be used. NOTE: Prepare
|
|
writeup somewhere on valid datums!
|
|
|
|
The OGRSpatialReference has built in support for a few well known coordinate
|
|
systems, which include "NAD27", "NAD83", "WGS72" and "WGS84" which can be
|
|
defined in a single call to SetWellKnownGeogCS().
|
|
|
|
\code
|
|
oSRS.SetWellKnownGeogCS( "WGS84" );
|
|
\endcode
|
|
|
|
Furthermore, any geographic coordinate system in the EPSG database can
|
|
be set by it's GCS code number if the EPSG database is available.
|
|
|
|
\code
|
|
oSRS.SetWellKnownGeogCS( "EPSG:4326" );
|
|
\endcode
|
|
|
|
For serialization, and transmission of projection definitions to other
|
|
packages, the OpenGIS Well Known Text format for coordinate systems is
|
|
used. An OGRSpatialReference can be initialized from well known text, or
|
|
converted back into well known text.
|
|
|
|
\code
|
|
char *pszWKT = NULL;
|
|
|
|
oSRS.SetWellKnownGeogCS( "WGS84" );
|
|
oSRS.exportToWkt( &pszWKT );
|
|
printf( "%s\n", pszWKT );
|
|
\endcode
|
|
|
|
gives something like:
|
|
|
|
<pre>
|
|
GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,
|
|
AUTHORITY["EPSG",7030]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY["EPSG",6326]],
|
|
PRIMEM["Greenwich",0,AUTHORITY["EPSG",8901]],UNIT["DMSH",0.0174532925199433,
|
|
AUTHORITY["EPSG",9108]],AXIS["Lat",NORTH],AXIS["Long",EAST],AUTHORITY["EPSG",
|
|
4326]]
|
|
</pre>
|
|
|
|
or in more readable form:
|
|
|
|
<pre>
|
|
GEOGCS["WGS 84",
|
|
DATUM["WGS_1984",
|
|
SPHEROID["WGS 84",6378137,298.257223563,
|
|
AUTHORITY["EPSG",7030]],
|
|
TOWGS84[0,0,0,0,0,0,0],
|
|
AUTHORITY["EPSG",6326]],
|
|
PRIMEM["Greenwich",0,AUTHORITY["EPSG",8901]],
|
|
UNIT["DMSH",0.0174532925199433,AUTHORITY["EPSG",9108]],
|
|
AXIS["Lat",NORTH],
|
|
AXIS["Long",EAST],
|
|
AUTHORITY["EPSG",4326]]
|
|
</pre>
|
|
|
|
The OGRSpatialReference::importFromWkt() method can be used to set an
|
|
OGRSpatialReference from a WKT coordinate system definition.
|
|
|
|
\section osr_tutorial_proj Defining a Projected Coordinate System
|
|
|
|
A projected coordinate system (such as UTM, Lambert Conformal Conic, etc)
|
|
requires and underlying geographic coordinate system as well as a definition
|
|
for the projection transform used to translate between linear positions
|
|
(in meters or feet) and angular long/lat positions. The following code
|
|
defines a UTM zone 17 projected coordinate system with an underlying
|
|
geographic coordinate system (datum) of WGS84.
|
|
|
|
\code
|
|
OGRSpatialReference oSRS;
|
|
|
|
oSRS.SetProjCS( "UTM 17 (WGS84) in northern hemisphere." );
|
|
oSRS.SetWellKnownGeogCS( "WGS84" );
|
|
oSRS.SetUTM( 17, TRUE );
|
|
\endcode
|
|
|
|
Calling SetProjCS() sets a user
|
|
name for the projected coordinate system and establishes that the system
|
|
is projected. The SetWellKnownGeogCS() associates a geographic coordinate
|
|
system, and the SetUTM() call sets detailed projection transformation
|
|
parameters. At this time the above order is important in order to
|
|
create a valid definition, but in the future the object will automatically
|
|
reorder the internal representation as needed to remain valid. For now
|
|
<b>be careful of the order of steps defining an OGRSpatialReference!</b>
|
|
|
|
The above definition would give a WKT version that looks something like
|
|
the following. Note that the UTM 17 was expanded into the details
|
|
transverse mercator definition of the UTM zone.
|
|
|
|
<pre>
|
|
PROJCS["UTM 17 (WGS84) in northern hemisphere.",
|
|
GEOGCS["WGS 84",
|
|
DATUM["WGS_1984",
|
|
SPHEROID["WGS 84",6378137,298.257223563,
|
|
AUTHORITY["EPSG",7030]],
|
|
TOWGS84[0,0,0,0,0,0,0],
|
|
AUTHORITY["EPSG",6326]],
|
|
PRIMEM["Greenwich",0,AUTHORITY["EPSG",8901]],
|
|
UNIT["DMSH",0.0174532925199433,AUTHORITY["EPSG",9108]],
|
|
AXIS["Lat",NORTH],
|
|
AXIS["Long",EAST],
|
|
AUTHORITY["EPSG",4326]],
|
|
PROJECTION["Transverse_Mercator"],
|
|
PARAMETER["latitude_of_origin",0],
|
|
PARAMETER["central_meridian",-81],
|
|
PARAMETER["scale_factor",0.9996],
|
|
PARAMETER["false_easting",500000],
|
|
PARAMETER["false_northing",0]]
|
|
</pre>
|
|
|
|
There are methods for many projection methods including SetTM() (Transverse
|
|
Mercator), SetLCC() (Lambert Conformal Conic), and SetMercator().
|
|
|
|
\section osr_tutorial_query Querying Coordinate System
|
|
|
|
Once an OGRSpatialReference has been established, various information about
|
|
it can be queried. It can be established if it is a projected or
|
|
geographic coordinate system using the OGRSpatialReference::IsProjected() and
|
|
OGRSpatialReference::IsGeographic() methods. The
|
|
OGRSpatialReference::GetSemiMajor(), OGRSpatialReference::GetSemiMinor() and
|
|
OGRSpatialReference::GetInvFlattening() methods can be used to get
|
|
information about the spheroid. The OGRSpatialReference::GetAttrValue()
|
|
method can be used to get the PROJCS, GEOGCS, DATUM, SPHEROID, and PROJECTION
|
|
names strings. The OGRSpatialReference::GetProjParm() method can be used to
|
|
get the projection parameters. The OGRSpatialReference::GetLinearUnits()
|
|
method can be used to fetch the linear units type, and translation to meters.
|
|
|
|
The following code (from ogr_srs_proj4.cpp) demonstrates use
|
|
of GetAttrValue() to get the projection, and GetProjParm() to get projection
|
|
parameters. The GetAttrValue() method searches for the first "value"
|
|
node associated with the named entry in the WKT text representation.
|
|
The #define'ed constants for projection parameters (such as
|
|
SRS_PP_CENTRAL_MERIDIAN) should be used when fetching projection parameter
|
|
with GetProjParm(). The code for the Set methods of the various projections
|
|
in ogrspatialreference.cpp can be consulted to find which parameters apply to
|
|
which projections.
|
|
|
|
\code
|
|
const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
|
|
|
|
if( pszProjection == NULL )
|
|
{
|
|
if( poSRS->IsGeographic() )
|
|
sprintf( szProj4+strlen(szProj4), "+proj=longlat " );
|
|
else
|
|
sprintf( szProj4+strlen(szProj4), "unknown " );
|
|
}
|
|
else if( EQUAL(pszProjection,SRS_PT_CYLINDRICAL_EQUAL_AREA) )
|
|
{
|
|
sprintf( szProj4+strlen(szProj4),
|
|
"+proj=cea +lon_0=%.9f +lat_ts=%.9f +x_0=%.3f +y_0=%.3f ",
|
|
poSRS->GetProjParm(SRS_PP_CENTRAL_MERIDIAN,0.0),
|
|
poSRS->GetProjParm(SRS_PP_STANDARD_PARALLEL_1,0.0),
|
|
poSRS->GetProjParm(SRS_PP_FALSE_EASTING,0.0),
|
|
poSRS->GetProjParm(SRS_PP_FALSE_NORTHING,0.0) );
|
|
}
|
|
...
|
|
\endcode
|
|
|
|
\section osr_tutorial_transform Coordinate Transformation
|
|
|
|
The OGRCoordinateTransformation class is used for translating positions
|
|
between different coordinate systems. New transformation objects are
|
|
created using OGRCreateCoordinateTransformation(), and then the
|
|
OGRCoordinateTransformation::Transform() method can be used to convert
|
|
points between coordinate systems.
|
|
|
|
\code
|
|
OGRSpatialReference oSourceSRS, oTargetSRS;
|
|
OGRCoordinateTransformation *poCT;
|
|
double x, y;
|
|
|
|
oSourceSRS.importFromEPSG( atoi(papszArgv[i+1]) );
|
|
oTargetSRS.importFromEPSG( atoi(papszArgv[i+2]) );
|
|
|
|
poCT = OGRCreateCoordinateTransformation( &oSourceSRS,
|
|
&oTargetSRS );
|
|
x = atof( papszArgv[i+3] );
|
|
y = atof( papszArgv[i+4] );
|
|
|
|
if( poCT == NULL || !poCT->Transform( 1, &x, &y ) )
|
|
printf( "Transformation failed.\n" );
|
|
else
|
|
printf( "(%f,%f) -> (%f,%f)\n",
|
|
atof( papszArgv[i+3] ),
|
|
atof( papszArgv[i+4] ),
|
|
x, y );
|
|
\endcode
|
|
|
|
There are a couple of points at which transformations can
|
|
fail. First, OGRCreateCoordinateTransformation() may fail,
|
|
generally because the internals recognise that no transformation
|
|
between the indicated systems can be established. This might
|
|
be due to use of a projection not supported by the internal
|
|
PROJ.4 library, differing datums for which no relationship
|
|
is known, or one of the coordinate systems being inadequately
|
|
defined. If OGRCreateCoordinateTransformation() fails it will
|
|
return a NULL.
|
|
|
|
The OGRCoordinateTransformation::Transform() method itself can
|
|
also fail. This may be as a delayed result of one of the above
|
|
problems, or as a result of an operation being numerically
|
|
undefined for one or more of the passed in points. The
|
|
Transform() function will return TRUE on success, or FALSE
|
|
if any of the points fail to transform. The point array is
|
|
left in an indeterminate state on error.
|
|
|
|
Though not shown above, the coordinate transformation service can
|
|
take 3D points, and will adjust elevations for elevation differents
|
|
in spheroids, and datums. At some point in the future shifts
|
|
between different vertical datums may also be applied. If no Z is
|
|
passed, it is assume that the point is on the geoide.
|
|
|
|
The following example shows how to conveniently create a lat/long coordinate
|
|
system using the same geographic coordinate system as a projected coordinate
|
|
system, and using that to transform between projected coordinates and
|
|
lat/long.
|
|
|
|
\code
|
|
OGRSpatialReference oUTM, *poLatLong;
|
|
OGRCoordinateTransformation *poTransform;
|
|
|
|
oUTM.SetProjCS("UTM 17 / WGS84");
|
|
oUTM.SetWellKnownGeogCS( "WGS84" );
|
|
oUTM.SetUTM( 17 );
|
|
|
|
poLatLong = oUTM.CloneGeogCS();
|
|
|
|
poTransform = OGRCreateCoordinateTransformation( &oUTM, poLatLong );
|
|
if( poTransform == NULL )
|
|
{
|
|
...
|
|
}
|
|
|
|
...
|
|
|
|
if( !poTransform->Transform( nPoints, x, y, z ) )
|
|
...
|
|
\endcode
|
|
|
|
\section osr_tutorial_apis Alternate Interfaces
|
|
|
|
A C interface to the coordinate system services is defined in
|
|
ogr_srs_api.h, and Python bindings are available via the osr.py module.
|
|
Methods are close analogs of the C++ methods but C and Python bindings
|
|
are missing for some C++ methods.
|
|
|
|
<h3>C Bindings</h3>
|
|
|
|
\code
|
|
typedef void *OGRSpatialReferenceH;
|
|
typedef void *OGRCoordinateTransformationH;
|
|
|
|
OGRSpatialReferenceH OSRNewSpatialReference( const char * );
|
|
void OSRDestroySpatialReference( OGRSpatialReferenceH );
|
|
|
|
int OSRReference( OGRSpatialReferenceH );
|
|
int OSRDereference( OGRSpatialReferenceH );
|
|
|
|
OGRErr OSRImportFromEPSG( OGRSpatialReferenceH, int );
|
|
OGRErr OSRImportFromWkt( OGRSpatialReferenceH, char ** );
|
|
OGRErr OSRExportToWkt( OGRSpatialReferenceH, char ** );
|
|
|
|
OGRErr OSRSetAttrValue( OGRSpatialReferenceH hSRS, const char * pszNodePath,
|
|
const char * pszNewNodeValue );
|
|
const char *OSRGetAttrValue( OGRSpatialReferenceH hSRS,
|
|
const char * pszName, int iChild);
|
|
|
|
OGRErr OSRSetLinearUnits( OGRSpatialReferenceH, const char *, double );
|
|
double OSRGetLinearUnits( OGRSpatialReferenceH, char ** );
|
|
|
|
int OSRIsGeographic( OGRSpatialReferenceH );
|
|
int OSRIsProjected( OGRSpatialReferenceH );
|
|
int OSRIsSameGeogCS( OGRSpatialReferenceH, OGRSpatialReferenceH );
|
|
int OSRIsSame( OGRSpatialReferenceH, OGRSpatialReferenceH );
|
|
|
|
OGRErr OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName );
|
|
OGRErr OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS,
|
|
const char * pszName );
|
|
|
|
OGRErr OSRSetGeogCS( OGRSpatialReferenceH hSRS,
|
|
const char * pszGeogName,
|
|
const char * pszDatumName,
|
|
const char * pszEllipsoidName,
|
|
double dfSemiMajor, double dfInvFlattening,
|
|
const char * pszPMName ,
|
|
double dfPMOffset ,
|
|
const char * pszUnits,
|
|
double dfConvertToRadians );
|
|
|
|
double OSRGetSemiMajor( OGRSpatialReferenceH, OGRErr * );
|
|
double OSRGetSemiMinor( OGRSpatialReferenceH, OGRErr * );
|
|
double OSRGetInvFlattening( OGRSpatialReferenceH, OGRErr * );
|
|
|
|
OGRErr OSRSetAuthority( OGRSpatialReferenceH hSRS,
|
|
const char * pszTargetKey,
|
|
const char * pszAuthority,
|
|
int nCode );
|
|
OGRErr OSRSetProjParm( OGRSpatialReferenceH, const char *, double );
|
|
double OSRGetProjParm( OGRSpatialReferenceH hSRS,
|
|
const char * pszParmName,
|
|
double dfDefault,
|
|
OGRErr * );
|
|
|
|
OGRErr OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth );
|
|
int OSRGetUTMZone( OGRSpatialReferenceH hSRS, int *pbNorth );
|
|
|
|
OGRCoordinateTransformationH
|
|
OCTNewCoordinateTransformation( OGRSpatialReferenceH hSourceSRS,
|
|
OGRSpatialReferenceH hTargetSRS );
|
|
void OCTDestroyCoordinateTransformation( OGRCoordinateTransformationH );
|
|
|
|
int OCTTransform( OGRCoordinateTransformationH hCT,
|
|
int nCount, double *x, double *y, double *z );
|
|
\endcode
|
|
|
|
<h3>Python Bindings</h3>
|
|
|
|
\code
|
|
class osr.SpatialReference
|
|
def __init__(self,obj=None):
|
|
def ImportFromWkt( self, wkt ):
|
|
def ExportToWkt(self):
|
|
def ImportFromEPSG(self,code):
|
|
def IsGeographic(self):
|
|
def IsProjected(self):
|
|
def GetAttrValue(self, name, child = 0):
|
|
def SetAttrValue(self, name, value):
|
|
def SetWellKnownGeogCS(self, name):
|
|
def SetProjCS(self, name = "unnamed" ):
|
|
def IsSameGeogCS(self, other):
|
|
def IsSame(self, other):
|
|
def SetLinearUnits(self, units_name, to_meters ):
|
|
def SetUTM(self, zone, is_north = 1):
|
|
|
|
class CoordinateTransformation:
|
|
def __init__(self,source,target):
|
|
def TransformPoint(self, x, y, z = 0):
|
|
def TransformPoints(self, points):
|
|
\endcode
|
|
|
|
\section osr_tutorial_impl Internal Implementation
|
|
|
|
The OGRCoordinateTransformation service is implemented on top of the
|
|
<a href="http://www.remotesensing.org/proj">PROJ.4</a> library originally
|
|
written by Gerald Evenden of the USGS.
|
|
|
|
*/
|