/gdal-1.9.1-fedora/ogr/ogr_srs_xml.cpp
C++ | 1336 lines | 744 code | 274 blank | 318 comment | 178 complexity | 99c67a4515223960699104003b8d65bc MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /******************************************************************************
- * $Id: ogr_srs_xml.cpp 16587 2009-03-15 00:09:42Z rouault $
- *
- * Project: OpenGIS Simple Features Reference Implementation
- * Purpose: OGRSpatialReference interface to OGC XML (014r4).
- * Author: Frank Warmerdam, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2001, Frank Warmerdam (warmerdam@pobox.com)
- *
- * 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_minixml.h"
- #include "cpl_multiproc.h"
- /************************************************************************/
- /* parseURN() */
- /* */
- /* Parses requested sections out of URN. The passed in URN */
- /* *is* altered but the returned values point into the */
- /* original string. */
- /************************************************************************/
- static int parseURN( char *pszURN,
- const char **ppszObjectType,
- const char **ppszAuthority,
- const char **ppszCode,
- const char **ppszVersion = NULL )
- {
- int i;
- if( ppszObjectType != NULL )
- *ppszObjectType = "";
- if( ppszAuthority != NULL )
- *ppszAuthority = "";
- if( ppszCode != NULL )
- *ppszCode = "";
- if( ppszVersion != NULL )
- *ppszVersion = "";
- /* -------------------------------------------------------------------- */
- /* Verify prefix. */
- /* -------------------------------------------------------------------- */
- if( !EQUALN(pszURN,"urn:ogc:def:",12) )
- return FALSE;
- /* -------------------------------------------------------------------- */
- /* Extract object type */
- /* -------------------------------------------------------------------- */
- if( ppszObjectType != NULL )
- *ppszObjectType = (const char *) pszURN + 12;
- i = 12;
- while( pszURN[i] != ':' && pszURN[i] != '\0' )
- i++;
- if( pszURN[i] == '\0' )
- return FALSE;
- pszURN[i] = '\0';
- i++;
- /* -------------------------------------------------------------------- */
- /* Extract authority */
- /* -------------------------------------------------------------------- */
- if( ppszAuthority != NULL )
- *ppszAuthority = (char *) pszURN + i;
- while( pszURN[i] != ':' && pszURN[i] != '\0' )
- i++;
- if( pszURN[i] == '\0' )
- return FALSE;
- pszURN[i] = '\0';
- i++;
- /* -------------------------------------------------------------------- */
- /* Extract version */
- /* -------------------------------------------------------------------- */
- if( ppszVersion != NULL )
- *ppszVersion = (char *) pszURN + i;
- while( pszURN[i] != ':' && pszURN[i] != '\0' )
- i++;
- if( pszURN[i] == '\0' )
- return FALSE;
- pszURN[i] = '\0';
- i++;
- /* -------------------------------------------------------------------- */
- /* Extract code. */
- /* -------------------------------------------------------------------- */
- if( ppszCode != NULL )
- *ppszCode = (char *) pszURN + i;
-
- return TRUE;
- }
- /************************************************************************/
- /* addURN() */
- /************************************************************************/
- static void addURN( CPLXMLNode *psTarget,
- const char *pszAuthority,
- const char *pszObjectType,
- int nCode,
- const char *pszVersion = "" )
- {
- char szURN[200];
- if( pszVersion == NULL )
- pszVersion = "";
- CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
- sprintf( szURN, "urn:ogc:def:%s:%s:%s:",
- pszObjectType, pszAuthority, pszVersion );
-
- if( nCode != 0 )
- sprintf( szURN + strlen(szURN), "%d", nCode );
-
- CPLCreateXMLNode(
- CPLCreateXMLNode( psTarget, CXT_Attribute, "xlink:href" ),
- CXT_Text, szURN );
- }
- /************************************************************************/
- /* AddValueIDWithURN() */
- /* */
- /* Adds element of the form <ElementName */
- /* xlink:href="urn_without_id">id</ElementName>" */
- /************************************************************************/
- static CPLXMLNode *
- AddValueIDWithURN( CPLXMLNode *psTarget,
- const char *pszElement,
- const char *pszAuthority,
- const char *pszObjectType,
- int nCode,
- const char *pszVersion = "" )
-
- {
- CPLXMLNode *psElement;
- psElement = CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
- addURN( psElement, pszAuthority, pszObjectType, nCode, pszVersion );
- return psElement;
- }
- /************************************************************************/
- /* addAuthorityIDBlock() */
- /* */
- /* Creates a structure like: */
- /* <srsId> */
- /* <name codeSpace="urn">code</name> */
- /* </srsId> */
- /************************************************************************/
- static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
- const char *pszElement,
- const char *pszAuthority,
- const char *pszObjectType,
- int nCode,
- const char *pszVersion = "" )
- {
- char szURN[200];
- /* -------------------------------------------------------------------- */
- /* Prepare partial URN without the actual code. */
- /* -------------------------------------------------------------------- */
- if( pszVersion == NULL )
- pszVersion = "";
- CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
- sprintf( szURN, "urn:ogc:def:%s:%s:%s:",
- pszObjectType, pszAuthority, pszVersion );
-
- /* -------------------------------------------------------------------- */
- /* Prepare the base name, eg. <srsID>. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psElement =
- CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
- /* -------------------------------------------------------------------- */
- /* Prepare the name element. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode * psName =
- CPLCreateXMLNode( psElement, CXT_Element, "gml:name" );
- /* -------------------------------------------------------------------- */
- /* Prepare the codespace attribute. */
- /* -------------------------------------------------------------------- */
- CPLCreateXMLNode(
- CPLCreateXMLNode( psName, CXT_Attribute, "gml:codeSpace" ),
- CXT_Text, szURN );
- /* -------------------------------------------------------------------- */
- /* Attach code value to name node. */
- /* -------------------------------------------------------------------- */
- char szCode[32];
- sprintf( szCode, "%d", nCode );
- CPLCreateXMLNode( psName, CXT_Text, szCode );
- return psElement;
- }
-
- /************************************************************************/
- /* addGMLId() */
- /************************************************************************/
- static void addGMLId( CPLXMLNode *psParent )
- {
- static void *hGMLIdMutex = NULL;
- CPLMutexHolderD( &hGMLIdMutex );
- CPLXMLNode *psId;
- static int nNextGMLId = 1;
- char szIdText[40];
- sprintf( szIdText, "ogrcrs%d", nNextGMLId++ );
-
- psId =
- CPLCreateXMLNode(
- CPLCreateXMLNode( psParent, CXT_Attribute, "gml:id" ),
- CXT_Text, szIdText );
- }
- /************************************************************************/
- /* exportAuthorityToXML() */
- /************************************************************************/
- static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
- const char *pszTagName,
- CPLXMLNode *psXMLParent,
- const char *pszObjectType,
- int bUseSubName = TRUE )
- {
- const OGR_SRSNode *poAuthority;
- /* -------------------------------------------------------------------- */
- /* Get authority node from parent. */
- /* -------------------------------------------------------------------- */
- if( poAuthParent->FindChild( "AUTHORITY" ) == -1 )
- return NULL;
- poAuthority = poAuthParent->GetChild(
- poAuthParent->FindChild( "AUTHORITY" ));
- /* -------------------------------------------------------------------- */
- /* Create identification. */
- /* -------------------------------------------------------------------- */
- const char *pszCode, *pszCodeSpace, *pszEdition;
- pszCode = poAuthority->GetChild(1)->GetValue();
- pszCodeSpace = poAuthority->GetChild(0)->GetValue();
- pszEdition = NULL;
- if( bUseSubName )
- return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace,
- pszObjectType, atoi(pszCode), pszEdition );
- else
- return AddValueIDWithURN( psXMLParent, pszTagName, pszCodeSpace,
- pszObjectType, atoi(pszCode), pszEdition );
-
- }
- /************************************************************************/
- /* addProjArg() */
- /************************************************************************/
- static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
- const char *pszMeasureType, double dfDefault,
- int nParameterID, const char *pszWKTName )
- {
- CPLXMLNode *psNode, *psValue;
- psNode = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesParameterValue" );
- /* -------------------------------------------------------------------- */
- /* Handle the UOM. */
- /* -------------------------------------------------------------------- */
- const char *pszUOMValue;
- if( EQUAL(pszMeasureType,"Angular") )
- pszUOMValue = "urn:ogc:def:uom:EPSG::9102";
- else
- pszUOMValue = "urn:ogc:def:uom:EPSG::9001";
- psValue = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
- CPLCreateXMLNode(
- CPLCreateXMLNode( psValue, CXT_Attribute, "gml:uom" ),
- CXT_Text, pszUOMValue );
-
- /* -------------------------------------------------------------------- */
- /* Add the parameter value itself. */
- /* -------------------------------------------------------------------- */
- double dfParmValue
- = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
-
- CPLCreateXMLNode( psValue, CXT_Text,
- CPLString().Printf( "%.16g", dfParmValue ) );
- /* -------------------------------------------------------------------- */
- /* Add the valueOfParameter. */
- /* -------------------------------------------------------------------- */
- AddValueIDWithURN( psNode, "gml:valueOfParameter", "EPSG", "parameter",
- nParameterID );
- }
- /************************************************************************/
- /* addAxis() */
- /* */
- /* Added the <usesAxis> element and down. */
- /************************************************************************/
- static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
- const char *pszAxis, // "Lat", "Long", "E" or "N"
- const OGR_SRSNode * /* poUnitsSrc */ )
- {
- CPLXMLNode *psAxisXML;
- psAxisXML =
- CPLCreateXMLNode(
- CPLCreateXMLNode( psXMLParent, CXT_Element, "gml:usesAxis" ),
- CXT_Element, "gml:CoordinateSystemAxis" );
- addGMLId( psAxisXML );
- if( EQUAL(pszAxis,"Lat") )
- {
- CPLCreateXMLNode(
- CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
- CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
- "Geodetic latitude" );
- addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9901 );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lat" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
- }
- else if( EQUAL(pszAxis,"Long") )
- {
- CPLCreateXMLNode(
- CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
- CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
- "Geodetic longitude" );
- addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9902 );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lon" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
- }
- else if( EQUAL(pszAxis,"E") )
- {
- CPLCreateXMLNode(
- CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
- CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Easting" );
- addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9906 );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "E" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
- }
- else if( EQUAL(pszAxis,"N") )
- {
- CPLCreateXMLNode(
- CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
- CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Northing" );
- addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9907 );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "N" );
- CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
- }
- else
- {
- CPLAssert( FALSE );
- }
- return psAxisXML;
- }
- /************************************************************************/
- /* exportGeogCSToXML() */
- /************************************************************************/
- static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
- {
- CPLXMLNode *psGCS_XML;
- const OGR_SRSNode *poGeogCS = poSRS->GetAttrNode( "GEOGCS" );
- if( poGeogCS == NULL )
- return NULL;
-
- /* -------------------------------------------------------------------- */
- /* Establish initial infrastructure. */
- /* -------------------------------------------------------------------- */
- psGCS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
- addGMLId( psGCS_XML );
-
- /* -------------------------------------------------------------------- */
- /* Attach symbolic name (srsName). */
- /* -------------------------------------------------------------------- */
- CPLCreateXMLElementAndValue( psGCS_XML, "gml:srsName",
- poGeogCS->GetChild(0)->GetValue() );
- /* -------------------------------------------------------------------- */
- /* Does the overall coordinate system have an authority? If so */
- /* attach as an identification section. */
- /* -------------------------------------------------------------------- */
- exportAuthorityToXML( poGeogCS, "gml:srsID", psGCS_XML, "crs" );
- /* -------------------------------------------------------------------- */
- /* Insert a big whack of fixed stuff defining the */
- /* ellipsoidalCS. Basically this defines the axes and their */
- /* units. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psECS;
- psECS = CPLCreateXMLNode(
- CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
- CXT_Element, "gml:EllipsoidalCS" );
- addGMLId( psECS );
- CPLCreateXMLElementAndValue( psECS, "gml:csName", "ellipsoidal" );
- addAuthorityIDBlock( psECS, "gml:csID", "EPSG", "cs", 6402 );
- addAxis( psECS, "Lat", NULL );
- addAxis( psECS, "Long", NULL );
- /* -------------------------------------------------------------------- */
- /* Start with the datum. */
- /* -------------------------------------------------------------------- */
- const OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
- CPLXMLNode *psDatumXML;
- if( poDatum == NULL )
- {
- CPLDestroyXMLNode( psGCS_XML );
- return NULL;
- }
- psDatumXML = CPLCreateXMLNode(
- CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
- CXT_Element, "gml:GeodeticDatum" );
-
- addGMLId( psDatumXML );
- /* -------------------------------------------------------------------- */
- /* Set the datumName. */
- /* -------------------------------------------------------------------- */
- CPLCreateXMLElementAndValue( psDatumXML, "gml:datumName",
- poDatum->GetChild(0)->GetValue() );
- /* -------------------------------------------------------------------- */
- /* Set authority id info if available. */
- /* -------------------------------------------------------------------- */
- exportAuthorityToXML( poDatum, "gml:datumID", psDatumXML, "datum" );
- /* -------------------------------------------------------------------- */
- /* Setup prime meridian information. */
- /* -------------------------------------------------------------------- */
- const OGR_SRSNode *poPMNode = poGeogCS->GetNode( "PRIMEM" );
- CPLXMLNode *psPM;
- char *pszPMName = (char* ) "Greenwich";
- double dfPMOffset = poSRS->GetPrimeMeridian( &pszPMName );
- psPM = CPLCreateXMLNode(
- CPLCreateXMLNode( psDatumXML, CXT_Element, "gml:usesPrimeMeridian" ),
- CXT_Element, "gml:PrimeMeridian" );
- addGMLId( psPM );
- CPLCreateXMLElementAndValue( psPM, "gml:meridianName", pszPMName );
- if( poPMNode )
- exportAuthorityToXML( poPMNode, "gml:meridianID", psPM, "meridian" );
- CPLXMLNode *psAngle;
- psAngle =
- CPLCreateXMLNode(
- CPLCreateXMLNode( psPM, CXT_Element, "gml:greenwichLongitude" ),
- CXT_Element, "gml:angle" );
-
- CPLCreateXMLNode( CPLCreateXMLNode( psAngle, CXT_Attribute, "gml:uom" ),
- CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
- CPLCreateXMLNode( psAngle, CXT_Text,
- CPLString().Printf( "%.16g", dfPMOffset ) );
-
- /* -------------------------------------------------------------------- */
- /* Translate the ellipsoid. */
- /* -------------------------------------------------------------------- */
- const OGR_SRSNode *poEllipsoid = poDatum->GetNode( "SPHEROID" );
- if( poEllipsoid != NULL )
- {
- CPLXMLNode *psEllipseXML;
- psEllipseXML =
- CPLCreateXMLNode(
- CPLCreateXMLNode(psDatumXML,CXT_Element,"gml:usesEllipsoid" ),
- CXT_Element, "gml:Ellipsoid" );
- addGMLId( psEllipseXML );
- CPLCreateXMLElementAndValue( psEllipseXML, "gml:ellipsoidName",
- poEllipsoid->GetChild(0)->GetValue() );
- exportAuthorityToXML( poEllipsoid, "gml:ellipsoidID", psEllipseXML,
- "ellipsoid");
-
- CPLXMLNode *psParmXML;
- psParmXML = CPLCreateXMLNode( psEllipseXML, CXT_Element,
- "gml:semiMajorAxis" );
- CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
- CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
- CPLCreateXMLNode( psParmXML, CXT_Text,
- poEllipsoid->GetChild(1)->GetValue() );
- psParmXML =
- CPLCreateXMLNode(
- CPLCreateXMLNode( psEllipseXML, CXT_Element,
- "gml:secondDefiningParameter" ),
- CXT_Element, "gml:inverseFlattening" );
-
- CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
- CXT_Text, "urn:ogc:def:uom:EPSG::9201" );
- CPLCreateXMLNode( psParmXML, CXT_Text,
- poEllipsoid->GetChild(2)->GetValue() );
- }
- return psGCS_XML;
- }
- /************************************************************************/
- /* exportProjCSToXML() */
- /************************************************************************/
- static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
- {
- const OGR_SRSNode *poProjCS = poSRS->GetAttrNode( "PROJCS" );
- if( poProjCS == NULL )
- return NULL;
-
- /* -------------------------------------------------------------------- */
- /* Establish initial infrastructure. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psCRS_XML;
- psCRS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
- addGMLId( psCRS_XML );
-
- /* -------------------------------------------------------------------- */
- /* Attach symbolic name (a name in a nameset). */
- /* -------------------------------------------------------------------- */
- CPLCreateXMLElementAndValue( psCRS_XML, "gml:srsName",
- poProjCS->GetChild(0)->GetValue() );
- /* -------------------------------------------------------------------- */
- /* Add authority info if we have it. */
- /* -------------------------------------------------------------------- */
- exportAuthorityToXML( poProjCS, "gml:srsID", psCRS_XML, "crs" );
- /* -------------------------------------------------------------------- */
- /* Use the GEOGCS as a <baseCRS> */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psBaseCRSXML =
- CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:baseCRS" );
- CPLAddXMLChild( psBaseCRSXML, exportGeogCSToXML( poSRS ) );
- /* -------------------------------------------------------------------- */
- /* Our projected coordinate system is "defined by Conversion". */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psDefinedBy;
- psDefinedBy = CPLCreateXMLNode( psCRS_XML, CXT_Element,
- "gml:definedByConversion" );
-
- /* -------------------------------------------------------------------- */
- /* Projections are handled as ParameterizedTransformations. */
- /* -------------------------------------------------------------------- */
- const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
- CPLXMLNode *psConv;
- psConv = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
- addGMLId( psConv );
- /* -------------------------------------------------------------------- */
- /* Transverse Mercator */
- /* -------------------------------------------------------------------- */
- if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
- {
- AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
- 9807 );
- addProjArg( poSRS, psConv, "Angular", 0.0,
- 8801, SRS_PP_LATITUDE_OF_ORIGIN );
- addProjArg( poSRS, psConv, "Angular", 0.0,
- 8802, SRS_PP_CENTRAL_MERIDIAN );
- addProjArg( poSRS, psConv, "Unitless", 1.0,
- 8805, SRS_PP_SCALE_FACTOR );
- addProjArg( poSRS, psConv, "Linear", 0.0,
- 8806, SRS_PP_FALSE_EASTING );
- addProjArg( poSRS, psConv, "Linear", 0.0,
- 8807, SRS_PP_FALSE_NORTHING );
- }
- /* -------------------------------------------------------------------- */
- /* Lambert Conformal Conic */
- /* -------------------------------------------------------------------- */
- else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
- {
- AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
- 9801 );
- addProjArg( poSRS, psConv, "Angular", 0.0,
- 8801, SRS_PP_LATITUDE_OF_ORIGIN );
- addProjArg( poSRS, psConv, "Angular", 0.0,
- 8802, SRS_PP_CENTRAL_MERIDIAN );
- addProjArg( poSRS, psConv, "Unitless", 1.0,
- 8805, SRS_PP_SCALE_FACTOR );
- addProjArg( poSRS, psConv, "Linear", 0.0,
- 8806, SRS_PP_FALSE_EASTING );
- addProjArg( poSRS, psConv, "Linear", 0.0,
- 8807, SRS_PP_FALSE_NORTHING );
- }
- /* -------------------------------------------------------------------- */
- /* Define the cartesian coordinate system. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psCCS;
- psCCS =
- CPLCreateXMLNode(
- CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:usesCartesianCS" ),
- CXT_Element, "gml:CartesianCS" );
- addGMLId( psCCS );
- CPLCreateXMLElementAndValue( psCCS, "gml:csName", "Cartesian" );
- addAuthorityIDBlock( psCCS, "gml:csID", "EPSG", "cs", 4400 );
- addAxis( psCCS, "E", NULL );
- addAxis( psCCS, "N", NULL );
- return psCRS_XML;
- }
- /************************************************************************/
- /* exportToXML() */
- /************************************************************************/
- /**
- * \brief Export coordinate system in XML format.
- *
- * Converts the loaded coordinate reference system into XML format
- * to the extent possible. The string returned in ppszRawXML should be
- * deallocated by the caller with CPLFree() when no longer needed.
- *
- * LOCAL_CS coordinate systems are not translatable. An empty string
- * will be returned along with OGRERR_NONE.
- *
- * This method is the equivelent of the C function OSRExportToXML().
- *
- * @param ppszRawXML pointer to which dynamically allocated XML definition
- * will be assigned.
- * @param pszDialect currently ignored. The dialect used is GML based.
- *
- * @return OGRERR_NONE on success or an error code on failure.
- */
- OGRErr OGRSpatialReference::exportToXML( char **ppszRawXML,
- const char * pszDialect ) const
- {
- CPLXMLNode *psXMLTree = NULL;
- if( IsGeographic() )
- {
- psXMLTree = exportGeogCSToXML( this );
- }
- else if( IsProjected() )
- {
- psXMLTree = exportProjCSToXML( this );
- }
- else
- return OGRERR_UNSUPPORTED_SRS;
- *ppszRawXML = CPLSerializeXMLTree( psXMLTree );
- CPLDestroyXMLNode( psXMLTree );
- return OGRERR_NONE;
- }
- /************************************************************************/
- /* OSRExportToXML() */
- /************************************************************************/
- /**
- * \brief Export coordinate system in XML format.
- *
- * This function is the same as OGRSpatialReference::exportToXML().
- */
- OGRErr OSRExportToXML( OGRSpatialReferenceH hSRS, char **ppszRawXML,
- const char *pszDialect )
- {
- VALIDATE_POINTER1( hSRS, "OSRExportToXML", CE_Failure );
- return ((OGRSpatialReference *) hSRS)->exportToXML( ppszRawXML,
- pszDialect );
- }
- #ifdef notdef
- /************************************************************************/
- /* importXMLUnits() */
- /************************************************************************/
- static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
- OGRSpatialReference *poSRS, const char *pszTarget)
- {
- const char *pszUnitName, *pszUnitsPer;
- OGR_SRSNode *poNode = poSRS->GetAttrNode( pszTarget );
- OGR_SRSNode *poUnits;
- CPLAssert( EQUAL(pszClass,"AngularUnit")
- || EQUAL(pszClass,"LinearUnit") );
-
- psSrcXML = CPLGetXMLNode( psSrcXML, pszClass );
- if( psSrcXML == NULL )
- goto DefaultTarget;
- pszUnitName = CPLGetXMLValue( psSrcXML, "NameSet.name", "unnamed" );
- if( EQUAL(pszClass,"AngularUnit") )
- pszUnitsPer = CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL );
- else
- pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
-
- if( pszUnitsPer == NULL )
- {
- CPLDebug( "OGR_SRS_XML",
- "Missing PerUnit value for %s.",
- pszClass );
- goto DefaultTarget;
- }
-
- if( poNode == NULL )
- {
- CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.",
- pszTarget );
- goto DefaultTarget;
- }
- if( poNode->FindChild("UNIT") != -1 )
- {
- poUnits = poNode->GetChild( poNode->FindChild( "UNIT" ) );
- poUnits->GetChild(0)->SetValue( pszUnitName );
- poUnits->GetChild(1)->SetValue( pszUnitsPer );
- }
- else
- {
- poUnits = new OGR_SRSNode( "UNIT" );
- poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
- poUnits->AddChild( new OGR_SRSNode( pszUnitsPer ) );
-
- poNode->AddChild( poUnits );
- }
- return;
- DefaultTarget:
- poUnits = new OGR_SRSNode( "UNIT" );
- if( EQUAL(pszClass,"AngularUnit") )
- {
- poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE ) );
- poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE_CONV ) );
- }
- else
- {
- poUnits->AddChild( new OGR_SRSNode( SRS_UL_METER ) );
- poUnits->AddChild( new OGR_SRSNode( "1.0" ) );
- }
- poNode->AddChild( poUnits );
- }
- #endif
- /************************************************************************/
- /* importXMLAuthority() */
- /************************************************************************/
- static void importXMLAuthority( CPLXMLNode *psSrcXML,
- OGRSpatialReference *poSRS,
- const char *pszSourceKey,
- const char *pszTargetKey )
- {
- CPLXMLNode *psIDNode = CPLGetXMLNode( psSrcXML, pszSourceKey );
- CPLXMLNode *psNameNode = CPLGetXMLNode( psIDNode, "name" );
- CPLXMLNode *psCodeSpace = CPLGetXMLNode( psNameNode, "codeSpace" );
- const char *pszAuthority, *pszCode;
- char *pszURN;
- int nCode = 0;
- if( psIDNode == NULL || psNameNode == NULL || psCodeSpace == NULL )
- return;
- pszURN = CPLStrdup(CPLGetXMLValue( psCodeSpace, "", "" ));
- if( !parseURN( pszURN, NULL, &pszAuthority, &pszCode ) )
- {
- CPLFree( pszURN );
- return;
- }
- if( strlen(pszCode) == 0 )
- pszCode = (char *) CPLGetXMLValue( psNameNode, "", "" );
- if( pszCode != NULL )
- nCode = atoi(pszCode);
- if( nCode != 0 )
- poSRS->SetAuthority( pszTargetKey, pszAuthority, nCode );
- CPLFree( pszURN );
- }
- /************************************************************************/
- /* ParseOGCDefURN() */
- /* */
- /* Parse out fields from a URN of the form: */
- /* urn:ogc:def:parameter:EPSG:6.3:9707 */
- /************************************************************************/
- static int ParseOGCDefURN( const char *pszURN,
- CPLString *poObjectType,
- CPLString *poAuthority,
- CPLString *poVersion,
- CPLString *poValue )
- {
- if( poObjectType != NULL )
- *poObjectType = "";
- if( poAuthority != NULL )
- *poAuthority = "";
- if( poVersion != NULL )
- *poVersion = "";
- if( poValue != NULL )
- *poValue = "";
- if( pszURN == NULL || !EQUALN(pszURN,"urn:ogc:def:",12) )
- return FALSE;
- char **papszTokens = CSLTokenizeStringComplex( pszURN + 12, ":",
- FALSE, TRUE );
- if( CSLCount(papszTokens) != 4 )
- {
- CSLDestroy( papszTokens );
- return FALSE;
- }
- if( poObjectType != NULL )
- *poObjectType = papszTokens[0];
- if( poAuthority != NULL )
- *poAuthority = papszTokens[1];
- if( poVersion != NULL )
- *poVersion = papszTokens[2];
- if( poValue != NULL )
- *poValue = papszTokens[3];
- CSLDestroy( papszTokens );
- return TRUE;
- }
- /************************************************************************/
- /* getEPSGObjectCodeValue() */
- /* */
- /* Fetch a code value from the indicated node. Should work on */
- /* something of the form <elem xlink:href="urn:...:n" /> or */
- /* something of the form <elem xlink:href="urn:...:">n</a>. */
- /************************************************************************/
- static int getEPSGObjectCodeValue( CPLXMLNode *psNode,
- const char *pszEPSGObjectType, /*"method" */
- int nDefault )
- {
- if( psNode == NULL )
- return nDefault;
-
- CPLString osObjectType, osAuthority, osValue;
- const char* pszHrefVal;
-
- pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
- if (pszHrefVal == NULL)
- pszHrefVal = CPLGetXMLValue( psNode, "href", NULL );
-
- if( !ParseOGCDefURN( pszHrefVal,
- &osObjectType, &osAuthority, NULL, &osValue ) )
- return nDefault;
- if( !EQUAL(osAuthority,"EPSG")
- || !EQUAL(osObjectType, pszEPSGObjectType) )
- return nDefault;
- if( strlen(osValue) > 0 )
- return atoi(osValue);
- const char *pszValue = CPLGetXMLValue( psNode, "", NULL);
- if( pszValue != NULL )
- return atoi(pszValue);
- else
- return nDefault;
- }
- /************************************************************************/
- /* getProjectionParm() */
- /************************************************************************/
- static double getProjectionParm( CPLXMLNode *psRootNode,
- int nParameterCode,
- const char * /*pszMeasureType */,
- double dfDefault )
- {
- CPLXMLNode *psUsesParameter;
- for( psUsesParameter = psRootNode->psChild;
- psUsesParameter != NULL;
- psUsesParameter = psUsesParameter->psNext )
- {
- if( psUsesParameter->eType != CXT_Element )
- continue;
- if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue")
- && !EQUAL(psUsesParameter->pszValue,"usesValue") )
- continue;
- if( getEPSGObjectCodeValue( CPLGetXMLNode(psUsesParameter,
- "valueOfParameter"),
- "parameter", 0 ) == nParameterCode )
- {
- const char *pszValue = CPLGetXMLValue( psUsesParameter, "value",
- NULL );
- if( pszValue != NULL )
- return atof(pszValue);
- else
- return dfDefault;
- }
- }
- return dfDefault;
- }
- /************************************************************************/
- /* getNormalizedValue() */
- /* */
- /* Parse a node to get it's numerical value, and then normalize */
- /* into meters of degrees depending on the measure type. */
- /************************************************************************/
- static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
- const char * /*pszMeasure*/,
- double dfDefault )
- {
- CPLXMLNode *psTargetNode;
- CPLXMLNode *psValueNode;
- if( pszPath == NULL || strlen(pszPath) == 0 )
- psTargetNode = psNode;
- else
- psTargetNode = CPLGetXMLNode( psNode, pszPath );
-
- if( psTargetNode == NULL )
- return dfDefault;
- for( psValueNode = psTargetNode->psChild;
- psValueNode != NULL && psValueNode->eType != CXT_Text;
- psValueNode = psValueNode->psNext ) {}
- if( psValueNode == NULL )
- return dfDefault;
-
- // Add normalization later.
- return atof(psValueNode->pszValue);
- }
- /************************************************************************/
- /* importGeogCSFromXML() */
- /************************************************************************/
- static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
- CPLXMLNode *psCRS )
- {
- const char *pszGeogName, *pszDatumName, *pszEllipsoidName, *pszPMName;
- double dfSemiMajor, dfInvFlattening, dfPMOffset = 0.0;
- /* -------------------------------------------------------------------- */
- /* Set the GEOGCS name from the srsName. */
- /* -------------------------------------------------------------------- */
- pszGeogName =
- CPLGetXMLValue( psCRS, "srsName", "Unnamed GeogCS" );
- /* -------------------------------------------------------------------- */
- /* If we don't seem to have a detailed coordinate system */
- /* definition, check if we can define based on an EPSG code. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psDatum;
- psDatum = CPLGetXMLNode( psCRS, "usesGeodeticDatum.GeodeticDatum" );
- if( psDatum == NULL )
- {
- OGRSpatialReference oIdSRS;
- oIdSRS.SetLocalCS( "dummy" );
- importXMLAuthority( psCRS, &oIdSRS, "srsID", "LOCAL_CS" );
- if( oIdSRS.GetAuthorityCode( "LOCAL_CS" ) != NULL
- && oIdSRS.GetAuthorityName( "LOCAL_CS" ) != NULL
- && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"),"EPSG") )
- {
- return poSRS->importFromEPSG(
- atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")) );
- }
- }
- /* -------------------------------------------------------------------- */
- /* Get datum name. */
- /* -------------------------------------------------------------------- */
- pszDatumName =
- CPLGetXMLValue( psDatum, "datumName", "Unnamed Datum" );
- /* -------------------------------------------------------------------- */
- /* Get ellipsoid information. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psE;
- psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
- pszEllipsoidName =
- CPLGetXMLValue( psE, "ellipsoidName", "Unnamed Ellipsoid" );
- dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear",
- SRS_WGS84_SEMIMAJOR );
- dfInvFlattening =
- getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening",
- "Unitless", 0.0 );
- if( dfInvFlattening == 0.0 )
- {
- CPLError( CE_Failure, CPLE_AppDefined,
- "Ellipsoid inverseFlattening corrupt or missing." );
- return OGRERR_CORRUPT_DATA;
- }
- /* -------------------------------------------------------------------- */
- /* Get the prime meridian. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psPM;
- psPM = CPLGetXMLNode( psDatum, "usesPrimeMeridian.PrimeMeridian" );
- if( psPM == NULL )
- {
- pszPMName = "Greenwich";
- dfPMOffset = 0.0;
- }
- else
- {
- pszPMName = CPLGetXMLValue( psPM, "meridianName",
- "Unnamed Prime Meridian");
- dfPMOffset =
- getNormalizedValue( psPM, "greenwichLongitude.angle",
- "Angular", 0.0 );
- }
- /* -------------------------------------------------------------------- */
- /* Set the geographic definition. */
- /* -------------------------------------------------------------------- */
- poSRS->SetGeogCS( pszGeogName, pszDatumName,
- pszEllipsoidName, dfSemiMajor, dfInvFlattening,
- pszPMName, dfPMOffset );
- /* -------------------------------------------------------------------- */
- /* Look for angular units. We don't check that all axes match */
- /* at this time. */
- /* -------------------------------------------------------------------- */
- #ifdef notdef
- CPLXMLNode *psAxis;
- psAxis = CPLGetXMLNode( psGeo2DCRS,
- "EllipsoidalCoordinateSystem.CoordinateAxis" );
- importXMLUnits( psAxis, "AngularUnit", poSRS, "GEOGCS" );
- #endif
- /* -------------------------------------------------------------------- */
- /* Can we set authorities for any of the levels? */
- /* -------------------------------------------------------------------- */
- importXMLAuthority( psCRS, poSRS, "srsID", "GEOGCS" );
- importXMLAuthority( psDatum, poSRS, "datumID", "GEOGCS|DATUM" );
- importXMLAuthority( psE, poSRS, "ellipsoidID",
- "GEOGCS|DATUM|SPHEROID" );
- importXMLAuthority( psDatum, poSRS,
- "usesPrimeMeridian.PrimeMeridian.meridianID",
- "GEOGCS|PRIMEM" );
- poSRS->Fixup();
-
- return OGRERR_NONE;
- }
- /************************************************************************/
- /* importProjCSFromXML() */
- /************************************************************************/
- static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
- CPLXMLNode *psCRS )
- {
- CPLXMLNode *psSubXML;
- OGRErr eErr;
- /* -------------------------------------------------------------------- */
- /* Setup the PROJCS node with a name. */
- /* -------------------------------------------------------------------- */
- poSRS->SetProjCS( CPLGetXMLValue( psCRS, "srsName", "Unnamed" ) );
- /* -------------------------------------------------------------------- */
- /* Get authority information if available. If we got it, and */
- /* we seem to be lacking inline definition values, try and */
- /* define according to the EPSG code for the PCS. */
- /* -------------------------------------------------------------------- */
- importXMLAuthority( psCRS, poSRS, "srsID", "PROJCS" );
- if( poSRS->GetAuthorityCode( "PROJCS" ) != NULL
- && poSRS->GetAuthorityName( "PROJCS" ) != NULL
- && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG")
- && (CPLGetXMLNode( psCRS, "definedByConversion.Conversion" ) == NULL
- || CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" ) == NULL) )
- {
- return poSRS->importFromEPSG( atoi(poSRS->GetAuthorityCode("PROJCS")) );
- }
- /* -------------------------------------------------------------------- */
- /* Try to set the GEOGCS info. */
- /* -------------------------------------------------------------------- */
-
- psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
- if( psSubXML != NULL )
- {
- eErr = importGeogCSFromXML( poSRS, psSubXML );
- if( eErr != OGRERR_NONE )
- return eErr;
- }
- /* -------------------------------------------------------------------- */
- /* Get the conversion node. It should be the only child of the */
- /* definedByConversion node. */
- /* -------------------------------------------------------------------- */
- CPLXMLNode *psConv = NULL;
- psConv = CPLGetXMLNode( psCRS, "definedByConversion.Conversion" );
- if( psConv == NULL || psConv->eType != CXT_Element )
- {
- CPLError( CE_Failure, CPLE_AppDefined,
- "Unable to find a conversion node under the definedByConversion\n"
- "node of the ProjectedCRS." );
- return OGRERR_CORRUPT_DATA;
- }
- /* -------------------------------------------------------------------- */
- /* Determine the conversion method in effect. */
- /* -------------------------------------------------------------------- */
- int nMethod = getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
- "method", 0 );
-
- /* -------------------------------------------------------------------- */
- /* Transverse Mercator. */
- /* -------------------------------------------------------------------- */
- if( nMethod == 9807 )
- {
- poSRS->SetTM(
- getProjectionParm( psConv, 8801, "Angular", 0.0 ),
- getProjectionParm( psConv, 8802, "Angular", 0.0 ),
- getProjectionParm( psConv, 8805, "Unitless", 1.0 ),
- getProjectionParm( psConv, 8806, "Linear", 0.0 ),
- getProjectionParm( psConv, 8807, "Linear", 0.0 ) );
- }
- /* -------------------------------------------------------------------- */
- /* Didn't recognise? */
- /* -------------------------------------------------------------------- */
- else
- {
- CPLError( CE_Failure, CPLE_AppDefined,
- "Conversion method %d not recognised.",
- nMethod );
- return OGRERR_CORRUPT_DATA;
- }
- /* -------------------------------------------------------------------- */
- /* Cleanup and return. */
- /* -------------------------------------------------------------------- */
- poSRS->Fixup();
- // Need to get linear units here!
- return OGRERR_NONE;
- }
- /************************************************************************/
- /* importFromXML() */
- /************************************************************************/
- /**
- * \brief Import coordinate system from XML format (GML only currently).
- *
- * This method is the same as the C function OSRImportFromXML()
- * @param pszXML XML string to import
- * @return OGRERR_NONE on success or OGRERR_CORRUPT_DATA on failure.
- */
- OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
- {
- CPLXMLNode *psTree;
- OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
- this->Clear();
-
- /* -------------------------…
Large files files are truncated, but you can click here to view the full file