ultimatepp/bazaar/plugin/gdal/ogr/ogrspatialreference.cpp
cxl 23ff1e7e82 .gdal moved to bazaar
git-svn-id: svn://ultimatepp.org/upp/trunk@9273 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2015-12-07 13:36:24 +00:00

7605 lines
262 KiB
C++

/******************************************************************************
* $Id: ogrspatialreference.cpp 29104 2015-05-02 01:44:39Z rouault $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: The OGRSpatialReference class.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Les Technologies SoftMap Inc.
* Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "ogr_spatialref.h"
#include "ogr_p.h"
#include "cpl_csv.h"
#include "cpl_http.h"
#include "cpl_atomic_ops.h"
#include "cpl_multiproc.h"
CPL_CVSID("$Id: ogrspatialreference.cpp 29104 2015-05-02 01:44:39Z rouault $");
// The current opinion is that WKT longitudes like central meridian
// should be relative to greenwich, not the prime meridian in use.
// Define the following if they should be relative to the prime meridian
// of then geogcs.
#undef WKT_LONGITUDE_RELATIVE_TO_PM
/************************************************************************/
/* OGRPrintDouble() */
/************************************************************************/
void OGRPrintDouble( char * pszStrBuf, double dfValue )
{
CPLsprintf( pszStrBuf, "%.16g", dfValue );
int nLen = strlen(pszStrBuf);
// The following hack is intended to truncate some "precision" in cases
// that appear to be roundoff error.
if( nLen > 15
&& (strcmp(pszStrBuf+nLen-6,"999999") == 0
|| strcmp(pszStrBuf+nLen-6,"000001") == 0) )
{
CPLsprintf( pszStrBuf, "%.15g", dfValue );
}
// force to user periods regardless of locale.
if( strchr( pszStrBuf, ',' ) != NULL )
{
char *pszDelim = strchr( pszStrBuf, ',' );
*pszDelim = '.';
}
}
/************************************************************************/
/* OGRSpatialReference() */
/************************************************************************/
/**
* \brief Constructor.
*
* This constructor takes an optional string argument which if passed
* should be a WKT representation of an SRS. Passing this is equivalent
* to not passing it, and then calling importFromWkt() with the WKT string.
*
* Note that newly created objects are given a reference count of one.
*
* The C function OSRNewSpatialReference() does the same thing as this
* constructor.
*
* @param pszWKT well known text definition to which the object should
* be initialized, or NULL (the default).
*/
OGRSpatialReference::OGRSpatialReference( const char * pszWKT )
{
bNormInfoSet = FALSE;
nRefCount = 1;
poRoot = NULL;
if( pszWKT != NULL )
importFromWkt( (char **) &pszWKT );
}
/************************************************************************/
/* OSRNewSpatialReference() */
/************************************************************************/
/**
* \brief Constructor.
*
* This function is the same as OGRSpatialReference::OGRSpatialReference()
*/
OGRSpatialReferenceH CPL_STDCALL OSRNewSpatialReference( const char *pszWKT )
{
OGRSpatialReference * poSRS;
poSRS = new OGRSpatialReference();
if( pszWKT != NULL && strlen(pszWKT) > 0 )
{
if( poSRS->importFromWkt( (char **) (&pszWKT) ) != OGRERR_NONE )
{
delete poSRS;
poSRS = NULL;
}
}
return (OGRSpatialReferenceH) poSRS;
}
/************************************************************************/
/* OGRSpatialReference() */
/* */
/* Simple copy constructor. See also Clone(). */
/************************************************************************/
OGRSpatialReference::OGRSpatialReference(const OGRSpatialReference &oOther)
{
bNormInfoSet = FALSE;
nRefCount = 1;
poRoot = NULL;
if( oOther.poRoot != NULL )
poRoot = oOther.poRoot->Clone();
}
/************************************************************************/
/* ~OGRSpatialReference() */
/************************************************************************/
/**
* \brief OGRSpatialReference destructor.
*
* The C function OSRDestroySpatialReference() does the same thing as this
* method. Preferred C++ method : OGRSpatialReference::DestroySpatialReference()
*
* @deprecated
*/
OGRSpatialReference::~OGRSpatialReference()
{
if( poRoot != NULL )
delete poRoot;
}
/************************************************************************/
/* DestroySpatialReference() */
/************************************************************************/
/**
* \brief OGRSpatialReference destructor.
*
* This static method will destroy a OGRSpatialReference. It is
* equivalent to calling delete on the object, but it ensures that the
* deallocation is properly executed within the OGR libraries heap on
* platforms where this can matter (win32).
*
* This function is the same as OSRDestroySpatialReference()
*
* @param poSRS the object to delete
*
* @since GDAL 1.7.0
*/
void OGRSpatialReference::DestroySpatialReference(OGRSpatialReference* poSRS)
{
delete poSRS;
}
/************************************************************************/
/* OSRDestroySpatialReference() */
/************************************************************************/
/**
* \brief OGRSpatialReference destructor.
*
* This function is the same as OGRSpatialReference::~OGRSpatialReference()
* and OGRSpatialReference::DestroySpatialReference()
*
* @param hSRS the object to delete
*/
void CPL_STDCALL OSRDestroySpatialReference( OGRSpatialReferenceH hSRS )
{
delete ((OGRSpatialReference *) hSRS);
}
/************************************************************************/
/* Clear() */
/************************************************************************/
/**
* \brief Wipe current definition.
*
* Returns OGRSpatialReference to a state with no definition, as it
* exists when first created. It does not affect reference counts.
*/
void OGRSpatialReference::Clear()
{
if( poRoot )
delete poRoot;
poRoot = NULL;
bNormInfoSet = FALSE;
dfFromGreenwich = 1.0;
dfToMeter = 1.0;
dfToDegrees = 1.0;
}
/************************************************************************/
/* operator=() */
/************************************************************************/
OGRSpatialReference &
OGRSpatialReference::operator=(const OGRSpatialReference &oSource)
{
Clear();
if( oSource.poRoot != NULL )
poRoot = oSource.poRoot->Clone();
return *this;
}
/************************************************************************/
/* Reference() */
/************************************************************************/
/**
* \brief Increments the reference count by one.
*
* The reference count is used keep track of the number of OGRGeometry objects
* referencing this SRS.
*
* The method does the same thing as the C function OSRReference().
*
* @return the updated reference count.
*/
int OGRSpatialReference::Reference()
{
return CPLAtomicInc(&nRefCount);
}
/************************************************************************/
/* OSRReference() */
/************************************************************************/
/**
* \brief Increments the reference count by one.
*
* This function is the same as OGRSpatialReference::Reference()
*/
int OSRReference( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRReference", 0 );
return ((OGRSpatialReference *) hSRS)->Reference();
}
/************************************************************************/
/* Dereference() */
/************************************************************************/
/**
* \brief Decrements the reference count by one.
*
* The method does the same thing as the C function OSRDereference().
*
* @return the updated reference count.
*/
int OGRSpatialReference::Dereference()
{
if( nRefCount <= 0 )
CPLDebug( "OSR",
"Dereference() called on an object with refcount %d,"
"likely already destroyed!",
nRefCount );
return CPLAtomicDec(&nRefCount);
}
/************************************************************************/
/* OSRDereference() */
/************************************************************************/
/**
* \brief Decrements the reference count by one.
*
* This function is the same as OGRSpatialReference::Dereference()
*/
int OSRDereference( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRDereference", 0 );
return ((OGRSpatialReference *) hSRS)->Dereference();
}
/************************************************************************/
/* GetReferenceCount() */
/************************************************************************/
/**
* \fn int OGRSpatialReference::GetReferenceCount() const;
*
* \brief Fetch current reference count.
*
* @return the current reference count.
*/
/************************************************************************/
/* Release() */
/************************************************************************/
/**
* \brief Decrements the reference count by one, and destroy if zero.
*
* The method does the same thing as the C function OSRRelease().
*/
void OGRSpatialReference::Release()
{
CPLAssert( NULL != this );
if( Dereference() <= 0 )
delete this;
}
/************************************************************************/
/* OSRRelease() */
/************************************************************************/
/**
* \brief Decrements the reference count by one, and destroy if zero.
*
* This function is the same as OGRSpatialReference::Release()
*/
void OSRRelease( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER0( hSRS, "OSRRelease" );
((OGRSpatialReference *) hSRS)->Release();
}
/************************************************************************/
/* SetRoot() */
/************************************************************************/
/**
* \brief Set the root SRS node.
*
* If the object has an existing tree of OGR_SRSNodes, they are destroyed
* as part of assigning the new root. Ownership of the passed OGR_SRSNode is
* is assumed by the OGRSpatialReference.
*
* @param poNewRoot object to assign as root.
*/
void OGRSpatialReference::SetRoot( OGR_SRSNode * poNewRoot )
{
if( poRoot != NULL )
delete poRoot;
poRoot = poNewRoot;
}
/************************************************************************/
/* GetAttrNode() */
/************************************************************************/
/**
* \brief Find named node in tree.
*
* This method does a pre-order traversal of the node tree searching for
* a node with this exact value (case insensitive), and returns it. Leaf
* nodes are not considered, under the assumption that they are just
* attribute value nodes.
*
* If a node appears more than once in the tree (such as UNIT for instance),
* the first encountered will be returned. Use GetNode() on a subtree to be
* more specific.
*
* @param pszNodePath the name of the node to search for. May contain multiple
* components such as "GEOGCS|UNIT".
*
* @return a pointer to the node found, or NULL if none.
*/
OGR_SRSNode *OGRSpatialReference::GetAttrNode( const char * pszNodePath )
{
char **papszPathTokens;
OGR_SRSNode *poNode;
papszPathTokens = CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
if( CSLCount( papszPathTokens ) < 1 )
{
CSLDestroy(papszPathTokens);
return NULL;
}
poNode = GetRoot();
for( int i = 0; poNode != NULL && papszPathTokens[i] != NULL; i++ )
{
poNode = poNode->GetNode( papszPathTokens[i] );
}
CSLDestroy( papszPathTokens );
return poNode;
}
const OGR_SRSNode *
OGRSpatialReference::GetAttrNode( const char * pszNodePath ) const
{
OGR_SRSNode *poNode;
poNode = ((OGRSpatialReference *) this)->GetAttrNode(pszNodePath);
return poNode;
}
/************************************************************************/
/* GetAttrValue() */
/************************************************************************/
/**
* \brief Fetch indicated attribute of named node.
*
* This method uses GetAttrNode() to find the named node, and then extracts
* the value of the indicated child. Thus a call to GetAttrValue("UNIT",1)
* would return the second child of the UNIT node, which is normally the
* length of the linear unit in meters.
*
* This method does the same thing as the C function OSRGetAttrValue().
*
* @param pszNodeName the tree node to look for (case insensitive).
* @param iAttr the child of the node to fetch (zero based).
*
* @return the requested value, or NULL if it fails for any reason.
*/
const char *OGRSpatialReference::GetAttrValue( const char * pszNodeName,
int iAttr ) const
{
const OGR_SRSNode *poNode;
poNode = GetAttrNode( pszNodeName );
if( poNode == NULL )
return NULL;
if( iAttr < 0 || iAttr >= poNode->GetChildCount() )
return NULL;
return poNode->GetChild(iAttr)->GetValue();
}
/************************************************************************/
/* OSRGetAttrValue() */
/************************************************************************/
/**
* \brief Fetch indicated attribute of named node.
*
* This function is the same as OGRSpatialReference::GetAttrValue()
*/
const char * CPL_STDCALL OSRGetAttrValue( OGRSpatialReferenceH hSRS,
const char * pszKey, int iChild )
{
VALIDATE_POINTER1( hSRS, "OSRGetAttrValue", NULL );
return ((OGRSpatialReference *) hSRS)->GetAttrValue( pszKey, iChild );
}
/************************************************************************/
/* Clone() */
/************************************************************************/
/**
* \brief Make a duplicate of this OGRSpatialReference.
*
* This method is the same as the C function OSRClone().
*
* @return a new SRS, which becomes the responsibility of the caller.
*/
OGRSpatialReference *OGRSpatialReference::Clone() const
{
OGRSpatialReference *poNewRef;
poNewRef = new OGRSpatialReference();
if( poRoot != NULL )
poNewRef->poRoot = poRoot->Clone();
return poNewRef;
}
/************************************************************************/
/* OSRClone() */
/************************************************************************/
/**
* \brief Make a duplicate of this OGRSpatialReference.
*
* This function is the same as OGRSpatialReference::Clone()
*/
OGRSpatialReferenceH CPL_STDCALL OSRClone( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRClone", NULL );
return (OGRSpatialReferenceH) ((OGRSpatialReference *) hSRS)->Clone();
}
/************************************************************************/
/* dumpReadable() */
/* */
/* Dump pretty wkt to stdout, mostly for debugging. */
/************************************************************************/
void OGRSpatialReference::dumpReadable()
{
char *pszPrettyWkt = NULL;
exportToPrettyWkt( &pszPrettyWkt, FALSE );
printf( "%s\n", pszPrettyWkt );
CPLFree( pszPrettyWkt );
}
/************************************************************************/
/* exportToPrettyWkt() */
/************************************************************************/
/**
* Convert this SRS into a a nicely formatted WKT string for display to a person.
*
* Note that the returned WKT string should be freed with OGRFree() or
* CPLFree() when no longer needed. It is the responsibility of the caller.
*
* This method is the same as the C function OSRExportToPrettyWkt().
*
* @param ppszResult the resulting string is returned in this pointer.
* @param bSimplify TRUE if the AXIS, AUTHORITY and EXTENSION nodes should be stripped off
*
* @return currently OGRERR_NONE is always returned, but the future it
* is possible error conditions will develop.
*/
OGRErr OGRSpatialReference::exportToPrettyWkt( char ** ppszResult,
int bSimplify ) const
{
if( poRoot == NULL )
{
*ppszResult = CPLStrdup("");
return OGRERR_NONE;
}
if( bSimplify )
{
OGRSpatialReference *poSimpleClone = Clone();
OGRErr eErr;
poSimpleClone->GetRoot()->StripNodes( "AXIS" );
poSimpleClone->GetRoot()->StripNodes( "AUTHORITY" );
poSimpleClone->GetRoot()->StripNodes( "EXTENSION" );
eErr = poSimpleClone->GetRoot()->exportToPrettyWkt( ppszResult, 1 );
delete poSimpleClone;
return eErr;
}
else
return poRoot->exportToPrettyWkt( ppszResult, 1 );
}
/************************************************************************/
/* OSRExportToPrettyWkt() */
/************************************************************************/
/**
* \brief Convert this SRS into a a nicely formatted WKT string for display to a person.
*
* This function is the same as OGRSpatialReference::exportToPrettyWkt().
*/
OGRErr CPL_STDCALL OSRExportToPrettyWkt( OGRSpatialReferenceH hSRS, char ** ppszReturn,
int bSimplify)
{
VALIDATE_POINTER1( hSRS, "OSRExportToPrettyWkt", CE_Failure );
*ppszReturn = NULL;
return ((OGRSpatialReference *) hSRS)->exportToPrettyWkt( ppszReturn,
bSimplify );
}
/************************************************************************/
/* exportToWkt() */
/************************************************************************/
/**
* \brief Convert this SRS into WKT format.
*
* Note that the returned WKT string should be freed with OGRFree() or
* CPLFree() when no longer needed. It is the responsibility of the caller.
*
* This method is the same as the C function OSRExportToWkt().
*
* @param ppszResult the resulting string is returned in this pointer.
*
* @return currently OGRERR_NONE is always returned, but the future it
* is possible error conditions will develop.
*/
OGRErr OGRSpatialReference::exportToWkt( char ** ppszResult ) const
{
if( poRoot == NULL )
{
*ppszResult = CPLStrdup("");
return OGRERR_NONE;
}
else
{
return poRoot->exportToWkt(ppszResult);
}
}
/************************************************************************/
/* OSRExportToWkt() */
/************************************************************************/
/**
* \brief Convert this SRS into WKT format.
*
* This function is the same as OGRSpatialReference::exportToWkt().
*/
OGRErr CPL_STDCALL OSRExportToWkt( OGRSpatialReferenceH hSRS,
char ** ppszReturn )
{
VALIDATE_POINTER1( hSRS, "OSRExportToWkt", CE_Failure );
*ppszReturn = NULL;
return ((OGRSpatialReference *) hSRS)->exportToWkt( ppszReturn );
}
/************************************************************************/
/* importFromWkt() */
/************************************************************************/
/**
* \brief Import from WKT string.
*
* This method will wipe the existing SRS definition, and
* reassign it based on the contents of the passed WKT string. Only as
* much of the input string as needed to construct this SRS is consumed from
* the input string, and the input string pointer
* is then updated to point to the remaining (unused) input.
*
* This method is the same as the C function OSRImportFromWkt().
*
* @param ppszInput Pointer to pointer to input. The pointer is updated to
* point to remaining unused input text.
*
* @return OGRERR_NONE if import succeeds, or OGRERR_CORRUPT_DATA if it
* fails for any reason.
*/
OGRErr OGRSpatialReference::importFromWkt( char ** ppszInput )
{
if ( !ppszInput || !*ppszInput )
return OGRERR_FAILURE;
Clear();
poRoot = new OGR_SRSNode();
OGRErr eErr = poRoot->importFromWkt( ppszInput );
if (eErr != OGRERR_NONE)
return eErr;
/* -------------------------------------------------------------------- */
/* The following seems to try and detect and unconsumed */
/* VERTCS[] coordinate system definition (ESRI style) and to */
/* import and attach it to the existing root. Likely we will */
/* need to extend this somewhat to bring it into an acceptable */
/* OGRSpatialReference organization at some point. */
/* -------------------------------------------------------------------- */
if (strlen(*ppszInput) > 0 && strstr(*ppszInput, "VERTCS"))
{
if(((*ppszInput)[0]) == ',')
(*ppszInput)++;
OGR_SRSNode *poNewChild = new OGR_SRSNode();
poRoot->AddChild( poNewChild );
return poNewChild->importFromWkt( ppszInput );
}
return eErr;
}
/************************************************************************/
/* OSRImportFromWkt() */
/************************************************************************/
/**
* \brief Import from WKT string.
*
* This function is the same as OGRSpatialReference::importFromWkt().
*/
OGRErr OSRImportFromWkt( OGRSpatialReferenceH hSRS, char **ppszInput )
{
VALIDATE_POINTER1( hSRS, "OSRImportFromWkt", CE_Failure );
return ((OGRSpatialReference *) hSRS)->importFromWkt( ppszInput );
}
/************************************************************************/
/* SetNode() */
/************************************************************************/
/**
* \brief Set attribute value in spatial reference.
*
* Missing intermediate nodes in the path will be created if not already
* in existance. If the attribute has no children one will be created and
* assigned the value otherwise the zeroth child will be assigned the value.
*
* This method does the same as the C function OSRSetAttrValue().
*
* @param pszNodePath full path to attribute to be set. For instance
* "PROJCS|GEOGCS|UNIT".
*
* @param pszNewNodeValue value to be assigned to node, such as "meter".
* This may be NULL if you just want to force creation of the intermediate
* path.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetNode( const char * pszNodePath,
const char * pszNewNodeValue )
{
char **papszPathTokens;
int i;
OGR_SRSNode *poNode;
papszPathTokens = CSLTokenizeStringComplex(pszNodePath, "|", TRUE, FALSE);
if( CSLCount( papszPathTokens ) < 1 )
return OGRERR_FAILURE;
if( GetRoot() == NULL || !EQUAL(papszPathTokens[0],GetRoot()->GetValue()) )
{
SetRoot( new OGR_SRSNode( papszPathTokens[0] ) );
}
poNode = GetRoot();
for( i = 1; papszPathTokens[i] != NULL; i++ )
{
int j;
for( j = 0; j < poNode->GetChildCount(); j++ )
{
if( EQUAL(poNode->GetChild( j )->GetValue(),papszPathTokens[i]) )
{
poNode = poNode->GetChild(j);
j = -1;
break;
}
}
if( j != -1 )
{
OGR_SRSNode *poNewNode = new OGR_SRSNode( papszPathTokens[i] );
poNode->AddChild( poNewNode );
poNode = poNewNode;
}
}
CSLDestroy( papszPathTokens );
if( pszNewNodeValue != NULL )
{
if( poNode->GetChildCount() > 0 )
poNode->GetChild(0)->SetValue( pszNewNodeValue );
else
poNode->AddChild( new OGR_SRSNode( pszNewNodeValue ) );
}
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetAttrValue() */
/************************************************************************/
/**
* \brief Set attribute value in spatial reference.
*
* This function is the same as OGRSpatialReference::SetNode()
*/
OGRErr CPL_STDCALL OSRSetAttrValue( OGRSpatialReferenceH hSRS,
const char * pszPath, const char * pszValue )
{
VALIDATE_POINTER1( hSRS, "OSRSetAttrValue", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetNode( pszPath, pszValue );
}
/************************************************************************/
/* SetNode() */
/************************************************************************/
OGRErr OGRSpatialReference::SetNode( const char *pszNodePath,
double dfValue )
{
char szValue[64];
if( ABS(dfValue - (int) dfValue) == 0.0 )
sprintf( szValue, "%d", (int) dfValue );
else
OGRPrintDouble( szValue, dfValue );
return SetNode( pszNodePath, szValue );
}
/************************************************************************/
/* SetAngularUnits() */
/************************************************************************/
/**
* \brief Set the angular units for the geographic coordinate system.
*
* This method creates a UNIT subnode with the specified values as a
* child of the GEOGCS node.
*
* This method does the same as the C function OSRSetAngularUnits().
*
* @param pszUnitsName the units name to be used. Some preferred units
* names can be found in ogr_srs_api.h such as SRS_UA_DEGREE.
*
* @param dfInRadians the value to multiple by an angle in the indicated
* units to transform to radians. Some standard conversion factors can
* be found in ogr_srs_api.h.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetAngularUnits( const char * pszUnitsName,
double dfInRadians )
{
OGR_SRSNode *poCS;
OGR_SRSNode *poUnits;
char szValue[128];
bNormInfoSet = FALSE;
poCS = GetAttrNode( "GEOGCS" );
if( poCS == NULL )
return OGRERR_FAILURE;
OGRPrintDouble( szValue, dfInRadians );
if( poCS->FindChild( "UNIT" ) >= 0 )
{
poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
if (poUnits->GetChildCount() < 2)
return OGRERR_FAILURE;
poUnits->GetChild(0)->SetValue( pszUnitsName );
poUnits->GetChild(1)->SetValue( szValue );
}
else
{
poUnits = new OGR_SRSNode( "UNIT" );
poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
poUnits->AddChild( new OGR_SRSNode( szValue ) );
poCS->AddChild( poUnits );
}
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetAngularUnits() */
/************************************************************************/
/**
* \brief Set the angular units for the geographic coordinate system.
*
* This function is the same as OGRSpatialReference::SetAngularUnits()
*/
OGRErr OSRSetAngularUnits( OGRSpatialReferenceH hSRS,
const char * pszUnits, double dfInRadians )
{
VALIDATE_POINTER1( hSRS, "OSRSetAngularUnits", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetAngularUnits( pszUnits,
dfInRadians );
}
/************************************************************************/
/* GetAngularUnits() */
/************************************************************************/
/**
* \brief Fetch angular geographic coordinate system units.
*
* If no units are available, a value of "degree" and SRS_UA_DEGREE_CONV
* will be assumed. This method only checks directly under the GEOGCS node
* for units.
*
* This method does the same thing as the C function OSRGetAngularUnits().
*
* @param ppszName a pointer to be updated with the pointer to the
* units name. The returned value remains internal to the OGRSpatialReference
* and shouldn't be freed, or modified. It may be invalidated on the next
* OGRSpatialReference call.
*
* @return the value to multiply by angular distances to transform them to
* radians.
*/
double OGRSpatialReference::GetAngularUnits( char ** ppszName ) const
{
const OGR_SRSNode *poCS = GetAttrNode( "GEOGCS" );
if( ppszName != NULL )
*ppszName = (char* ) "degree";
if( poCS == NULL )
return CPLAtof(SRS_UA_DEGREE_CONV);
for( int iChild = 0; iChild < poCS->GetChildCount(); iChild++ )
{
const OGR_SRSNode *poChild = poCS->GetChild(iChild);
if( EQUAL(poChild->GetValue(),"UNIT")
&& poChild->GetChildCount() >= 2 )
{
if( ppszName != NULL )
*ppszName = (char *) poChild->GetChild(0)->GetValue();
return CPLAtof( poChild->GetChild(1)->GetValue() );
}
}
return 1.0;
}
/************************************************************************/
/* OSRGetAngularUnits() */
/************************************************************************/
/**
* \brief Fetch angular geographic coordinate system units.
*
* This function is the same as OGRSpatialReference::GetAngularUnits()
*/
double OSRGetAngularUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
{
VALIDATE_POINTER1( hSRS, "OSRGetAngularUnits", 0 );
return ((OGRSpatialReference *) hSRS)->GetAngularUnits( ppszName );
}
/************************************************************************/
/* SetLinearUnitsAndUpdateParameters() */
/************************************************************************/
/**
* \brief Set the linear units for the projection.
*
* This method creates a UNIT subnode with the specified values as a
* child of the PROJCS or LOCAL_CS node. It works the same as the
* SetLinearUnits() method, but it also updates all existing linear
* projection parameter values from the old units to the new units.
*
* @param pszName the units name to be used. Some preferred units
* names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
* and SRS_UL_US_FOOT.
*
* @param dfInMeters the value to multiple by a length in the indicated
* units to transform to meters. Some standard conversion factors can
* be found in ogr_srs_api.h.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetLinearUnitsAndUpdateParameters(
const char *pszName, double dfInMeters )
{
double dfOldInMeters = GetLinearUnits();
OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
if( dfInMeters == 0.0 )
return OGRERR_FAILURE;
if( dfInMeters == dfOldInMeters || poPROJCS == NULL )
return SetLinearUnits( pszName, dfInMeters );
for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
{
const OGR_SRSNode *poChild = poPROJCS->GetChild(iChild);
if( EQUAL(poChild->GetValue(),"PARAMETER")
&& poChild->GetChildCount() > 1 )
{
char *pszParmName = CPLStrdup(poChild->GetChild(0)->GetValue());
if( IsLinearParameter( pszParmName ) )
{
double dfOldValue = GetProjParm( pszParmName );
SetProjParm( pszParmName,
dfOldValue * dfOldInMeters / dfInMeters );
}
CPLFree( pszParmName );
}
}
return SetLinearUnits( pszName, dfInMeters );
}
/************************************************************************/
/* OSRSetLinearUnitsAndUpdateParameters() */
/************************************************************************/
/**
* \brief Set the linear units for the projection.
*
* This function is the same as OGRSpatialReference::SetLinearUnitsAndUpdateParameters()
*/
OGRErr OSRSetLinearUnitsAndUpdateParameters( OGRSpatialReferenceH hSRS,
const char * pszUnits,
double dfInMeters )
{
VALIDATE_POINTER1( hSRS, "OSRSetLinearUnitsAndUpdateParameters",
CE_Failure );
return ((OGRSpatialReference *) hSRS)->
SetLinearUnitsAndUpdateParameters( pszUnits, dfInMeters );
}
/************************************************************************/
/* SetLinearUnits() */
/************************************************************************/
/**
* \brief Set the linear units for the projection.
*
* This method creates a UNIT subnode with the specified values as a
* child of the PROJCS, GEOCCS or LOCAL_CS node.
*
* This method does the same as the C function OSRSetLinearUnits().
*
* @param pszUnitsName the units name to be used. Some preferred units
* names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
* and SRS_UL_US_FOOT.
*
* @param dfInMeters the value to multiple by a length in the indicated
* units to transform to meters. Some standard conversion factors can
* be found in ogr_srs_api.h.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetLinearUnits( const char * pszUnitsName,
double dfInMeters )
{
return SetTargetLinearUnits( NULL, pszUnitsName, dfInMeters );
}
/************************************************************************/
/* OSRSetLinearUnits() */
/************************************************************************/
/**
* \brief Set the linear units for the projection.
*
* This function is the same as OGRSpatialReference::SetLinearUnits()
*/
OGRErr OSRSetLinearUnits( OGRSpatialReferenceH hSRS,
const char * pszUnits, double dfInMeters )
{
VALIDATE_POINTER1( hSRS, "OSRSetLinearUnits", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLinearUnits( pszUnits,
dfInMeters );
}
/************************************************************************/
/* SetTargetLinearUnits() */
/************************************************************************/
/**
* \brief Set the linear units for the projection.
*
* This method creates a UNIT subnode with the specified values as a
* child of the target node.
*
* This method does the same as the C function OSRSetTargetLinearUnits().
*
* @param pszTargetKey the keyword to set the linear units for. ie. "PROJCS" or "VERT_CS"
*
* @param pszUnitsName the units name to be used. Some preferred units
* names can be found in ogr_srs_api.h such as SRS_UL_METER, SRS_UL_FOOT
* and SRS_UL_US_FOOT.
*
* @param dfInMeters the value to multiple by a length in the indicated
* units to transform to meters. Some standard conversion factors can
* be found in ogr_srs_api.h.
*
* @return OGRERR_NONE on success.
*
* @since OGR 1.9.0
*/
OGRErr OGRSpatialReference::SetTargetLinearUnits( const char *pszTargetKey,
const char * pszUnitsName,
double dfInMeters )
{
OGR_SRSNode *poCS;
OGR_SRSNode *poUnits;
char szValue[128];
bNormInfoSet = FALSE;
if( pszTargetKey == NULL )
{
poCS = GetAttrNode( "PROJCS" );
if( poCS == NULL )
poCS = GetAttrNode( "LOCAL_CS" );
if( poCS == NULL )
poCS = GetAttrNode( "GEOCCS" );
if( poCS == NULL && IsVertical() )
poCS = GetAttrNode( "VERT_CS" );
}
else
poCS = GetAttrNode( pszTargetKey );
if( poCS == NULL )
return OGRERR_FAILURE;
if( dfInMeters == (int) dfInMeters )
sprintf( szValue, "%d", (int) dfInMeters );
else
OGRPrintDouble( szValue, dfInMeters );
if( poCS->FindChild( "UNIT" ) >= 0 )
{
poUnits = poCS->GetChild( poCS->FindChild( "UNIT" ) );
if (poUnits->GetChildCount() < 2)
return OGRERR_FAILURE;
poUnits->GetChild(0)->SetValue( pszUnitsName );
poUnits->GetChild(1)->SetValue( szValue );
if( poUnits->FindChild( "AUTHORITY" ) != -1 )
poUnits->DestroyChild( poUnits->FindChild( "AUTHORITY" ) );
}
else
{
poUnits = new OGR_SRSNode( "UNIT" );
poUnits->AddChild( new OGR_SRSNode( pszUnitsName ) );
poUnits->AddChild( new OGR_SRSNode( szValue ) );
poCS->AddChild( poUnits );
}
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetLinearUnits() */
/************************************************************************/
/**
* \brief Set the linear units for the target node.
*
* This function is the same as OGRSpatialReference::SetTargetLinearUnits()
*
* @since OGR 1.9.0
*/
OGRErr OSRSetTargetLinearUnits( OGRSpatialReferenceH hSRS,
const char *pszTargetKey,
const char * pszUnits, double dfInMeters )
{
VALIDATE_POINTER1( hSRS, "OSRSetTargetLinearUnits", CE_Failure );
return ((OGRSpatialReference *) hSRS)->
SetTargetLinearUnits( pszTargetKey, pszUnits, dfInMeters );
}
/************************************************************************/
/* GetLinearUnits() */
/************************************************************************/
/**
* \brief Fetch linear projection units.
*
* If no units are available, a value of "Meters" and 1.0 will be assumed.
* This method only checks directly under the PROJCS, GEOCCS or LOCAL_CS node
* for units.
*
* This method does the same thing as the C function OSRGetLinearUnits()/
*
* @param ppszName a pointer to be updated with the pointer to the
* units name. The returned value remains internal to the OGRSpatialReference
* and shouldn't be freed, or modified. It may be invalidated on the next
* OGRSpatialReference call.
*
* @return the value to multiply by linear distances to transform them to
* meters.
*/
double OGRSpatialReference::GetLinearUnits( char ** ppszName ) const
{
return GetTargetLinearUnits( NULL, ppszName );
}
/************************************************************************/
/* OSRGetLinearUnits() */
/************************************************************************/
/**
* \brief Fetch linear projection units.
*
* This function is the same as OGRSpatialReference::GetLinearUnits()
*/
double OSRGetLinearUnits( OGRSpatialReferenceH hSRS, char ** ppszName )
{
VALIDATE_POINTER1( hSRS, "OSRGetLinearUnits", 0 );
return ((OGRSpatialReference *) hSRS)->GetLinearUnits( ppszName );
}
/************************************************************************/
/* GetTargetLinearUnits() */
/************************************************************************/
/**
* \brief Fetch linear units for target.
*
* If no units are available, a value of "Meters" and 1.0 will be assumed.
*
* This method does the same thing as the C function OSRGetTargetLinearUnits()/
*
* @param pszTargetKey the key to look on. ie. "PROJCS" or "VERT_CS".
* @param ppszName a pointer to be updated with the pointer to the
* units name. The returned value remains internal to the OGRSpatialReference
* and shouldn't be freed, or modified. It may be invalidated on the next
* OGRSpatialReference call.
*
* @return the value to multiply by linear distances to transform them to
* meters.
*
* @since OGR 1.9.0
*/
double OGRSpatialReference::GetTargetLinearUnits( const char *pszTargetKey,
char ** ppszName ) const
{
const OGR_SRSNode *poCS;
if( pszTargetKey == NULL )
{
poCS = GetAttrNode( "PROJCS" );
if( poCS == NULL )
poCS = GetAttrNode( "LOCAL_CS" );
if( poCS == NULL )
poCS = GetAttrNode( "GEOCCS" );
if( poCS == NULL && IsVertical() )
poCS = GetAttrNode( "VERT_CS" );
}
else
poCS = GetAttrNode( pszTargetKey );
if( ppszName != NULL )
*ppszName = (char*) "unknown";
if( poCS == NULL )
return 1.0;
for( int iChild = 0; iChild < poCS->GetChildCount(); iChild++ )
{
const OGR_SRSNode *poChild = poCS->GetChild(iChild);
if( EQUAL(poChild->GetValue(),"UNIT")
&& poChild->GetChildCount() >= 2 )
{
if( ppszName != NULL )
*ppszName = (char *) poChild->GetChild(0)->GetValue();
return CPLAtof( poChild->GetChild(1)->GetValue() );
}
}
return 1.0;
}
/************************************************************************/
/* OSRGetTargetLinearUnits() */
/************************************************************************/
/**
* \brief Fetch linear projection units.
*
* This function is the same as OGRSpatialReference::GetTargetLinearUnits()
*
* @since OGR 1.9.0
*/
double OSRGetTargetLinearUnits( OGRSpatialReferenceH hSRS,
const char *pszTargetKey,
char ** ppszName )
{
VALIDATE_POINTER1( hSRS, "OSRGetTargetLinearUnits", 0 );
return ((OGRSpatialReference *) hSRS)->GetTargetLinearUnits( pszTargetKey,
ppszName );
}
/************************************************************************/
/* GetPrimeMeridian() */
/************************************************************************/
/**
* \brief Fetch prime meridian info.
*
* Returns the offset of the prime meridian from greenwich in degrees,
* and the prime meridian name (if requested). If no PRIMEM value exists
* in the coordinate system definition a value of "Greenwich" and an
* offset of 0.0 is assumed.
*
* If the prime meridian name is returned, the pointer is to an internal
* copy of the name. It should not be freed, altered or depended on after
* the next OGR call.
*
* This method is the same as the C function OSRGetPrimeMeridian().
*
* @param ppszName return location for prime meridian name. If NULL, name
* is not returned.
*
* @return the offset to the GEOGCS prime meridian from greenwich in decimal
* degrees.
*/
double OGRSpatialReference::GetPrimeMeridian( char **ppszName ) const
{
const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
if( poPRIMEM != NULL && poPRIMEM->GetChildCount() >= 2
&& CPLAtof(poPRIMEM->GetChild(1)->GetValue()) != 0.0 )
{
if( ppszName != NULL )
*ppszName = (char *) poPRIMEM->GetChild(0)->GetValue();
return CPLAtof(poPRIMEM->GetChild(1)->GetValue());
}
if( ppszName != NULL )
*ppszName = (char*) SRS_PM_GREENWICH;
return 0.0;
}
/************************************************************************/
/* OSRGetPrimeMeridian() */
/************************************************************************/
/**
* \brief Fetch prime meridian info.
*
* This function is the same as OGRSpatialReference::GetPrimeMeridian()
*/
double OSRGetPrimeMeridian( OGRSpatialReferenceH hSRS, char **ppszName )
{
VALIDATE_POINTER1( hSRS, "OSRGetPrimeMeridian", 0 );
return ((OGRSpatialReference *) hSRS)->GetPrimeMeridian( ppszName );
}
/************************************************************************/
/* SetGeogCS() */
/************************************************************************/
/**
* \brief Set geographic coordinate system.
*
* This method is used to set the datum, ellipsoid, prime meridian and
* angular units for a geographic coordinate system. It can be used on it's
* own to establish a geographic spatial reference, or applied to a
* projected coordinate system to establish the underlying geographic
* coordinate system.
*
* This method does the same as the C function OSRSetGeogCS().
*
* @param pszGeogName user visible name for the geographic coordinate system
* (not to serve as a key).
*
* @param pszDatumName key name for this datum. The OpenGIS specification
* lists some known values, and otherwise EPSG datum names with a standard
* transformation are considered legal keys.
*
* @param pszSpheroidName user visible spheroid name (not to serve as a key)
*
* @param dfSemiMajor the semi major axis of the spheroid.
*
* @param dfInvFlattening the inverse flattening for the spheroid.
* This can be computed from the semi minor axis as
* 1/f = 1.0 / (1.0 - semiminor/semimajor).
*
* @param pszPMName the name of the prime merdidian (not to serve as a key)
* If this is NULL a default value of "Greenwich" will be used.
*
* @param dfPMOffset the longitude of greenwich relative to this prime
* meridian.
*
* @param pszAngularUnits the angular units name (see ogr_srs_api.h for some
* standard names). If NULL a value of "degrees" will be assumed.
*
* @param dfConvertToRadians value to multiply angular units by to transform
* them to radians. A value of SRS_UL_DEGREE_CONV will be used if
* pszAngularUnits is NULL.
*
* @return OGRERR_NONE on success.
*/
OGRErr
OGRSpatialReference::SetGeogCS( const char * pszGeogName,
const char * pszDatumName,
const char * pszSpheroidName,
double dfSemiMajor, double dfInvFlattening,
const char * pszPMName, double dfPMOffset,
const char * pszAngularUnits,
double dfConvertToRadians )
{
bNormInfoSet = FALSE;
/* -------------------------------------------------------------------- */
/* For a geocentric coordinate system we want to set the datum */
/* and ellipsoid based on the GEOGCS. Create the GEOGCS in a */
/* temporary srs and use the copy method which has special */
/* handling for GEOCCS. */
/* -------------------------------------------------------------------- */
if( IsGeocentric() )
{
OGRSpatialReference oGCS;
oGCS.SetGeogCS( pszGeogName, pszDatumName, pszSpheroidName,
dfSemiMajor, dfInvFlattening,
pszPMName, dfPMOffset,
pszAngularUnits, dfConvertToRadians );
return CopyGeogCSFrom( &oGCS );
}
/* -------------------------------------------------------------------- */
/* Do we already have a GEOGCS? If so, blow it away so it can */
/* be properly replaced. */
/* -------------------------------------------------------------------- */
if( GetAttrNode( "GEOGCS" ) != NULL )
{
OGR_SRSNode *poCS;
if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
Clear();
else if( (poCS = GetAttrNode( "PROJCS" )) != NULL
&& poCS->FindChild( "GEOGCS" ) != -1 )
poCS->DestroyChild( poCS->FindChild( "GEOGCS" ) );
else
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Set defaults for various parameters. */
/* -------------------------------------------------------------------- */
if( pszGeogName == NULL )
pszGeogName = "unnamed";
if( pszPMName == NULL )
pszPMName = SRS_PM_GREENWICH;
if( pszDatumName == NULL )
pszDatumName = "unknown";
if( pszSpheroidName == NULL )
pszSpheroidName = "unnamed";
if( pszAngularUnits == NULL )
{
pszAngularUnits = SRS_UA_DEGREE;
dfConvertToRadians = CPLAtof(SRS_UA_DEGREE_CONV);
}
/* -------------------------------------------------------------------- */
/* Build the GEOGCS object. */
/* -------------------------------------------------------------------- */
char szValue[128];
OGR_SRSNode *poGeogCS, *poSpheroid, *poDatum, *poPM, *poUnits;
poGeogCS = new OGR_SRSNode( "GEOGCS" );
poGeogCS->AddChild( new OGR_SRSNode( pszGeogName ) );
/* -------------------------------------------------------------------- */
/* Setup the spheroid. */
/* -------------------------------------------------------------------- */
poSpheroid = new OGR_SRSNode( "SPHEROID" );
poSpheroid->AddChild( new OGR_SRSNode( pszSpheroidName ) );
OGRPrintDouble( szValue, dfSemiMajor );
poSpheroid->AddChild( new OGR_SRSNode(szValue) );
OGRPrintDouble( szValue, dfInvFlattening );
poSpheroid->AddChild( new OGR_SRSNode(szValue) );
/* -------------------------------------------------------------------- */
/* Setup the Datum. */
/* -------------------------------------------------------------------- */
poDatum = new OGR_SRSNode( "DATUM" );
poDatum->AddChild( new OGR_SRSNode(pszDatumName) );
poDatum->AddChild( poSpheroid );
/* -------------------------------------------------------------------- */
/* Setup the prime meridian. */
/* -------------------------------------------------------------------- */
if( dfPMOffset == 0.0 )
strcpy( szValue, "0" );
else
OGRPrintDouble( szValue, dfPMOffset );
poPM = new OGR_SRSNode( "PRIMEM" );
poPM->AddChild( new OGR_SRSNode( pszPMName ) );
poPM->AddChild( new OGR_SRSNode( szValue ) );
/* -------------------------------------------------------------------- */
/* Setup the rotational units. */
/* -------------------------------------------------------------------- */
OGRPrintDouble( szValue, dfConvertToRadians );
poUnits = new OGR_SRSNode( "UNIT" );
poUnits->AddChild( new OGR_SRSNode(pszAngularUnits) );
poUnits->AddChild( new OGR_SRSNode(szValue) );
/* -------------------------------------------------------------------- */
/* Complete the GeogCS */
/* -------------------------------------------------------------------- */
poGeogCS->AddChild( poDatum );
poGeogCS->AddChild( poPM );
poGeogCS->AddChild( poUnits );
/* -------------------------------------------------------------------- */
/* Attach below the PROJCS if there is one, or make this the root. */
/* -------------------------------------------------------------------- */
if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(),"PROJCS") )
poRoot->InsertChild( poGeogCS, 1 );
else
SetRoot( poGeogCS );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGeogCS() */
/************************************************************************/
/**
* \brief Set geographic coordinate system.
*
* This function is the same as OGRSpatialReference::SetGeogCS()
*/
OGRErr OSRSetGeogCS( OGRSpatialReferenceH hSRS,
const char * pszGeogName,
const char * pszDatumName,
const char * pszSpheroidName,
double dfSemiMajor, double dfInvFlattening,
const char * pszPMName, double dfPMOffset,
const char * pszAngularUnits,
double dfConvertToRadians )
{
VALIDATE_POINTER1( hSRS, "OSRSetGeogCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGeogCS(
pszGeogName, pszDatumName,
pszSpheroidName, dfSemiMajor, dfInvFlattening,
pszPMName, dfPMOffset, pszAngularUnits, dfConvertToRadians );
}
/************************************************************************/
/* SetWellKnownGeogCS() */
/************************************************************************/
/**
* \brief Set a GeogCS based on well known name.
*
* This may be called on an empty OGRSpatialReference to make a geographic
* coordinate system, or on something with an existing PROJCS node to
* set the underlying geographic coordinate system of a projected coordinate
* system.
*
* The following well known text values are currently supported:
* <ul>
* <li> "WGS84": same as "EPSG:4326" but has no dependence on EPSG data files.
* <li> "WGS72": same as "EPSG:4322" but has no dependence on EPSG data files.
* <li> "NAD27": same as "EPSG:4267" but has no dependence on EPSG data files.
* <li> "NAD83": same as "EPSG:4269" but has no dependence on EPSG data files.
* <li> "EPSG:n": same as doing an ImportFromEPSG(n).
* </ul>
*
* @param pszName name of well known geographic coordinate system.
* @return OGRERR_NONE on success, or OGRERR_FAILURE if the name isn't
* recognised, the target object is already initialized, or an EPSG value
* can't be successfully looked up.
*/
OGRErr OGRSpatialReference::SetWellKnownGeogCS( const char * pszName )
{
OGRSpatialReference oSRS2;
OGRErr eErr;
/* -------------------------------------------------------------------- */
/* Check for EPSG authority numbers. */
/* -------------------------------------------------------------------- */
if( EQUALN(pszName, "EPSG:",5) )
{
eErr = oSRS2.importFromEPSG( atoi(pszName+5) );
if( eErr != OGRERR_NONE )
return eErr;
if( !oSRS2.IsGeographic() )
return OGRERR_FAILURE;
return CopyGeogCSFrom( &oSRS2 );
}
/* -------------------------------------------------------------------- */
/* Check for EPSGA authority numbers. */
/* -------------------------------------------------------------------- */
if( EQUALN(pszName, "EPSGA:",6) )
{
eErr = oSRS2.importFromEPSGA( atoi(pszName+6) );
if( eErr != OGRERR_NONE )
return eErr;
if( !oSRS2.IsGeographic() )
return OGRERR_FAILURE;
return CopyGeogCSFrom( &oSRS2 );
}
/* -------------------------------------------------------------------- */
/* Check for simple names. */
/* -------------------------------------------------------------------- */
char *pszWKT = NULL;
if( EQUAL(pszName, "WGS84") || EQUAL(pszName,"CRS84") || EQUAL(pszName,"CRS:84") )
pszWKT = (char* ) SRS_WKT_WGS84;
else if( EQUAL(pszName, "WGS72") )
pszWKT = (char* ) "GEOGCS[\"WGS 72\",DATUM[\"WGS_1972\",SPHEROID[\"WGS 72\",6378135,298.26,AUTHORITY[\"EPSG\",\"7043\"]],TOWGS84[0,0,4.5,0,0,0.554,0.2263],AUTHORITY[\"EPSG\",\"6322\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4322\"]]";
else if( EQUAL(pszName, "NAD27") || EQUAL(pszName, "CRS27") || EQUAL(pszName,"CRS:27") )
pszWKT = (char* ) "GEOGCS[\"NAD27\",DATUM[\"North_American_Datum_1927\",SPHEROID[\"Clarke 1866\",6378206.4,294.978698213898,AUTHORITY[\"EPSG\",\"7008\"]],AUTHORITY[\"EPSG\",\"6267\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4267\"]]";
else if( EQUAL(pszName, "NAD83") || EQUAL(pszName,"CRS83") || EQUAL(pszName,"CRS:83") )
pszWKT = (char* ) "GEOGCS[\"NAD83\",DATUM[\"North_American_Datum_1983\",SPHEROID[\"GRS 1980\",6378137,298.257222101,AUTHORITY[\"EPSG\",\"7019\"]],TOWGS84[0,0,0,0,0,0,0],AUTHORITY[\"EPSG\",\"6269\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.0174532925199433,AUTHORITY[\"EPSG\",\"9108\"]],AUTHORITY[\"EPSG\",\"4269\"]]";
else
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* Import the WKT */
/* -------------------------------------------------------------------- */
eErr = oSRS2.importFromWkt( &pszWKT );
if( eErr != OGRERR_NONE )
return eErr;
/* -------------------------------------------------------------------- */
/* Copy over. */
/* -------------------------------------------------------------------- */
return CopyGeogCSFrom( &oSRS2 );
}
/************************************************************************/
/* OSRSetWellKnownGeogCS() */
/************************************************************************/
/**
* \brief Set a GeogCS based on well known name.
*
* This function is the same as OGRSpatialReference::SetWellKnownGeogCS()
*/
OGRErr OSRSetWellKnownGeogCS( OGRSpatialReferenceH hSRS, const char *pszName )
{
VALIDATE_POINTER1( hSRS, "OSRSetWellKnownGeogCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetWellKnownGeogCS( pszName );
}
/************************************************************************/
/* CopyGeogCSFrom() */
/************************************************************************/
/**
* \brief Copy GEOGCS from another OGRSpatialReference.
*
* The GEOGCS information is copied into this OGRSpatialReference from another.
* If this object has a PROJCS root already, the GEOGCS is installed within
* it, otherwise it is installed as the root.
*
* @param poSrcSRS the spatial reference to copy the GEOGCS information from.
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr OGRSpatialReference::CopyGeogCSFrom(
const OGRSpatialReference * poSrcSRS )
{
const OGR_SRSNode *poGeogCS = NULL;
bNormInfoSet = FALSE;
/* -------------------------------------------------------------------- */
/* Handle geocentric coordinate systems specially. We just */
/* want to copy the DATUM and PRIMEM nodes. */
/* -------------------------------------------------------------------- */
if( IsGeocentric() )
{
if( GetRoot()->FindChild( "DATUM" ) != -1 )
GetRoot()->DestroyChild( GetRoot()->FindChild( "DATUM" ) );
if( GetRoot()->FindChild( "PRIMEM" ) != -1 )
GetRoot()->DestroyChild( GetRoot()->FindChild( "PRIMEM" ) );
const OGR_SRSNode *poDatum = poSrcSRS->GetAttrNode( "DATUM" );
const OGR_SRSNode *poPrimeM = poSrcSRS->GetAttrNode( "PRIMEM" );
if( poDatum == NULL || poPrimeM == NULL )
return OGRERR_FAILURE;
poRoot->InsertChild( poDatum->Clone(), 1 );
poRoot->InsertChild( poPrimeM->Clone(), 2 );
return OGRERR_NONE;
}
/* -------------------------------------------------------------------- */
/* Do we already have a GEOGCS? If so, blow it away so it can */
/* be properly replaced. */
/* -------------------------------------------------------------------- */
if( GetAttrNode( "GEOGCS" ) != NULL )
{
OGR_SRSNode *poPROJCS;
if( EQUAL(GetRoot()->GetValue(),"GEOGCS") )
Clear();
else if( (poPROJCS = GetAttrNode( "PROJCS" )) != NULL
&& poPROJCS->FindChild( "GEOGCS" ) != -1 )
poPROJCS->DestroyChild( poPROJCS->FindChild( "GEOGCS" ) );
else
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Find the GEOGCS node on the source. */
/* -------------------------------------------------------------------- */
poGeogCS = poSrcSRS->GetAttrNode( "GEOGCS" );
if( poGeogCS == NULL )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* Attach below the PROJCS if there is one, or make this the root. */
/* -------------------------------------------------------------------- */
if( GetRoot() != NULL && EQUAL(GetRoot()->GetValue(),"PROJCS") )
poRoot->InsertChild( poGeogCS->Clone(), 1 );
else
SetRoot( poGeogCS->Clone() );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRCopyGeogCSFrom() */
/************************************************************************/
/**
* \brief Copy GEOGCS from another OGRSpatialReference.
*
* This function is the same as OGRSpatialReference::CopyGeogCSFrom()
*/
OGRErr OSRCopyGeogCSFrom( OGRSpatialReferenceH hSRS,
OGRSpatialReferenceH hSrcSRS )
{
VALIDATE_POINTER1( hSRS, "OSRCopyGeogCSFrom", CE_Failure );
VALIDATE_POINTER1( hSrcSRS, "OSRCopyGeogCSFrom", CE_Failure );
return ((OGRSpatialReference *) hSRS)->CopyGeogCSFrom(
(const OGRSpatialReference *) hSrcSRS );
}
/************************************************************************/
/* SetFromUserInput() */
/************************************************************************/
/**
* \brief Set spatial reference from various text formats.
*
* This method will examine the provided input, and try to deduce the
* format, and then use it to initialize the spatial reference system. It
* may take the following forms:
*
* <ol>
* <li> Well Known Text definition - passed on to importFromWkt().
* <li> "EPSG:n" - number passed on to importFromEPSG().
* <li> "EPSGA:n" - number passed on to importFromEPSGA().
* <li> "AUTO:proj_id,unit_id,lon0,lat0" - WMS auto projections.
* <li> "urn:ogc:def:crs:EPSG::n" - ogc urns
* <li> PROJ.4 definitions - passed on to importFromProj4().
* <li> filename - file read for WKT, XML or PROJ.4 definition.
* <li> well known name accepted by SetWellKnownGeogCS(), such as NAD27, NAD83,
* WGS84 or WGS72.
* <li> WKT (directly or in a file) in ESRI format should be prefixed with
* ESRI:: to trigger an automatic morphFromESRI().
* <li> "IGNF:xxx" - "+init=IGNF:xxx" passed on to importFromProj4().
* </ol>
*
* It is expected that this method will be extended in the future to support
* XML and perhaps a simplified "minilanguage" for indicating common UTM and
* State Plane definitions.
*
* This method is intended to be flexible, but by it's nature it is
* imprecise as it must guess information about the format intended. When
* possible applications should call the specific method appropriate if the
* input is known to be in a particular format.
*
* This method does the same thing as the OSRSetFromUserInput() function.
*
* @param pszDefinition text definition to try to deduce SRS from.
*
* @return OGRERR_NONE on success, or an error code if the name isn't
* recognised, the definition is corrupt, or an EPSG value can't be
* successfully looked up.
*/
OGRErr OGRSpatialReference::SetFromUserInput( const char * pszDefinition )
{
int bESRI = FALSE;
OGRErr err;
if( EQUALN(pszDefinition,"ESRI::",6) )
{
bESRI = TRUE;
pszDefinition += 6;
}
/* -------------------------------------------------------------------- */
/* Is it a recognised syntax? */
/* -------------------------------------------------------------------- */
if( EQUALN(pszDefinition,"PROJCS",6)
|| EQUALN(pszDefinition,"GEOGCS",6)
|| EQUALN(pszDefinition,"COMPD_CS",8)
|| EQUALN(pszDefinition,"GEOCCS",6)
|| EQUALN(pszDefinition,"VERT_CS",7)
|| EQUALN(pszDefinition,"LOCAL_CS",8) )
{
err = importFromWkt( (char **) &pszDefinition );
if( err == OGRERR_NONE && bESRI )
err = morphFromESRI();
return err;
}
if( EQUALN(pszDefinition,"EPSG:",5)
|| EQUALN(pszDefinition,"EPSGA:",6) )
{
OGRErr eStatus;
if( EQUALN(pszDefinition,"EPSG:",5) )
eStatus = importFromEPSG( atoi(pszDefinition+5) );
else /* if( EQUALN(pszDefinition,"EPSGA:",6) ) */
eStatus = importFromEPSGA( atoi(pszDefinition+6) );
// Do we want to turn this into a compound definition
// with a vertical datum?
if( eStatus == OGRERR_NONE && strchr( pszDefinition, '+' ) != NULL )
{
OGRSpatialReference oVertSRS;
eStatus = oVertSRS.importFromEPSG(
atoi(strchr(pszDefinition,'+')+1) );
if( eStatus == OGRERR_NONE )
{
OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
Clear();
CPLString osName = poHorizSRS->GetChild(0)->GetValue();
osName += " + ";
osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
SetNode( "COMPD_CS", osName );
GetRoot()->AddChild( poHorizSRS );
GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
}
return eStatus;
}
else
return eStatus;
}
if( EQUALN(pszDefinition,"urn:ogc:def:crs:",16)
|| EQUALN(pszDefinition,"urn:ogc:def:crs,crs:",20)
|| EQUALN(pszDefinition,"urn:x-ogc:def:crs:",18)
|| EQUALN(pszDefinition,"urn:opengis:crs:",16)
|| EQUALN(pszDefinition,"urn:opengis:def:crs:",20))
return importFromURN( pszDefinition );
if( EQUALN(pszDefinition,"http://opengis.net/def/crs",26)
|| EQUALN(pszDefinition,"http://www.opengis.net/def/crs",30)
|| EQUALN(pszDefinition,"www.opengis.net/def/crs",23))
return importFromCRSURL( pszDefinition );
if( EQUALN(pszDefinition,"AUTO:",5) )
return importFromWMSAUTO( pszDefinition );
if( EQUALN(pszDefinition,"OGC:",4) ) // WMS/WCS OGC codes like OGC:CRS84
return SetWellKnownGeogCS( pszDefinition+4 );
if( EQUALN(pszDefinition,"CRS:",4) )
return SetWellKnownGeogCS( pszDefinition );
if( EQUALN(pszDefinition,"DICT:",5)
&& strstr(pszDefinition,",") )
{
char *pszFile = CPLStrdup(pszDefinition+5);
char *pszCode = strstr(pszFile,",") + 1;
pszCode[-1] = '\0';
err = importFromDict( pszFile, pszCode );
CPLFree( pszFile );
if( err == OGRERR_NONE && bESRI )
err = morphFromESRI();
return err;
}
if( EQUAL(pszDefinition,"NAD27")
|| EQUAL(pszDefinition,"NAD83")
|| EQUAL(pszDefinition,"WGS84")
|| EQUAL(pszDefinition,"WGS72") )
{
Clear();
return SetWellKnownGeogCS( pszDefinition );
}
if( strstr(pszDefinition,"+proj") != NULL
|| strstr(pszDefinition,"+init") != NULL )
return importFromProj4( pszDefinition );
if( EQUALN(pszDefinition,"IGNF:", 5) )
{
char* pszProj4Str = (char*) CPLMalloc(6 + strlen(pszDefinition) + 1);
strcpy(pszProj4Str, "+init=");
strcat(pszProj4Str, pszDefinition);
err = importFromProj4( pszProj4Str );
CPLFree(pszProj4Str);
return err;
}
if( EQUALN(pszDefinition,"http://",7) )
{
return importFromUrl (pszDefinition);
}
if( EQUAL(pszDefinition,"osgb:BNG") )
{
return importFromEPSG(27700);
}
/* -------------------------------------------------------------------- */
/* Try to open it as a file. */
/* -------------------------------------------------------------------- */
FILE *fp;
int nBufMax = 100000;
char *pszBufPtr, *pszBuffer;
int nBytes;
fp = VSIFOpen( pszDefinition, "rt" );
if( fp == NULL )
return OGRERR_CORRUPT_DATA;
pszBuffer = (char *) CPLMalloc(nBufMax);
nBytes = VSIFRead( pszBuffer, 1, nBufMax-1, fp );
VSIFClose( fp );
if( nBytes == nBufMax-1 )
{
CPLDebug( "OGR",
"OGRSpatialReference::SetFromUserInput(%s), opened file\n"
"but it is to large for our generous buffer. Is it really\n"
"just a WKT definition?", pszDefinition );
CPLFree( pszBuffer );
return OGRERR_FAILURE;
}
pszBuffer[nBytes] = '\0';
pszBufPtr = pszBuffer;
while( pszBufPtr[0] == ' ' || pszBufPtr[0] == '\n' )
pszBufPtr++;
if( pszBufPtr[0] == '<' )
err = importFromXML( pszBufPtr );
else if( (strstr(pszBuffer,"+proj") != NULL
|| strstr(pszBuffer,"+init") != NULL)
&& (strstr(pszBuffer,"EXTENSION") == NULL
&& strstr(pszBuffer,"extension") == NULL) )
err = importFromProj4( pszBufPtr );
else
{
if( EQUALN(pszBufPtr,"ESRI::",6) )
{
bESRI = TRUE;
pszBufPtr += 6;
}
err = importFromWkt( &pszBufPtr );
if( err == OGRERR_NONE && bESRI )
err = morphFromESRI();
}
CPLFree( pszBuffer );
return err;
}
/************************************************************************/
/* OSRSetFromUserInput() */
/************************************************************************/
/**
* \brief Set spatial reference from various text formats.
*
* This function is the same as OGRSpatialReference::SetFromUserInput()
*/
OGRErr CPL_STDCALL OSRSetFromUserInput( OGRSpatialReferenceH hSRS,
const char *pszDef )
{
VALIDATE_POINTER1( hSRS, "OSRSetFromUserInput", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetFromUserInput( pszDef );
}
/************************************************************************/
/* ImportFromUrl() */
/************************************************************************/
/**
* \brief Set spatial reference from a URL.
*
* This method will download the spatial reference at a given URL and
* feed it into SetFromUserInput for you.
*
* This method does the same thing as the OSRImportFromUrl() function.
*
* @param pszUrl text definition to try to deduce SRS from.
*
* @return OGRERR_NONE on success, or an error code with the curl
* error message if it is unable to dowload data.
*/
OGRErr OGRSpatialReference::importFromUrl( const char * pszUrl )
{
if( !EQUALN(pszUrl,"http://",7) )
{
CPLError( CE_Failure, CPLE_AppDefined,
"The given string is not recognized as a URL"
"starting with 'http://' -- %s", pszUrl );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Fetch the result. */
/* -------------------------------------------------------------------- */
CPLErrorReset();
const char* pszHeaders = "HEADERS=Accept: application/x-ogcwkt";
const char* pszTimeout = "TIMEOUT=10";
char *apszOptions[] = {
(char *) pszHeaders,
(char *) pszTimeout,
NULL
};
CPLHTTPResult *psResult = CPLHTTPFetch( pszUrl, apszOptions );
/* -------------------------------------------------------------------- */
/* Try to handle errors. */
/* -------------------------------------------------------------------- */
if ( psResult == NULL)
return OGRERR_FAILURE;
if( psResult->nDataLen == 0
|| CPLGetLastErrorNo() != 0 || psResult->pabyData == NULL )
{
if (CPLGetLastErrorNo() == 0)
{
CPLError( CE_Failure, CPLE_AppDefined,
"No data was returned from the given URL" );
}
CPLHTTPDestroyResult( psResult );
return OGRERR_FAILURE;
}
if (psResult->nStatus != 0)
{
CPLError( CE_Failure, CPLE_AppDefined,
"Curl reports error: %d: %s", psResult->nStatus, psResult->pszErrBuf );
CPLHTTPDestroyResult( psResult );
return OGRERR_FAILURE;
}
if( EQUALN( (const char*) psResult->pabyData,"http://",7) )
{
CPLError( CE_Failure, CPLE_AppDefined,
"The data that was downloaded also starts with 'http://' "
"and cannot be passed into SetFromUserInput. Is this "
"really a spatial reference definition? ");
CPLHTTPDestroyResult( psResult );
return OGRERR_FAILURE;
}
if( OGRERR_NONE != SetFromUserInput( (const char *) psResult->pabyData )) {
CPLHTTPDestroyResult( psResult );
return OGRERR_FAILURE;
}
CPLHTTPDestroyResult( psResult );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRimportFromUrl() */
/************************************************************************/
/**
* \brief Set spatial reference from a URL.
*
* This function is the same as OGRSpatialReference::importFromUrl()
*/
OGRErr OSRImportFromUrl( OGRSpatialReferenceH hSRS, const char *pszUrl )
{
VALIDATE_POINTER1( hSRS, "OSRImportFromUrl", CE_Failure );
return ((OGRSpatialReference *) hSRS)->importFromUrl( pszUrl );
}
/************************************************************************/
/* importFromURNPart() */
/************************************************************************/
OGRErr OGRSpatialReference::importFromURNPart(const char* pszAuthority,
const char* pszCode,
const char* pszURN)
{
/* -------------------------------------------------------------------- */
/* Is this an EPSG code? Note that we import it with EPSG */
/* preferred axis ordering for geographic coordinate systems! */
/* -------------------------------------------------------------------- */
if( EQUALN(pszAuthority,"EPSG",4) )
return importFromEPSGA( atoi(pszCode) );
/* -------------------------------------------------------------------- */
/* Is this an IAU code? Lets try for the IAU2000 dictionary. */
/* -------------------------------------------------------------------- */
if( EQUALN(pszAuthority,"IAU",3) )
return importFromDict( "IAU2000.wkt", pszCode );
/* -------------------------------------------------------------------- */
/* Is this an OGC code? */
/* -------------------------------------------------------------------- */
if( !EQUALN(pszAuthority,"OGC",3) )
{
CPLError( CE_Failure, CPLE_AppDefined,
"URN %s has unrecognised authority.",
pszURN );
return OGRERR_FAILURE;
}
if( EQUALN(pszCode,"CRS84",5) )
return SetWellKnownGeogCS( pszCode );
else if( EQUALN(pszCode,"CRS83",5) )
return SetWellKnownGeogCS( pszCode );
else if( EQUALN(pszCode,"CRS27",5) )
return SetWellKnownGeogCS( pszCode );
else if( EQUALN(pszCode,"84",2) ) /* urn:ogc:def:crs:OGC:2:84 */
return SetWellKnownGeogCS( "CRS84" );
/* -------------------------------------------------------------------- */
/* Handle auto codes. We need to convert from format */
/* AUTO42001:99:8888 to format AUTO:42001,99,8888. */
/* -------------------------------------------------------------------- */
else if( EQUALN(pszCode,"AUTO",4) )
{
char szWMSAuto[100];
int i;
if( strlen(pszCode) > sizeof(szWMSAuto)-2 )
return OGRERR_FAILURE;
strcpy( szWMSAuto, "AUTO:" );
strcpy( szWMSAuto + 5, pszCode + 4 );
for( i = 5; szWMSAuto[i] != '\0'; i++ )
{
if( szWMSAuto[i] == ':' )
szWMSAuto[i] = ',';
}
return importFromWMSAUTO( szWMSAuto );
}
/* -------------------------------------------------------------------- */
/* Not a recognise OGC item. */
/* -------------------------------------------------------------------- */
CPLError( CE_Failure, CPLE_AppDefined,
"URN %s value not supported.",
pszURN );
return OGRERR_FAILURE;
}
/************************************************************************/
/* importFromURN() */
/* */
/* See OGC recommendation paper 06-023r1 or later for details. */
/************************************************************************/
/**
* \brief Initialize from OGC URN.
*
* Initializes this spatial reference from a coordinate system defined
* by an OGC URN prefixed with "urn:ogc:def:crs:" per recommendation
* paper 06-023r1. Currently EPSG and OGC authority values are supported,
* including OGC auto codes, but not including CRS1 or CRS88 (NAVD88).
*
* This method is also support through SetFromUserInput() which can
* normally be used for URNs.
*
* @param pszURN the urn string.
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr OGRSpatialReference::importFromURN( const char *pszURN )
{
const char *pszCur;
if( EQUALN(pszURN,"urn:ogc:def:crs:",16) )
pszCur = pszURN + 16;
else if( EQUALN(pszURN,"urn:ogc:def:crs,crs:",20) )
pszCur = pszURN + 20;
else if( EQUALN(pszURN,"urn:x-ogc:def:crs:",18) )
pszCur = pszURN + 18;
else if( EQUALN(pszURN,"urn:opengis:crs:",16) )
pszCur = pszURN + 16;
else if( EQUALN(pszURN,"urn:opengis:def:crs:",20) )
pszCur = pszURN + 20;
else
{
CPLError( CE_Failure, CPLE_AppDefined,
"URN %s not a supported format.", pszURN );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Clear any existing definition. */
/* -------------------------------------------------------------------- */
if( GetRoot() != NULL )
{
delete poRoot;
poRoot = NULL;
}
/* -------------------------------------------------------------------- */
/* Find code (ignoring version) out of string like: */
/* */
/* authority:[version]:code */
/* -------------------------------------------------------------------- */
const char *pszAuthority = pszCur;
// skip authority
while( *pszCur != ':' && *pszCur )
pszCur++;
if( *pszCur == ':' )
pszCur++;
// skip version
const char* pszBeforeVersion = pszCur;
while( *pszCur != ':' && *pszCur )
pszCur++;
if( *pszCur == ':' )
pszCur++;
else
/* We come here in the case, the content to parse is authority:code (instead of authority::code) */
/* which is probably illegal according to http://www.opengeospatial.org/ogcUrnPolicy */
/* but such content is found for example in what is returned by GeoServer */
pszCur = pszBeforeVersion;
const char *pszCode = pszCur;
const char* pszComma = strchr(pszCur, ',');
if (pszComma == NULL)
return importFromURNPart(pszAuthority, pszCode, pszURN);
/* There's a second part with the vertical SRS */
pszCur = pszComma + 1;
if (strncmp(pszCur, "crs:", 4) != 0)
{
CPLError( CE_Failure, CPLE_AppDefined,
"URN %s not a supported format.", pszURN );
return OGRERR_FAILURE;
}
pszCur += 4;
char* pszFirstCode = CPLStrdup(pszCode);
pszFirstCode[pszComma - pszCode] = '\0';
OGRErr eStatus = importFromURNPart(pszAuthority, pszFirstCode, pszURN);
CPLFree(pszFirstCode);
// Do we want to turn this into a compound definition
// with a vertical datum?
if( eStatus == OGRERR_NONE )
{
OGRSpatialReference oVertSRS;
/* -------------------------------------------------------------------- */
/* Find code (ignoring version) out of string like: */
/* */
/* authority:[version]:code */
/* -------------------------------------------------------------------- */
pszAuthority = pszCur;
// skip authority
while( *pszCur != ':' && *pszCur )
pszCur++;
if( *pszCur == ':' )
pszCur++;
// skip version
pszBeforeVersion = pszCur;
while( *pszCur != ':' && *pszCur )
pszCur++;
if( *pszCur == ':' )
pszCur++;
else
pszCur = pszBeforeVersion;
pszCode = pszCur;
eStatus = oVertSRS.importFromURNPart(pszAuthority, pszCode, pszURN);
if( eStatus == OGRERR_NONE )
{
OGR_SRSNode *poHorizSRS = GetRoot()->Clone();
Clear();
CPLString osName = poHorizSRS->GetChild(0)->GetValue();
osName += " + ";
osName += oVertSRS.GetRoot()->GetChild(0)->GetValue();
SetNode( "COMPD_CS", osName );
GetRoot()->AddChild( poHorizSRS );
GetRoot()->AddChild( oVertSRS.GetRoot()->Clone() );
}
return eStatus;
}
else
return eStatus;
}
/************************************************************************/
/* importFromCRSURL() */
/* */
/* See OGC Best Practice document 11-135 for details. */
/************************************************************************/
/**
* \brief Initialize from OGC URL.
*
* Initializes this spatial reference from a coordinate system defined
* by an OGC URL prefixed with "http://opengis.net/def/crs" per best practice
* paper 11-135. Currently EPSG and OGC authority values are supported,
* including OGC auto codes, but not including CRS1 or CRS88 (NAVD88).
*
* This method is also supported through SetFromUserInput() which can
* normally be used for URLs.
*
* @param pszURL the URL string.
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr OGRSpatialReference::importFromCRSURL( const char *pszURL )
{
const char *pszCur;
if( EQUALN(pszURL,"http://opengis.net/def/crs",26) )
pszCur = pszURL + 26;
else if( EQUALN(pszURL,"http://www.opengis.net/def/crs",30) )
pszCur = pszURL + 30;
else if( EQUALN(pszURL,"www.opengis.net/def/crs",23) )
pszCur = pszURL + 23;
else
{
CPLError( CE_Failure, CPLE_AppDefined,
"URL %s not a supported format.", pszURL );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Clear any existing definition. */
/* -------------------------------------------------------------------- */
if( GetRoot() != NULL )
{
delete poRoot;
poRoot = NULL;
}
if( EQUALN(pszCur, "-compound?1=", 12) )
{
/* -------------------------------------------------------------------- */
/* It's a compound CRS, of the form: */
/* */
/* http://opengis.net/def/crs-compound?1=URL1&2=URL2&3=URL3&.. */
/* -------------------------------------------------------------------- */
pszCur += 12;
// extract each component CRS URL
int iComponentUrl = 2;
CPLString osName = "";
Clear();
while (iComponentUrl != -1)
{
char searchStr[5];
sprintf(searchStr, "&%d=", iComponentUrl);
const char* pszUrlEnd = strstr(pszCur, searchStr);
// figure out the next component URL
char* pszComponentUrl;
if( pszUrlEnd )
{
size_t nLen = pszUrlEnd - pszCur;
pszComponentUrl = (char*) CPLMalloc(nLen + 1);
strncpy(pszComponentUrl, pszCur, nLen);
pszComponentUrl[nLen] = '\0';
++iComponentUrl;
pszCur += nLen + strlen(searchStr);
}
else
{
if( iComponentUrl == 2 )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Compound CRS URLs must have at least two component CRSs." );
return OGRERR_FAILURE;
}
else
{
pszComponentUrl = CPLStrdup(pszCur);
// no more components
iComponentUrl = -1;
}
}
OGRSpatialReference oComponentSRS;
OGRErr eStatus = oComponentSRS.importFromCRSURL( pszComponentUrl );
CPLFree(pszComponentUrl);
pszComponentUrl = NULL;
if( eStatus == OGRERR_NONE )
{
if( osName.length() != 0 )
{
osName += " + ";
}
osName += oComponentSRS.GetRoot()->GetValue();
SetNode( "COMPD_CS", osName );
GetRoot()->AddChild( oComponentSRS.GetRoot()->Clone() );
}
else
return eStatus;
}
return OGRERR_NONE;
}
else
{
/* -------------------------------------------------------------------- */
/* It's a normal CRS URL, of the form: */
/* */
/* http://opengis.net/def/crs/AUTHORITY/VERSION/CODE */
/* -------------------------------------------------------------------- */
++pszCur;
const char *pszAuthority = pszCur;
// skip authority
while( *pszCur != '/' && *pszCur )
pszCur++;
if( *pszCur == '/' )
pszCur++;
// skip version
while( *pszCur != '/' && *pszCur )
pszCur++;
if( *pszCur == '/' )
pszCur++;
const char *pszCode = pszCur;
return importFromURNPart( pszAuthority, pszCode, pszURL );
}
}
/************************************************************************/
/* importFromWMSAUTO() */
/************************************************************************/
/**
* \brief Initialize from WMSAUTO string.
*
* Note that the WMS 1.3 specification does not include the
* units code, while apparently earlier specs do. We try to
* guess around this.
*
* @param pszDefinition the WMSAUTO string
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr OGRSpatialReference::importFromWMSAUTO( const char * pszDefinition )
{
char **papszTokens;
int nProjId, nUnitsId;
double dfRefLong, dfRefLat = 0.0;
/* -------------------------------------------------------------------- */
/* Tokenize */
/* -------------------------------------------------------------------- */
if( EQUALN(pszDefinition,"AUTO:",5) )
pszDefinition += 5;
papszTokens = CSLTokenizeStringComplex( pszDefinition, ",", FALSE, TRUE );
if( CSLCount(papszTokens) == 4 )
{
nProjId = atoi(papszTokens[0]);
nUnitsId = atoi(papszTokens[1]);
dfRefLong = CPLAtof(papszTokens[2]);
dfRefLat = CPLAtof(papszTokens[3]);
}
else if( CSLCount(papszTokens) == 3 && atoi(papszTokens[0]) == 42005 )
{
nProjId = atoi(papszTokens[0]);
nUnitsId = atoi(papszTokens[1]);
dfRefLong = CPLAtof(papszTokens[2]);
dfRefLat = 0.0;
}
else if( CSLCount(papszTokens) == 3 )
{
nProjId = atoi(papszTokens[0]);
nUnitsId = 9001;
dfRefLong = CPLAtof(papszTokens[1]);
dfRefLat = CPLAtof(papszTokens[2]);
}
else if( CSLCount(papszTokens) == 2 && atoi(papszTokens[0]) == 42005 )
{
nProjId = atoi(papszTokens[0]);
nUnitsId = 9001;
dfRefLong = CPLAtof(papszTokens[1]);
}
else
{
CSLDestroy( papszTokens );
CPLError( CE_Failure, CPLE_AppDefined,
"AUTO projection has wrong number of arguments, expected\n"
"AUTO:proj_id,units_id,ref_long,ref_lat or"
"AUTO:proj_id,ref_long,ref_lat" );
return OGRERR_FAILURE;
}
CSLDestroy( papszTokens );
/* -------------------------------------------------------------------- */
/* Build coordsys. */
/* -------------------------------------------------------------------- */
Clear();
switch( nProjId )
{
case 42001: // Auto UTM
SetUTM( (int) floor( (dfRefLong + 180.0) / 6.0 ) + 1,
dfRefLat >= 0.0 );
break;
case 42002: // Auto TM (strangely very UTM-like).
SetTM( 0, dfRefLong, 0.9996,
500000.0, (dfRefLat >= 0.0) ? 0.0 : 10000000.0 );
break;
case 42003: // Auto Orthographic.
SetOrthographic( dfRefLat, dfRefLong, 0.0, 0.0 );
break;
case 42004: // Auto Equirectangular
SetEquirectangular( dfRefLat, dfRefLong, 0.0, 0.0 );
break;
case 42005:
SetMollweide( dfRefLong, 0.0, 0.0 );
break;
default:
CPLError( CE_Failure, CPLE_AppDefined,
"Unsupported projection id in importFromWMSAUTO(): %d",
nProjId );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Set units. */
/* -------------------------------------------------------------------- */
switch( nUnitsId )
{
case 9001:
SetLinearUnits( SRS_UL_METER, 1.0 );
break;
case 9002:
SetLinearUnits( "Foot", 0.3048 );
break;
case 9003:
SetLinearUnits( "US survey foot", CPLAtof(SRS_UL_US_FOOT_CONV) );
break;
default:
CPLError( CE_Failure, CPLE_AppDefined,
"Unsupported units code (%d).",
nUnitsId );
return OGRERR_FAILURE;
break;
}
SetAuthority( "PROJCS|UNIT", "EPSG", nUnitsId );
/* -------------------------------------------------------------------- */
/* Set WGS84. */
/* -------------------------------------------------------------------- */
SetWellKnownGeogCS( "WGS84" );
return OGRERR_NONE;
}
/************************************************************************/
/* GetSemiMajor() */
/************************************************************************/
/**
* \brief Get spheroid semi major axis.
*
* This method does the same thing as the C function OSRGetSemiMajor().
*
* @param pnErr if non-NULL set to OGRERR_FAILURE if semi major axis
* can be found.
*
* @return semi-major axis, or SRS_WGS84_SEMIMAJOR if it can't be found.
*/
double OGRSpatialReference::GetSemiMajor( OGRErr * pnErr ) const
{
const OGR_SRSNode *poSpheroid = GetAttrNode( "SPHEROID" );
if( pnErr != NULL )
*pnErr = OGRERR_NONE;
if( poSpheroid != NULL && poSpheroid->GetChildCount() >= 3 )
{
return CPLAtof( poSpheroid->GetChild(1)->GetValue() );
}
else
{
if( pnErr != NULL )
*pnErr = OGRERR_FAILURE;
return SRS_WGS84_SEMIMAJOR;
}
}
/************************************************************************/
/* OSRGetSemiMajor() */
/************************************************************************/
/**
* \brief Get spheroid semi major axis.
*
* This function is the same as OGRSpatialReference::GetSemiMajor()
*/
double OSRGetSemiMajor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
{
VALIDATE_POINTER1( hSRS, "OSRGetSemiMajor", 0 );
return ((OGRSpatialReference *) hSRS)->GetSemiMajor( pnErr );
}
/************************************************************************/
/* GetInvFlattening() */
/************************************************************************/
/**
* \brief Get spheroid inverse flattening.
*
* This method does the same thing as the C function OSRGetInvFlattening().
*
* @param pnErr if non-NULL set to OGRERR_FAILURE if no inverse flattening
* can be found.
*
* @return inverse flattening, or SRS_WGS84_INVFLATTENING if it can't be found.
*/
double OGRSpatialReference::GetInvFlattening( OGRErr * pnErr ) const
{
const OGR_SRSNode *poSpheroid = GetAttrNode( "SPHEROID" );
if( pnErr != NULL )
*pnErr = OGRERR_NONE;
if( poSpheroid != NULL && poSpheroid->GetChildCount() >= 3 )
{
return CPLAtof( poSpheroid->GetChild(2)->GetValue() );
}
else
{
if( pnErr != NULL )
*pnErr = OGRERR_FAILURE;
return SRS_WGS84_INVFLATTENING;
}
}
/************************************************************************/
/* OSRGetInvFlattening() */
/************************************************************************/
/**
* \brief Get spheroid inverse flattening.
*
* This function is the same as OGRSpatialReference::GetInvFlattening()
*/
double OSRGetInvFlattening( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
{
VALIDATE_POINTER1( hSRS, "OSRGetInvFlattening", 0 );
return ((OGRSpatialReference *) hSRS)->GetInvFlattening( pnErr );
}
/************************************************************************/
/* GetSemiMinor() */
/************************************************************************/
/**
* \brief Get spheroid semi minor axis.
*
* This method does the same thing as the C function OSRGetSemiMinor().
*
* @param pnErr if non-NULL set to OGRERR_FAILURE if semi minor axis
* can be found.
*
* @return semi-minor axis, or WGS84 semi minor if it can't be found.
*/
double OGRSpatialReference::GetSemiMinor( OGRErr * pnErr ) const
{
double dfInvFlattening, dfSemiMajor;
dfSemiMajor = GetSemiMajor( pnErr );
dfInvFlattening = GetInvFlattening( pnErr );
return OSRCalcSemiMinorFromInvFlattening(dfSemiMajor, dfInvFlattening);
}
/************************************************************************/
/* OSRGetSemiMinor() */
/************************************************************************/
/**
* \brief Get spheroid semi minor axis.
*
* This function is the same as OGRSpatialReference::GetSemiMinor()
*/
double OSRGetSemiMinor( OGRSpatialReferenceH hSRS, OGRErr *pnErr )
{
VALIDATE_POINTER1( hSRS, "OSRGetSemiMinor", 0 );
return ((OGRSpatialReference *) hSRS)->GetSemiMinor( pnErr );
}
/************************************************************************/
/* SetLocalCS() */
/************************************************************************/
/**
* \brief Set the user visible LOCAL_CS name.
*
* This method is the same as the C function OSRSetLocalCS().
*
* This method will ensure a LOCAL_CS node is created as the root,
* and set the provided name on it. It must be used before SetLinearUnits().
*
* @param pszName the user visible name to assign. Not used as a key.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetLocalCS( const char * pszName )
{
OGR_SRSNode *poCS = GetAttrNode( "LOCAL_CS" );
if( poCS == NULL && GetRoot() != NULL )
{
CPLDebug( "OGR",
"OGRSpatialReference::SetLocalCS(%s) failed.\n"
"It appears an incompatible root node (%s) already exists.\n",
pszName, GetRoot()->GetValue() );
return OGRERR_FAILURE;
}
else
{
SetNode( "LOCAL_CS", pszName );
return OGRERR_NONE;
}
}
/************************************************************************/
/* OSRSetLocalCS() */
/************************************************************************/
/**
* \brief Set the user visible LOCAL_CS name.
*
* This function is the same as OGRSpatialReference::SetLocalCS()
*/
OGRErr OSRSetLocalCS( OGRSpatialReferenceH hSRS, const char * pszName )
{
VALIDATE_POINTER1( hSRS, "OSRSetLocalCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLocalCS( pszName );
}
/************************************************************************/
/* SetGeocCS() */
/************************************************************************/
/**
* \brief Set the user visible GEOCCS name.
*
* This method is the same as the C function OSRSetGeocCS().
* This method will ensure a GEOCCS node is created as the root,
* and set the provided name on it. If used on a GEOGCS coordinate system,
* the DATUM and PRIMEM nodes from the GEOGCS will be tarnsferred over to
* the GEOGCS.
*
* @param pszName the user visible name to assign. Not used as a key.
*
* @return OGRERR_NONE on success.
*
* @since OGR 1.9.0
*/
OGRErr OGRSpatialReference::SetGeocCS( const char * pszName )
{
OGR_SRSNode *poGeogCS = NULL;
OGR_SRSNode *poGeocCS = GetAttrNode( "GEOCCS" );
if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
{
poGeogCS = poRoot;
poRoot = NULL;
}
if( poGeocCS == NULL && GetRoot() != NULL )
{
CPLDebug( "OGR",
"OGRSpatialReference::SetGeocCS(%s) failed.\n"
"It appears an incompatible root node (%s) already exists.\n",
pszName, GetRoot()->GetValue() );
return OGRERR_FAILURE;
}
SetNode( "GEOCCS", pszName );
if( poGeogCS != NULL )
{
OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
OGR_SRSNode *poPRIMEM = poGeogCS->GetNode( "PRIMEM" );
if ( poDatum != NULL && poPRIMEM != NULL )
{
poRoot->InsertChild( poDatum->Clone(), 1 );
poRoot->InsertChild( poPRIMEM->Clone(), 2 );
}
delete poGeogCS;
}
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGeocCS() */
/************************************************************************/
/**
* \brief Set the user visible PROJCS name.
*
* This function is the same as OGRSpatialReference::SetGeocCS()
*
* @since OGR 1.9.0
*/
OGRErr OSRSetGeocCS( OGRSpatialReferenceH hSRS, const char * pszName )
{
VALIDATE_POINTER1( hSRS, "OSRSetGeocCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGeocCS( pszName );
}
/************************************************************************/
/* SetVertCS() */
/************************************************************************/
/**
* \brief Set the user visible VERT_CS name.
*
* This method is the same as the C function OSRSetVertCS().
* This method will ensure a VERT_CS node is created if needed. If the
* existing coordinate system is GEOGCS or PROJCS rooted, then it will be
* turned into a COMPD_CS.
*
* @param pszVertCSName the user visible name of the vertical coordinate
* system. Not used as a key.
*
* @param pszVertDatumName the user visible name of the vertical datum. It
* is helpful if this matches the EPSG name.
*
* @param nVertDatumType the OGC vertical datum type, usually 2005.
*
* @return OGRERR_NONE on success.
*
* @since OGR 1.9.0
*/
OGRErr OGRSpatialReference::SetVertCS( const char * pszVertCSName,
const char * pszVertDatumName,
int nVertDatumType )
{
/* -------------------------------------------------------------------- */
/* Handle the case where we want to make a compound coordinate */
/* system. */
/* -------------------------------------------------------------------- */
if( IsProjected() || IsGeographic() )
{
OGR_SRSNode *poNewRoot = new OGR_SRSNode( "COMPD_CS" );
poNewRoot->AddChild( poRoot );
poRoot = poNewRoot;
}
else if( GetAttrNode( "VERT_CS" ) == NULL )
Clear();
/* -------------------------------------------------------------------- */
/* If we already have a VERT_CS, wipe and recreate the root */
/* otherwise create the VERT_CS now. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poVertCS = GetAttrNode( "VERT_CS" );
if( poVertCS != NULL )
{
poVertCS->ClearChildren();
}
else
{
poVertCS = new OGR_SRSNode( "VERT_CS" );
if( poRoot != NULL && EQUAL(poRoot->GetValue(),"COMPD_CS") )
{
poRoot->AddChild( poVertCS );
}
else
SetRoot( poVertCS );
}
/* -------------------------------------------------------------------- */
/* Set the name, datumname, and type. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poVertDatum;
poVertCS->AddChild( new OGR_SRSNode( pszVertCSName ) );
poVertDatum = new OGR_SRSNode( "VERT_DATUM" );
poVertCS->AddChild( poVertDatum );
poVertDatum->AddChild( new OGR_SRSNode( pszVertDatumName ) );
CPLString osVertDatumType;
osVertDatumType.Printf( "%d", nVertDatumType );
poVertDatum->AddChild( new OGR_SRSNode( osVertDatumType ) );
// add default axis node.
OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
poAxis->AddChild( new OGR_SRSNode( "Up" ) );
poAxis->AddChild( new OGR_SRSNode( "UP" ) );
poVertCS->AddChild( poAxis );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetVertCS() */
/************************************************************************/
/**
* \brief Setup the vertical coordinate system.
*
* This function is the same as OGRSpatialReference::SetVertCS()
*
* @since OGR 1.9.0
*/
OGRErr OSRSetVertCS( OGRSpatialReferenceH hSRS,
const char * pszVertCSName,
const char * pszVertDatumName,
int nVertDatumType )
{
VALIDATE_POINTER1( hSRS, "OSRSetVertCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetVertCS( pszVertCSName,
pszVertDatumName,
nVertDatumType );
}
/************************************************************************/
/* SetCompoundCS() */
/************************************************************************/
/**
* \brief Setup a compound coordinate system.
*
* This method is the same as the C function OSRSetCompoundCS().
* This method is replace the current SRS with a COMPD_CS coordinate system
* consisting of the passed in horizontal and vertical coordinate systems.
*
* @param pszName the name of the compound coordinate system.
*
* @param poHorizSRS the horizontal SRS (PROJCS or GEOGCS).
*
* @param poVertSRS the vertical SRS (VERT_CS).
*
* @return OGRERR_NONE on success.
*/
OGRErr
OGRSpatialReference::SetCompoundCS( const char *pszName,
const OGRSpatialReference *poHorizSRS,
const OGRSpatialReference *poVertSRS )
{
/* -------------------------------------------------------------------- */
/* Verify these are legal horizontal and vertical coordinate */
/* systems. */
/* -------------------------------------------------------------------- */
if( !poVertSRS->IsVertical() )
{
CPLError( CE_Failure, CPLE_AppDefined,
"SetCompoundCS() fails, vertical component is not VERT_CS." );
return OGRERR_FAILURE;
}
if( !poHorizSRS->IsProjected()
&& !poHorizSRS->IsGeographic() )
{
CPLError( CE_Failure, CPLE_AppDefined,
"SetCompoundCS() fails, horizontal component is not PROJCS or GEOGCS." );
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* Replace with compound srs. */
/* -------------------------------------------------------------------- */
Clear();
poRoot = new OGR_SRSNode( "COMPD_CS" );
poRoot->AddChild( new OGR_SRSNode( pszName ) );
poRoot->AddChild( poHorizSRS->GetRoot()->Clone() );
poRoot->AddChild( poVertSRS->GetRoot()->Clone() );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetCompoundCS() */
/************************************************************************/
/**
* \brief Setup a compound coordinate system.
*
* This function is the same as OGRSpatialReference::SetCompoundCS()
*/
OGRErr OSRSetCompoundCS( OGRSpatialReferenceH hSRS,
const char *pszName,
OGRSpatialReferenceH hHorizSRS,
OGRSpatialReferenceH hVertSRS )
{
VALIDATE_POINTER1( hSRS, "OSRSetCompoundCS", CE_Failure );
VALIDATE_POINTER1( hHorizSRS, "OSRSetCompoundCS", CE_Failure );
VALIDATE_POINTER1( hVertSRS, "OSRSetCompoundCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->
SetCompoundCS( pszName,
(OGRSpatialReference *) hHorizSRS,
(OGRSpatialReference *) hVertSRS );
}
/************************************************************************/
/* SetProjCS() */
/************************************************************************/
/**
* \brief Set the user visible PROJCS name.
*
* This method is the same as the C function OSRSetProjCS().
*
* This method will ensure a PROJCS node is created as the root,
* and set the provided name on it. If used on a GEOGCS coordinate system,
* the GEOGCS node will be demoted to be a child of the new PROJCS root.
*
* @param pszName the user visible name to assign. Not used as a key.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetProjCS( const char * pszName )
{
OGR_SRSNode *poGeogCS = NULL;
OGR_SRSNode *poProjCS = GetAttrNode( "PROJCS" );
if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
{
poGeogCS = poRoot;
poRoot = NULL;
}
if( poProjCS == NULL && GetRoot() != NULL )
{
CPLDebug( "OGR",
"OGRSpatialReference::SetProjCS(%s) failed.\n"
"It appears an incompatible root node (%s) already exists.\n",
pszName, GetRoot()->GetValue() );
return OGRERR_FAILURE;
}
SetNode( "PROJCS", pszName );
if( poGeogCS != NULL )
poRoot->InsertChild( poGeogCS, 1 );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetProjCS() */
/************************************************************************/
/**
* \brief Set the user visible PROJCS name.
*
* This function is the same as OGRSpatialReference::SetProjCS()
*/
OGRErr OSRSetProjCS( OGRSpatialReferenceH hSRS, const char * pszName )
{
VALIDATE_POINTER1( hSRS, "OSRSetProjCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetProjCS( pszName );
}
/************************************************************************/
/* SetProjection() */
/************************************************************************/
/**
* \brief Set a projection name.
*
* This method is the same as the C function OSRSetProjection().
*
* @param pszProjection the projection name, which should be selected from
* the macros in ogr_srs_api.h, such as SRS_PT_TRANSVERSE_MERCATOR.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetProjection( const char * pszProjection )
{
OGR_SRSNode *poGeogCS = NULL;
OGRErr eErr;
if( poRoot != NULL && EQUAL(poRoot->GetValue(),"GEOGCS") )
{
poGeogCS = poRoot;
poRoot = NULL;
}
if( !GetAttrNode( "PROJCS" ) )
{
SetNode( "PROJCS", "unnamed" );
}
eErr = SetNode( "PROJCS|PROJECTION", pszProjection );
if( eErr != OGRERR_NONE )
return eErr;
if( poGeogCS != NULL )
poRoot->InsertChild( poGeogCS, 1 );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetProjection() */
/************************************************************************/
/**
* \brief Set a projection name.
*
* This function is the same as OGRSpatialReference::SetProjection()
*/
OGRErr OSRSetProjection( OGRSpatialReferenceH hSRS,
const char * pszProjection )
{
VALIDATE_POINTER1( hSRS, "OSRSetProjection", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetProjection( pszProjection );
}
/************************************************************************/
/* SetProjParm() */
/************************************************************************/
/**
* \brief Set a projection parameter value.
*
* Adds a new PARAMETER under the PROJCS with the indicated name and value.
*
* This method is the same as the C function OSRSetProjParm().
*
* Please check http://www.remotesensing.org/geotiff/proj_list pages for
* legal parameter names for specific projections.
*
*
* @param pszParmName the parameter name, which should be selected from
* the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
*
* @param dfValue value to assign.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetProjParm( const char * pszParmName,
double dfValue )
{
OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
OGR_SRSNode *poParm;
char szValue[64];
if( poPROJCS == NULL )
return OGRERR_FAILURE;
OGRPrintDouble( szValue, dfValue );
/* -------------------------------------------------------------------- */
/* Try to find existing parameter with this name. */
/* -------------------------------------------------------------------- */
for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
{
poParm = poPROJCS->GetChild( iChild );
if( EQUAL(poParm->GetValue(),"PARAMETER")
&& poParm->GetChildCount() == 2
&& EQUAL(poParm->GetChild(0)->GetValue(),pszParmName) )
{
poParm->GetChild(1)->SetValue( szValue );
return OGRERR_NONE;
}
}
/* -------------------------------------------------------------------- */
/* Otherwise create a new parameter and append. */
/* -------------------------------------------------------------------- */
poParm = new OGR_SRSNode( "PARAMETER" );
poParm->AddChild( new OGR_SRSNode( pszParmName ) );
poParm->AddChild( new OGR_SRSNode( szValue ) );
poPROJCS->AddChild( poParm );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetProjParm() */
/************************************************************************/
/**
* \brief Set a projection parameter value.
*
* This function is the same as OGRSpatialReference::SetProjParm()
*/
OGRErr OSRSetProjParm( OGRSpatialReferenceH hSRS,
const char * pszParmName, double dfValue )
{
VALIDATE_POINTER1( hSRS, "OSRSetProjParm", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetProjParm( pszParmName, dfValue );
}
/************************************************************************/
/* FindProjParm() */
/************************************************************************/
/**
* \brief Return the child index of the named projection parameter on
* its parent PROJCS node.
*
* @param pszParameter projection parameter to look for
* @param poPROJCS projection CS node to look in. If NULL is passed,
* the PROJCS node of the SpatialReference object will be searched.
*
* @return the child index of the named projection parameter. -1 on failure
*/
int OGRSpatialReference::FindProjParm( const char *pszParameter,
const OGR_SRSNode *poPROJCS ) const
{
const OGR_SRSNode *poParameter = NULL;
if( poPROJCS == NULL )
poPROJCS = GetAttrNode( "PROJCS" );
if( poPROJCS == NULL )
return -1;
/* -------------------------------------------------------------------- */
/* Search for requested parameter. */
/* -------------------------------------------------------------------- */
int iChild;
for( iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
{
poParameter = poPROJCS->GetChild(iChild);
if( EQUAL(poParameter->GetValue(),"PARAMETER")
&& poParameter->GetChildCount() == 2
&& EQUAL(poPROJCS->GetChild(iChild)->GetChild(0)->GetValue(),
pszParameter) )
{
return iChild;
}
}
/* -------------------------------------------------------------------- */
/* Try similar names, for selected parameters. */
/* -------------------------------------------------------------------- */
iChild = -1;
if( EQUAL(pszParameter,SRS_PP_LATITUDE_OF_ORIGIN) )
{
iChild = FindProjParm( SRS_PP_LATITUDE_OF_CENTER, poPROJCS );
}
else if( EQUAL(pszParameter,SRS_PP_CENTRAL_MERIDIAN) )
{
iChild = FindProjParm(SRS_PP_LONGITUDE_OF_CENTER, poPROJCS );
if( iChild == -1 )
iChild = FindProjParm(SRS_PP_LONGITUDE_OF_ORIGIN, poPROJCS );
}
return iChild;
}
/************************************************************************/
/* GetProjParm() */
/************************************************************************/
/**
* \brief Fetch a projection parameter value.
*
* NOTE: This code should be modified to translate non degree angles into
* degrees based on the GEOGCS unit. This has not yet been done.
*
* This method is the same as the C function OSRGetProjParm().
*
* @param pszName the name of the parameter to fetch, from the set of
* SRS_PP codes in ogr_srs_api.h.
*
* @param dfDefaultValue the value to return if this parameter doesn't exist.
*
* @param pnErr place to put error code on failure. Ignored if NULL.
*
* @return value of parameter.
*/
double OGRSpatialReference::GetProjParm( const char * pszName,
double dfDefaultValue,
OGRErr *pnErr ) const
{
const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
if( pnErr != NULL )
*pnErr = OGRERR_NONE;
/* -------------------------------------------------------------------- */
/* Find the desired parameter. */
/* -------------------------------------------------------------------- */
int iChild = FindProjParm( pszName, poPROJCS );
if( iChild != -1 )
{
const OGR_SRSNode *poParameter = NULL;
poParameter = poPROJCS->GetChild(iChild);
return CPLAtof(poParameter->GetChild(1)->GetValue());
}
/* -------------------------------------------------------------------- */
/* Return default value on failure. */
/* -------------------------------------------------------------------- */
if( pnErr != NULL )
*pnErr = OGRERR_FAILURE;
return dfDefaultValue;
}
/************************************************************************/
/* OSRGetProjParm() */
/************************************************************************/
/**
* \brief Fetch a projection parameter value.
*
* This function is the same as OGRSpatialReference::GetProjParm()
*/
double OSRGetProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
double dfDefaultValue, OGRErr *pnErr )
{
VALIDATE_POINTER1( hSRS, "OSRGetProjParm", 0 );
return ((OGRSpatialReference *) hSRS)->
GetProjParm(pszName, dfDefaultValue, pnErr);
}
/************************************************************************/
/* GetNormProjParm() */
/************************************************************************/
/**
* \brief Fetch a normalized projection parameter value.
*
* This method is the same as GetProjParm() except that the value of
* the parameter is "normalized" into degrees or meters depending on
* whether it is linear or angular.
*
* This method is the same as the C function OSRGetNormProjParm().
*
* @param pszName the name of the parameter to fetch, from the set of
* SRS_PP codes in ogr_srs_api.h.
*
* @param dfDefaultValue the value to return if this parameter doesn't exist.
*
* @param pnErr place to put error code on failure. Ignored if NULL.
*
* @return value of parameter.
*/
double OGRSpatialReference::GetNormProjParm( const char * pszName,
double dfDefaultValue,
OGRErr *pnErr ) const
{
double dfRawResult;
OGRErr nError;
if( pnErr == NULL )
pnErr = &nError;
GetNormInfo();
dfRawResult = GetProjParm( pszName, dfDefaultValue, pnErr );
// If we got the default just return it unadjusted.
if( *pnErr != OGRERR_NONE )
return dfRawResult;
if( dfToDegrees != 1.0 && IsAngularParameter(pszName) )
dfRawResult *= dfToDegrees;
if( dfToMeter != 1.0 && IsLinearParameter( pszName ) )
return dfRawResult * dfToMeter;
#ifdef WKT_LONGITUDE_RELATIVE_TO_PM
else if( dfFromGreenwich != 0.0 && IsLongitudeParameter( pszName ) )
return dfRawResult + dfFromGreenwich;
#endif
else
return dfRawResult;
}
/************************************************************************/
/* OSRGetNormProjParm() */
/************************************************************************/
/**
* \brief This function is the same as OGRSpatialReference::
*
* This function is the same as OGRSpatialReference::GetNormProjParm()
*/
double OSRGetNormProjParm( OGRSpatialReferenceH hSRS, const char *pszName,
double dfDefaultValue, OGRErr *pnErr )
{
VALIDATE_POINTER1( hSRS, "OSRGetNormProjParm", 0 );
return ((OGRSpatialReference *) hSRS)->
GetNormProjParm(pszName, dfDefaultValue, pnErr);
}
/************************************************************************/
/* SetNormProjParm() */
/************************************************************************/
/**
* \brief Set a projection parameter with a normalized value.
*
* This method is the same as SetProjParm() except that the value of
* the parameter passed in is assumed to be in "normalized" form (decimal
* degrees for angular values, meters for linear values. The values are
* converted in a form suitable for the GEOGCS and linear units in effect.
*
* This method is the same as the C function OSRSetNormProjParm().
*
* @param pszName the parameter name, which should be selected from
* the macros in ogr_srs_api.h, such as SRS_PP_CENTRAL_MERIDIAN.
*
* @param dfValue value to assign.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetNormProjParm( const char * pszName,
double dfValue )
{
GetNormInfo();
if( (dfToDegrees != 1.0 || dfFromGreenwich != 0.0)
&& IsAngularParameter(pszName) )
{
#ifdef WKT_LONGITUDE_RELATIVE_TO_PM
if( dfFromGreenwich != 0.0 && IsLongitudeParameter( pszName ) )
dfValue -= dfFromGreenwich;
#endif
dfValue /= dfToDegrees;
}
else if( dfToMeter != 1.0 && IsLinearParameter( pszName ) )
dfValue /= dfToMeter;
return SetProjParm( pszName, dfValue );
}
/************************************************************************/
/* OSRSetNormProjParm() */
/************************************************************************/
/**
* \brief Set a projection parameter with a normalized value.
*
* This function is the same as OGRSpatialReference::SetNormProjParm()
*/
OGRErr OSRSetNormProjParm( OGRSpatialReferenceH hSRS,
const char * pszParmName, double dfValue )
{
VALIDATE_POINTER1( hSRS, "OSRSetNormProjParm", CE_Failure );
return ((OGRSpatialReference *) hSRS)->
SetNormProjParm( pszParmName, dfValue );
}
/************************************************************************/
/* SetTM() */
/************************************************************************/
OGRErr OGRSpatialReference::SetTM( double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_TRANSVERSE_MERCATOR );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetTM() */
/************************************************************************/
OGRErr OSRSetTM( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetTM", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTM(
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetTMVariant() */
/************************************************************************/
OGRErr OGRSpatialReference::SetTMVariant(
const char *pszVariantName,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( pszVariantName );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetTMVariant() */
/************************************************************************/
OGRErr OSRSetTMVariant( OGRSpatialReferenceH hSRS,
const char *pszVariantName,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetTMVariant", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTMVariant(
pszVariantName,
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetTMSO() */
/************************************************************************/
OGRErr OGRSpatialReference::SetTMSO( double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_TRANSVERSE_MERCATOR_SOUTH_ORIENTED );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* SetTPED() */
/************************************************************************/
OGRErr OGRSpatialReference::SetTPED( double dfLat1, double dfLong1,
double dfLat2, double dfLong2,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_TWO_POINT_EQUIDISTANT );
SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT, dfLat1 );
SetNormProjParm( SRS_PP_LONGITUDE_OF_1ST_POINT, dfLong1 );
SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT, dfLat2 );
SetNormProjParm( SRS_PP_LONGITUDE_OF_2ND_POINT, dfLong2 );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetTPED() */
/************************************************************************/
OGRErr OSRSetTPED( OGRSpatialReferenceH hSRS,
double dfLat1, double dfLong1,
double dfLat2, double dfLong2,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetTPED", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTPED(
dfLat1, dfLong1, dfLat2, dfLong2,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* OSRSetTMSO() */
/************************************************************************/
OGRErr OSRSetTMSO( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetTMSO", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTMSO(
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetTMG() */
/************************************************************************/
OGRErr
OGRSpatialReference::SetTMG( double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
SetProjection( SRS_PT_TUNISIA_MINING_GRID );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetTMG() */
/************************************************************************/
OGRErr OSRSetTMG( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetTMG", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTMG(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetACEA() */
/************************************************************************/
OGRErr OGRSpatialReference::SetACEA( double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_ALBERS_CONIC_EQUAL_AREA );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, dfStdP2 );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetACEA() */
/************************************************************************/
OGRErr OSRSetACEA( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetACEA", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetACEA(
dfStdP1, dfStdP2,
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetAE() */
/************************************************************************/
OGRErr OGRSpatialReference::SetAE( double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_AZIMUTHAL_EQUIDISTANT );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetAE() */
/************************************************************************/
OGRErr OSRSetAE( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetACEA", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetAE(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetBonne() */
/************************************************************************/
OGRErr OGRSpatialReference::SetBonne(
double dfStdP1, double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
SetProjection( SRS_PT_BONNE );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetBonne() */
/************************************************************************/
OGRErr OSRSetBonne( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetBonne", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetBonne(
dfStdP1, dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetCEA() */
/************************************************************************/
OGRErr OGRSpatialReference::SetCEA( double dfStdP1, double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_CYLINDRICAL_EQUAL_AREA );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetCEA() */
/************************************************************************/
OGRErr OSRSetCEA( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetCEA", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetCEA(
dfStdP1, dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetCS() */
/************************************************************************/
OGRErr OGRSpatialReference::SetCS( double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_CASSINI_SOLDNER );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetCS() */
/************************************************************************/
OGRErr OSRSetCS( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetCS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetCS(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEC() */
/************************************************************************/
OGRErr OGRSpatialReference::SetEC( double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_EQUIDISTANT_CONIC );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, dfStdP2 );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEC() */
/************************************************************************/
OGRErr OSRSetEC( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEC(
dfStdP1, dfStdP2,
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEckert() */
/************************************************************************/
OGRErr OGRSpatialReference::SetEckert( int nVariation /* 1-6 */,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
if( nVariation == 1 )
SetProjection( SRS_PT_ECKERT_I );
else if( nVariation == 2 )
SetProjection( SRS_PT_ECKERT_II );
else if( nVariation == 3 )
SetProjection( SRS_PT_ECKERT_III );
else if( nVariation == 4 )
SetProjection( SRS_PT_ECKERT_IV );
else if( nVariation == 5 )
SetProjection( SRS_PT_ECKERT_V );
else if( nVariation == 6 )
SetProjection( SRS_PT_ECKERT_VI );
else
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unsupported Eckert variation (%d).",
nVariation );
return OGRERR_UNSUPPORTED_SRS;
}
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEckert() */
/************************************************************************/
OGRErr OSRSetEckert( OGRSpatialReferenceH hSRS,
int nVariation,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEckert", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEckert(
nVariation, dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEckertIV() */
/* */
/* Deprecated */
/************************************************************************/
OGRErr OGRSpatialReference::SetEckertIV( double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_ECKERT_IV );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEckertIV() */
/************************************************************************/
OGRErr OSRSetEckertIV( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEckertIV", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEckertIV(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEckertVI() */
/* */
/* Deprecated */
/************************************************************************/
OGRErr OGRSpatialReference::SetEckertVI( double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_ECKERT_VI );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEckertVI() */
/************************************************************************/
OGRErr OSRSetEckertVI( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEckertVI", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEckertVI(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEquirectangular() */
/************************************************************************/
OGRErr OGRSpatialReference::SetEquirectangular(
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_EQUIRECTANGULAR );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEquirectangular() */
/************************************************************************/
OGRErr OSRSetEquirectangular( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEquirectangular(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetEquirectangular2() */
/* Generalized form */
/************************************************************************/
OGRErr OGRSpatialReference::SetEquirectangular2(
double dfCenterLat, double dfCenterLong,
double dfStdParallel1,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_EQUIRECTANGULAR );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdParallel1 );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetEquirectangular2() */
/************************************************************************/
OGRErr OSRSetEquirectangular2( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfStdParallel1,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetEquirectangular2", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetEquirectangular2(
dfCenterLat, dfCenterLong,
dfStdParallel1,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetGS() */
/************************************************************************/
OGRErr OGRSpatialReference::SetGS( double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_GALL_STEREOGRAPHIC );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGS() */
/************************************************************************/
OGRErr OSRSetGS( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetGS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGS(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetGH() */
/************************************************************************/
OGRErr OGRSpatialReference::SetGH( double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_GOODE_HOMOLOSINE );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGH() */
/************************************************************************/
OGRErr OSRSetGH( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetGH", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGH(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetIGH() */
/************************************************************************/
OGRErr OGRSpatialReference::SetIGH()
{
SetProjection( SRS_PT_IGH );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetIGH() */
/************************************************************************/
OGRErr OSRSetIGH( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRSetIGH", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetIGH();
}
/************************************************************************/
/* SetGEOS() */
/************************************************************************/
OGRErr OGRSpatialReference::SetGEOS( double dfCentralMeridian,
double dfSatelliteHeight,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_GEOSTATIONARY_SATELLITE );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_SATELLITE_HEIGHT, dfSatelliteHeight );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGEOS() */
/************************************************************************/
OGRErr OSRSetGEOS( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfSatelliteHeight,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetGEOS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGEOS(
dfCentralMeridian, dfSatelliteHeight,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetGaussSchreiberTMercator() */
/************************************************************************/
OGRErr OGRSpatialReference::SetGaussSchreiberTMercator(
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_GAUSSSCHREIBERTMERCATOR );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGaussSchreiberTMercator() */
/************************************************************************/
OGRErr OSRSetGaussSchreiberTMercator( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetGaussSchreiberTMercator", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGaussSchreiberTMercator(
dfCenterLat, dfCenterLong, dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetGnomonic() */
/************************************************************************/
OGRErr OGRSpatialReference::SetGnomonic(
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_GNOMONIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetGnomonic() */
/************************************************************************/
OGRErr OSRSetGnomonic( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetGnomonic", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetGnomonic(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetHOMAC() */
/************************************************************************/
/**
* \brief Set an Hotine Oblique Mercator Azimuth Center projection using
* azimuth angle.
*
* This projection corresponds to EPSG projection method 9815, also
* sometimes known as hotine oblique mercator (variant B).
*
* This method does the same thing as the C function OSRSetHOMAC().
*
* @param dfCenterLat Latitude of the projection origin.
* @param dfCenterLong Longitude of the projection origin.
* @param dfAzimuth Azimuth, measured clockwise from North, of the projection
* centerline.
* @param dfRectToSkew ?.
* @param dfScale Scale factor applies to the projection origin.
* @param dfFalseEasting False easting.
* @param dfFalseNorthing False northing.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetHOMAC( double dfCenterLat, double dfCenterLong,
double dfAzimuth, double dfRectToSkew,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_HOTINE_OBLIQUE_MERCATOR_AZIMUTH_CENTER );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_AZIMUTH, dfAzimuth );
SetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, dfRectToSkew );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetHOMAC() */
/************************************************************************/
/**
* \brief Set an Oblique Mercator projection using azimuth angle.
*
* This is the same as the C++ method OGRSpatialReference::SetHOMAC()
*/
OGRErr OSRSetHOMAC( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfAzimuth, double dfRectToSkew,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetHOMAC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetHOMAC(
dfCenterLat, dfCenterLong,
dfAzimuth, dfRectToSkew,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetHOM() */
/************************************************************************/
/**
* \brief Set a Hotine Oblique Mercator projection using azimuth angle.
*
* This projection corresponds to EPSG projection method 9812, also
* sometimes known as hotine oblique mercator (variant A)..
*
* This method does the same thing as the C function OSRSetHOM().
*
* @param dfCenterLat Latitude of the projection origin.
* @param dfCenterLong Longitude of the projection origin.
* @param dfAzimuth Azimuth, measured clockwise from North, of the projection
* centerline.
* @param dfRectToSkew ?.
* @param dfScale Scale factor applies to the projection origin.
* @param dfFalseEasting False easting.
* @param dfFalseNorthing False northing.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetHOM( double dfCenterLat, double dfCenterLong,
double dfAzimuth, double dfRectToSkew,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_HOTINE_OBLIQUE_MERCATOR );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_AZIMUTH, dfAzimuth );
SetNormProjParm( SRS_PP_RECTIFIED_GRID_ANGLE, dfRectToSkew );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetHOM() */
/************************************************************************/
/**
* \brief Set a Hotine Oblique Mercator projection using azimuth angle.
*
* This is the same as the C++ method OGRSpatialReference::SetHOM()
*/
OGRErr OSRSetHOM( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfAzimuth, double dfRectToSkew,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetHOM", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetHOM(
dfCenterLat, dfCenterLong,
dfAzimuth, dfRectToSkew,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetHOM2PNO() */
/************************************************************************/
/**
* \brief Set a Hotine Oblique Mercator projection using two points on projection
* centerline.
*
* This method does the same thing as the C function OSRSetHOM2PNO().
*
* @param dfCenterLat Latitude of the projection origin.
* @param dfLat1 Latitude of the first point on center line.
* @param dfLong1 Longitude of the first point on center line.
* @param dfLat2 Latitude of the second point on center line.
* @param dfLong2 Longitude of the second point on center line.
* @param dfScale Scale factor applies to the projection origin.
* @param dfFalseEasting False easting.
* @param dfFalseNorthing False northing.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetHOM2PNO( double dfCenterLat,
double dfLat1, double dfLong1,
double dfLat2, double dfLong2,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_HOTINE_OBLIQUE_MERCATOR_TWO_POINT_NATURAL_ORIGIN );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LATITUDE_OF_POINT_1, dfLat1 );
SetNormProjParm( SRS_PP_LONGITUDE_OF_POINT_1, dfLong1 );
SetNormProjParm( SRS_PP_LATITUDE_OF_POINT_2, dfLat2 );
SetNormProjParm( SRS_PP_LONGITUDE_OF_POINT_2, dfLong2 );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetHOM2PNO() */
/************************************************************************/
/**
* \brief Set a Hotine Oblique Mercator projection using two points on projection
* centerline.
*
* This is the same as the C++ method OGRSpatialReference::SetHOM2PNO()
*/
OGRErr OSRSetHOM2PNO( OGRSpatialReferenceH hSRS,
double dfCenterLat,
double dfLat1, double dfLong1,
double dfLat2, double dfLong2,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetHOM2PNO", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetHOM2PNO(
dfCenterLat,
dfLat1, dfLong1,
dfLat2, dfLong2,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetIWMPolyconic() */
/************************************************************************/
OGRErr OGRSpatialReference::SetIWMPolyconic(
double dfLat1, double dfLat2,
double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
SetProjection( SRS_PT_IMW_POLYCONIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_1ST_POINT, dfLat1 );
SetNormProjParm( SRS_PP_LATITUDE_OF_2ND_POINT, dfLat2 );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetIWMPolyconic() */
/************************************************************************/
OGRErr OSRSetIWMPolyconic( OGRSpatialReferenceH hSRS,
double dfLat1, double dfLat2,
double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetIWMPolyconic", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetIWMPolyconic(
dfLat1, dfLat2, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetKrovak() */
/************************************************************************/
OGRErr OGRSpatialReference::SetKrovak( double dfCenterLat, double dfCenterLong,
double dfAzimuth,
double dfPseudoStdParallel1,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_KROVAK );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_AZIMUTH, dfAzimuth );
SetNormProjParm( SRS_PP_PSEUDO_STD_PARALLEL_1, dfPseudoStdParallel1 );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetKrovak() */
/************************************************************************/
OGRErr OSRSetKrovak( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfAzimuth, double dfPseudoStdParallel1,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetKrovak", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetKrovak(
dfCenterLat, dfCenterLong,
dfAzimuth, dfPseudoStdParallel1,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetLAEA() */
/************************************************************************/
OGRErr OGRSpatialReference::SetLAEA( double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_LAMBERT_AZIMUTHAL_EQUAL_AREA );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetLAEA() */
/************************************************************************/
OGRErr OSRSetLAEA( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetLAEA", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLAEA(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetLCC() */
/************************************************************************/
OGRErr OGRSpatialReference::SetLCC( double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, dfStdP2 );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetLCC() */
/************************************************************************/
OGRErr OSRSetLCC( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetLCC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLCC(
dfStdP1, dfStdP2,
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetLCC1SP() */
/************************************************************************/
OGRErr OGRSpatialReference::SetLCC1SP( double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetLCC1SP() */
/************************************************************************/
OGRErr OSRSetLCC1SP( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetLCC1SP", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLCC1SP(
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetLCCB() */
/************************************************************************/
OGRErr OGRSpatialReference::SetLCCB( double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_LAMBERT_CONFORMAL_CONIC_2SP_BELGIUM );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_2, dfStdP2 );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetLCCB() */
/************************************************************************/
OGRErr OSRSetLCCB( OGRSpatialReferenceH hSRS,
double dfStdP1, double dfStdP2,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetLCCB", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetLCCB(
dfStdP1, dfStdP2,
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetMC() */
/************************************************************************/
OGRErr OGRSpatialReference::SetMC( double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_MILLER_CYLINDRICAL );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfCenterLat );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetMC() */
/************************************************************************/
OGRErr OSRSetMC( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetMC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetMC(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetMercator() */
/************************************************************************/
OGRErr OGRSpatialReference::SetMercator( double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_MERCATOR_1SP );
if( dfCenterLat != 0.0 )
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetMercator() */
/************************************************************************/
OGRErr OSRSetMercator( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetMercator", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetMercator(
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetMercator2SP() */
/************************************************************************/
OGRErr OGRSpatialReference::SetMercator2SP(
double dfStdP1,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_MERCATOR_2SP );
SetNormProjParm( SRS_PP_STANDARD_PARALLEL_1, dfStdP1 );
if( dfCenterLat != 0.0 )
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetMercator2SP() */
/************************************************************************/
OGRErr OSRSetMercator2SP( OGRSpatialReferenceH hSRS,
double dfStdP1,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetMercator2SP", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetMercator2SP(
dfStdP1,
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetMollweide() */
/************************************************************************/
OGRErr OGRSpatialReference::SetMollweide( double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_MOLLWEIDE );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetMollweide() */
/************************************************************************/
OGRErr OSRSetMollweide( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetMollweide", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetMollweide(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetNZMG() */
/************************************************************************/
OGRErr OGRSpatialReference::SetNZMG( double dfCenterLat, double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_NEW_ZEALAND_MAP_GRID );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetNZMG() */
/************************************************************************/
OGRErr OSRSetNZMG( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetNZMG", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetNZMG(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetOS() */
/************************************************************************/
OGRErr OGRSpatialReference::SetOS( double dfOriginLat, double dfCMeridian,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_OBLIQUE_STEREOGRAPHIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfOriginLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCMeridian );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetOS() */
/************************************************************************/
OGRErr OSRSetOS( OGRSpatialReferenceH hSRS,
double dfOriginLat, double dfCMeridian,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetOS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetOS(
dfOriginLat, dfCMeridian,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetOrthographic() */
/************************************************************************/
OGRErr OGRSpatialReference::SetOrthographic(
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
SetProjection( SRS_PT_ORTHOGRAPHIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetOrthographic() */
/************************************************************************/
OGRErr OSRSetOrthographic( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetOrthographic", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetOrthographic(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetPolyconic() */
/************************************************************************/
OGRErr OGRSpatialReference::SetPolyconic(
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
// note: it seems that by some definitions this should include a
// scale_factor parameter.
SetProjection( SRS_PT_POLYCONIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetPolyconic() */
/************************************************************************/
OGRErr OSRSetPolyconic( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetPolyconic", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetPolyconic(
dfCenterLat, dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetPS() */
/************************************************************************/
OGRErr OGRSpatialReference::SetPS(
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
SetProjection( SRS_PT_POLAR_STEREOGRAPHIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetPS() */
/************************************************************************/
OGRErr OSRSetPS( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetPS", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetPS(
dfCenterLat, dfCenterLong,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetRobinson() */
/************************************************************************/
OGRErr OGRSpatialReference::SetRobinson( double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_ROBINSON );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetRobinson() */
/************************************************************************/
OGRErr OSRSetRobinson( OGRSpatialReferenceH hSRS,
double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetRobinson", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetRobinson(
dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetSinusoidal() */
/************************************************************************/
OGRErr OGRSpatialReference::SetSinusoidal( double dfCenterLong,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_SINUSOIDAL );
SetNormProjParm( SRS_PP_LONGITUDE_OF_CENTER, dfCenterLong );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetSinusoidal() */
/************************************************************************/
OGRErr OSRSetSinusoidal( OGRSpatialReferenceH hSRS,
double dfCenterLong,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetSinusoidal", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetSinusoidal(
dfCenterLong,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetStereographic() */
/************************************************************************/
OGRErr OGRSpatialReference::SetStereographic(
double dfOriginLat, double dfCMeridian,
double dfScale,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_STEREOGRAPHIC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfOriginLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCMeridian );
SetNormProjParm( SRS_PP_SCALE_FACTOR, dfScale );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetStereographic() */
/************************************************************************/
OGRErr OSRSetStereographic( OGRSpatialReferenceH hSRS,
double dfOriginLat, double dfCMeridian,
double dfScale,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetStereographic", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetStereographic(
dfOriginLat, dfCMeridian,
dfScale,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetSOC() */
/* */
/* NOTE: This definition isn't really used in practice any more */
/* and should be considered deprecated. It seems that swiss */
/* oblique mercator is now define as Hotine_Oblique_Mercator */
/* with an azimuth of 90 and a rectified_grid_angle of 90. See */
/* EPSG:2056 and Bug 423. */
/************************************************************************/
OGRErr OGRSpatialReference::SetSOC( double dfLatitudeOfOrigin,
double dfCentralMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_SWISS_OBLIQUE_CYLINDRICAL );
SetNormProjParm( SRS_PP_LATITUDE_OF_CENTER, dfLatitudeOfOrigin );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCentralMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetSOC() */
/************************************************************************/
OGRErr OSRSetSOC( OGRSpatialReferenceH hSRS,
double dfLatitudeOfOrigin, double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetSOC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetSOC(
dfLatitudeOfOrigin, dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetVDG() */
/************************************************************************/
OGRErr OGRSpatialReference::SetVDG( double dfCMeridian,
double dfFalseEasting,
double dfFalseNorthing )
{
SetProjection( SRS_PT_VANDERGRINTEN );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCMeridian );
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetVDG() */
/************************************************************************/
OGRErr OSRSetVDG( OGRSpatialReferenceH hSRS,
double dfCentralMeridian,
double dfFalseEasting, double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetVDG", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetVDG(
dfCentralMeridian,
dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetUTM() */
/************************************************************************/
/**
* \brief Set UTM projection definition.
*
* This will generate a projection definition with the full set of
* transverse mercator projection parameters for the given UTM zone.
* If no PROJCS[] description is set yet, one will be set to look
* like "UTM Zone %d, {Northern, Southern} Hemisphere".
*
* This method is the same as the C function OSRSetUTM().
*
* @param nZone UTM zone.
*
* @param bNorth TRUE for northern hemisphere, or FALSE for southern
* hemisphere.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetUTM( int nZone, int bNorth )
{
SetProjection( SRS_PT_TRANSVERSE_MERCATOR );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0 );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, nZone * 6 - 183 );
SetNormProjParm( SRS_PP_SCALE_FACTOR, 0.9996 );
SetNormProjParm( SRS_PP_FALSE_EASTING, 500000.0 );
if( bNorth )
SetNormProjParm( SRS_PP_FALSE_NORTHING, 0 );
else
SetNormProjParm( SRS_PP_FALSE_NORTHING, 10000000 );
if( EQUAL(GetAttrValue("PROJCS"),"unnamed") )
{
char szUTMName[128];
if( bNorth )
sprintf( szUTMName, "UTM Zone %d, Northern Hemisphere", nZone );
else
sprintf( szUTMName, "UTM Zone %d, Southern Hemisphere", nZone );
SetNode( "PROJCS", szUTMName );
}
SetLinearUnits( SRS_UL_METER, 1.0 );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetUTM() */
/************************************************************************/
/**
* \brief Set UTM projection definition.
*
* This is the same as the C++ method OGRSpatialReference::SetUTM()
*/
OGRErr OSRSetUTM( OGRSpatialReferenceH hSRS, int nZone, int bNorth )
{
VALIDATE_POINTER1( hSRS, "OSRSetUTM", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetUTM( nZone, bNorth );
}
/************************************************************************/
/* GetUTMZone() */
/* */
/* Returns zero if it isn't UTM. */
/************************************************************************/
/**
* \brief Get utm zone information.
*
* This is the same as the C function OSRGetUTMZone().
*
* In SWIG bindings (Python, Java, etc) the GetUTMZone() method returns a
* zone which is negative in the southern hemisphere instead of having the
* pbNorth flag used in the C and C++ interface.
*
* @param pbNorth pointer to in to set to TRUE if northern hemisphere, or
* FALSE if southern.
*
* @return UTM zone number or zero if this isn't a UTM definition.
*/
int OGRSpatialReference::GetUTMZone( int * pbNorth ) const
{
const char *pszProjection = GetAttrValue( "PROJECTION" );
if( pszProjection == NULL
|| !EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
return 0;
if( GetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, 0.0 ) != 0.0 )
return 0;
if( GetProjParm( SRS_PP_SCALE_FACTOR, 1.0 ) != 0.9996 )
return 0;
if( fabs(GetNormProjParm( SRS_PP_FALSE_EASTING, 0.0 )-500000.0) > 0.001 )
return 0;
double dfFalseNorthing = GetNormProjParm( SRS_PP_FALSE_NORTHING, 0.0);
if( dfFalseNorthing != 0.0
&& fabs(dfFalseNorthing-10000000.0) > 0.001 )
return 0;
if( pbNorth != NULL )
*pbNorth = (dfFalseNorthing == 0);
double dfCentralMeridian = GetNormProjParm( SRS_PP_CENTRAL_MERIDIAN,
0.0);
double dfZone = ( dfCentralMeridian + 186.0 ) / 6.0;
if( ABS(dfZone - (int) dfZone - 0.5 ) > 0.00001
|| dfCentralMeridian < -177.00001
|| dfCentralMeridian > 177.000001 )
return 0;
else
return (int) dfZone;
}
/************************************************************************/
/* OSRGetUTMZone() */
/************************************************************************/
/**
* \brief Get utm zone information.
*
* This is the same as the C++ method OGRSpatialReference::GetUTMZone()
*/
int OSRGetUTMZone( OGRSpatialReferenceH hSRS, int *pbNorth )
{
VALIDATE_POINTER1( hSRS, "OSRGetUTMZone", 0 );
return ((OGRSpatialReference *) hSRS)->GetUTMZone( pbNorth );
}
/************************************************************************/
/* SetWagner() */
/************************************************************************/
OGRErr OGRSpatialReference::SetWagner( int nVariation /* 1 -- 7 */,
double dfCenterLat,
double dfFalseEasting,
double dfFalseNorthing )
{
if( nVariation == 1 )
SetProjection( SRS_PT_WAGNER_I );
else if( nVariation == 2 )
SetProjection( SRS_PT_WAGNER_II );
else if( nVariation == 3 )
{
SetProjection( SRS_PT_WAGNER_III );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
}
else if( nVariation == 4 )
SetProjection( SRS_PT_WAGNER_IV );
else if( nVariation == 5 )
SetProjection( SRS_PT_WAGNER_V );
else if( nVariation == 6 )
SetProjection( SRS_PT_WAGNER_VI );
else if( nVariation == 7 )
SetProjection( SRS_PT_WAGNER_VII );
else
{
CPLError( CE_Failure, CPLE_AppDefined,
"Unsupported Wagner variation (%d).", nVariation );
return OGRERR_UNSUPPORTED_SRS;
}
SetNormProjParm( SRS_PP_FALSE_EASTING, dfFalseEasting );
SetNormProjParm( SRS_PP_FALSE_NORTHING, dfFalseNorthing );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetWagner() */
/************************************************************************/
OGRErr OSRSetWagner( OGRSpatialReferenceH hSRS,
int nVariation, double dfCenterLat,
double dfFalseEasting,
double dfFalseNorthing )
{
VALIDATE_POINTER1( hSRS, "OSRSetWagner", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetWagner(
nVariation, dfCenterLat, dfFalseEasting, dfFalseNorthing );
}
/************************************************************************/
/* SetQSC() */
/************************************************************************/
OGRErr OGRSpatialReference::SetQSC( double dfCenterLat, double dfCenterLong )
{
SetProjection( SRS_PT_QSC );
SetNormProjParm( SRS_PP_LATITUDE_OF_ORIGIN, dfCenterLat );
SetNormProjParm( SRS_PP_CENTRAL_MERIDIAN, dfCenterLong );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetQSC() */
/************************************************************************/
OGRErr OSRSetQSC( OGRSpatialReferenceH hSRS,
double dfCenterLat, double dfCenterLong )
{
VALIDATE_POINTER1( hSRS, "OSRSetQSC", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetQSC(
dfCenterLat, dfCenterLong );
}
/************************************************************************/
/* SetAuthority() */
/************************************************************************/
/**
* \brief Set the authority for a node.
*
* This method is the same as the C function OSRSetAuthority().
*
* @param pszTargetKey the partial or complete path to the node to
* set an authority on. ie. "PROJCS", "GEOGCS" or "GEOGCS|UNIT".
*
* @param pszAuthority authority name, such as "EPSG".
*
* @param nCode code for value with this authority.
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetAuthority( const char *pszTargetKey,
const char * pszAuthority,
int nCode )
{
/* -------------------------------------------------------------------- */
/* Find the node below which the authority should be put. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poNode = GetAttrNode( pszTargetKey );
if( poNode == NULL )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* If there is an existing AUTHORITY child blow it away before */
/* trying to set a new one. */
/* -------------------------------------------------------------------- */
int iOldChild = poNode->FindChild( "AUTHORITY" );
if( iOldChild != -1 )
poNode->DestroyChild( iOldChild );
/* -------------------------------------------------------------------- */
/* Create a new authority node. */
/* -------------------------------------------------------------------- */
char szCode[32];
OGR_SRSNode *poAuthNode;
sprintf( szCode, "%d", nCode );
poAuthNode = new OGR_SRSNode( "AUTHORITY" );
poAuthNode->AddChild( new OGR_SRSNode( pszAuthority ) );
poAuthNode->AddChild( new OGR_SRSNode( szCode ) );
poNode->AddChild( poAuthNode );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetAuthority() */
/************************************************************************/
/**
* \brief Set the authority for a node.
*
* This function is the same as OGRSpatialReference::SetAuthority().
*/
OGRErr OSRSetAuthority( OGRSpatialReferenceH hSRS,
const char *pszTargetKey,
const char * pszAuthority,
int nCode )
{
VALIDATE_POINTER1( hSRS, "OSRSetAuthority", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetAuthority( pszTargetKey,
pszAuthority,
nCode );
}
/************************************************************************/
/* GetAuthorityCode() */
/************************************************************************/
/**
* \brief Get the authority code for a node.
*
* This method is used to query an AUTHORITY[] node from within the
* WKT tree, and fetch the code value.
*
* While in theory values may be non-numeric, for the EPSG authority all
* code values should be integral.
*
* This method is the same as the C function OSRGetAuthorityCode().
*
* @param pszTargetKey the partial or complete path to the node to
* get an authority from. ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to
* search for an authority node on the root element.
*
* @return value code from authority node, or NULL on failure. The value
* returned is internal and should not be freed or modified.
*/
const char *
OGRSpatialReference::GetAuthorityCode( const char *pszTargetKey ) const
{
/* -------------------------------------------------------------------- */
/* Find the node below which the authority should be put. */
/* -------------------------------------------------------------------- */
const OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Fetch AUTHORITY child if there is one. */
/* -------------------------------------------------------------------- */
if( poNode->FindChild("AUTHORITY") == -1 )
return NULL;
poNode = poNode->GetChild(poNode->FindChild("AUTHORITY"));
/* -------------------------------------------------------------------- */
/* Create a new authority node. */
/* -------------------------------------------------------------------- */
if( poNode->GetChildCount() < 2 )
return NULL;
return poNode->GetChild(1)->GetValue();
}
/************************************************************************/
/* OSRGetAuthorityCode() */
/************************************************************************/
/**
* \brief Get the authority code for a node.
*
* This function is the same as OGRSpatialReference::GetAuthorityCode().
*/
const char *OSRGetAuthorityCode( OGRSpatialReferenceH hSRS,
const char *pszTargetKey )
{
VALIDATE_POINTER1( hSRS, "OSRGetAuthorityCode", NULL );
return ((OGRSpatialReference *) hSRS)->GetAuthorityCode( pszTargetKey );
}
/************************************************************************/
/* GetAuthorityName() */
/************************************************************************/
/**
* \brief Get the authority name for a node.
*
* This method is used to query an AUTHORITY[] node from within the
* WKT tree, and fetch the authority name value.
*
* The most common authority is "EPSG".
*
* This method is the same as the C function OSRGetAuthorityName().
*
* @param pszTargetKey the partial or complete path to the node to
* get an authority from. ie. "PROJCS", "GEOGCS", "GEOGCS|UNIT" or NULL to
* search for an authority node on the root element.
*
* @return value code from authority node, or NULL on failure. The value
* returned is internal and should not be freed or modified.
*/
const char *
OGRSpatialReference::GetAuthorityName( const char *pszTargetKey ) const
{
/* -------------------------------------------------------------------- */
/* Find the node below which the authority should be put. */
/* -------------------------------------------------------------------- */
const OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Fetch AUTHORITY child if there is one. */
/* -------------------------------------------------------------------- */
if( poNode->FindChild("AUTHORITY") == -1 )
return NULL;
poNode = poNode->GetChild(poNode->FindChild("AUTHORITY"));
/* -------------------------------------------------------------------- */
/* Create a new authority node. */
/* -------------------------------------------------------------------- */
if( poNode->GetChildCount() < 2 )
return NULL;
return poNode->GetChild(0)->GetValue();
}
/************************************************************************/
/* OSRGetAuthorityName() */
/************************************************************************/
/**
* \brief Get the authority name for a node.
*
* This function is the same as OGRSpatialReference::GetAuthorityName().
*/
const char *OSRGetAuthorityName( OGRSpatialReferenceH hSRS,
const char *pszTargetKey )
{
VALIDATE_POINTER1( hSRS, "OSRGetAuthorityName", NULL );
return ((OGRSpatialReference *) hSRS)->GetAuthorityName( pszTargetKey );
}
/************************************************************************/
/* StripVertical() */
/************************************************************************/
/**
* \brief Convert a compound cs into a horizontal CS.
*
* If this SRS is of type COMPD_CS[] then the vertical CS and the root COMPD_CS
* nodes are stripped resulting and only the horizontal coordinate system
* portion remains (normally PROJCS, GEOGCS or LOCAL_CS).
*
* If this is not a compound coordinate system then nothing is changed.
*
* @since OGR 1.8.0
*/
OGRErr OGRSpatialReference::StripVertical()
{
if( GetRoot() == NULL
|| !EQUAL(GetRoot()->GetValue(),"COMPD_CS") )
return OGRERR_NONE;
OGR_SRSNode *poHorizontalCS = GetRoot()->GetChild( 1 );
if( poHorizontalCS != NULL )
poHorizontalCS = poHorizontalCS->Clone();
SetRoot( poHorizontalCS );
return OGRERR_NONE;
}
/************************************************************************/
/* StripCTParms() */
/************************************************************************/
/**
* \brief Strip OGC CT Parameters.
*
* This method will remove all components of the coordinate system
* that are specific to the OGC CT Specification. That is it will attempt
* to strip it down to being compatible with the Simple Features 1.0
* specification.
*
* This method is the same as the C function OSRStripCTParms().
*
* @param poCurrent node to operate on. NULL to operate on whole tree.
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr OGRSpatialReference::StripCTParms( OGR_SRSNode * poCurrent )
{
if( poCurrent == NULL )
{
StripVertical();
poCurrent = GetRoot();
}
if( poCurrent == NULL )
return OGRERR_NONE;
if( poCurrent == GetRoot() && EQUAL(poCurrent->GetValue(),"LOCAL_CS") )
{
delete poCurrent;
poRoot = NULL;
return OGRERR_NONE;
}
if( poCurrent == NULL )
return OGRERR_NONE;
poCurrent->StripNodes( "AUTHORITY" );
poCurrent->StripNodes( "TOWGS84" );
poCurrent->StripNodes( "AXIS" );
poCurrent->StripNodes( "EXTENSION" );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRStripCTParms() */
/************************************************************************/
/**
* \brief Strip OGC CT Parameters.
*
* This function is the same as OGRSpatialReference::StripCTParms().
*/
OGRErr OSRStripCTParms( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRStripCTParms", CE_Failure );
return ((OGRSpatialReference *) hSRS)->StripCTParms( NULL );
}
/************************************************************************/
/* IsCompound() */
/************************************************************************/
/**
* \brief Check if coordinate system is compound.
*
* This method is the same as the C function OSRIsCompound().
*
* @return TRUE if this is rooted with a COMPD_CS node.
*/
int OGRSpatialReference::IsCompound() const
{
if( poRoot == NULL )
return FALSE;
return EQUAL(poRoot->GetValue(),"COMPD_CS");
}
/************************************************************************/
/* OSRIsCompound() */
/************************************************************************/
/**
* \brief Check if the coordinate system is compound.
*
* This function is the same as OGRSpatialReference::IsCompound().
*/
int OSRIsCompound( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsCompound", 0 );
return ((OGRSpatialReference *) hSRS)->IsCompound();
}
/************************************************************************/
/* IsProjected() */
/************************************************************************/
/**
* \brief Check if projected coordinate system.
*
* This method is the same as the C function OSRIsProjected().
*
* @return TRUE if this contains a PROJCS node indicating a it is a
* projected coordinate system.
*/
int OGRSpatialReference::IsProjected() const
{
if( poRoot == NULL )
return FALSE;
if( EQUAL(poRoot->GetValue(),"PROJCS") )
return TRUE;
else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
return GetAttrNode( "PROJCS" ) != NULL;
else
return FALSE;
}
/************************************************************************/
/* OSRIsProjected() */
/************************************************************************/
/**
* \brief Check if projected coordinate system.
*
* This function is the same as OGRSpatialReference::IsProjected().
*/
int OSRIsProjected( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsProjected", 0 );
return ((OGRSpatialReference *) hSRS)->IsProjected();
}
/************************************************************************/
/* IsGeocentric() */
/************************************************************************/
/**
* \brief Check if geocentric coordinate system.
*
* This method is the same as the C function OSRIsGeocentric().
*
* @return TRUE if this contains a GEOCCS node indicating a it is a
* geocentric coordinate system.
*
* @since OGR 1.9.0
*/
int OGRSpatialReference::IsGeocentric() const
{
if( poRoot == NULL )
return FALSE;
if( EQUAL(poRoot->GetValue(),"GEOCCS") )
return TRUE;
else
return FALSE;
}
/************************************************************************/
/* OSRIsGeocentric() */
/************************************************************************/
/**
* \brief Check if geocentric coordinate system.
*
* This function is the same as OGRSpatialReference::IsGeocentric().
*
* @since OGR 1.9.0
*/
int OSRIsGeocentric( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsGeocentric", 0 );
return ((OGRSpatialReference *) hSRS)->IsGeocentric();
}
/************************************************************************/
/* IsGeographic() */
/************************************************************************/
/**
* \brief Check if geographic coordinate system.
*
* This method is the same as the C function OSRIsGeographic().
*
* @return TRUE if this spatial reference is geographic ... that is the
* root is a GEOGCS node.
*/
int OGRSpatialReference::IsGeographic() const
{
if( GetRoot() == NULL )
return FALSE;
if( EQUAL(poRoot->GetValue(),"GEOGCS") )
return TRUE;
else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
return GetAttrNode( "GEOGCS" ) != NULL
&& GetAttrNode( "PROJCS" ) == NULL;
else
return FALSE;
}
/************************************************************************/
/* OSRIsGeographic() */
/************************************************************************/
/**
* \brief Check if geographic coordinate system.
*
* This function is the same as OGRSpatialReference::IsGeographic().
*/
int OSRIsGeographic( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsGeographic", 0 );
return ((OGRSpatialReference *) hSRS)->IsGeographic();
}
/************************************************************************/
/* IsLocal() */
/************************************************************************/
/**
* \brief Check if local coordinate system.
*
* This method is the same as the C function OSRIsLocal().
*
* @return TRUE if this spatial reference is local ... that is the
* root is a LOCAL_CS node.
*/
int OGRSpatialReference::IsLocal() const
{
if( GetRoot() == NULL )
return FALSE;
return EQUAL(GetRoot()->GetValue(),"LOCAL_CS");
}
/************************************************************************/
/* OSRIsLocal() */
/************************************************************************/
/**
* \brief Check if local coordinate system.
*
* This function is the same as OGRSpatialReference::IsLocal().
*/
int OSRIsLocal( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsLocal", 0 );
return ((OGRSpatialReference *) hSRS)->IsLocal();
}
/************************************************************************/
/* IsVertical() */
/************************************************************************/
/**
* \brief Check if vertical coordinate system.
*
* This method is the same as the C function OSRIsVertical().
*
* @return TRUE if this contains a VERT_CS node indicating a it is a
* vertical coordinate system.
*
* @since OGR 1.8.0
*/
int OGRSpatialReference::IsVertical() const
{
if( poRoot == NULL )
return FALSE;
if( EQUAL(poRoot->GetValue(),"VERT_CS") )
return TRUE;
else if( EQUAL(poRoot->GetValue(),"COMPD_CS") )
return GetAttrNode( "VERT_CS" ) != NULL;
else
return FALSE;
}
/************************************************************************/
/* OSRIsVertical() */
/************************************************************************/
/**
* \brief Check if vertical coordinate system.
*
* This function is the same as OGRSpatialReference::IsVertical().
*
* @since OGR 1.8.0
*/
int OSRIsVertical( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRIsVertical", 0 );
return ((OGRSpatialReference *) hSRS)->IsVertical();
}
/************************************************************************/
/* CloneGeogCS() */
/************************************************************************/
/**
* \brief Make a duplicate of the GEOGCS node of this OGRSpatialReference object.
*
* @return a new SRS, which becomes the responsibility of the caller.
*/
OGRSpatialReference *OGRSpatialReference::CloneGeogCS() const
{
const OGR_SRSNode *poGeogCS;
OGRSpatialReference * poNewSRS;
/* -------------------------------------------------------------------- */
/* We have to reconstruct the GEOGCS node for geocentric */
/* coordinate systems. */
/* -------------------------------------------------------------------- */
if( IsGeocentric() )
{
const OGR_SRSNode *poDatum = GetAttrNode( "DATUM" );
const OGR_SRSNode *poPRIMEM = GetAttrNode( "PRIMEM" );
OGR_SRSNode *poGeogCS;
if( poDatum == NULL || poPRIMEM == NULL )
return NULL;
poGeogCS = new OGR_SRSNode( "GEOGCS" );
poGeogCS->AddChild( new OGR_SRSNode( "unnamed" ) );
poGeogCS->AddChild( poDatum->Clone() );
poGeogCS->AddChild( poPRIMEM->Clone() );
poNewSRS = new OGRSpatialReference();
poNewSRS->SetRoot( poGeogCS );
poNewSRS->SetAngularUnits( "degree", CPLAtof(SRS_UA_DEGREE_CONV) );
return poNewSRS;
}
/* -------------------------------------------------------------------- */
/* For all others we just search the tree, and duplicate. */
/* -------------------------------------------------------------------- */
poGeogCS = GetAttrNode( "GEOGCS" );
if( poGeogCS == NULL )
return NULL;
poNewSRS = new OGRSpatialReference();
poNewSRS->SetRoot( poGeogCS->Clone() );
return poNewSRS;
}
/************************************************************************/
/* OSRCloneGeogCS() */
/************************************************************************/
/**
* \brief Make a duplicate of the GEOGCS node of this OGRSpatialReference object.
*
* This function is the same as OGRSpatialReference::CloneGeogCS().
*/
OGRSpatialReferenceH CPL_STDCALL OSRCloneGeogCS( OGRSpatialReferenceH hSource )
{
VALIDATE_POINTER1( hSource, "OSRCloneGeogCS", NULL );
return (OGRSpatialReferenceH)
((OGRSpatialReference *) hSource)->CloneGeogCS();
}
/************************************************************************/
/* IsSameGeogCS() */
/************************************************************************/
/**
* \brief Do the GeogCS'es match?
*
* This method is the same as the C function OSRIsSameGeogCS().
*
* @param poOther the SRS being compared against.
*
* @return TRUE if they are the same or FALSE otherwise.
*/
int OGRSpatialReference::IsSameGeogCS( const OGRSpatialReference *poOther ) const
{
const char *pszThisValue, *pszOtherValue;
/* -------------------------------------------------------------------- */
/* Does the datum name match? Note that we assume */
/* compatibility if either is missing a datum. */
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "DATUM" );
pszOtherValue = poOther->GetAttrValue( "DATUM" );
if( pszThisValue != NULL && pszOtherValue != NULL
&& !EQUAL(pszThisValue,pszOtherValue) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Do the datum TOWGS84 values match if present? */
/* -------------------------------------------------------------------- */
double adfTOWGS84[7], adfOtherTOWGS84[7];
int i;
this->GetTOWGS84( adfTOWGS84, 7 );
poOther->GetTOWGS84( adfOtherTOWGS84, 7 );
for( i = 0; i < 7; i++ )
{
if( fabs(adfTOWGS84[i] - adfOtherTOWGS84[i]) > 0.00001 )
return FALSE;
}
/* -------------------------------------------------------------------- */
/* Do the prime meridians match? If missing assume a value of zero.*/
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "PRIMEM", 1 );
if( pszThisValue == NULL )
pszThisValue = "0.0";
pszOtherValue = poOther->GetAttrValue( "PRIMEM", 1 );
if( pszOtherValue == NULL )
pszOtherValue = "0.0";
if( CPLAtof(pszOtherValue) != CPLAtof(pszThisValue) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Do the units match? */
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "GEOGCS|UNIT", 1 );
if( pszThisValue == NULL )
pszThisValue = SRS_UA_DEGREE_CONV;
pszOtherValue = poOther->GetAttrValue( "GEOGCS|UNIT", 1 );
if( pszOtherValue == NULL )
pszOtherValue = SRS_UA_DEGREE_CONV;
if( ABS(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
return FALSE;
/* -------------------------------------------------------------------- */
/* Does the spheroid match. Check semi major, and inverse */
/* flattening. */
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "SPHEROID", 1 );
pszOtherValue = poOther->GetAttrValue( "SPHEROID", 1 );
if( pszThisValue != NULL && pszOtherValue != NULL
&& ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.01 )
return FALSE;
pszThisValue = this->GetAttrValue( "SPHEROID", 2 );
pszOtherValue = poOther->GetAttrValue( "SPHEROID", 2 );
if( pszThisValue != NULL && pszOtherValue != NULL
&& ABS(CPLAtof(pszThisValue) - CPLAtof(pszOtherValue)) > 0.0001 )
return FALSE;
return TRUE;
}
/************************************************************************/
/* OSRIsSameGeogCS() */
/************************************************************************/
/**
* \brief Do the GeogCS'es match?
*
* This function is the same as OGRSpatialReference::IsSameGeogCS().
*/
int OSRIsSameGeogCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
{
VALIDATE_POINTER1( hSRS1, "OSRIsSameGeogCS", 0 );
VALIDATE_POINTER1( hSRS2, "OSRIsSameGeogCS", 0 );
return ((OGRSpatialReference *) hSRS1)->IsSameGeogCS(
(OGRSpatialReference *) hSRS2 );
}
/************************************************************************/
/* IsSameVertCS() */
/************************************************************************/
/**
* \brief Do the VertCS'es match?
*
* This method is the same as the C function OSRIsSameVertCS().
*
* @param poOther the SRS being compared against.
*
* @return TRUE if they are the same or FALSE otherwise.
*/
int OGRSpatialReference::IsSameVertCS( const OGRSpatialReference *poOther ) const
{
const char *pszThisValue, *pszOtherValue;
/* -------------------------------------------------------------------- */
/* Does the datum name match? */
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "VERT_DATUM" );
pszOtherValue = poOther->GetAttrValue( "VERT_DATUM" );
if( pszThisValue == NULL || pszOtherValue == NULL
|| !EQUAL(pszThisValue, pszOtherValue) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Do the units match? */
/* -------------------------------------------------------------------- */
pszThisValue = this->GetAttrValue( "VERT_CS|UNIT", 1 );
if( pszThisValue == NULL )
pszThisValue = "1.0";
pszOtherValue = poOther->GetAttrValue( "VERT_CS|UNIT", 1 );
if( pszOtherValue == NULL )
pszOtherValue = "1.0";
if( ABS(CPLAtof(pszOtherValue) - CPLAtof(pszThisValue)) > 0.00000001 )
return FALSE;
return TRUE;
}
/************************************************************************/
/* OSRIsSameVertCS() */
/************************************************************************/
/**
* \brief Do the VertCS'es match?
*
* This function is the same as OGRSpatialReference::IsSameVertCS().
*/
int OSRIsSameVertCS( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
{
VALIDATE_POINTER1( hSRS1, "OSRIsSameVertCS", 0 );
VALIDATE_POINTER1( hSRS2, "OSRIsSameVertCS", 0 );
return ((OGRSpatialReference *) hSRS1)->IsSameVertCS(
(OGRSpatialReference *) hSRS2 );
}
/************************************************************************/
/* IsSame() */
/************************************************************************/
/**
* \brief Do these two spatial references describe the same system ?
*
* @param poOtherSRS the SRS being compared to.
*
* @return TRUE if equivalent or FALSE otherwise.
*/
int OGRSpatialReference::IsSame( const OGRSpatialReference * poOtherSRS ) const
{
if( GetRoot() == NULL && poOtherSRS->GetRoot() == NULL )
return TRUE;
else if( GetRoot() == NULL || poOtherSRS->GetRoot() == NULL )
return FALSE;
/* -------------------------------------------------------------------- */
/* Compare geographic coordinate system. */
/* -------------------------------------------------------------------- */
if( !IsSameGeogCS( poOtherSRS ) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Do the have the same root types? Ie. is one PROJCS and one */
/* GEOGCS or perhaps LOCALCS? */
/* -------------------------------------------------------------------- */
if( !EQUAL(GetRoot()->GetValue(),poOtherSRS->GetRoot()->GetValue()) )
return FALSE;
/* -------------------------------------------------------------------- */
/* Compare projected coordinate system. */
/* -------------------------------------------------------------------- */
if( IsProjected() )
{
const char *pszValue1, *pszValue2;
const OGR_SRSNode *poPROJCS = GetAttrNode( "PROJCS" );
pszValue1 = this->GetAttrValue( "PROJECTION" );
pszValue2 = poOtherSRS->GetAttrValue( "PROJECTION" );
if( pszValue1 == NULL || pszValue2 == NULL
|| !EQUAL(pszValue1,pszValue2) )
return FALSE;
for( int iChild = 0; iChild < poPROJCS->GetChildCount(); iChild++ )
{
const OGR_SRSNode *poNode;
poNode = poPROJCS->GetChild( iChild );
if( !EQUAL(poNode->GetValue(),"PARAMETER")
|| poNode->GetChildCount() != 2 )
continue;
/* this this eventually test within some epsilon? */
if( this->GetProjParm( poNode->GetChild(0)->GetValue() )
!= poOtherSRS->GetProjParm( poNode->GetChild(0)->GetValue() ) )
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* If they are LOCALCS/PROJCS, do they have the same units? */
/* -------------------------------------------------------------------- */
if( IsLocal() || IsProjected() )
{
if( GetLinearUnits() != 0.0 )
{
double dfRatio;
dfRatio = poOtherSRS->GetLinearUnits() / GetLinearUnits();
if( dfRatio < 0.9999999999 || dfRatio > 1.000000001 )
return FALSE;
}
}
/* -------------------------------------------------------------------- */
/* Compare vertical coordinate system. */
/* -------------------------------------------------------------------- */
if( IsVertical() && !IsSameVertCS( poOtherSRS ) )
return FALSE;
return TRUE;
}
/************************************************************************/
/* OSRIsSame() */
/************************************************************************/
/**
* \brief Do these two spatial references describe the same system ?
*
* This function is the same as OGRSpatialReference::IsSame().
*/
int OSRIsSame( OGRSpatialReferenceH hSRS1, OGRSpatialReferenceH hSRS2 )
{
VALIDATE_POINTER1( hSRS1, "OSRIsSame", 0 );
VALIDATE_POINTER1( hSRS2, "OSRIsSame", 0 );
return ((OGRSpatialReference *) hSRS1)->IsSame(
(OGRSpatialReference *) hSRS2 );
}
/************************************************************************/
/* SetTOWGS84() */
/************************************************************************/
/**
* \brief Set the Bursa-Wolf conversion to WGS84.
*
* This will create the TOWGS84 node as a child of the DATUM. It will fail
* if there is no existing DATUM node. Unlike most OGRSpatialReference
* methods it will insert itself in the appropriate order, and will replace
* an existing TOWGS84 node if there is one.
*
* The parameters have the same meaning as EPSG transformation 9606
* (Position Vector 7-param. transformation).
*
* This method is the same as the C function OSRSetTOWGS84().
*
* @param dfDX X child in meters.
* @param dfDY Y child in meters.
* @param dfDZ Z child in meters.
* @param dfEX X rotation in arc seconds (optional, defaults to zero).
* @param dfEY Y rotation in arc seconds (optional, defaults to zero).
* @param dfEZ Z rotation in arc seconds (optional, defaults to zero).
* @param dfPPM scaling factor (parts per million).
*
* @return OGRERR_NONE on success.
*/
OGRErr OGRSpatialReference::SetTOWGS84( double dfDX, double dfDY, double dfDZ,
double dfEX, double dfEY, double dfEZ,
double dfPPM )
{
OGR_SRSNode *poDatum, *poTOWGS84;
int iPosition;
char szValue[64];
poDatum = GetAttrNode( "DATUM" );
if( poDatum == NULL )
return OGRERR_FAILURE;
if( poDatum->FindChild( "TOWGS84" ) != -1 )
poDatum->DestroyChild( poDatum->FindChild( "TOWGS84" ) );
iPosition = poDatum->GetChildCount();
if( poDatum->FindChild("AUTHORITY") != -1 )
{
iPosition = poDatum->FindChild("AUTHORITY");
}
poTOWGS84 = new OGR_SRSNode("TOWGS84");
OGRPrintDouble( szValue, dfDX );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfDY );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfDZ );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfEX );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfEY );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfEZ );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
OGRPrintDouble( szValue, dfPPM );
poTOWGS84->AddChild( new OGR_SRSNode( szValue ) );
poDatum->InsertChild( poTOWGS84, iPosition );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetTOWGS84() */
/************************************************************************/
/**
* \brief Set the Bursa-Wolf conversion to WGS84.
*
* This function is the same as OGRSpatialReference::SetTOWGS84().
*/
OGRErr OSRSetTOWGS84( OGRSpatialReferenceH hSRS,
double dfDX, double dfDY, double dfDZ,
double dfEX, double dfEY, double dfEZ,
double dfPPM )
{
VALIDATE_POINTER1( hSRS, "OSRSetTOWGS84", CE_Failure );
return ((OGRSpatialReference *) hSRS)->SetTOWGS84( dfDX, dfDY, dfDZ,
dfEX, dfEY, dfEZ,
dfPPM );
}
/************************************************************************/
/* GetTOWGS84() */
/************************************************************************/
/**
* \brief Fetch TOWGS84 parameters, if available.
*
* @param padfCoeff array into which up to 7 coefficients are placed.
* @param nCoeffCount size of padfCoeff - defaults to 7.
*
* @return OGRERR_NONE on success, or OGRERR_FAILURE if there is no
* TOWGS84 node available.
*/
OGRErr OGRSpatialReference::GetTOWGS84( double * padfCoeff,
int nCoeffCount ) const
{
const OGR_SRSNode *poNode = GetAttrNode( "TOWGS84" );
memset( padfCoeff, 0, sizeof(double) * nCoeffCount );
if( poNode == NULL )
return OGRERR_FAILURE;
for( int i = 0; i < nCoeffCount && i < poNode->GetChildCount(); i++ )
{
padfCoeff[i] = CPLAtof(poNode->GetChild(i)->GetValue());
}
return OGRERR_NONE;
}
/************************************************************************/
/* OSRGetTOWGS84() */
/************************************************************************/
/**
* \brief Fetch TOWGS84 parameters, if available.
*
* This function is the same as OGRSpatialReference::GetTOWGS84().
*/
OGRErr OSRGetTOWGS84( OGRSpatialReferenceH hSRS,
double * padfCoeff, int nCoeffCount )
{
VALIDATE_POINTER1( hSRS, "OSRGetTOWGS84", CE_Failure );
return ((OGRSpatialReference *) hSRS)->GetTOWGS84( padfCoeff, nCoeffCount);
}
/************************************************************************/
/* IsAngularParameter() */
/* */
/* Is the passed projection parameter an angular one? */
/************************************************************************/
int OGRSpatialReference::IsAngularParameter( const char *pszParameterName )
{
if( EQUALN(pszParameterName,"long",4)
|| EQUALN(pszParameterName,"lati",4)
|| EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN)
|| EQUALN(pszParameterName,"standard_parallel",17)
|| EQUAL(pszParameterName,SRS_PP_AZIMUTH)
|| EQUAL(pszParameterName,SRS_PP_RECTIFIED_GRID_ANGLE) )
return TRUE;
else
return FALSE;
}
/************************************************************************/
/* IsLongitudeParameter() */
/* */
/* Is the passed projection parameter an angular longitude */
/* (relative to a prime meridian)? */
/************************************************************************/
int OGRSpatialReference::IsLongitudeParameter( const char *pszParameterName )
{
if( EQUALN(pszParameterName,"long",4)
|| EQUAL(pszParameterName,SRS_PP_CENTRAL_MERIDIAN) )
return TRUE;
else
return FALSE;
}
/************************************************************************/
/* IsLinearParameter() */
/* */
/* Is the passed projection parameter an linear one measured in */
/* meters or some similar linear measure. */
/************************************************************************/
int OGRSpatialReference::IsLinearParameter( const char *pszParameterName )
{
if( EQUALN(pszParameterName,"false_",6)
|| EQUAL(pszParameterName,SRS_PP_SATELLITE_HEIGHT) )
return TRUE;
else
return FALSE;
}
/************************************************************************/
/* GetNormInfo() */
/************************************************************************/
/**
* \brief Set the internal information for normalizing linear, and angular values.
*/
void OGRSpatialReference::GetNormInfo(void) const
{
if( bNormInfoSet )
return;
/* -------------------------------------------------------------------- */
/* Initialize values. */
/* -------------------------------------------------------------------- */
OGRSpatialReference *poThis = (OGRSpatialReference *) this;
poThis->bNormInfoSet = TRUE;
poThis->dfFromGreenwich = GetPrimeMeridian(NULL);
poThis->dfToMeter = GetLinearUnits(NULL);
poThis->dfToDegrees = GetAngularUnits(NULL) / CPLAtof(SRS_UA_DEGREE_CONV);
if( fabs(poThis->dfToDegrees-1.0) < 0.000000001 )
poThis->dfToDegrees = 1.0;
}
/************************************************************************/
/* FixupOrdering() */
/************************************************************************/
/**
* \brief Correct parameter ordering to match CT Specification.
*
* Some mechanisms to create WKT using OGRSpatialReference, and some
* imported WKT fail to maintain the order of parameters required according
* to the BNF definitions in the OpenGIS SF-SQL and CT Specifications. This
* method attempts to massage things back into the required order.
*
* This method is the same as the C function OSRFixupOrdering().
*
* @return OGRERR_NONE on success or an error code if something goes
* wrong.
*/
OGRErr OGRSpatialReference::FixupOrdering()
{
if( GetRoot() != NULL )
return GetRoot()->FixupOrdering();
else
return OGRERR_NONE;
}
/************************************************************************/
/* OSRFixupOrdering() */
/************************************************************************/
/**
* \brief Correct parameter ordering to match CT Specification.
*
* This function is the same as OGRSpatialReference::FixupOrdering().
*/
OGRErr OSRFixupOrdering( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRFixupOrdering", CE_Failure );
return ((OGRSpatialReference *) hSRS)->FixupOrdering();
}
/************************************************************************/
/* Fixup() */
/************************************************************************/
/**
* \brief Fixup as needed.
*
* Some mechanisms to create WKT using OGRSpatialReference, and some
* imported WKT, are not valid according to the OGC CT specification. This
* method attempts to fill in any missing defaults that are required, and
* fixup ordering problems (using OSRFixupOrdering()) so that the resulting
* WKT is valid.
*
* This method should be expected to evolve over time to as problems are
* discovered. The following are amoung the fixup actions this method will
* take:
*
* - Fixup the ordering of nodes to match the BNF WKT ordering, using
* the FixupOrdering() method.
*
* - Add missing linear or angular units nodes.
*
* This method is the same as the C function OSRFixup().
*
* @return OGRERR_NONE on success or an error code if something goes
* wrong.
*/
OGRErr OGRSpatialReference::Fixup()
{
/* -------------------------------------------------------------------- */
/* Ensure linear units defaulted to METER if missing for PROJCS, */
/* GEOCCS or LOCAL_CS. */
/* -------------------------------------------------------------------- */
const OGR_SRSNode *poCS = GetAttrNode( "PROJCS" );
if( poCS == NULL )
poCS = GetAttrNode( "LOCAL_CS" );
if( poCS == NULL )
poCS = GetAttrNode( "GEOCCS" );
if( poCS != NULL && poCS->FindChild( "UNIT" ) == -1 )
SetLinearUnits( SRS_UL_METER, 1.0 );
/* -------------------------------------------------------------------- */
/* Ensure angular units defaulted to degrees on the GEOGCS. */
/* -------------------------------------------------------------------- */
poCS = GetAttrNode( "GEOGCS" );
if( poCS != NULL && poCS->FindChild( "UNIT" ) == -1 )
SetAngularUnits( SRS_UA_DEGREE, CPLAtof(SRS_UA_DEGREE_CONV) );
return FixupOrdering();
}
/************************************************************************/
/* OSRFixup() */
/************************************************************************/
/**
* \brief Fixup as needed.
*
* This function is the same as OGRSpatialReference::Fixup().
*/
OGRErr OSRFixup( OGRSpatialReferenceH hSRS )
{
VALIDATE_POINTER1( hSRS, "OSRFixup", CE_Failure );
return ((OGRSpatialReference *) hSRS)->Fixup();
}
/************************************************************************/
/* GetExtension() */
/************************************************************************/
/**
* \brief Fetch extension value.
*
* Fetch the value of the named EXTENSION item for the identified
* target node.
*
* @param pszTargetKey the name or path to the parent node of the EXTENSION.
* @param pszName the name of the extension being fetched.
* @param pszDefault the value to return if the extension is not found.
*
* @return node value if successful or pszDefault on failure.
*/
const char *OGRSpatialReference::GetExtension( const char *pszTargetKey,
const char *pszName,
const char *pszDefault ) const
{
/* -------------------------------------------------------------------- */
/* Find the target node. */
/* -------------------------------------------------------------------- */
const OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Fetch matching EXTENSION if there is one. */
/* -------------------------------------------------------------------- */
for( int i = poNode->GetChildCount()-1; i >= 0; i-- )
{
const OGR_SRSNode *poChild = poNode->GetChild(i);
if( EQUAL(poChild->GetValue(),"EXTENSION")
&& poChild->GetChildCount() >= 2 )
{
if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
return poChild->GetChild(1)->GetValue();
}
}
return pszDefault;
}
/************************************************************************/
/* SetExtension() */
/************************************************************************/
/**
* \brief Set extension value.
*
* Set the value of the named EXTENSION item for the identified
* target node.
*
* @param pszTargetKey the name or path to the parent node of the EXTENSION.
* @param pszName the name of the extension being fetched.
* @param pszValue the value to set
*
* @return OGRERR_NONE on success
*/
OGRErr OGRSpatialReference::SetExtension( const char *pszTargetKey,
const char *pszName,
const char *pszValue )
{
/* -------------------------------------------------------------------- */
/* Find the target node. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* Fetch matching EXTENSION if there is one. */
/* -------------------------------------------------------------------- */
for( int i = poNode->GetChildCount()-1; i >= 0; i-- )
{
OGR_SRSNode *poChild = poNode->GetChild(i);
if( EQUAL(poChild->GetValue(),"EXTENSION")
&& poChild->GetChildCount() >= 2 )
{
if( EQUAL(poChild->GetChild(0)->GetValue(),pszName) )
{
poChild->GetChild(1)->SetValue( pszValue );
return OGRERR_NONE;
}
}
}
/* -------------------------------------------------------------------- */
/* Create a new EXTENSION node. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poAuthNode;
poAuthNode = new OGR_SRSNode( "EXTENSION" );
poAuthNode->AddChild( new OGR_SRSNode( pszName ) );
poAuthNode->AddChild( new OGR_SRSNode( pszValue ) );
poNode->AddChild( poAuthNode );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRCleanup() */
/************************************************************************/
CPL_C_START
void CleanupESRIDatumMappingTable();
CPL_C_END
static void CleanupSRSWGS84Thread();
/**
* \brief Cleanup cached SRS related memory.
*
* This function will attempt to cleanup any cache spatial reference
* related information, such as cached tables of coordinate systems.
*/
void OSRCleanup( void )
{
CleanupESRIDatumMappingTable();
CSVDeaccess( NULL );
OCTCleanupProjMutex();
CleanupSRSWGS84Thread();
}
/************************************************************************/
/* GetAxis() */
/************************************************************************/
/**
* \brief Fetch the orientation of one axis.
*
* Fetches the the request axis (iAxis - zero based) from the
* indicated portion of the coordinate system (pszTargetKey) which
* should be either "GEOGCS" or "PROJCS".
*
* No CPLError is issued on routine failures (such as not finding the AXIS).
*
* This method is equivalent to the C function OSRGetAxis().
*
* @param pszTargetKey the coordinate system part to query ("PROJCS" or "GEOGCS").
* @param iAxis the axis to query (0 for first, 1 for second).
* @param peOrientation location into which to place the fetch orientation, may be NULL.
*
* @return the name of the axis or NULL on failure.
*/
const char *
OGRSpatialReference::GetAxis( const char *pszTargetKey, int iAxis,
OGRAxisOrientation *peOrientation ) const
{
if( peOrientation != NULL )
*peOrientation = OAO_Other;
/* -------------------------------------------------------------------- */
/* Find the target node. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return NULL;
/* -------------------------------------------------------------------- */
/* Find desired child AXIS. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poAxis = NULL;
int iChild, nChildCount = poNode->GetChildCount();
for( iChild = 0; iChild < nChildCount; iChild++ )
{
OGR_SRSNode *poChild = poNode->GetChild( iChild );
if( !EQUAL(poChild->GetValue(),"AXIS") )
continue;
if( iAxis == 0 )
{
poAxis = poChild;
break;
}
iAxis--;
}
if( poAxis == NULL )
return NULL;
if( poAxis->GetChildCount() < 2 )
return NULL;
/* -------------------------------------------------------------------- */
/* Extract name and orientation if possible. */
/* -------------------------------------------------------------------- */
if( peOrientation != NULL )
{
const char *pszOrientation = poAxis->GetChild(1)->GetValue();
if( EQUAL(pszOrientation,"NORTH") )
*peOrientation = OAO_North;
else if( EQUAL(pszOrientation,"EAST") )
*peOrientation = OAO_East;
else if( EQUAL(pszOrientation,"SOUTH") )
*peOrientation = OAO_South;
else if( EQUAL(pszOrientation,"WEST") )
*peOrientation = OAO_West;
else if( EQUAL(pszOrientation,"UP") )
*peOrientation = OAO_Up;
else if( EQUAL(pszOrientation,"DOWN") )
*peOrientation = OAO_Down;
else if( EQUAL(pszOrientation,"OTHER") )
*peOrientation = OAO_Other;
else
{
CPLDebug( "OSR", "Unrecognised orientation value '%s'.",
pszOrientation );
}
}
return poAxis->GetChild(0)->GetValue();
}
/************************************************************************/
/* OSRGetAxis() */
/************************************************************************/
/**
* \brief Fetch the orientation of one axis.
*
* This method is the equivalent of the C++ method OGRSpatialReference::GetAxis
*/
const char *OSRGetAxis( OGRSpatialReferenceH hSRS,
const char *pszTargetKey, int iAxis,
OGRAxisOrientation *peOrientation )
{
VALIDATE_POINTER1( hSRS, "OSRGetAxis", NULL );
return ((OGRSpatialReference *) hSRS)->GetAxis( pszTargetKey, iAxis,
peOrientation );
}
/************************************************************************/
/* OSRAxisEnumToName() */
/************************************************************************/
/**
* \brief Return the string representation for the OGRAxisOrientation enumeration.
*
* For example "NORTH" for OAO_North.
*
* @return an internal string
*/
const char *OSRAxisEnumToName( OGRAxisOrientation eOrientation )
{
if( eOrientation == OAO_North )
return "NORTH";
if( eOrientation == OAO_East )
return "EAST";
if( eOrientation == OAO_South )
return "SOUTH";
if( eOrientation == OAO_West )
return "WEST";
if( eOrientation == OAO_Up )
return "UP";
if( eOrientation == OAO_Down )
return "DOWN";
if( eOrientation == OAO_Other )
return "OTHER";
return "UNKNOWN";
}
/************************************************************************/
/* SetAxes() */
/************************************************************************/
/**
* \brief Set the axes for a coordinate system.
*
* Set the names, and orientations of the axes for either a projected
* (PROJCS) or geographic (GEOGCS) coordinate system.
*
* This method is equivalent to the C function OSRSetAxes().
*
* @param pszTargetKey either "PROJCS" or "GEOGCS", must already exist in SRS.
* @param pszXAxisName name of first axis, normally "Long" or "Easting".
* @param eXAxisOrientation normally OAO_East.
* @param pszYAxisName name of second axis, normally "Lat" or "Northing".
* @param eYAxisOrientation normally OAO_North.
*
* @return OGRERR_NONE on success or an error code.
*/
OGRErr
OGRSpatialReference::SetAxes( const char *pszTargetKey,
const char *pszXAxisName,
OGRAxisOrientation eXAxisOrientation,
const char *pszYAxisName,
OGRAxisOrientation eYAxisOrientation )
{
/* -------------------------------------------------------------------- */
/* Find the target node. */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poNode;
if( pszTargetKey == NULL )
poNode = poRoot;
else
poNode= ((OGRSpatialReference *) this)->GetAttrNode( pszTargetKey );
if( poNode == NULL )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* Strip any existing AXIS children. */
/* -------------------------------------------------------------------- */
while( poNode->FindChild( "AXIS" ) >= 0 )
poNode->DestroyChild( poNode->FindChild( "AXIS" ) );
/* -------------------------------------------------------------------- */
/* Insert desired axes */
/* -------------------------------------------------------------------- */
OGR_SRSNode *poAxis = new OGR_SRSNode( "AXIS" );
poAxis->AddChild( new OGR_SRSNode( pszXAxisName ) );
poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(eXAxisOrientation) ));
poNode->AddChild( poAxis );
poAxis = new OGR_SRSNode( "AXIS" );
poAxis->AddChild( new OGR_SRSNode( pszYAxisName ) );
poAxis->AddChild( new OGR_SRSNode( OSRAxisEnumToName(eYAxisOrientation) ));
poNode->AddChild( poAxis );
return OGRERR_NONE;
}
/************************************************************************/
/* OSRSetAxes() */
/************************************************************************/
/**
* \brief Set the axes for a coordinate system.
*
* This method is the equivalent of the C++ method OGRSpatialReference::SetAxes
*/
OGRErr OSRSetAxes( OGRSpatialReferenceH hSRS,
const char *pszTargetKey,
const char *pszXAxisName,
OGRAxisOrientation eXAxisOrientation,
const char *pszYAxisName,
OGRAxisOrientation eYAxisOrientation )
{
VALIDATE_POINTER1( hSRS, "OSRSetAxes", OGRERR_FAILURE );
return ((OGRSpatialReference *) hSRS)->SetAxes( pszTargetKey,
pszXAxisName,
eXAxisOrientation,
pszYAxisName,
eYAxisOrientation );
}
#ifdef HAVE_MITAB
char CPL_DLL *MITABSpatialRef2CoordSys( OGRSpatialReference * );
OGRSpatialReference CPL_DLL * MITABCoordSys2SpatialRef( const char * );
#endif
/************************************************************************/
/* OSRExportToMICoordSys() */
/************************************************************************/
/**
* \brief Export coordinate system in Mapinfo style CoordSys format.
*
* This method is the equivalent of the C++ method OGRSpatialReference::exportToMICoordSys
*/
OGRErr OSRExportToMICoordSys( OGRSpatialReferenceH hSRS, char ** ppszReturn )
{
VALIDATE_POINTER1( hSRS, "OSRExportToMICoordSys", CE_Failure );
*ppszReturn = NULL;
return ((OGRSpatialReference *) hSRS)->exportToMICoordSys( ppszReturn );
}
/************************************************************************/
/* exportToMICoordSys() */
/************************************************************************/
/**
* \brief Export coordinate system in Mapinfo style CoordSys format.
*
* Note that the returned WKT string should be freed with OGRFree() or
* CPLFree() when no longer needed. It is the responsibility of the caller.
*
* This method is the same as the C function OSRExportToMICoordSys().
*
* @param ppszResult pointer to which dynamically allocated Mapinfo CoordSys
* definition will be assigned.
*
* @return OGRERR_NONE on success, OGRERR_FAILURE on failure,
* OGRERR_UNSUPPORTED_OPERATION if MITAB library was not linked in.
*/
OGRErr OGRSpatialReference::exportToMICoordSys( char **ppszResult ) const
{
#ifdef HAVE_MITAB
*ppszResult = MITABSpatialRef2CoordSys( (OGRSpatialReference *) this );
if( *ppszResult != NULL && strlen(*ppszResult) > 0 )
return OGRERR_NONE;
else
return OGRERR_FAILURE;
#else
CPLError( CE_Failure, CPLE_NotSupported,
"MITAB not available, CoordSys support disabled." );
return OGRERR_UNSUPPORTED_OPERATION;
#endif
}
/************************************************************************/
/* OSRImportFromMICoordSys() */
/************************************************************************/
/**
* \brief Import Mapinfo style CoordSys definition.
*
* This method is the equivalent of the C++ method OGRSpatialReference::importFromMICoordSys
*/
OGRErr OSRImportFromMICoordSys( OGRSpatialReferenceH hSRS,
const char *pszCoordSys )
{
VALIDATE_POINTER1( hSRS, "OSRImportFromMICoordSys", CE_Failure );
return ((OGRSpatialReference *)hSRS)->importFromMICoordSys( pszCoordSys );
}
/************************************************************************/
/* importFromMICoordSys() */
/************************************************************************/
/**
* \brief Import Mapinfo style CoordSys definition.
*
* The OGRSpatialReference is initialized from the passed Mapinfo style CoordSys definition string.
*
* This method is the equivalent of the C function OSRImportFromMICoordSys().
*
* @param pszCoordSys Mapinfo style CoordSys definition string.
*
* @return OGRERR_NONE on success, OGRERR_FAILURE on failure,
* OGRERR_UNSUPPORTED_OPERATION if MITAB library was not linked in.
*/
OGRErr OGRSpatialReference::importFromMICoordSys( const char *pszCoordSys )
{
#ifdef HAVE_MITAB
OGRSpatialReference *poResult = MITABCoordSys2SpatialRef( pszCoordSys );
if( poResult == NULL )
return OGRERR_FAILURE;
*this = *poResult;
delete poResult;
return OGRERR_NONE;
#else
CPLError( CE_Failure, CPLE_NotSupported,
"MITAB not available, CoordSys support disabled." );
return OGRERR_UNSUPPORTED_OPERATION;
#endif
}
/************************************************************************/
/* OSRCalcInvFlattening() */
/************************************************************************/
/**
* \brief Compute inverse flattening from semi-major and semi-minor axis
*
* @param dfSemiMajor Semi-major axis length.
* @param dfSemiMinor Semi-minor axis length.
*
* @return inverse flattening, or 0 if both axis are equal.
* @since GDAL 2.0
*/
double OSRCalcInvFlattening( double dfSemiMajor, double dfSemiMinor )
{
if( fabs(dfSemiMajor-dfSemiMinor) < 1e-1 )
return 0;
else if( dfSemiMajor <= 0 || dfSemiMinor <= 0 || dfSemiMinor > dfSemiMajor )
{
CPLError(CE_Failure, CPLE_IllegalArg,
"OSRCalcInvFlattening(): Wrong input values");
return 0;
}
else
return dfSemiMajor / (dfSemiMajor - dfSemiMinor);
}
/************************************************************************/
/* OSRCalcInvFlattening() */
/************************************************************************/
/**
* \brief Compute semi-minor axis from semi-major axis and inverse flattening.
*
* @param dfSemiMajor Semi-major axis length.
* @param dfInvFlattening Inverse flattening or 0 for sphere.
*
* @return semi-minor axis
* @since GDAL 2.0
*/
double OSRCalcSemiMinorFromInvFlattening( double dfSemiMajor, double dfInvFlattening )
{
if( fabs(dfInvFlattening) < 0.000000000001 )
return dfSemiMajor;
else if( dfSemiMajor <= 0.0 || dfInvFlattening <= 1.0 )
{
CPLError(CE_Failure, CPLE_IllegalArg,
"OSRCalcSemiMinorFromInvFlattening(): Wrong input values");
return dfSemiMajor;
}
else
return dfSemiMajor * (1.0 - 1.0/dfInvFlattening);
}
/************************************************************************/
/* GetWGS84SRS() */
/************************************************************************/
static OGRSpatialReference* poSRSWGS84 = NULL;
static CPLMutex* hMutex = NULL;
/**
* \brief Returns an instance of a SRS object with WGS84 WKT.
*
* The reference counter of the returned object is not increased by this operation.
*
* @return instance.
* @since GDAL 2.0
*/
OGRSpatialReference* OGRSpatialReference::GetWGS84SRS()
{
CPLMutexHolderD(&hMutex);
if( poSRSWGS84 == NULL )
poSRSWGS84 = new OGRSpatialReference(SRS_WKT_WGS84);
return poSRSWGS84;
}
/************************************************************************/
/* CleanupSRSWGS84Thread() */
/************************************************************************/
static void CleanupSRSWGS84Thread()
{
if( hMutex != NULL )
{
poSRSWGS84->Release();
poSRSWGS84 = NULL;
CPLDestroyMutex(hMutex);
hMutex = NULL;
}
}