?? gml2ogrgeometry.cpp
字號:
/******************************************************************************
* $Id: gml2ogrgeometry.cpp 10646 2007-01-18 02:38:10Z warmerdam $
*
* 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.
*
*/
#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;
}
/************************************************************************/
/* GML2OGRGeometry_XMLNode() */
/* */
/* Translates the passed XMLnode and it's children into an */
/* OGRGeometry. This is used recursively for geometry */
/* collections. */
/************************************************************************/
static OGRGeometry *GML2OGRGeometry_XMLNode( CPLXMLNode *psNode )
{
const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
/* -------------------------------------------------------------------- */
/* Polygon */
/* -------------------------------------------------------------------- */
if( EQUAL(pszBaseGeometry,"Polygon") )
{
CPLXMLNode *psChild;
OGRPolygon *poPolygon = new OGRPolygon();
OGRLinearRing *poRing;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -