📄 gml2ogrgeometry.cpp
字号:
/****************************************************************************** * $Id: gml2ogrgeometry.cpp,v 1.10 2005/07/20 02:33:24 fwarmerdam Exp $ * * Project: GML Reader * Purpose: Code to translate between GML and OGR geometry forms. * Author: Frank Warmerdam, warmerdam@pobox.com * ****************************************************************************** * Copyright (c) 2002, Frank Warmerdam * * 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. ***************************************************************************** * * Independent Security Audit 2003/04/17 Andrey Kiselev: * Completed audit of this module. All functions may be used without buffer * overflows and stack corruptions with any kind of input data. * * Security Audit 2003/03/28 warmerda: * Completed security audit. I believe that this module may be safely used * to parse, arbitrary GML potentially provided by a hostile source without * compromising the system. * * $Log: gml2ogrgeometry.cpp,v $ * Revision 1.10 2005/07/20 02:33:24 fwarmerdam * fix up dimension support * * Revision 1.9 2005/03/08 19:51:15 fwarmerdam * added gml:pos support * * Revision 1.8 2004/01/06 18:40:06 warmerda * do not crash if polygon fails to parse during multipolygon assembly * * Revision 1.7 2003/09/22 05:34:46 warmerda * implemented support for various kinds of geometry collections * * Revision 1.6 2003/04/17 08:23:07 dron * Completed security audit, few fixes in error format strings. * * Revision 1.5 2003/03/28 05:46:43 warmerda * completed security audit, fix error report risk * * Revision 1.4 2003/03/12 20:52:07 warmerda * implemented support for gml:Box * * Revision 1.3 2003/03/07 21:30:15 warmerda * expand tabs * * Revision 1.2 2003/03/07 14:52:40 warmerda * fixed type casting issing * * Revision 1.1 2003/03/06 20:28:38 warmerda * Migrated to here (gdal/ogr) from gdal/ogr/ogrsf_frmts/gml. * Changed to implement the C API entry points (OGR_G_*). * Added API to take/return CPLXMLNode's directly. * * Revision 1.4 2002/03/11 17:09:42 warmerda * added multipolygon support * * Revision 1.3 2002/03/07 22:37:10 warmerda * use ogr_gml_geom.h * * Revision 1.2 2002/03/06 20:07:12 warmerda * fixed point reading * * Revision 1.1 2002/01/24 17:39:22 warmerda * New * */#include "cpl_minixml.h"#include "ogr_geometry.h"#include "ogr_api.h"#include "cpl_error.h"#include "cpl_string.h"#include <ctype.h>/************************************************************************//* BareGMLElement() *//* *//* Returns the passed string with any namespace prefix *//* stripped off. *//************************************************************************/static const char *BareGMLElement( const char *pszInput ){ const char *pszReturn; pszReturn = strchr( pszInput, ':' ); if( pszReturn == NULL ) pszReturn = pszInput; else pszReturn++; return pszReturn;}/************************************************************************//* FindBareXMLChild() *//* *//* Find a child node with the indicated "bare" name, that is *//* after any namespace qualifiers have been stripped off. *//************************************************************************/static CPLXMLNode *FindBareXMLChild( CPLXMLNode *psParent, const char *pszBareName ){ CPLXMLNode *psCandidate = psParent->psChild; while( psCandidate != NULL ) { if( psCandidate->eType == CXT_Element && EQUAL(BareGMLElement(psCandidate->pszValue), pszBareName) ) return psCandidate; psCandidate = psCandidate->psNext; } return NULL;}/************************************************************************//* GetElementText() *//************************************************************************/static const char *GetElementText( CPLXMLNode *psElement ){ if( psElement == NULL ) return NULL; CPLXMLNode *psChild = psElement->psChild; while( psChild != NULL ) { if( psChild->eType == CXT_Text ) return psChild->pszValue; psChild = psChild->psNext; } return NULL;}/************************************************************************//* AddPoint() *//* *//* Add a point to the passed geometry. *//************************************************************************/static int AddPoint( OGRGeometry *poGeometry, double dfX, double dfY, double dfZ, int nDimension ){ if( poGeometry->getGeometryType() == wkbPoint || poGeometry->getGeometryType() == wkbPoint25D ) { OGRPoint *poPoint = (OGRPoint *) poGeometry; if( poPoint->getX() != 0.0 || poPoint->getY() != 0.0 ) { CPLError( CE_Failure, CPLE_AppDefined, "More than one coordinate for <Point> element."); return FALSE; } poPoint->setX( dfX ); poPoint->setY( dfY ); if( nDimension == 3 ) poPoint->setZ( dfZ ); return TRUE; } else if( poGeometry->getGeometryType() == wkbLineString || poGeometry->getGeometryType() == wkbLineString25D ) { if( nDimension == 3 ) ((OGRLineString *) poGeometry)->addPoint( dfX, dfY, dfZ ); else ((OGRLineString *) poGeometry)->addPoint( dfX, dfY ); return TRUE; } else { CPLAssert( FALSE ); return FALSE; }}/************************************************************************//* ParseGMLCoordinates() *//************************************************************************/int ParseGMLCoordinates( CPLXMLNode *psGeomNode, OGRGeometry *poGeometry ){ CPLXMLNode *psCoordinates = FindBareXMLChild( psGeomNode, "coordinates" ); int iCoord = 0;/* -------------------------------------------------------------------- *//* Handle <coordinates> case. *//* -------------------------------------------------------------------- */ if( psCoordinates != NULL ) { const char *pszCoordString = GetElementText( psCoordinates ); if( pszCoordString == NULL ) { CPLError( CE_Failure, CPLE_AppDefined, "<coordinates> element missing value." ); return FALSE; } while( *pszCoordString != '\0' ) { double dfX, dfY, dfZ = 0.0; int nDimension = 2; // parse out 2 or 3 tuple. dfX = atof( pszCoordString ); while( *pszCoordString != '\0' && *pszCoordString != ',' && !isspace(*pszCoordString) ) pszCoordString++; if( *pszCoordString == '\0' || isspace(*pszCoordString) ) { CPLError( CE_Failure, CPLE_AppDefined, "Corrupt <coordinates> value." ); return FALSE; } pszCoordString++; dfY = atof( pszCoordString ); while( *pszCoordString != '\0' && *pszCoordString != ',' && !isspace(*pszCoordString) ) pszCoordString++; if( *pszCoordString == ',' ) { pszCoordString++; dfZ = atof( pszCoordString ); nDimension = 3; while( *pszCoordString != '\0' && *pszCoordString != ',' && !isspace(*pszCoordString) ) pszCoordString++; } while( isspace(*pszCoordString) ) pszCoordString++; if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) ) return FALSE; iCoord++; } return iCoord > 0; }/* -------------------------------------------------------------------- *//* Is this a "pos"? I think this is a GML 3 construct. *//* -------------------------------------------------------------------- */ CPLXMLNode *psPos = FindBareXMLChild( psGeomNode, "pos" ); if( psPos != NULL ) { char **papszTokens = CSLTokenizeStringComplex( GetElementText( psPos ), " ,", FALSE, FALSE ); int bSuccess = FALSE; if( CSLCount( papszTokens ) > 2 ) { bSuccess = AddPoint( poGeometry, atof(papszTokens[0]), atof(papszTokens[1]), atof(papszTokens[2]), 3 ); } else if( CSLCount( papszTokens ) > 1 ) { bSuccess = AddPoint( poGeometry, atof(papszTokens[0]), atof(papszTokens[1]), 0.0, 2 ); } else { CPLError( CE_Failure, CPLE_AppDefined, "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.", GetElementText( psPos ) ); } CSLDestroy( papszTokens ); return bSuccess; } /* -------------------------------------------------------------------- *//* Handle form with a list of <coord> items each with an <X>, *//* and <Y> element. *//* -------------------------------------------------------------------- */ CPLXMLNode *psCoordNode; for( psCoordNode = psGeomNode->psChild; psCoordNode != NULL; psCoordNode = psCoordNode->psNext ) { if( psCoordNode->eType != CXT_Element || !EQUAL(BareGMLElement(psCoordNode->pszValue),"coord") ) continue; CPLXMLNode *psXNode, *psYNode, *psZNode; double dfX, dfY, dfZ = 0.0; int nDimension = 2; psXNode = FindBareXMLChild( psCoordNode, "X" ); psYNode = FindBareXMLChild( psCoordNode, "Y" ); psZNode = FindBareXMLChild( psCoordNode, "Z" ); if( psXNode == NULL || psYNode == NULL || GetElementText(psXNode) == NULL || GetElementText(psYNode) == NULL || (psZNode != NULL && GetElementText(psZNode) == NULL) ) { CPLError( CE_Failure, CPLE_AppDefined, "Corrupt <coord> element, missing <X> or <Y> element?" ); return FALSE; } dfX = atof( GetElementText(psXNode) ); dfY = atof( GetElementText(psYNode) ); if( psZNode != NULL && GetElementText(psZNode) != NULL ) { dfZ = atof( GetElementText(psZNode) ); nDimension = 3; } if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) ) return FALSE; iCoord++; } return iCoord > 0.0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -