PageRenderTime 56ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/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

  1. /******************************************************************************
  2. * $Id: ogr_srs_xml.cpp 16587 2009-03-15 00:09:42Z rouault $
  3. *
  4. * Project: OpenGIS Simple Features Reference Implementation
  5. * Purpose: OGRSpatialReference interface to OGC XML (014r4).
  6. * Author: Frank Warmerdam, warmerdam@pobox.com
  7. *
  8. ******************************************************************************
  9. * Copyright (c) 2001, Frank Warmerdam (warmerdam@pobox.com)
  10. *
  11. * Permission is hereby granted, free of charge, to any person obtaining a
  12. * copy of this software and associated documentation files (the "Software"),
  13. * to deal in the Software without restriction, including without limitation
  14. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  15. * and/or sell copies of the Software, and to permit persons to whom the
  16. * Software is furnished to do so, subject to the following conditions:
  17. *
  18. * The above copyright notice and this permission notice shall be included
  19. * in all copies or substantial portions of the Software.
  20. *
  21. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  22. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  23. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  24. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  25. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  26. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27. * DEALINGS IN THE SOFTWARE.
  28. ****************************************************************************/
  29. #include "ogr_spatialref.h"
  30. #include "ogr_p.h"
  31. #include "cpl_minixml.h"
  32. #include "cpl_multiproc.h"
  33. /************************************************************************/
  34. /* parseURN() */
  35. /* */
  36. /* Parses requested sections out of URN. The passed in URN */
  37. /* *is* altered but the returned values point into the */
  38. /* original string. */
  39. /************************************************************************/
  40. static int parseURN( char *pszURN,
  41. const char **ppszObjectType,
  42. const char **ppszAuthority,
  43. const char **ppszCode,
  44. const char **ppszVersion = NULL )
  45. {
  46. int i;
  47. if( ppszObjectType != NULL )
  48. *ppszObjectType = "";
  49. if( ppszAuthority != NULL )
  50. *ppszAuthority = "";
  51. if( ppszCode != NULL )
  52. *ppszCode = "";
  53. if( ppszVersion != NULL )
  54. *ppszVersion = "";
  55. /* -------------------------------------------------------------------- */
  56. /* Verify prefix. */
  57. /* -------------------------------------------------------------------- */
  58. if( !EQUALN(pszURN,"urn:ogc:def:",12) )
  59. return FALSE;
  60. /* -------------------------------------------------------------------- */
  61. /* Extract object type */
  62. /* -------------------------------------------------------------------- */
  63. if( ppszObjectType != NULL )
  64. *ppszObjectType = (const char *) pszURN + 12;
  65. i = 12;
  66. while( pszURN[i] != ':' && pszURN[i] != '\0' )
  67. i++;
  68. if( pszURN[i] == '\0' )
  69. return FALSE;
  70. pszURN[i] = '\0';
  71. i++;
  72. /* -------------------------------------------------------------------- */
  73. /* Extract authority */
  74. /* -------------------------------------------------------------------- */
  75. if( ppszAuthority != NULL )
  76. *ppszAuthority = (char *) pszURN + i;
  77. while( pszURN[i] != ':' && pszURN[i] != '\0' )
  78. i++;
  79. if( pszURN[i] == '\0' )
  80. return FALSE;
  81. pszURN[i] = '\0';
  82. i++;
  83. /* -------------------------------------------------------------------- */
  84. /* Extract version */
  85. /* -------------------------------------------------------------------- */
  86. if( ppszVersion != NULL )
  87. *ppszVersion = (char *) pszURN + i;
  88. while( pszURN[i] != ':' && pszURN[i] != '\0' )
  89. i++;
  90. if( pszURN[i] == '\0' )
  91. return FALSE;
  92. pszURN[i] = '\0';
  93. i++;
  94. /* -------------------------------------------------------------------- */
  95. /* Extract code. */
  96. /* -------------------------------------------------------------------- */
  97. if( ppszCode != NULL )
  98. *ppszCode = (char *) pszURN + i;
  99. return TRUE;
  100. }
  101. /************************************************************************/
  102. /* addURN() */
  103. /************************************************************************/
  104. static void addURN( CPLXMLNode *psTarget,
  105. const char *pszAuthority,
  106. const char *pszObjectType,
  107. int nCode,
  108. const char *pszVersion = "" )
  109. {
  110. char szURN[200];
  111. if( pszVersion == NULL )
  112. pszVersion = "";
  113. CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
  114. sprintf( szURN, "urn:ogc:def:%s:%s:%s:",
  115. pszObjectType, pszAuthority, pszVersion );
  116. if( nCode != 0 )
  117. sprintf( szURN + strlen(szURN), "%d", nCode );
  118. CPLCreateXMLNode(
  119. CPLCreateXMLNode( psTarget, CXT_Attribute, "xlink:href" ),
  120. CXT_Text, szURN );
  121. }
  122. /************************************************************************/
  123. /* AddValueIDWithURN() */
  124. /* */
  125. /* Adds element of the form <ElementName */
  126. /* xlink:href="urn_without_id">id</ElementName>" */
  127. /************************************************************************/
  128. static CPLXMLNode *
  129. AddValueIDWithURN( CPLXMLNode *psTarget,
  130. const char *pszElement,
  131. const char *pszAuthority,
  132. const char *pszObjectType,
  133. int nCode,
  134. const char *pszVersion = "" )
  135. {
  136. CPLXMLNode *psElement;
  137. psElement = CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
  138. addURN( psElement, pszAuthority, pszObjectType, nCode, pszVersion );
  139. return psElement;
  140. }
  141. /************************************************************************/
  142. /* addAuthorityIDBlock() */
  143. /* */
  144. /* Creates a structure like: */
  145. /* <srsId> */
  146. /* <name codeSpace="urn">code</name> */
  147. /* </srsId> */
  148. /************************************************************************/
  149. static CPLXMLNode *addAuthorityIDBlock( CPLXMLNode *psTarget,
  150. const char *pszElement,
  151. const char *pszAuthority,
  152. const char *pszObjectType,
  153. int nCode,
  154. const char *pszVersion = "" )
  155. {
  156. char szURN[200];
  157. /* -------------------------------------------------------------------- */
  158. /* Prepare partial URN without the actual code. */
  159. /* -------------------------------------------------------------------- */
  160. if( pszVersion == NULL )
  161. pszVersion = "";
  162. CPLAssert( strlen(pszAuthority)+strlen(pszObjectType) < sizeof(szURN)-30 );
  163. sprintf( szURN, "urn:ogc:def:%s:%s:%s:",
  164. pszObjectType, pszAuthority, pszVersion );
  165. /* -------------------------------------------------------------------- */
  166. /* Prepare the base name, eg. <srsID>. */
  167. /* -------------------------------------------------------------------- */
  168. CPLXMLNode *psElement =
  169. CPLCreateXMLNode( psTarget, CXT_Element, pszElement );
  170. /* -------------------------------------------------------------------- */
  171. /* Prepare the name element. */
  172. /* -------------------------------------------------------------------- */
  173. CPLXMLNode * psName =
  174. CPLCreateXMLNode( psElement, CXT_Element, "gml:name" );
  175. /* -------------------------------------------------------------------- */
  176. /* Prepare the codespace attribute. */
  177. /* -------------------------------------------------------------------- */
  178. CPLCreateXMLNode(
  179. CPLCreateXMLNode( psName, CXT_Attribute, "gml:codeSpace" ),
  180. CXT_Text, szURN );
  181. /* -------------------------------------------------------------------- */
  182. /* Attach code value to name node. */
  183. /* -------------------------------------------------------------------- */
  184. char szCode[32];
  185. sprintf( szCode, "%d", nCode );
  186. CPLCreateXMLNode( psName, CXT_Text, szCode );
  187. return psElement;
  188. }
  189. /************************************************************************/
  190. /* addGMLId() */
  191. /************************************************************************/
  192. static void addGMLId( CPLXMLNode *psParent )
  193. {
  194. static void *hGMLIdMutex = NULL;
  195. CPLMutexHolderD( &hGMLIdMutex );
  196. CPLXMLNode *psId;
  197. static int nNextGMLId = 1;
  198. char szIdText[40];
  199. sprintf( szIdText, "ogrcrs%d", nNextGMLId++ );
  200. psId =
  201. CPLCreateXMLNode(
  202. CPLCreateXMLNode( psParent, CXT_Attribute, "gml:id" ),
  203. CXT_Text, szIdText );
  204. }
  205. /************************************************************************/
  206. /* exportAuthorityToXML() */
  207. /************************************************************************/
  208. static CPLXMLNode *exportAuthorityToXML( const OGR_SRSNode *poAuthParent,
  209. const char *pszTagName,
  210. CPLXMLNode *psXMLParent,
  211. const char *pszObjectType,
  212. int bUseSubName = TRUE )
  213. {
  214. const OGR_SRSNode *poAuthority;
  215. /* -------------------------------------------------------------------- */
  216. /* Get authority node from parent. */
  217. /* -------------------------------------------------------------------- */
  218. if( poAuthParent->FindChild( "AUTHORITY" ) == -1 )
  219. return NULL;
  220. poAuthority = poAuthParent->GetChild(
  221. poAuthParent->FindChild( "AUTHORITY" ));
  222. /* -------------------------------------------------------------------- */
  223. /* Create identification. */
  224. /* -------------------------------------------------------------------- */
  225. const char *pszCode, *pszCodeSpace, *pszEdition;
  226. pszCode = poAuthority->GetChild(1)->GetValue();
  227. pszCodeSpace = poAuthority->GetChild(0)->GetValue();
  228. pszEdition = NULL;
  229. if( bUseSubName )
  230. return addAuthorityIDBlock( psXMLParent, pszTagName, pszCodeSpace,
  231. pszObjectType, atoi(pszCode), pszEdition );
  232. else
  233. return AddValueIDWithURN( psXMLParent, pszTagName, pszCodeSpace,
  234. pszObjectType, atoi(pszCode), pszEdition );
  235. }
  236. /************************************************************************/
  237. /* addProjArg() */
  238. /************************************************************************/
  239. static void addProjArg( const OGRSpatialReference *poSRS, CPLXMLNode *psBase,
  240. const char *pszMeasureType, double dfDefault,
  241. int nParameterID, const char *pszWKTName )
  242. {
  243. CPLXMLNode *psNode, *psValue;
  244. psNode = CPLCreateXMLNode( psBase, CXT_Element, "gml:usesParameterValue" );
  245. /* -------------------------------------------------------------------- */
  246. /* Handle the UOM. */
  247. /* -------------------------------------------------------------------- */
  248. const char *pszUOMValue;
  249. if( EQUAL(pszMeasureType,"Angular") )
  250. pszUOMValue = "urn:ogc:def:uom:EPSG::9102";
  251. else
  252. pszUOMValue = "urn:ogc:def:uom:EPSG::9001";
  253. psValue = CPLCreateXMLNode( psNode, CXT_Element, "gml:value" );
  254. CPLCreateXMLNode(
  255. CPLCreateXMLNode( psValue, CXT_Attribute, "gml:uom" ),
  256. CXT_Text, pszUOMValue );
  257. /* -------------------------------------------------------------------- */
  258. /* Add the parameter value itself. */
  259. /* -------------------------------------------------------------------- */
  260. double dfParmValue
  261. = poSRS->GetNormProjParm( pszWKTName, dfDefault, NULL );
  262. CPLCreateXMLNode( psValue, CXT_Text,
  263. CPLString().Printf( "%.16g", dfParmValue ) );
  264. /* -------------------------------------------------------------------- */
  265. /* Add the valueOfParameter. */
  266. /* -------------------------------------------------------------------- */
  267. AddValueIDWithURN( psNode, "gml:valueOfParameter", "EPSG", "parameter",
  268. nParameterID );
  269. }
  270. /************************************************************************/
  271. /* addAxis() */
  272. /* */
  273. /* Added the <usesAxis> element and down. */
  274. /************************************************************************/
  275. static CPLXMLNode *addAxis( CPLXMLNode *psXMLParent,
  276. const char *pszAxis, // "Lat", "Long", "E" or "N"
  277. const OGR_SRSNode * /* poUnitsSrc */ )
  278. {
  279. CPLXMLNode *psAxisXML;
  280. psAxisXML =
  281. CPLCreateXMLNode(
  282. CPLCreateXMLNode( psXMLParent, CXT_Element, "gml:usesAxis" ),
  283. CXT_Element, "gml:CoordinateSystemAxis" );
  284. addGMLId( psAxisXML );
  285. if( EQUAL(pszAxis,"Lat") )
  286. {
  287. CPLCreateXMLNode(
  288. CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
  289. CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
  290. CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
  291. "Geodetic latitude" );
  292. addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9901 );
  293. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lat" );
  294. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
  295. }
  296. else if( EQUAL(pszAxis,"Long") )
  297. {
  298. CPLCreateXMLNode(
  299. CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
  300. CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
  301. CPLCreateXMLElementAndValue( psAxisXML, "gml:name",
  302. "Geodetic longitude" );
  303. addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9902 );
  304. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "Lon" );
  305. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
  306. }
  307. else if( EQUAL(pszAxis,"E") )
  308. {
  309. CPLCreateXMLNode(
  310. CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
  311. CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
  312. CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Easting" );
  313. addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9906 );
  314. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "E" );
  315. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "east" );
  316. }
  317. else if( EQUAL(pszAxis,"N") )
  318. {
  319. CPLCreateXMLNode(
  320. CPLCreateXMLNode( psAxisXML, CXT_Attribute, "gml:uom" ),
  321. CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
  322. CPLCreateXMLElementAndValue( psAxisXML, "gml:name", "Northing" );
  323. addAuthorityIDBlock( psAxisXML, "gml:axisID", "EPSG", "axis", 9907 );
  324. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisAbbrev", "N" );
  325. CPLCreateXMLElementAndValue( psAxisXML, "gml:axisDirection", "north" );
  326. }
  327. else
  328. {
  329. CPLAssert( FALSE );
  330. }
  331. return psAxisXML;
  332. }
  333. /************************************************************************/
  334. /* exportGeogCSToXML() */
  335. /************************************************************************/
  336. static CPLXMLNode *exportGeogCSToXML( const OGRSpatialReference *poSRS )
  337. {
  338. CPLXMLNode *psGCS_XML;
  339. const OGR_SRSNode *poGeogCS = poSRS->GetAttrNode( "GEOGCS" );
  340. if( poGeogCS == NULL )
  341. return NULL;
  342. /* -------------------------------------------------------------------- */
  343. /* Establish initial infrastructure. */
  344. /* -------------------------------------------------------------------- */
  345. psGCS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:GeographicCRS" );
  346. addGMLId( psGCS_XML );
  347. /* -------------------------------------------------------------------- */
  348. /* Attach symbolic name (srsName). */
  349. /* -------------------------------------------------------------------- */
  350. CPLCreateXMLElementAndValue( psGCS_XML, "gml:srsName",
  351. poGeogCS->GetChild(0)->GetValue() );
  352. /* -------------------------------------------------------------------- */
  353. /* Does the overall coordinate system have an authority? If so */
  354. /* attach as an identification section. */
  355. /* -------------------------------------------------------------------- */
  356. exportAuthorityToXML( poGeogCS, "gml:srsID", psGCS_XML, "crs" );
  357. /* -------------------------------------------------------------------- */
  358. /* Insert a big whack of fixed stuff defining the */
  359. /* ellipsoidalCS. Basically this defines the axes and their */
  360. /* units. */
  361. /* -------------------------------------------------------------------- */
  362. CPLXMLNode *psECS;
  363. psECS = CPLCreateXMLNode(
  364. CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesEllipsoidalCS" ),
  365. CXT_Element, "gml:EllipsoidalCS" );
  366. addGMLId( psECS );
  367. CPLCreateXMLElementAndValue( psECS, "gml:csName", "ellipsoidal" );
  368. addAuthorityIDBlock( psECS, "gml:csID", "EPSG", "cs", 6402 );
  369. addAxis( psECS, "Lat", NULL );
  370. addAxis( psECS, "Long", NULL );
  371. /* -------------------------------------------------------------------- */
  372. /* Start with the datum. */
  373. /* -------------------------------------------------------------------- */
  374. const OGR_SRSNode *poDatum = poGeogCS->GetNode( "DATUM" );
  375. CPLXMLNode *psDatumXML;
  376. if( poDatum == NULL )
  377. {
  378. CPLDestroyXMLNode( psGCS_XML );
  379. return NULL;
  380. }
  381. psDatumXML = CPLCreateXMLNode(
  382. CPLCreateXMLNode( psGCS_XML, CXT_Element, "gml:usesGeodeticDatum" ),
  383. CXT_Element, "gml:GeodeticDatum" );
  384. addGMLId( psDatumXML );
  385. /* -------------------------------------------------------------------- */
  386. /* Set the datumName. */
  387. /* -------------------------------------------------------------------- */
  388. CPLCreateXMLElementAndValue( psDatumXML, "gml:datumName",
  389. poDatum->GetChild(0)->GetValue() );
  390. /* -------------------------------------------------------------------- */
  391. /* Set authority id info if available. */
  392. /* -------------------------------------------------------------------- */
  393. exportAuthorityToXML( poDatum, "gml:datumID", psDatumXML, "datum" );
  394. /* -------------------------------------------------------------------- */
  395. /* Setup prime meridian information. */
  396. /* -------------------------------------------------------------------- */
  397. const OGR_SRSNode *poPMNode = poGeogCS->GetNode( "PRIMEM" );
  398. CPLXMLNode *psPM;
  399. char *pszPMName = (char* ) "Greenwich";
  400. double dfPMOffset = poSRS->GetPrimeMeridian( &pszPMName );
  401. psPM = CPLCreateXMLNode(
  402. CPLCreateXMLNode( psDatumXML, CXT_Element, "gml:usesPrimeMeridian" ),
  403. CXT_Element, "gml:PrimeMeridian" );
  404. addGMLId( psPM );
  405. CPLCreateXMLElementAndValue( psPM, "gml:meridianName", pszPMName );
  406. if( poPMNode )
  407. exportAuthorityToXML( poPMNode, "gml:meridianID", psPM, "meridian" );
  408. CPLXMLNode *psAngle;
  409. psAngle =
  410. CPLCreateXMLNode(
  411. CPLCreateXMLNode( psPM, CXT_Element, "gml:greenwichLongitude" ),
  412. CXT_Element, "gml:angle" );
  413. CPLCreateXMLNode( CPLCreateXMLNode( psAngle, CXT_Attribute, "gml:uom" ),
  414. CXT_Text, "urn:ogc:def:uom:EPSG::9102" );
  415. CPLCreateXMLNode( psAngle, CXT_Text,
  416. CPLString().Printf( "%.16g", dfPMOffset ) );
  417. /* -------------------------------------------------------------------- */
  418. /* Translate the ellipsoid. */
  419. /* -------------------------------------------------------------------- */
  420. const OGR_SRSNode *poEllipsoid = poDatum->GetNode( "SPHEROID" );
  421. if( poEllipsoid != NULL )
  422. {
  423. CPLXMLNode *psEllipseXML;
  424. psEllipseXML =
  425. CPLCreateXMLNode(
  426. CPLCreateXMLNode(psDatumXML,CXT_Element,"gml:usesEllipsoid" ),
  427. CXT_Element, "gml:Ellipsoid" );
  428. addGMLId( psEllipseXML );
  429. CPLCreateXMLElementAndValue( psEllipseXML, "gml:ellipsoidName",
  430. poEllipsoid->GetChild(0)->GetValue() );
  431. exportAuthorityToXML( poEllipsoid, "gml:ellipsoidID", psEllipseXML,
  432. "ellipsoid");
  433. CPLXMLNode *psParmXML;
  434. psParmXML = CPLCreateXMLNode( psEllipseXML, CXT_Element,
  435. "gml:semiMajorAxis" );
  436. CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
  437. CXT_Text, "urn:ogc:def:uom:EPSG::9001" );
  438. CPLCreateXMLNode( psParmXML, CXT_Text,
  439. poEllipsoid->GetChild(1)->GetValue() );
  440. psParmXML =
  441. CPLCreateXMLNode(
  442. CPLCreateXMLNode( psEllipseXML, CXT_Element,
  443. "gml:secondDefiningParameter" ),
  444. CXT_Element, "gml:inverseFlattening" );
  445. CPLCreateXMLNode( CPLCreateXMLNode(psParmXML,CXT_Attribute,"gml:uom"),
  446. CXT_Text, "urn:ogc:def:uom:EPSG::9201" );
  447. CPLCreateXMLNode( psParmXML, CXT_Text,
  448. poEllipsoid->GetChild(2)->GetValue() );
  449. }
  450. return psGCS_XML;
  451. }
  452. /************************************************************************/
  453. /* exportProjCSToXML() */
  454. /************************************************************************/
  455. static CPLXMLNode *exportProjCSToXML( const OGRSpatialReference *poSRS )
  456. {
  457. const OGR_SRSNode *poProjCS = poSRS->GetAttrNode( "PROJCS" );
  458. if( poProjCS == NULL )
  459. return NULL;
  460. /* -------------------------------------------------------------------- */
  461. /* Establish initial infrastructure. */
  462. /* -------------------------------------------------------------------- */
  463. CPLXMLNode *psCRS_XML;
  464. psCRS_XML = CPLCreateXMLNode( NULL, CXT_Element, "gml:ProjectedCRS" );
  465. addGMLId( psCRS_XML );
  466. /* -------------------------------------------------------------------- */
  467. /* Attach symbolic name (a name in a nameset). */
  468. /* -------------------------------------------------------------------- */
  469. CPLCreateXMLElementAndValue( psCRS_XML, "gml:srsName",
  470. poProjCS->GetChild(0)->GetValue() );
  471. /* -------------------------------------------------------------------- */
  472. /* Add authority info if we have it. */
  473. /* -------------------------------------------------------------------- */
  474. exportAuthorityToXML( poProjCS, "gml:srsID", psCRS_XML, "crs" );
  475. /* -------------------------------------------------------------------- */
  476. /* Use the GEOGCS as a <baseCRS> */
  477. /* -------------------------------------------------------------------- */
  478. CPLXMLNode *psBaseCRSXML =
  479. CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:baseCRS" );
  480. CPLAddXMLChild( psBaseCRSXML, exportGeogCSToXML( poSRS ) );
  481. /* -------------------------------------------------------------------- */
  482. /* Our projected coordinate system is "defined by Conversion". */
  483. /* -------------------------------------------------------------------- */
  484. CPLXMLNode *psDefinedBy;
  485. psDefinedBy = CPLCreateXMLNode( psCRS_XML, CXT_Element,
  486. "gml:definedByConversion" );
  487. /* -------------------------------------------------------------------- */
  488. /* Projections are handled as ParameterizedTransformations. */
  489. /* -------------------------------------------------------------------- */
  490. const char *pszProjection = poSRS->GetAttrValue("PROJECTION");
  491. CPLXMLNode *psConv;
  492. psConv = CPLCreateXMLNode( psDefinedBy, CXT_Element, "gml:Conversion");
  493. addGMLId( psConv );
  494. /* -------------------------------------------------------------------- */
  495. /* Transverse Mercator */
  496. /* -------------------------------------------------------------------- */
  497. if( EQUAL(pszProjection,SRS_PT_TRANSVERSE_MERCATOR) )
  498. {
  499. AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
  500. 9807 );
  501. addProjArg( poSRS, psConv, "Angular", 0.0,
  502. 8801, SRS_PP_LATITUDE_OF_ORIGIN );
  503. addProjArg( poSRS, psConv, "Angular", 0.0,
  504. 8802, SRS_PP_CENTRAL_MERIDIAN );
  505. addProjArg( poSRS, psConv, "Unitless", 1.0,
  506. 8805, SRS_PP_SCALE_FACTOR );
  507. addProjArg( poSRS, psConv, "Linear", 0.0,
  508. 8806, SRS_PP_FALSE_EASTING );
  509. addProjArg( poSRS, psConv, "Linear", 0.0,
  510. 8807, SRS_PP_FALSE_NORTHING );
  511. }
  512. /* -------------------------------------------------------------------- */
  513. /* Lambert Conformal Conic */
  514. /* -------------------------------------------------------------------- */
  515. else if( EQUAL(pszProjection, SRS_PT_LAMBERT_CONFORMAL_CONIC_1SP) )
  516. {
  517. AddValueIDWithURN( psConv, "gml:usesMethod", "EPSG", "method",
  518. 9801 );
  519. addProjArg( poSRS, psConv, "Angular", 0.0,
  520. 8801, SRS_PP_LATITUDE_OF_ORIGIN );
  521. addProjArg( poSRS, psConv, "Angular", 0.0,
  522. 8802, SRS_PP_CENTRAL_MERIDIAN );
  523. addProjArg( poSRS, psConv, "Unitless", 1.0,
  524. 8805, SRS_PP_SCALE_FACTOR );
  525. addProjArg( poSRS, psConv, "Linear", 0.0,
  526. 8806, SRS_PP_FALSE_EASTING );
  527. addProjArg( poSRS, psConv, "Linear", 0.0,
  528. 8807, SRS_PP_FALSE_NORTHING );
  529. }
  530. /* -------------------------------------------------------------------- */
  531. /* Define the cartesian coordinate system. */
  532. /* -------------------------------------------------------------------- */
  533. CPLXMLNode *psCCS;
  534. psCCS =
  535. CPLCreateXMLNode(
  536. CPLCreateXMLNode( psCRS_XML, CXT_Element, "gml:usesCartesianCS" ),
  537. CXT_Element, "gml:CartesianCS" );
  538. addGMLId( psCCS );
  539. CPLCreateXMLElementAndValue( psCCS, "gml:csName", "Cartesian" );
  540. addAuthorityIDBlock( psCCS, "gml:csID", "EPSG", "cs", 4400 );
  541. addAxis( psCCS, "E", NULL );
  542. addAxis( psCCS, "N", NULL );
  543. return psCRS_XML;
  544. }
  545. /************************************************************************/
  546. /* exportToXML() */
  547. /************************************************************************/
  548. /**
  549. * \brief Export coordinate system in XML format.
  550. *
  551. * Converts the loaded coordinate reference system into XML format
  552. * to the extent possible. The string returned in ppszRawXML should be
  553. * deallocated by the caller with CPLFree() when no longer needed.
  554. *
  555. * LOCAL_CS coordinate systems are not translatable. An empty string
  556. * will be returned along with OGRERR_NONE.
  557. *
  558. * This method is the equivelent of the C function OSRExportToXML().
  559. *
  560. * @param ppszRawXML pointer to which dynamically allocated XML definition
  561. * will be assigned.
  562. * @param pszDialect currently ignored. The dialect used is GML based.
  563. *
  564. * @return OGRERR_NONE on success or an error code on failure.
  565. */
  566. OGRErr OGRSpatialReference::exportToXML( char **ppszRawXML,
  567. const char * pszDialect ) const
  568. {
  569. CPLXMLNode *psXMLTree = NULL;
  570. if( IsGeographic() )
  571. {
  572. psXMLTree = exportGeogCSToXML( this );
  573. }
  574. else if( IsProjected() )
  575. {
  576. psXMLTree = exportProjCSToXML( this );
  577. }
  578. else
  579. return OGRERR_UNSUPPORTED_SRS;
  580. *ppszRawXML = CPLSerializeXMLTree( psXMLTree );
  581. CPLDestroyXMLNode( psXMLTree );
  582. return OGRERR_NONE;
  583. }
  584. /************************************************************************/
  585. /* OSRExportToXML() */
  586. /************************************************************************/
  587. /**
  588. * \brief Export coordinate system in XML format.
  589. *
  590. * This function is the same as OGRSpatialReference::exportToXML().
  591. */
  592. OGRErr OSRExportToXML( OGRSpatialReferenceH hSRS, char **ppszRawXML,
  593. const char *pszDialect )
  594. {
  595. VALIDATE_POINTER1( hSRS, "OSRExportToXML", CE_Failure );
  596. return ((OGRSpatialReference *) hSRS)->exportToXML( ppszRawXML,
  597. pszDialect );
  598. }
  599. #ifdef notdef
  600. /************************************************************************/
  601. /* importXMLUnits() */
  602. /************************************************************************/
  603. static void importXMLUnits( CPLXMLNode *psSrcXML, const char *pszClass,
  604. OGRSpatialReference *poSRS, const char *pszTarget)
  605. {
  606. const char *pszUnitName, *pszUnitsPer;
  607. OGR_SRSNode *poNode = poSRS->GetAttrNode( pszTarget );
  608. OGR_SRSNode *poUnits;
  609. CPLAssert( EQUAL(pszClass,"AngularUnit")
  610. || EQUAL(pszClass,"LinearUnit") );
  611. psSrcXML = CPLGetXMLNode( psSrcXML, pszClass );
  612. if( psSrcXML == NULL )
  613. goto DefaultTarget;
  614. pszUnitName = CPLGetXMLValue( psSrcXML, "NameSet.name", "unnamed" );
  615. if( EQUAL(pszClass,"AngularUnit") )
  616. pszUnitsPer = CPLGetXMLValue( psSrcXML, "radiansPerUnit", NULL );
  617. else
  618. pszUnitsPer = CPLGetXMLValue( psSrcXML, "metresPerUnit", NULL );
  619. if( pszUnitsPer == NULL )
  620. {
  621. CPLDebug( "OGR_SRS_XML",
  622. "Missing PerUnit value for %s.",
  623. pszClass );
  624. goto DefaultTarget;
  625. }
  626. if( poNode == NULL )
  627. {
  628. CPLDebug( "OGR_SRS_XML", "Can't find %s in importXMLUnits.",
  629. pszTarget );
  630. goto DefaultTarget;
  631. }
  632. if( poNode->FindChild("UNIT") != -1 )
  633. {
  634. poUnits = poNode->GetChild( poNode->FindChild( "UNIT" ) );
  635. poUnits->GetChild(0)->SetValue( pszUnitName );
  636. poUnits->GetChild(1)->SetValue( pszUnitsPer );
  637. }
  638. else
  639. {
  640. poUnits = new OGR_SRSNode( "UNIT" );
  641. poUnits->AddChild( new OGR_SRSNode( pszUnitName ) );
  642. poUnits->AddChild( new OGR_SRSNode( pszUnitsPer ) );
  643. poNode->AddChild( poUnits );
  644. }
  645. return;
  646. DefaultTarget:
  647. poUnits = new OGR_SRSNode( "UNIT" );
  648. if( EQUAL(pszClass,"AngularUnit") )
  649. {
  650. poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE ) );
  651. poUnits->AddChild( new OGR_SRSNode( SRS_UA_DEGREE_CONV ) );
  652. }
  653. else
  654. {
  655. poUnits->AddChild( new OGR_SRSNode( SRS_UL_METER ) );
  656. poUnits->AddChild( new OGR_SRSNode( "1.0" ) );
  657. }
  658. poNode->AddChild( poUnits );
  659. }
  660. #endif
  661. /************************************************************************/
  662. /* importXMLAuthority() */
  663. /************************************************************************/
  664. static void importXMLAuthority( CPLXMLNode *psSrcXML,
  665. OGRSpatialReference *poSRS,
  666. const char *pszSourceKey,
  667. const char *pszTargetKey )
  668. {
  669. CPLXMLNode *psIDNode = CPLGetXMLNode( psSrcXML, pszSourceKey );
  670. CPLXMLNode *psNameNode = CPLGetXMLNode( psIDNode, "name" );
  671. CPLXMLNode *psCodeSpace = CPLGetXMLNode( psNameNode, "codeSpace" );
  672. const char *pszAuthority, *pszCode;
  673. char *pszURN;
  674. int nCode = 0;
  675. if( psIDNode == NULL || psNameNode == NULL || psCodeSpace == NULL )
  676. return;
  677. pszURN = CPLStrdup(CPLGetXMLValue( psCodeSpace, "", "" ));
  678. if( !parseURN( pszURN, NULL, &pszAuthority, &pszCode ) )
  679. {
  680. CPLFree( pszURN );
  681. return;
  682. }
  683. if( strlen(pszCode) == 0 )
  684. pszCode = (char *) CPLGetXMLValue( psNameNode, "", "" );
  685. if( pszCode != NULL )
  686. nCode = atoi(pszCode);
  687. if( nCode != 0 )
  688. poSRS->SetAuthority( pszTargetKey, pszAuthority, nCode );
  689. CPLFree( pszURN );
  690. }
  691. /************************************************************************/
  692. /* ParseOGCDefURN() */
  693. /* */
  694. /* Parse out fields from a URN of the form: */
  695. /* urn:ogc:def:parameter:EPSG:6.3:9707 */
  696. /************************************************************************/
  697. static int ParseOGCDefURN( const char *pszURN,
  698. CPLString *poObjectType,
  699. CPLString *poAuthority,
  700. CPLString *poVersion,
  701. CPLString *poValue )
  702. {
  703. if( poObjectType != NULL )
  704. *poObjectType = "";
  705. if( poAuthority != NULL )
  706. *poAuthority = "";
  707. if( poVersion != NULL )
  708. *poVersion = "";
  709. if( poValue != NULL )
  710. *poValue = "";
  711. if( pszURN == NULL || !EQUALN(pszURN,"urn:ogc:def:",12) )
  712. return FALSE;
  713. char **papszTokens = CSLTokenizeStringComplex( pszURN + 12, ":",
  714. FALSE, TRUE );
  715. if( CSLCount(papszTokens) != 4 )
  716. {
  717. CSLDestroy( papszTokens );
  718. return FALSE;
  719. }
  720. if( poObjectType != NULL )
  721. *poObjectType = papszTokens[0];
  722. if( poAuthority != NULL )
  723. *poAuthority = papszTokens[1];
  724. if( poVersion != NULL )
  725. *poVersion = papszTokens[2];
  726. if( poValue != NULL )
  727. *poValue = papszTokens[3];
  728. CSLDestroy( papszTokens );
  729. return TRUE;
  730. }
  731. /************************************************************************/
  732. /* getEPSGObjectCodeValue() */
  733. /* */
  734. /* Fetch a code value from the indicated node. Should work on */
  735. /* something of the form <elem xlink:href="urn:...:n" /> or */
  736. /* something of the form <elem xlink:href="urn:...:">n</a>. */
  737. /************************************************************************/
  738. static int getEPSGObjectCodeValue( CPLXMLNode *psNode,
  739. const char *pszEPSGObjectType, /*"method" */
  740. int nDefault )
  741. {
  742. if( psNode == NULL )
  743. return nDefault;
  744. CPLString osObjectType, osAuthority, osValue;
  745. const char* pszHrefVal;
  746. pszHrefVal = CPLGetXMLValue( psNode, "xlink:href", NULL );
  747. if (pszHrefVal == NULL)
  748. pszHrefVal = CPLGetXMLValue( psNode, "href", NULL );
  749. if( !ParseOGCDefURN( pszHrefVal,
  750. &osObjectType, &osAuthority, NULL, &osValue ) )
  751. return nDefault;
  752. if( !EQUAL(osAuthority,"EPSG")
  753. || !EQUAL(osObjectType, pszEPSGObjectType) )
  754. return nDefault;
  755. if( strlen(osValue) > 0 )
  756. return atoi(osValue);
  757. const char *pszValue = CPLGetXMLValue( psNode, "", NULL);
  758. if( pszValue != NULL )
  759. return atoi(pszValue);
  760. else
  761. return nDefault;
  762. }
  763. /************************************************************************/
  764. /* getProjectionParm() */
  765. /************************************************************************/
  766. static double getProjectionParm( CPLXMLNode *psRootNode,
  767. int nParameterCode,
  768. const char * /*pszMeasureType */,
  769. double dfDefault )
  770. {
  771. CPLXMLNode *psUsesParameter;
  772. for( psUsesParameter = psRootNode->psChild;
  773. psUsesParameter != NULL;
  774. psUsesParameter = psUsesParameter->psNext )
  775. {
  776. if( psUsesParameter->eType != CXT_Element )
  777. continue;
  778. if( !EQUAL(psUsesParameter->pszValue,"usesParameterValue")
  779. && !EQUAL(psUsesParameter->pszValue,"usesValue") )
  780. continue;
  781. if( getEPSGObjectCodeValue( CPLGetXMLNode(psUsesParameter,
  782. "valueOfParameter"),
  783. "parameter", 0 ) == nParameterCode )
  784. {
  785. const char *pszValue = CPLGetXMLValue( psUsesParameter, "value",
  786. NULL );
  787. if( pszValue != NULL )
  788. return atof(pszValue);
  789. else
  790. return dfDefault;
  791. }
  792. }
  793. return dfDefault;
  794. }
  795. /************************************************************************/
  796. /* getNormalizedValue() */
  797. /* */
  798. /* Parse a node to get it's numerical value, and then normalize */
  799. /* into meters of degrees depending on the measure type. */
  800. /************************************************************************/
  801. static double getNormalizedValue( CPLXMLNode *psNode, const char *pszPath,
  802. const char * /*pszMeasure*/,
  803. double dfDefault )
  804. {
  805. CPLXMLNode *psTargetNode;
  806. CPLXMLNode *psValueNode;
  807. if( pszPath == NULL || strlen(pszPath) == 0 )
  808. psTargetNode = psNode;
  809. else
  810. psTargetNode = CPLGetXMLNode( psNode, pszPath );
  811. if( psTargetNode == NULL )
  812. return dfDefault;
  813. for( psValueNode = psTargetNode->psChild;
  814. psValueNode != NULL && psValueNode->eType != CXT_Text;
  815. psValueNode = psValueNode->psNext ) {}
  816. if( psValueNode == NULL )
  817. return dfDefault;
  818. // Add normalization later.
  819. return atof(psValueNode->pszValue);
  820. }
  821. /************************************************************************/
  822. /* importGeogCSFromXML() */
  823. /************************************************************************/
  824. static OGRErr importGeogCSFromXML( OGRSpatialReference *poSRS,
  825. CPLXMLNode *psCRS )
  826. {
  827. const char *pszGeogName, *pszDatumName, *pszEllipsoidName, *pszPMName;
  828. double dfSemiMajor, dfInvFlattening, dfPMOffset = 0.0;
  829. /* -------------------------------------------------------------------- */
  830. /* Set the GEOGCS name from the srsName. */
  831. /* -------------------------------------------------------------------- */
  832. pszGeogName =
  833. CPLGetXMLValue( psCRS, "srsName", "Unnamed GeogCS" );
  834. /* -------------------------------------------------------------------- */
  835. /* If we don't seem to have a detailed coordinate system */
  836. /* definition, check if we can define based on an EPSG code. */
  837. /* -------------------------------------------------------------------- */
  838. CPLXMLNode *psDatum;
  839. psDatum = CPLGetXMLNode( psCRS, "usesGeodeticDatum.GeodeticDatum" );
  840. if( psDatum == NULL )
  841. {
  842. OGRSpatialReference oIdSRS;
  843. oIdSRS.SetLocalCS( "dummy" );
  844. importXMLAuthority( psCRS, &oIdSRS, "srsID", "LOCAL_CS" );
  845. if( oIdSRS.GetAuthorityCode( "LOCAL_CS" ) != NULL
  846. && oIdSRS.GetAuthorityName( "LOCAL_CS" ) != NULL
  847. && EQUAL(oIdSRS.GetAuthorityName("LOCAL_CS"),"EPSG") )
  848. {
  849. return poSRS->importFromEPSG(
  850. atoi(oIdSRS.GetAuthorityCode("LOCAL_CS")) );
  851. }
  852. }
  853. /* -------------------------------------------------------------------- */
  854. /* Get datum name. */
  855. /* -------------------------------------------------------------------- */
  856. pszDatumName =
  857. CPLGetXMLValue( psDatum, "datumName", "Unnamed Datum" );
  858. /* -------------------------------------------------------------------- */
  859. /* Get ellipsoid information. */
  860. /* -------------------------------------------------------------------- */
  861. CPLXMLNode *psE;
  862. psE = CPLGetXMLNode( psDatum, "usesEllipsoid.Ellipsoid" );
  863. pszEllipsoidName =
  864. CPLGetXMLValue( psE, "ellipsoidName", "Unnamed Ellipsoid" );
  865. dfSemiMajor = getNormalizedValue( psE, "semiMajorAxis", "Linear",
  866. SRS_WGS84_SEMIMAJOR );
  867. dfInvFlattening =
  868. getNormalizedValue( psE, "secondDefiningParameter.inverseFlattening",
  869. "Unitless", 0.0 );
  870. if( dfInvFlattening == 0.0 )
  871. {
  872. CPLError( CE_Failure, CPLE_AppDefined,
  873. "Ellipsoid inverseFlattening corrupt or missing." );
  874. return OGRERR_CORRUPT_DATA;
  875. }
  876. /* -------------------------------------------------------------------- */
  877. /* Get the prime meridian. */
  878. /* -------------------------------------------------------------------- */
  879. CPLXMLNode *psPM;
  880. psPM = CPLGetXMLNode( psDatum, "usesPrimeMeridian.PrimeMeridian" );
  881. if( psPM == NULL )
  882. {
  883. pszPMName = "Greenwich";
  884. dfPMOffset = 0.0;
  885. }
  886. else
  887. {
  888. pszPMName = CPLGetXMLValue( psPM, "meridianName",
  889. "Unnamed Prime Meridian");
  890. dfPMOffset =
  891. getNormalizedValue( psPM, "greenwichLongitude.angle",
  892. "Angular", 0.0 );
  893. }
  894. /* -------------------------------------------------------------------- */
  895. /* Set the geographic definition. */
  896. /* -------------------------------------------------------------------- */
  897. poSRS->SetGeogCS( pszGeogName, pszDatumName,
  898. pszEllipsoidName, dfSemiMajor, dfInvFlattening,
  899. pszPMName, dfPMOffset );
  900. /* -------------------------------------------------------------------- */
  901. /* Look for angular units. We don't check that all axes match */
  902. /* at this time. */
  903. /* -------------------------------------------------------------------- */
  904. #ifdef notdef
  905. CPLXMLNode *psAxis;
  906. psAxis = CPLGetXMLNode( psGeo2DCRS,
  907. "EllipsoidalCoordinateSystem.CoordinateAxis" );
  908. importXMLUnits( psAxis, "AngularUnit", poSRS, "GEOGCS" );
  909. #endif
  910. /* -------------------------------------------------------------------- */
  911. /* Can we set authorities for any of the levels? */
  912. /* -------------------------------------------------------------------- */
  913. importXMLAuthority( psCRS, poSRS, "srsID", "GEOGCS" );
  914. importXMLAuthority( psDatum, poSRS, "datumID", "GEOGCS|DATUM" );
  915. importXMLAuthority( psE, poSRS, "ellipsoidID",
  916. "GEOGCS|DATUM|SPHEROID" );
  917. importXMLAuthority( psDatum, poSRS,
  918. "usesPrimeMeridian.PrimeMeridian.meridianID",
  919. "GEOGCS|PRIMEM" );
  920. poSRS->Fixup();
  921. return OGRERR_NONE;
  922. }
  923. /************************************************************************/
  924. /* importProjCSFromXML() */
  925. /************************************************************************/
  926. static OGRErr importProjCSFromXML( OGRSpatialReference *poSRS,
  927. CPLXMLNode *psCRS )
  928. {
  929. CPLXMLNode *psSubXML;
  930. OGRErr eErr;
  931. /* -------------------------------------------------------------------- */
  932. /* Setup the PROJCS node with a name. */
  933. /* -------------------------------------------------------------------- */
  934. poSRS->SetProjCS( CPLGetXMLValue( psCRS, "srsName", "Unnamed" ) );
  935. /* -------------------------------------------------------------------- */
  936. /* Get authority information if available. If we got it, and */
  937. /* we seem to be lacking inline definition values, try and */
  938. /* define according to the EPSG code for the PCS. */
  939. /* -------------------------------------------------------------------- */
  940. importXMLAuthority( psCRS, poSRS, "srsID", "PROJCS" );
  941. if( poSRS->GetAuthorityCode( "PROJCS" ) != NULL
  942. && poSRS->GetAuthorityName( "PROJCS" ) != NULL
  943. && EQUAL(poSRS->GetAuthorityName("PROJCS"),"EPSG")
  944. && (CPLGetXMLNode( psCRS, "definedByConversion.Conversion" ) == NULL
  945. || CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" ) == NULL) )
  946. {
  947. return poSRS->importFromEPSG( atoi(poSRS->GetAuthorityCode("PROJCS")) );
  948. }
  949. /* -------------------------------------------------------------------- */
  950. /* Try to set the GEOGCS info. */
  951. /* -------------------------------------------------------------------- */
  952. psSubXML = CPLGetXMLNode( psCRS, "baseCRS.GeographicCRS" );
  953. if( psSubXML != NULL )
  954. {
  955. eErr = importGeogCSFromXML( poSRS, psSubXML );
  956. if( eErr != OGRERR_NONE )
  957. return eErr;
  958. }
  959. /* -------------------------------------------------------------------- */
  960. /* Get the conversion node. It should be the only child of the */
  961. /* definedByConversion node. */
  962. /* -------------------------------------------------------------------- */
  963. CPLXMLNode *psConv = NULL;
  964. psConv = CPLGetXMLNode( psCRS, "definedByConversion.Conversion" );
  965. if( psConv == NULL || psConv->eType != CXT_Element )
  966. {
  967. CPLError( CE_Failure, CPLE_AppDefined,
  968. "Unable to find a conversion node under the definedByConversion\n"
  969. "node of the ProjectedCRS." );
  970. return OGRERR_CORRUPT_DATA;
  971. }
  972. /* -------------------------------------------------------------------- */
  973. /* Determine the conversion method in effect. */
  974. /* -------------------------------------------------------------------- */
  975. int nMethod = getEPSGObjectCodeValue( CPLGetXMLNode( psConv, "usesMethod"),
  976. "method", 0 );
  977. /* -------------------------------------------------------------------- */
  978. /* Transverse Mercator. */
  979. /* -------------------------------------------------------------------- */
  980. if( nMethod == 9807 )
  981. {
  982. poSRS->SetTM(
  983. getProjectionParm( psConv, 8801, "Angular", 0.0 ),
  984. getProjectionParm( psConv, 8802, "Angular", 0.0 ),
  985. getProjectionParm( psConv, 8805, "Unitless", 1.0 ),
  986. getProjectionParm( psConv, 8806, "Linear", 0.0 ),
  987. getProjectionParm( psConv, 8807, "Linear", 0.0 ) );
  988. }
  989. /* -------------------------------------------------------------------- */
  990. /* Didn't recognise? */
  991. /* -------------------------------------------------------------------- */
  992. else
  993. {
  994. CPLError( CE_Failure, CPLE_AppDefined,
  995. "Conversion method %d not recognised.",
  996. nMethod );
  997. return OGRERR_CORRUPT_DATA;
  998. }
  999. /* -------------------------------------------------------------------- */
  1000. /* Cleanup and return. */
  1001. /* -------------------------------------------------------------------- */
  1002. poSRS->Fixup();
  1003. // Need to get linear units here!
  1004. return OGRERR_NONE;
  1005. }
  1006. /************************************************************************/
  1007. /* importFromXML() */
  1008. /************************************************************************/
  1009. /**
  1010. * \brief Import coordinate system from XML format (GML only currently).
  1011. *
  1012. * This method is the same as the C function OSRImportFromXML()
  1013. * @param pszXML XML string to import
  1014. * @return OGRERR_NONE on success or OGRERR_CORRUPT_DATA on failure.
  1015. */
  1016. OGRErr OGRSpatialReference::importFromXML( const char *pszXML )
  1017. {
  1018. CPLXMLNode *psTree;
  1019. OGRErr eErr = OGRERR_UNSUPPORTED_SRS;
  1020. this->Clear();
  1021. /* -------------------------…

Large files files are truncated, but you can click here to view the full file