mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-19 06:05:31 -06:00
1142 lines
44 KiB
C++
1142 lines
44 KiB
C++
/******************************************************************************
|
|
* $Id: ogr2gmlgeometry.cpp 27959 2014-11-14 18:29:21Z rouault $
|
|
*
|
|
* Project: GML Translator
|
|
* Purpose: Code to translate OGRGeometry to GML string representation.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
|
|
* Copyright (c) 2009-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*****************************************************************************
|
|
*
|
|
* Independent Security Audit 2003/04/17 Andrey Kiselev:
|
|
* Completed audit of this module. All functions may be used without buffer
|
|
* overflows and stack corruptions if caller could be trusted.
|
|
*
|
|
* Security Audit 2003/03/28 warmerda:
|
|
* Completed security audit. I believe that this module may be safely used
|
|
* to generate GML from arbitrary but well formed OGRGeomety objects that
|
|
* come from a potentially hostile source, but through a trusted OGR importer
|
|
* without compromising the system.
|
|
*
|
|
*/
|
|
|
|
#include "cpl_minixml.h"
|
|
#include "ogr_geometry.h"
|
|
#include "ogr_api.h"
|
|
#include "ogr_p.h"
|
|
#include "cpl_error.h"
|
|
#include "cpl_conv.h"
|
|
|
|
#define SRSDIM_LOC_GEOMETRY (1 << 0)
|
|
#define SRSDIM_LOC_POSLIST (1 << 1)
|
|
|
|
/************************************************************************/
|
|
/* MakeGMLCoordinate() */
|
|
/************************************************************************/
|
|
|
|
static void MakeGMLCoordinate( char *pszTarget,
|
|
double x, double y, double z, int b3D )
|
|
|
|
{
|
|
OGRMakeWktCoordinate( pszTarget, x, y, z, b3D ? 3 : 2 );
|
|
while( *pszTarget != '\0' )
|
|
{
|
|
if( *pszTarget == ' ' )
|
|
*pszTarget = ',';
|
|
pszTarget++;
|
|
}
|
|
|
|
#ifdef notdef
|
|
if( !b3D )
|
|
{
|
|
if( x == (int) x && y == (int) y )
|
|
sprintf( pszTarget, "%d,%d", (int) x, (int) y );
|
|
else if( fabs(x) < 370 && fabs(y) < 370 )
|
|
CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
|
|
else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 )
|
|
CPLsprintf( pszTarget, "%.16g,%.16g", x, y );
|
|
else
|
|
CPLsprintf( pszTarget, "%.3f,%.3f", x, y );
|
|
}
|
|
else
|
|
{
|
|
if( x == (int) x && y == (int) y && z == (int) z )
|
|
sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
|
|
else if( fabs(x) < 370 && fabs(y) < 370 )
|
|
CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
|
|
else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0
|
|
|| fabs(z) > 100000000.0 )
|
|
CPLsprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
|
|
else
|
|
CPLsprintf( pszTarget, "%.3f,%.3f,%.3f", x, y, z );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* _GrowBuffer() */
|
|
/************************************************************************/
|
|
|
|
static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
|
|
|
|
{
|
|
if( nNeeded+1 >= *pnMaxLength )
|
|
{
|
|
*pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
|
|
*ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AppendString() */
|
|
/************************************************************************/
|
|
|
|
static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
|
|
const char *pszTextToAppend )
|
|
|
|
{
|
|
_GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1,
|
|
ppszText, pnMaxLength );
|
|
|
|
strcat( *ppszText + *pnLength, pszTextToAppend );
|
|
*pnLength += strlen( *ppszText + *pnLength );
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* AppendCoordinateList() */
|
|
/************************************************************************/
|
|
|
|
static void AppendCoordinateList( OGRLineString *poLine,
|
|
char **ppszText, int *pnLength,
|
|
int *pnMaxLength )
|
|
|
|
{
|
|
char szCoordinate[256];
|
|
int b3D = wkbHasZ(poLine->getGeometryType());
|
|
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
_GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
|
|
|
|
strcat( *ppszText + *pnLength, "<gml:coordinates>" );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
|
|
|
|
for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
|
|
{
|
|
MakeGMLCoordinate( szCoordinate,
|
|
poLine->getX(iPoint),
|
|
poLine->getY(iPoint),
|
|
poLine->getZ(iPoint),
|
|
b3D );
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate)+1,
|
|
ppszText, pnMaxLength );
|
|
|
|
if( iPoint != 0 )
|
|
strcat( *ppszText + *pnLength, " " );
|
|
|
|
strcat( *ppszText + *pnLength, szCoordinate );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
}
|
|
|
|
_GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
|
|
strcat( *ppszText + *pnLength, "</gml:coordinates>" );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR2GMLGeometryAppend() */
|
|
/************************************************************************/
|
|
|
|
static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry,
|
|
char **ppszText, int *pnLength,
|
|
int *pnMaxLength,
|
|
int bIsSubGeometry )
|
|
|
|
{
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for Spatial Reference System attached to given geometry */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
// Buffer for srsName attribute (srsName="...")
|
|
char szAttributes[30] = { 0 };
|
|
int nAttrsLength = 0;
|
|
|
|
const OGRSpatialReference* poSRS = NULL;
|
|
poSRS = poGeometry->getSpatialReference();
|
|
|
|
if( NULL != poSRS && !bIsSubGeometry )
|
|
{
|
|
const char* pszAuthName = NULL;
|
|
const char* pszAuthCode = NULL;
|
|
const char* pszTarget = NULL;
|
|
|
|
if (poSRS->IsProjected())
|
|
pszTarget = "PROJCS";
|
|
else
|
|
pszTarget = "GEOGCS";
|
|
|
|
pszAuthName = poSRS->GetAuthorityName( pszTarget );
|
|
if( NULL != pszAuthName )
|
|
{
|
|
if( EQUAL( pszAuthName, "EPSG" ) )
|
|
{
|
|
pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
|
|
if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
|
|
{
|
|
sprintf( szAttributes, " srsName=\"%s:%s\"",
|
|
pszAuthName, pszAuthCode );
|
|
|
|
nAttrsLength = strlen(szAttributes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
OGRwkbGeometryType eType = poGeometry->getGeometryType();
|
|
OGRwkbGeometryType eFType = wkbFlatten(eType);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* 2D Point */
|
|
/* -------------------------------------------------------------------- */
|
|
if( eType == wkbPoint )
|
|
{
|
|
char szCoordinate[256];
|
|
OGRPoint *poPoint = (OGRPoint *) poGeometry;
|
|
|
|
MakeGMLCoordinate( szCoordinate,
|
|
poPoint->getX(), poPoint->getY(), 0.0, FALSE );
|
|
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
|
|
ppszText, pnMaxLength );
|
|
|
|
sprintf( *ppszText + *pnLength,
|
|
"<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
|
|
szAttributes, szCoordinate );
|
|
|
|
*pnLength += strlen( *ppszText + *pnLength );
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* 3D Point */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eType == wkbPoint25D )
|
|
{
|
|
char szCoordinate[256];
|
|
OGRPoint *poPoint = (OGRPoint *) poGeometry;
|
|
|
|
MakeGMLCoordinate( szCoordinate,
|
|
poPoint->getX(), poPoint->getY(), poPoint->getZ(),
|
|
TRUE );
|
|
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
|
|
ppszText, pnMaxLength );
|
|
|
|
sprintf( *ppszText + *pnLength,
|
|
"<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
|
|
szAttributes, szCoordinate );
|
|
|
|
*pnLength += strlen( *ppszText + *pnLength );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* LineString and LinearRing */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbLineString )
|
|
{
|
|
int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
|
|
|
|
// Buffer for tag name + srsName attribute if set
|
|
const size_t nLineTagLength = 16;
|
|
char* pszLineTagName = NULL;
|
|
pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
|
|
|
|
if( bRing )
|
|
{
|
|
sprintf( pszLineTagName, "<gml:LinearRing%s>", szAttributes );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
pszLineTagName );
|
|
}
|
|
else
|
|
{
|
|
sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
pszLineTagName );
|
|
}
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszLineTagName );
|
|
|
|
AppendCoordinateList( (OGRLineString *) poGeometry,
|
|
ppszText, pnLength, pnMaxLength );
|
|
|
|
if( bRing )
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:LinearRing>" );
|
|
else
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:LineString>" );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Polygon */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbPolygon )
|
|
{
|
|
OGRPolygon *poPolygon = (OGRPolygon *) poGeometry;
|
|
|
|
// Buffer for polygon tag name + srsName attribute if set
|
|
const size_t nPolyTagLength = 13;
|
|
char* pszPolyTagName = NULL;
|
|
pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
|
|
|
|
// Compose Polygon tag with or without srsName attribute
|
|
sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
pszPolyTagName );
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszPolyTagName );
|
|
|
|
// Don't add srsName to polygon rings
|
|
|
|
if( poPolygon->getExteriorRing() != NULL )
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:outerBoundaryIs>" );
|
|
|
|
if( !OGR2GMLGeometryAppend( poPolygon->getExteriorRing(),
|
|
ppszText, pnLength, pnMaxLength,
|
|
TRUE ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:outerBoundaryIs>" );
|
|
}
|
|
|
|
for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
|
|
{
|
|
OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:innerBoundaryIs>" );
|
|
|
|
if( !OGR2GMLGeometryAppend( poRing, ppszText, pnLength,
|
|
pnMaxLength, TRUE ) )
|
|
return FALSE;
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:innerBoundaryIs>" );
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:Polygon>" );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* MultiPolygon, MultiLineString, MultiPoint, MultiGeometry */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbMultiPolygon
|
|
|| eFType == wkbMultiLineString
|
|
|| eFType == wkbMultiPoint
|
|
|| eFType == wkbGeometryCollection )
|
|
{
|
|
OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
|
|
int iMember;
|
|
const char *pszElemClose = NULL;
|
|
const char *pszMemberElem = NULL;
|
|
|
|
// Buffer for opening tag + srsName attribute
|
|
char* pszElemOpen = NULL;
|
|
|
|
if( eFType == wkbMultiPolygon )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiPolygon%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiPolygon>";
|
|
pszMemberElem = "polygonMember>";
|
|
}
|
|
else if( eFType == wkbMultiLineString )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiLineString%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiLineString>";
|
|
pszMemberElem = "lineStringMember>";
|
|
}
|
|
else if( eFType == wkbMultiPoint )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiPoint>";
|
|
pszMemberElem = "pointMember>";
|
|
}
|
|
else
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiGeometry>";
|
|
pszMemberElem = "geometryMember>";
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
|
|
|
|
for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
|
|
{
|
|
OGRGeometry *poMember = poGC->getGeometryRef( iMember );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
|
|
|
|
if( !OGR2GMLGeometryAppend( poMember,
|
|
ppszText, pnLength, pnMaxLength,
|
|
TRUE ) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszElemOpen );
|
|
}
|
|
else
|
|
{
|
|
CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s",
|
|
OGRGeometryTypeToName(eType));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportEnvelopeToGMLTree() */
|
|
/* */
|
|
/* Export the envelope of a geometry as a gml:Box. */
|
|
/************************************************************************/
|
|
|
|
CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
|
|
|
|
{
|
|
CPLXMLNode *psBox, *psCoord;
|
|
OGREnvelope sEnvelope;
|
|
char szCoordinate[256];
|
|
char *pszY;
|
|
|
|
memset( &sEnvelope, 0, sizeof(sEnvelope) );
|
|
((OGRGeometry *) hGeometry)->getEnvelope( &sEnvelope );
|
|
|
|
if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0
|
|
&& sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
|
|
{
|
|
/* there is apparently a special way of representing a null box
|
|
geometry ... we should use it here eventually. */
|
|
|
|
return NULL;
|
|
}
|
|
|
|
psBox = CPLCreateXMLNode( NULL, CXT_Element, "gml:Box" );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Add minxy coordinate. */
|
|
/* -------------------------------------------------------------------- */
|
|
psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
|
|
|
|
MakeGMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0,
|
|
FALSE );
|
|
pszY = strstr(szCoordinate,",") + 1;
|
|
pszY[-1] = '\0';
|
|
|
|
CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
|
|
CPLCreateXMLElementAndValue( psCoord, "gml:Y", pszY );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Add maxxy coordinate. */
|
|
/* -------------------------------------------------------------------- */
|
|
psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
|
|
|
|
MakeGMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0,
|
|
FALSE );
|
|
pszY = strstr(szCoordinate,",") + 1;
|
|
pszY[-1] = '\0';
|
|
|
|
CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
|
|
CPLCreateXMLElementAndValue( psCoord, "gml:Y", pszY );
|
|
|
|
return psBox;
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* AppendGML3CoordinateList() */
|
|
/************************************************************************/
|
|
|
|
static void AppendGML3CoordinateList( const OGRSimpleCurve *poLine, int bCoordSwap,
|
|
char **ppszText, int *pnLength,
|
|
int *pnMaxLength, int nSRSDimensionLocFlags )
|
|
|
|
{
|
|
char szCoordinate[256];
|
|
int b3D = wkbHasZ(poLine->getGeometryType());
|
|
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
_GrowBuffer( *pnLength + 40, ppszText, pnMaxLength );
|
|
|
|
if (b3D && (nSRSDimensionLocFlags & SRSDIM_LOC_POSLIST) != 0)
|
|
strcat( *ppszText + *pnLength, "<gml:posList srsDimension=\"3\">" );
|
|
else
|
|
strcat( *ppszText + *pnLength, "<gml:posList>" );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
|
|
|
|
for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
|
|
{
|
|
if (bCoordSwap)
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poLine->getY(iPoint),
|
|
poLine->getX(iPoint),
|
|
poLine->getZ(iPoint),
|
|
b3D ? 3 : 2 );
|
|
else
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poLine->getX(iPoint),
|
|
poLine->getY(iPoint),
|
|
poLine->getZ(iPoint),
|
|
b3D ? 3 : 2 );
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate)+1,
|
|
ppszText, pnMaxLength );
|
|
|
|
if( iPoint != 0 )
|
|
strcat( *ppszText + *pnLength, " " );
|
|
|
|
strcat( *ppszText + *pnLength, szCoordinate );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
}
|
|
|
|
_GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
|
|
strcat( *ppszText + *pnLength, "</gml:posList>" );
|
|
*pnLength += strlen(*ppszText + *pnLength);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR2GML3GeometryAppend() */
|
|
/************************************************************************/
|
|
|
|
static int OGR2GML3GeometryAppend( const OGRGeometry *poGeometry,
|
|
const OGRSpatialReference* poParentSRS,
|
|
char **ppszText, int *pnLength,
|
|
int *pnMaxLength,
|
|
int bIsSubGeometry,
|
|
int bLongSRS,
|
|
int bLineStringAsCurve,
|
|
const char* pszGMLId,
|
|
int nSRSDimensionLocFlags,
|
|
int bForceLineStringAsLinearRing )
|
|
|
|
{
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for Spatial Reference System attached to given geometry */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
// Buffer for srsName, srsDimension and gml:id attributes (srsName="..." gml:id="...")
|
|
char szAttributes[256];
|
|
int nAttrsLength = 0;
|
|
|
|
szAttributes[0] = 0;
|
|
|
|
const OGRSpatialReference* poSRS = NULL;
|
|
if (poParentSRS)
|
|
poSRS = poParentSRS;
|
|
else
|
|
poParentSRS = poSRS = poGeometry->getSpatialReference();
|
|
|
|
int bCoordSwap = FALSE;
|
|
|
|
if( NULL != poSRS )
|
|
{
|
|
const char* pszAuthName = NULL;
|
|
const char* pszAuthCode = NULL;
|
|
const char* pszTarget = NULL;
|
|
|
|
if (poSRS->IsProjected())
|
|
pszTarget = "PROJCS";
|
|
else
|
|
pszTarget = "GEOGCS";
|
|
|
|
pszAuthName = poSRS->GetAuthorityName( pszTarget );
|
|
if( NULL != pszAuthName )
|
|
{
|
|
if( EQUAL( pszAuthName, "EPSG" ) )
|
|
{
|
|
pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
|
|
if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
|
|
{
|
|
if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
|
|
((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting()))
|
|
{
|
|
OGRSpatialReference oSRS;
|
|
if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
|
|
{
|
|
if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
|
|
bCoordSwap = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!bIsSubGeometry)
|
|
{
|
|
if (bLongSRS)
|
|
{
|
|
snprintf( szAttributes, sizeof(szAttributes),
|
|
" srsName=\"urn:ogc:def:crs:%s::%s\"",
|
|
pszAuthName, pszAuthCode );
|
|
}
|
|
else
|
|
{
|
|
snprintf( szAttributes, sizeof(szAttributes),
|
|
" srsName=\"%s:%s\"",
|
|
pszAuthName, pszAuthCode );
|
|
}
|
|
|
|
nAttrsLength = strlen(szAttributes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if( (nSRSDimensionLocFlags & SRSDIM_LOC_GEOMETRY) != 0 &&
|
|
wkbHasZ(poGeometry->getGeometryType()) )
|
|
{
|
|
strcat(szAttributes, " srsDimension=\"3\"");
|
|
nAttrsLength = strlen(szAttributes);
|
|
|
|
nSRSDimensionLocFlags &= ~SRSDIM_LOC_GEOMETRY;
|
|
}
|
|
|
|
if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
|
|
{
|
|
strcat(szAttributes, " gml:id=\"");
|
|
strcat(szAttributes, pszGMLId);
|
|
strcat(szAttributes, "\"");
|
|
nAttrsLength = strlen(szAttributes);
|
|
}
|
|
|
|
OGRwkbGeometryType eType = poGeometry->getGeometryType();
|
|
OGRwkbGeometryType eFType = wkbFlatten(eType);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* 2D Point */
|
|
/* -------------------------------------------------------------------- */
|
|
if( eType == wkbPoint )
|
|
{
|
|
char szCoordinate[256];
|
|
OGRPoint *poPoint = (OGRPoint *) poGeometry;
|
|
|
|
if (bCoordSwap)
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poPoint->getY(), poPoint->getX(), 0.0, 2 );
|
|
else
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poPoint->getX(), poPoint->getY(), 0.0, 2 );
|
|
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
|
|
ppszText, pnMaxLength );
|
|
|
|
sprintf( *ppszText + *pnLength,
|
|
"<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
|
|
szAttributes, szCoordinate );
|
|
|
|
*pnLength += strlen( *ppszText + *pnLength );
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* 3D Point */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eType == wkbPoint25D )
|
|
{
|
|
char szCoordinate[256];
|
|
OGRPoint *poPoint = (OGRPoint *) poGeometry;
|
|
|
|
if (bCoordSwap)
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 );
|
|
else
|
|
OGRMakeWktCoordinate( szCoordinate,
|
|
poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
|
|
|
|
_GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
|
|
ppszText, pnMaxLength );
|
|
|
|
sprintf( *ppszText + *pnLength,
|
|
"<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
|
|
szAttributes, szCoordinate );
|
|
|
|
*pnLength += strlen( *ppszText + *pnLength );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* LineString and LinearRing */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbLineString )
|
|
{
|
|
int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING") ||
|
|
bForceLineStringAsLinearRing;
|
|
if (!bRing && bLineStringAsCurve)
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:Curve" );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
szAttributes );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"><gml:segments><gml:LineStringSegment>" );
|
|
AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
|
|
ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:LineStringSegment></gml:segments></gml:Curve>" );
|
|
}
|
|
else
|
|
{
|
|
// Buffer for tag name + srsName attribute if set
|
|
const size_t nLineTagLength = 16;
|
|
char* pszLineTagName = NULL;
|
|
pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
|
|
|
|
if( bRing )
|
|
{
|
|
/* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:LinearRing>" );
|
|
}
|
|
else
|
|
{
|
|
sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
pszLineTagName );
|
|
}
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszLineTagName );
|
|
|
|
AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
|
|
ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
|
|
|
|
if( bRing )
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:LinearRing>" );
|
|
else
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:LineString>" );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* ArcString or Circle */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbCircularString )
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:Curve" );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
szAttributes );
|
|
OGRSimpleCurve* poSC = (OGRSimpleCurve *) poGeometry;
|
|
/* SQL MM has a unique type for arc and circle, GML not */
|
|
if( poSC->getNumPoints() == 3 &&
|
|
poSC->getX(0) == poSC->getX(2) &&
|
|
poSC->getY(0) == poSC->getY(2) )
|
|
{
|
|
double dfMidX = (poSC->getX(0) + poSC->getX(1)) / 2;
|
|
double dfMidY = (poSC->getY(0) + poSC->getY(1)) / 2;
|
|
double dfDirX = (poSC->getX(1) - poSC->getX(0)) / 2;
|
|
double dfDirY = (poSC->getY(1) - poSC->getY(0)) / 2;
|
|
double dfNormX = -dfDirY;
|
|
double dfNormY = dfDirX;
|
|
double dfNewX = dfMidX + dfNormX;
|
|
double dfNewY = dfMidY + dfNormY;
|
|
OGRLineString* poLS = new OGRLineString();
|
|
OGRPoint p;
|
|
poSC->getPoint(0, &p);
|
|
poLS->addPoint(&p);
|
|
poSC->getPoint(1, &p);
|
|
if( poSC->getCoordinateDimension() == 3 )
|
|
poLS->addPoint(dfNewX, dfNewY, p.getZ());
|
|
else
|
|
poLS->addPoint(dfNewX, dfNewY);
|
|
poLS->addPoint(&p);
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"><gml:segments><gml:Circle>" );
|
|
AppendGML3CoordinateList( poLS, bCoordSwap,
|
|
ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:Circle></gml:segments></gml:Curve>" );
|
|
delete poLS;
|
|
}
|
|
else
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"><gml:segments><gml:ArcString>" );
|
|
AppendGML3CoordinateList( poSC, bCoordSwap,
|
|
ppszText, pnLength, pnMaxLength, nSRSDimensionLocFlags );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:ArcString></gml:segments></gml:Curve>" );
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* CompositeCurve */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbCompoundCurve )
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:CompositeCurve" );
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
szAttributes );
|
|
AppendString( ppszText, pnLength, pnMaxLength,">");
|
|
|
|
OGRCompoundCurve* poCC = (OGRCompoundCurve*)poGeometry;
|
|
for(int i=0;i<poCC->getNumCurves();i++)
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:curveMember>" );
|
|
if( !OGR2GML3GeometryAppend( poCC->getCurve(i), poSRS, ppszText, pnLength,
|
|
pnMaxLength, TRUE, bLongSRS,
|
|
bLineStringAsCurve,
|
|
NULL, nSRSDimensionLocFlags, FALSE) )
|
|
return FALSE;
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:curveMember>" );
|
|
}
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:CompositeCurve>" );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Polygon */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbPolygon || eFType == wkbCurvePolygon )
|
|
{
|
|
OGRCurvePolygon *poCP = (OGRCurvePolygon *) poGeometry;
|
|
|
|
// Buffer for polygon tag name + srsName attribute if set
|
|
const size_t nPolyTagLength = 13;
|
|
char* pszPolyTagName = NULL;
|
|
pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
|
|
|
|
// Compose Polygon tag with or without srsName attribute
|
|
sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
pszPolyTagName );
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszPolyTagName );
|
|
|
|
// Don't add srsName to polygon rings
|
|
|
|
if( poCP->getExteriorRingCurve() != NULL )
|
|
{
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:exterior>" );
|
|
|
|
if( !OGR2GML3GeometryAppend( poCP->getExteriorRingCurve(), poSRS,
|
|
ppszText, pnLength, pnMaxLength,
|
|
TRUE, bLongSRS, bLineStringAsCurve,
|
|
NULL, nSRSDimensionLocFlags, TRUE) )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:exterior>" );
|
|
}
|
|
|
|
for( int iRing = 0; iRing < poCP->getNumInteriorRings(); iRing++ )
|
|
{
|
|
OGRCurve *poRing = poCP->getInteriorRingCurve(iRing);
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"<gml:interior>" );
|
|
|
|
if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength,
|
|
pnMaxLength, TRUE, bLongSRS,
|
|
bLineStringAsCurve,
|
|
NULL, nSRSDimensionLocFlags, TRUE) )
|
|
return FALSE;
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:interior>" );
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength,
|
|
"</gml:Polygon>" );
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* MultiSurface, MultiCurve, MultiPoint, MultiGeometry */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( eFType == wkbMultiPolygon
|
|
|| eFType == wkbMultiSurface
|
|
|| eFType == wkbMultiLineString
|
|
|| eFType == wkbMultiCurve
|
|
|| eFType == wkbMultiPoint
|
|
|| eFType == wkbGeometryCollection )
|
|
{
|
|
OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
|
|
int iMember;
|
|
const char *pszElemClose = NULL;
|
|
const char *pszMemberElem = NULL;
|
|
|
|
// Buffer for opening tag + srsName attribute
|
|
char* pszElemOpen = NULL;
|
|
|
|
if( eFType == wkbMultiPolygon || eFType == wkbMultiSurface )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiSurface%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiSurface>";
|
|
pszMemberElem = "surfaceMember>";
|
|
}
|
|
else if( eFType == wkbMultiLineString || eFType == wkbMultiCurve )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiCurve%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiCurve>";
|
|
pszMemberElem = "curveMember>";
|
|
}
|
|
else if( eFType == wkbMultiPoint )
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiPoint>";
|
|
pszMemberElem = "pointMember>";
|
|
}
|
|
else
|
|
{
|
|
pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
|
|
sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
|
|
|
|
pszElemClose = "MultiGeometry>";
|
|
pszMemberElem = "geometryMember>";
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
|
|
|
|
for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
|
|
{
|
|
OGRGeometry *poMember = poGC->getGeometryRef( iMember );
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
|
|
|
|
char* pszGMLIdSub = NULL;
|
|
if (pszGMLId != NULL)
|
|
pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
|
|
|
|
if( !OGR2GML3GeometryAppend( poMember, poSRS,
|
|
ppszText, pnLength, pnMaxLength,
|
|
TRUE, bLongSRS, bLineStringAsCurve,
|
|
pszGMLIdSub, nSRSDimensionLocFlags, FALSE ) )
|
|
{
|
|
CPLFree(pszGMLIdSub);
|
|
return FALSE;
|
|
}
|
|
|
|
CPLFree(pszGMLIdSub);
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
|
|
}
|
|
|
|
AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
|
|
AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
|
|
|
|
// FREE TAG BUFFER
|
|
CPLFree( pszElemOpen );
|
|
}
|
|
else
|
|
{
|
|
CPLError(CE_Failure, CPLE_NotSupported, "Unsupported geometry type %s",
|
|
OGRGeometryTypeToName(eType));
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToGMLTree() */
|
|
/************************************************************************/
|
|
|
|
CPLXMLNode *OGR_G_ExportToGMLTree( OGRGeometryH hGeometry )
|
|
|
|
{
|
|
char *pszText;
|
|
CPLXMLNode *psTree;
|
|
|
|
pszText = OGR_G_ExportToGML( hGeometry );
|
|
if( pszText == NULL )
|
|
return NULL;
|
|
|
|
psTree = CPLParseXMLString( pszText );
|
|
|
|
CPLFree( pszText );
|
|
|
|
return psTree;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToGML() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Convert a geometry into GML format.
|
|
*
|
|
* The GML geometry is expressed directly in terms of GML basic data
|
|
* types assuming the this is available in the gml namespace. The returned
|
|
* string should be freed with CPLFree() when no longer required.
|
|
*
|
|
* This method is the same as the C++ method OGRGeometry::exportToGML().
|
|
*
|
|
* @param hGeometry handle to the geometry.
|
|
* @return A GML fragment or NULL in case of error.
|
|
*/
|
|
|
|
char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
|
|
|
|
{
|
|
return OGR_G_ExportToGMLEx(hGeometry, NULL);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToGMLEx() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Convert a geometry into GML format.
|
|
*
|
|
* The GML geometry is expressed directly in terms of GML basic data
|
|
* types assuming the this is available in the gml namespace. The returned
|
|
* string should be freed with CPLFree() when no longer required.
|
|
*
|
|
* The supported options are :
|
|
* <ul>
|
|
* <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
|
|
* <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
|
|
* Otherwise gml:LineString will be used .
|
|
* <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
|
|
* be written with the "urn:ogc:def:crs:EPSG::" prefix.
|
|
* In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
|
|
* imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
|
|
* If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
|
|
* <li> GMLID=astring. If specified, a gml:id attribute will be written in the top-level geometry element with the provided value.
|
|
* Required for GML 3.2 compatibility.
|
|
* <li> SRSDIMENSION_LOC=POSLIST/GEOMETRY/GEOMETRY,POSLIST. (Only valid for FORMAT=GML3, GDAL >= 2.0) Default to POSLIST.
|
|
* For 2.5D geometries, define the location where to attach the srsDimension attribute.
|
|
* There are diverging implementations. Some put in on the <gml:posList> element, other
|
|
* on the top geometry element.
|
|
* </ul>
|
|
*
|
|
* Note that curve geometries like CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
|
|
* MULTICURVE or MULTISURFACE are not supported in GML 2.
|
|
*
|
|
* This method is the same as the C++ method OGRGeometry::exportToGML().
|
|
*
|
|
* @param hGeometry handle to the geometry.
|
|
* @param papszOptions NULL-terminated list of options.
|
|
* @return A GML fragment or NULL in case of error.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
|
|
|
|
{
|
|
char *pszText;
|
|
int nLength = 0, nMaxLength = 1;
|
|
|
|
if( hGeometry == NULL )
|
|
return CPLStrdup( "" );
|
|
|
|
pszText = (char *) CPLMalloc(nMaxLength);
|
|
pszText[0] = '\0';
|
|
|
|
const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
|
|
if (pszFormat && EQUAL(pszFormat, "GML3"))
|
|
{
|
|
const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
|
|
int bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
|
|
int bLongSRS = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES"));
|
|
const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
|
|
const char* pszSRSDimensionLoc = CSLFetchNameValueDef(papszOptions,"SRSDIMENSION_LOC","POSLIST");
|
|
char** papszSRSDimensionLoc = CSLTokenizeString2(pszSRSDimensionLoc, ",", 0);
|
|
int nSRSDimensionLocFlags = 0;
|
|
for(int i=0; papszSRSDimensionLoc[i] != NULL; i++)
|
|
{
|
|
if( EQUAL(papszSRSDimensionLoc[i], "POSLIST") )
|
|
nSRSDimensionLocFlags |= SRSDIM_LOC_POSLIST;
|
|
else if( EQUAL(papszSRSDimensionLoc[i], "GEOMETRY") )
|
|
nSRSDimensionLocFlags |= SRSDIM_LOC_GEOMETRY;
|
|
else
|
|
CPLDebug("OGR", "Unrecognized location for srsDimension : %s",
|
|
papszSRSDimensionLoc[i]);
|
|
}
|
|
CSLDestroy(papszSRSDimensionLoc);
|
|
if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
|
|
&nLength, &nMaxLength, FALSE, bLongSRS,
|
|
bLineStringAsCurve, pszGMLId, nSRSDimensionLocFlags, FALSE ))
|
|
{
|
|
CPLFree( pszText );
|
|
return NULL;
|
|
}
|
|
else
|
|
return pszText;
|
|
}
|
|
|
|
if( !OGR2GMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText,
|
|
&nLength, &nMaxLength, FALSE ))
|
|
{
|
|
CPLFree( pszText );
|
|
return NULL;
|
|
}
|
|
else
|
|
return pszText;
|
|
}
|