LCOV - code coverage report
Current view: directory - ogr - ogr2gmlgeometry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 355 309 87.0 %
Date: 2013-03-30 Functions: 11 8 72.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr2gmlgeometry.cpp 25727 2013-03-10 14:56:33Z rouault $
       3                 :  *
       4                 :  * Project:  GML Translator
       5                 :  * Purpose:  Code to translate OGRGeometry to GML string representation.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, 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 OR
      22                 :  * 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                 :  *
      30                 :  * Independent Security Audit 2003/04/17 Andrey Kiselev:
      31                 :  *   Completed audit of this module. All functions may be used without buffer
      32                 :  *   overflows and stack corruptions if caller could be trusted.
      33                 :  *
      34                 :  * Security Audit 2003/03/28 warmerda:
      35                 :  *   Completed security audit.  I believe that this module may be safely used 
      36                 :  *   to generate GML from arbitrary but well formed OGRGeomety objects that
      37                 :  *   come from a potentially hostile source, but through a trusted OGR importer
      38                 :  *   without compromising the system.
      39                 :  *
      40                 :  */
      41                 : 
      42                 : #include "cpl_minixml.h"
      43                 : #include "ogr_geometry.h"
      44                 : #include "ogr_api.h"
      45                 : #include "ogr_p.h"
      46                 : #include "cpl_error.h"
      47                 : #include "cpl_conv.h"
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                        MakeGMLCoordinate()                           */
      51                 : /************************************************************************/
      52                 : 
      53             438 : static void MakeGMLCoordinate( char *pszTarget, 
      54                 :                                double x, double y, double z, int b3D )
      55                 : 
      56                 : {
      57             438 :     OGRMakeWktCoordinate( pszTarget, x, y, z, b3D ? 3 : 2 );
      58           11018 :     while( *pszTarget != '\0' )
      59                 :     {
      60           10142 :         if( *pszTarget == ' ' )
      61             706 :             *pszTarget = ',';
      62           10142 :         pszTarget++;
      63                 :     }
      64                 : 
      65                 : #ifdef notdef
      66                 :     if( !b3D )
      67                 :     {
      68                 :         if( x == (int) x && y == (int) y )
      69                 :             sprintf( pszTarget, "%d,%d", (int) x, (int) y );
      70                 :         else if( fabs(x) < 370 && fabs(y) < 370 )
      71                 :             sprintf( pszTarget, "%.16g,%.16g", x, y );
      72                 :         else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 )
      73                 :             sprintf( pszTarget, "%.16g,%.16g", x, y );
      74                 :         else
      75                 :             sprintf( pszTarget, "%.3f,%.3f", x, y );
      76                 :     }
      77                 :     else
      78                 :     {
      79                 :         if( x == (int) x && y == (int) y && z == (int) z )
      80                 :             sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
      81                 :         else if( fabs(x) < 370 && fabs(y) < 370 )
      82                 :             sprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
      83                 :         else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 
      84                 :                  || fabs(z) > 100000000.0 )
      85                 :             sprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
      86                 :         else
      87                 :             sprintf( pszTarget, "%.3f,%.3f,%.3f", x, y, z );
      88                 :     }
      89                 : #endif
      90             438 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                            _GrowBuffer()                             */
      94                 : /************************************************************************/
      95                 : 
      96            1453 : static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
      97                 : 
      98                 : {
      99            1453 :     if( nNeeded+1 >= *pnMaxLength )
     100                 :     {
     101             362 :         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
     102             362 :         *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
     103                 :     }
     104            1453 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                            AppendString()                            */
     108                 : /************************************************************************/
     109                 : 
     110             574 : static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
     111                 :                           const char *pszTextToAppend )
     112                 : 
     113                 : {
     114                 :     _GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1, 
     115             574 :                  ppszText, pnMaxLength );
     116                 : 
     117             574 :     strcat( *ppszText + *pnLength, pszTextToAppend );
     118             574 :     *pnLength += strlen( *ppszText + *pnLength );
     119             574 : }
     120                 : 
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                        AppendCoordinateList()                        */
     124                 : /************************************************************************/
     125                 : 
     126              44 : static void AppendCoordinateList( OGRLineString *poLine, 
     127                 :                                   char **ppszText, int *pnLength, 
     128                 :                                   int *pnMaxLength )
     129                 : 
     130                 : {
     131                 :     char        szCoordinate[256];
     132              44 :     int         b3D = (poLine->getGeometryType() & wkb25DBit);
     133                 : 
     134              44 :     *pnLength += strlen(*ppszText + *pnLength);
     135              44 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     136                 : 
     137              44 :     strcat( *ppszText + *pnLength, "<gml:coordinates>" );
     138              44 :     *pnLength += strlen(*ppszText + *pnLength);
     139                 : 
     140                 :     
     141             449 :     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     142                 :     {
     143                 :         MakeGMLCoordinate( szCoordinate, 
     144                 :                            poLine->getX(iPoint),
     145                 :                            poLine->getY(iPoint),
     146                 :                            poLine->getZ(iPoint),
     147             405 :                            b3D );
     148                 :         _GrowBuffer( *pnLength + strlen(szCoordinate)+1, 
     149             405 :                      ppszText, pnMaxLength );
     150                 : 
     151             405 :         if( iPoint != 0 )
     152             361 :             strcat( *ppszText + *pnLength, " " );
     153                 :             
     154             405 :         strcat( *ppszText + *pnLength, szCoordinate );
     155             405 :         *pnLength += strlen(*ppszText + *pnLength);
     156                 :     }
     157                 :     
     158              44 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     159              44 :     strcat( *ppszText + *pnLength, "</gml:coordinates>" );
     160              44 :     *pnLength += strlen(*ppszText + *pnLength);
     161              44 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                       OGR2GMLGeometryAppend()                        */
     165                 : /************************************************************************/
     166                 : 
     167             115 : static int OGR2GMLGeometryAppend( OGRGeometry *poGeometry, 
     168                 :                                   char **ppszText, int *pnLength, 
     169                 :                                   int *pnMaxLength,
     170                 :                                   int bIsSubGeometry )
     171                 : 
     172                 : {
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Check for Spatial Reference System attached to given geometry   */
     176                 : /* -------------------------------------------------------------------- */
     177                 : 
     178                 :     // Buffer for srsName attribute (srsName="...")
     179             115 :     char szAttributes[30] = { 0 };
     180             115 :     int nAttrsLength = 0;
     181                 : 
     182             115 :     const OGRSpatialReference* poSRS = NULL;
     183             115 :     poSRS = poGeometry->getSpatialReference();
     184                 : 
     185             115 :     if( NULL != poSRS && !bIsSubGeometry )
     186                 :     {
     187              24 :         const char* pszAuthName = NULL;
     188              24 :         const char* pszAuthCode = NULL;
     189              24 :         const char* pszTarget = NULL;
     190                 : 
     191              24 :         if (poSRS->IsProjected())
     192              12 :             pszTarget = "PROJCS";
     193                 :         else
     194              12 :             pszTarget = "GEOGCS";
     195                 : 
     196              24 :         pszAuthName = poSRS->GetAuthorityName( pszTarget );
     197              24 :         if( NULL != pszAuthName )
     198                 :         {
     199              14 :             if( EQUAL( pszAuthName, "EPSG" ) )
     200                 :             {
     201              14 :                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
     202              14 :                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
     203                 :                 {
     204                 :                     sprintf( szAttributes, " srsName=\"%s:%s\"",
     205              14 :                             pszAuthName, pszAuthCode );
     206                 : 
     207              14 :                     nAttrsLength = strlen(szAttributes);
     208                 :                 }
     209                 :             }
     210                 :         }
     211                 :     }
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      2D Point                                                        */
     215                 : /* -------------------------------------------------------------------- */
     216             115 :     if( poGeometry->getGeometryType() == wkbPoint )
     217                 :     {
     218                 :         char    szCoordinate[256];
     219              29 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     220                 : 
     221                 :         MakeGMLCoordinate( szCoordinate, 
     222              29 :                            poPoint->getX(), poPoint->getY(), 0.0, FALSE );
     223                 : 
     224                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
     225              29 :                      ppszText, pnMaxLength );
     226                 : 
     227                 :         sprintf( *ppszText + *pnLength, 
     228                 :                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
     229              29 :                  szAttributes, szCoordinate );
     230                 : 
     231              29 :         *pnLength += strlen( *ppszText + *pnLength );
     232                 :     }
     233                 : /* -------------------------------------------------------------------- */
     234                 : /*      3D Point                                                        */
     235                 : /* -------------------------------------------------------------------- */
     236              86 :     else if( poGeometry->getGeometryType() == wkbPoint25D )
     237                 :     {
     238                 :         char    szCoordinate[256];
     239               4 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     240                 : 
     241                 :         MakeGMLCoordinate( szCoordinate, 
     242                 :                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
     243               4 :                            TRUE );
     244                 :                            
     245                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
     246               4 :                      ppszText, pnMaxLength );
     247                 : 
     248                 :         sprintf( *ppszText + *pnLength, 
     249                 :                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
     250               4 :                  szAttributes, szCoordinate );
     251                 : 
     252               4 :         *pnLength += strlen( *ppszText + *pnLength );
     253                 :     }
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      LineString and LinearRing                                       */
     257                 : /* -------------------------------------------------------------------- */
     258             135 :     else if( poGeometry->getGeometryType() == wkbLineString 
     259              53 :              || poGeometry->getGeometryType() == wkbLineString25D )
     260                 :     {
     261              44 :         int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
     262                 : 
     263                 :         // Buffer for tag name + srsName attribute if set
     264              44 :         const size_t nLineTagLength = 16;
     265              44 :         char* pszLineTagName = NULL;
     266              44 :         pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
     267                 : 
     268              44 :         if( bRing )
     269                 :         {
     270              26 :             sprintf( pszLineTagName, "<gml:LinearRing%s>", szAttributes );
     271                 : 
     272                 :             AppendString( ppszText, pnLength, pnMaxLength,
     273              26 :                           pszLineTagName );
     274                 :         }
     275                 :         else
     276                 :         {
     277              18 :             sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
     278                 : 
     279                 :             AppendString( ppszText, pnLength, pnMaxLength,
     280              18 :                           pszLineTagName );
     281                 :         }
     282                 : 
     283                 :         // FREE TAG BUFFER
     284              44 :         CPLFree( pszLineTagName );
     285                 : 
     286                 :         AppendCoordinateList( (OGRLineString *) poGeometry, 
     287              44 :                               ppszText, pnLength, pnMaxLength );
     288                 :         
     289              44 :         if( bRing )
     290                 :             AppendString( ppszText, pnLength, pnMaxLength,
     291              26 :                           "</gml:LinearRing>" );
     292                 :         else
     293                 :             AppendString( ppszText, pnLength, pnMaxLength,
     294              18 :                           "</gml:LineString>" );
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Polygon                                                         */
     299                 : /* -------------------------------------------------------------------- */
     300              64 :     else if( poGeometry->getGeometryType() == wkbPolygon 
     301              26 :              || poGeometry->getGeometryType() == wkbPolygon25D )
     302                 :     {
     303              24 :         OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
     304                 : 
     305                 :         // Buffer for polygon tag name + srsName attribute if set
     306              24 :         const size_t nPolyTagLength = 13;
     307              24 :         char* pszPolyTagName = NULL;
     308              24 :         pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
     309                 : 
     310                 :         // Compose Polygon tag with or without srsName attribute
     311              24 :         sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
     312                 : 
     313                 :         AppendString( ppszText, pnLength, pnMaxLength,
     314              24 :                       pszPolyTagName );
     315                 : 
     316                 :         // FREE TAG BUFFER
     317              24 :         CPLFree( pszPolyTagName );
     318                 : 
     319                 :         // Don't add srsName to polygon rings
     320                 : 
     321              24 :         if( poPolygon->getExteriorRing() != NULL )
     322                 :         {
     323                 :             AppendString( ppszText, pnLength, pnMaxLength,
     324              24 :                           "<gml:outerBoundaryIs>" );
     325                 : 
     326              24 :             if( !OGR2GMLGeometryAppend( poPolygon->getExteriorRing(), 
     327                 :                                         ppszText, pnLength, pnMaxLength,
     328                 :                                         TRUE ) )
     329                 :             {
     330               0 :                 return FALSE;
     331                 :             }
     332                 :             
     333                 :             AppendString( ppszText, pnLength, pnMaxLength,
     334              24 :                           "</gml:outerBoundaryIs>" );
     335                 :         }
     336                 : 
     337              26 :         for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
     338                 :         {
     339               2 :             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
     340                 : 
     341                 :             AppendString( ppszText, pnLength, pnMaxLength,
     342               2 :                           "<gml:innerBoundaryIs>" );
     343                 :             
     344               2 :             if( !OGR2GMLGeometryAppend( poRing, ppszText, pnLength, 
     345                 :                                         pnMaxLength, TRUE ) )
     346               0 :                 return FALSE;
     347                 :             
     348                 :             AppendString( ppszText, pnLength, pnMaxLength,
     349               2 :                           "</gml:innerBoundaryIs>" );
     350                 :         }
     351                 : 
     352                 :         AppendString( ppszText, pnLength, pnMaxLength,
     353              24 :                       "</gml:Polygon>" );
     354                 :     }
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      MultiPolygon, MultiLineString, MultiPoint, MultiGeometry        */
     358                 : /* -------------------------------------------------------------------- */
     359              33 :     else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon 
     360              10 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
     361               6 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
     362               3 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     363                 :     {
     364              14 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
     365                 :         int             iMember;
     366              14 :         const char *pszElemClose = NULL;
     367              14 :         const char *pszMemberElem = NULL;
     368                 : 
     369                 :         // Buffer for opening tag + srsName attribute
     370              14 :         char* pszElemOpen = NULL;
     371                 : 
     372              14 :         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
     373                 :         {
     374               4 :             pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
     375               4 :             sprintf( pszElemOpen, "MultiPolygon%s>", szAttributes );
     376                 : 
     377               4 :             pszElemClose = "MultiPolygon>";
     378               4 :             pszMemberElem = "polygonMember>";
     379                 :         }
     380              10 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
     381                 :         {
     382               4 :             pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
     383               4 :             sprintf( pszElemOpen, "MultiLineString%s>", szAttributes );
     384                 : 
     385               4 :             pszElemClose = "MultiLineString>";
     386               4 :             pszMemberElem = "lineStringMember>";
     387                 :         }
     388               6 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
     389                 :         {
     390               3 :             pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
     391               3 :             sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
     392                 : 
     393               3 :             pszElemClose = "MultiPoint>";
     394               3 :             pszMemberElem = "pointMember>";
     395                 :         }
     396                 :         else
     397                 :         {
     398               3 :             pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
     399               3 :             sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
     400                 : 
     401               3 :             pszElemClose = "MultiGeometry>";
     402               3 :             pszMemberElem = "geometryMember>";
     403                 :         }
     404                 : 
     405              14 :         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     406              14 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
     407                 : 
     408              53 :         for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
     409                 :         {
     410              39 :             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
     411                 : 
     412              39 :             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     413              39 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     414                 :             
     415              39 :             if( !OGR2GMLGeometryAppend( poMember, 
     416                 :                                         ppszText, pnLength, pnMaxLength,
     417                 :                                         TRUE ) )
     418                 :             {
     419               0 :                 return FALSE;
     420                 :             }
     421                 :             
     422              39 :             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     423              39 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     424                 :         }
     425                 : 
     426              14 :         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     427              14 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
     428                 : 
     429                 :         // FREE TAG BUFFER
     430              14 :         CPLFree( pszElemOpen );
     431                 :     }
     432                 :     else
     433                 :     {
     434               0 :         return FALSE;
     435                 :     }
     436                 : 
     437             115 :     return TRUE;
     438                 : }
     439                 : 
     440                 : /************************************************************************/
     441                 : /*                   OGR_G_ExportEnvelopeToGMLTree()                    */
     442                 : /*                                                                      */
     443                 : /*      Export the envelope of a geometry as a gml:Box.                 */
     444                 : /************************************************************************/
     445                 : 
     446               0 : CPLXMLNode *OGR_G_ExportEnvelopeToGMLTree( OGRGeometryH hGeometry )
     447                 : 
     448                 : {
     449                 :     CPLXMLNode *psBox, *psCoord;
     450               0 :     OGREnvelope sEnvelope;
     451                 :     char        szCoordinate[256];
     452                 :     char       *pszY;
     453                 : 
     454               0 :     memset( &sEnvelope, 0, sizeof(sEnvelope) );
     455               0 :     ((OGRGeometry *) hGeometry)->getEnvelope( &sEnvelope );
     456                 : 
     457               0 :     if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0 
     458                 :         && sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
     459                 :     {
     460                 :         /* there is apparently a special way of representing a null box
     461                 :            geometry ... we should use it here eventually. */
     462                 : 
     463               0 :         return NULL;
     464                 :     }
     465                 : 
     466               0 :     psBox = CPLCreateXMLNode( NULL, CXT_Element, "gml:Box" );
     467                 : 
     468                 : /* -------------------------------------------------------------------- */
     469                 : /*      Add minxy coordinate.                                           */
     470                 : /* -------------------------------------------------------------------- */
     471               0 :     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
     472                 :     
     473                 :     MakeGMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0, 
     474               0 :                        FALSE );
     475               0 :     pszY = strstr(szCoordinate,",") + 1;
     476               0 :     pszY[-1] = '\0';
     477                 : 
     478               0 :     CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
     479               0 :     CPLCreateXMLElementAndValue( psCoord, "gml:Y", pszY );
     480                 : 
     481                 : /* -------------------------------------------------------------------- */
     482                 : /*      Add maxxy coordinate.                                           */
     483                 : /* -------------------------------------------------------------------- */
     484               0 :     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "gml:coord" );
     485                 :     
     486                 :     MakeGMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0, 
     487               0 :                        FALSE );
     488               0 :     pszY = strstr(szCoordinate,",") + 1;
     489               0 :     pszY[-1] = '\0';
     490                 : 
     491               0 :     CPLCreateXMLElementAndValue( psCoord, "gml:X", szCoordinate );
     492               0 :     CPLCreateXMLElementAndValue( psCoord, "gml:Y", pszY );
     493                 : 
     494               0 :     return psBox;
     495                 : }
     496                 : 
     497                 : 
     498                 : /************************************************************************/
     499                 : /*                     AppendGML3CoordinateList()                       */
     500                 : /************************************************************************/
     501                 : 
     502              24 : static void AppendGML3CoordinateList( OGRLineString *poLine, int bCoordSwap,
     503                 :                                   char **ppszText, int *pnLength,
     504                 :                                   int *pnMaxLength )
     505                 : 
     506                 : {
     507                 :     char        szCoordinate[256];
     508              24 :     int         b3D = (poLine->getGeometryType() & wkb25DBit);
     509                 : 
     510              24 :     *pnLength += strlen(*ppszText + *pnLength);
     511              24 :     _GrowBuffer( *pnLength + 40, ppszText, pnMaxLength );
     512                 : 
     513              24 :     if (b3D)
     514              12 :         strcat( *ppszText + *pnLength, "<gml:posList srsDimension=\"3\">" );
     515                 :     else
     516              12 :         strcat( *ppszText + *pnLength, "<gml:posList>" );
     517              24 :     *pnLength += strlen(*ppszText + *pnLength);
     518                 : 
     519                 : 
     520             313 :     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     521                 :     {
     522             289 :         if (bCoordSwap)
     523                 :             OGRMakeWktCoordinate( szCoordinate,
     524                 :                            poLine->getY(iPoint),
     525                 :                            poLine->getX(iPoint),
     526                 :                            poLine->getZ(iPoint),
     527               0 :                            b3D ? 3 : 2 );
     528                 :         else
     529                 :             OGRMakeWktCoordinate( szCoordinate,
     530                 :                            poLine->getX(iPoint),
     531                 :                            poLine->getY(iPoint),
     532                 :                            poLine->getZ(iPoint),
     533             289 :                            b3D ? 3 : 2 );
     534                 :         _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
     535             289 :                      ppszText, pnMaxLength );
     536                 : 
     537             289 :         if( iPoint != 0 )
     538             265 :             strcat( *ppszText + *pnLength, " " );
     539                 : 
     540             289 :         strcat( *ppszText + *pnLength, szCoordinate );
     541             289 :         *pnLength += strlen(*ppszText + *pnLength);
     542                 :     }
     543                 : 
     544              24 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     545              24 :     strcat( *ppszText + *pnLength, "</gml:posList>" );
     546              24 :     *pnLength += strlen(*ppszText + *pnLength);
     547              24 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                      OGR2GML3GeometryAppend()                        */
     551                 : /************************************************************************/
     552                 : 
     553              59 : static int OGR2GML3GeometryAppend( OGRGeometry *poGeometry,
     554                 :                                    const OGRSpatialReference* poParentSRS,
     555                 :                                   char **ppszText, int *pnLength,
     556                 :                                   int *pnMaxLength,
     557                 :                                   int bIsSubGeometry,
     558                 :                                   int bLongSRS,
     559                 :                                   int bLineStringAsCurve,
     560                 :                                   const char* pszGMLId = NULL)
     561                 : 
     562                 : {
     563                 : 
     564                 : /* -------------------------------------------------------------------- */
     565                 : /*      Check for Spatial Reference System attached to given geometry   */
     566                 : /* -------------------------------------------------------------------- */
     567                 : 
     568                 :     // Buffer for srsName and gml:id attributes (srsName="..." gml:id="...")
     569                 :     char szAttributes[256];
     570              59 :     int nAttrsLength = 0;
     571                 : 
     572              59 :     szAttributes[0] = 0;
     573                 : 
     574              59 :     const OGRSpatialReference* poSRS = NULL;
     575              59 :     if (poParentSRS)
     576              10 :         poSRS = poParentSRS;
     577                 :     else
     578              49 :         poParentSRS = poSRS = poGeometry->getSpatialReference();
     579                 : 
     580              59 :     int bCoordSwap = FALSE;
     581                 : 
     582              59 :     if( NULL != poSRS )
     583                 :     {
     584              31 :         const char* pszAuthName = NULL;
     585              31 :         const char* pszAuthCode = NULL;
     586              31 :         const char* pszTarget = NULL;
     587                 : 
     588              31 :         if (poSRS->IsProjected())
     589              21 :             pszTarget = "PROJCS";
     590                 :         else
     591              10 :             pszTarget = "GEOGCS";
     592                 : 
     593              31 :         pszAuthName = poSRS->GetAuthorityName( pszTarget );
     594              31 :         if( NULL != pszAuthName )
     595                 :         {
     596              11 :             if( EQUAL( pszAuthName, "EPSG" ) )
     597                 :             {
     598              11 :                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
     599              11 :                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
     600                 :                 {
     601              11 :                     if (bLongSRS && !(((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong() ||
     602                 :                                       ((OGRSpatialReference*)poSRS)->EPSGTreatsAsNorthingEasting()))
     603                 :                     {
     604               9 :                         OGRSpatialReference oSRS;
     605               9 :                         if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
     606                 :                         {
     607               9 :                             if (oSRS.EPSGTreatsAsLatLong() || oSRS.EPSGTreatsAsNorthingEasting())
     608               8 :                                 bCoordSwap = TRUE;
     609               9 :                         }
     610                 :                     }
     611                 : 
     612              11 :                     if (!bIsSubGeometry)
     613                 :                     {
     614              11 :                         if (bLongSRS)
     615                 :                         {
     616                 :                             snprintf( szAttributes, sizeof(szAttributes),
     617                 :                                       " srsName=\"urn:ogc:def:crs:%s::%s\"",
     618              10 :                                       pszAuthName, pszAuthCode );
     619                 :                         }
     620                 :                         else
     621                 :                         {
     622                 :                             snprintf( szAttributes, sizeof(szAttributes),
     623                 :                                       " srsName=\"%s:%s\"",
     624               1 :                                       pszAuthName, pszAuthCode );
     625                 :                         }
     626                 : 
     627              11 :                         nAttrsLength = strlen(szAttributes);
     628                 :                     }
     629                 :                 }
     630                 :             }
     631                 :         }
     632                 :     }
     633                 : 
     634              59 :     if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
     635                 :     {
     636               2 :         strcat(szAttributes, " gml:id=\"");
     637               2 :         strcat(szAttributes, pszGMLId);
     638               2 :         strcat(szAttributes, "\"");
     639               2 :         nAttrsLength = strlen(szAttributes);
     640                 :     }
     641                 : 
     642                 : /* -------------------------------------------------------------------- */
     643                 : /*      2D Point                                                        */
     644                 : /* -------------------------------------------------------------------- */
     645              59 :     if( poGeometry->getGeometryType() == wkbPoint )
     646                 :     {
     647                 :         char    szCoordinate[256];
     648              15 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     649                 : 
     650              15 :         if (bCoordSwap)
     651                 :             OGRMakeWktCoordinate( szCoordinate,
     652               8 :                            poPoint->getY(), poPoint->getX(), 0.0, 2 );
     653                 :         else
     654                 :             OGRMakeWktCoordinate( szCoordinate,
     655               7 :                            poPoint->getX(), poPoint->getY(), 0.0, 2 );
     656                 : 
     657                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
     658              15 :                      ppszText, pnMaxLength );
     659                 : 
     660                 :         sprintf( *ppszText + *pnLength,
     661                 :                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
     662              15 :                  szAttributes, szCoordinate );
     663                 : 
     664              15 :         *pnLength += strlen( *ppszText + *pnLength );
     665                 :     }
     666                 : /* -------------------------------------------------------------------- */
     667                 : /*      3D Point                                                        */
     668                 : /* -------------------------------------------------------------------- */
     669              44 :     else if( poGeometry->getGeometryType() == wkbPoint25D )
     670                 :     {
     671                 :         char    szCoordinate[256];
     672               1 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     673                 : 
     674               1 :         if (bCoordSwap)
     675                 :             OGRMakeWktCoordinate( szCoordinate,
     676               0 :                            poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 );
     677                 :         else
     678                 :             OGRMakeWktCoordinate( szCoordinate,
     679               1 :                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
     680                 : 
     681                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
     682               1 :                      ppszText, pnMaxLength );
     683                 : 
     684                 :         sprintf( *ppszText + *pnLength,
     685                 :                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
     686               1 :                  szAttributes, szCoordinate );
     687                 : 
     688               1 :         *pnLength += strlen( *ppszText + *pnLength );
     689                 :     }
     690                 : 
     691                 : /* -------------------------------------------------------------------- */
     692                 : /*      LineString and LinearRing                                       */
     693                 : /* -------------------------------------------------------------------- */
     694              74 :     else if( poGeometry->getGeometryType() == wkbLineString
     695              31 :              || poGeometry->getGeometryType() == wkbLineString25D )
     696                 :     {
     697              24 :         int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
     698              28 :         if (!bRing && bLineStringAsCurve)
     699                 :         {
     700                 :             AppendString( ppszText, pnLength, pnMaxLength,
     701               4 :                             "<gml:Curve" );
     702                 :             AppendString( ppszText, pnLength, pnMaxLength,
     703               4 :                             szAttributes );
     704                 :             AppendString( ppszText, pnLength, pnMaxLength,
     705               4 :                             "><gml:segments><gml:LineStringSegment>" );
     706                 :             AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
     707               4 :                                 ppszText, pnLength, pnMaxLength );
     708                 :             AppendString( ppszText, pnLength, pnMaxLength,
     709               4 :                             "</gml:LineStringSegment></gml:segments></gml:Curve>" );
     710                 :         }
     711                 :         else
     712                 :         {
     713                 :             // Buffer for tag name + srsName attribute if set
     714              20 :             const size_t nLineTagLength = 16;
     715              20 :             char* pszLineTagName = NULL;
     716              20 :             pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
     717                 : 
     718              20 :             if( bRing )
     719                 :             {
     720                 :                 /* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */
     721                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     722              15 :                             "<gml:LinearRing>" );
     723                 :             }
     724                 :             else
     725                 :             {
     726               5 :                 sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
     727                 : 
     728                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     729               5 :                             pszLineTagName );
     730                 :             }
     731                 : 
     732                 :             // FREE TAG BUFFER
     733              20 :             CPLFree( pszLineTagName );
     734                 : 
     735                 :             AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
     736              20 :                                 ppszText, pnLength, pnMaxLength );
     737                 : 
     738              20 :             if( bRing )
     739                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     740              15 :                             "</gml:LinearRing>" );
     741                 :             else
     742                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     743               5 :                             "</gml:LineString>" );
     744                 :         }
     745                 :     }
     746                 : 
     747                 : /* -------------------------------------------------------------------- */
     748                 : /*      Polygon                                                         */
     749                 : /* -------------------------------------------------------------------- */
     750              34 :     else if( poGeometry->getGeometryType() == wkbPolygon
     751              15 :              || poGeometry->getGeometryType() == wkbPolygon25D )
     752                 :     {
     753              14 :         OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
     754                 : 
     755                 :         // Buffer for polygon tag name + srsName attribute if set
     756              14 :         const size_t nPolyTagLength = 13;
     757              14 :         char* pszPolyTagName = NULL;
     758              14 :         pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
     759                 : 
     760                 :         // Compose Polygon tag with or without srsName attribute
     761              14 :         sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
     762                 : 
     763                 :         AppendString( ppszText, pnLength, pnMaxLength,
     764              14 :                       pszPolyTagName );
     765                 : 
     766                 :         // FREE TAG BUFFER
     767              14 :         CPLFree( pszPolyTagName );
     768                 : 
     769                 :         // Don't add srsName to polygon rings
     770                 : 
     771              14 :         if( poPolygon->getExteriorRing() != NULL )
     772                 :         {
     773                 :             AppendString( ppszText, pnLength, pnMaxLength,
     774              14 :                           "<gml:exterior>" );
     775                 : 
     776              14 :             if( !OGR2GML3GeometryAppend( poPolygon->getExteriorRing(), poSRS,
     777                 :                                         ppszText, pnLength, pnMaxLength,
     778                 :                                         TRUE, bLongSRS, bLineStringAsCurve ) )
     779                 :             {
     780               0 :                 return FALSE;
     781                 :             }
     782                 : 
     783                 :             AppendString( ppszText, pnLength, pnMaxLength,
     784              14 :                           "</gml:exterior>" );
     785                 :         }
     786                 : 
     787              15 :         for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
     788                 :         {
     789               1 :             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
     790                 : 
     791                 :             AppendString( ppszText, pnLength, pnMaxLength,
     792               1 :                           "<gml:interior>" );
     793                 : 
     794               1 :             if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength,
     795                 :                                         pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve ) )
     796               0 :                 return FALSE;
     797                 : 
     798                 :             AppendString( ppszText, pnLength, pnMaxLength,
     799               1 :                           "</gml:interior>" );
     800                 :         }
     801                 : 
     802                 :         AppendString( ppszText, pnLength, pnMaxLength,
     803              14 :                       "</gml:Polygon>" );
     804                 :     }
     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      MultiPolygon, MultiLineString, MultiPoint, MultiGeometry        */
     808                 : /* -------------------------------------------------------------------- */
     809              12 :     else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon
     810               4 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
     811               2 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
     812               1 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     813                 :     {
     814               5 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
     815                 :         int             iMember;
     816               5 :         const char *pszElemClose = NULL;
     817               5 :         const char *pszMemberElem = NULL;
     818                 : 
     819                 :         // Buffer for opening tag + srsName attribute
     820               5 :         char* pszElemOpen = NULL;
     821                 : 
     822               5 :         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
     823                 :         {
     824               1 :             pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
     825               1 :             sprintf( pszElemOpen, "MultiSurface%s>", szAttributes );
     826                 : 
     827               1 :             pszElemClose = "MultiSurface>";
     828               1 :             pszMemberElem = "surfaceMember>";
     829                 :         }
     830               4 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
     831                 :         {
     832               2 :             pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
     833               2 :             sprintf( pszElemOpen, "MultiCurve%s>", szAttributes );
     834                 : 
     835               2 :             pszElemClose = "MultiCurve>";
     836               2 :             pszMemberElem = "curveMember>";
     837                 :         }
     838               2 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
     839                 :         {
     840               1 :             pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
     841               1 :             sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
     842                 : 
     843               1 :             pszElemClose = "MultiPoint>";
     844               1 :             pszMemberElem = "pointMember>";
     845                 :         }
     846                 :         else
     847                 :         {
     848               1 :             pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
     849               1 :             sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
     850                 : 
     851               1 :             pszElemClose = "MultiGeometry>";
     852               1 :             pszMemberElem = "geometryMember>";
     853                 :         }
     854                 : 
     855               5 :         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     856               5 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
     857                 : 
     858              15 :         for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
     859                 :         {
     860              10 :             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
     861                 : 
     862              10 :             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     863              10 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     864                 : 
     865              10 :             char* pszGMLIdSub = NULL;
     866              10 :             if (pszGMLId != NULL)
     867               0 :                 pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
     868                 : 
     869              10 :             if( !OGR2GML3GeometryAppend( poMember, poSRS,
     870                 :                                         ppszText, pnLength, pnMaxLength,
     871                 :                                         TRUE, bLongSRS, bLineStringAsCurve,
     872                 :                                          pszGMLIdSub) )
     873                 :             {
     874               0 :                 CPLFree(pszGMLIdSub);
     875               0 :                 return FALSE;
     876                 :             }
     877                 : 
     878              10 :             CPLFree(pszGMLIdSub);
     879                 : 
     880              10 :             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     881              10 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     882                 :         }
     883                 : 
     884               5 :         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     885               5 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
     886                 : 
     887                 :         // FREE TAG BUFFER
     888               5 :         CPLFree( pszElemOpen );
     889                 :     }
     890                 :     else
     891                 :     {
     892               0 :         return FALSE;
     893                 :     }
     894                 : 
     895              59 :     return TRUE;
     896                 : }
     897                 : 
     898                 : /************************************************************************/
     899                 : /*                       OGR_G_ExportToGMLTree()                        */
     900                 : /************************************************************************/
     901                 : 
     902               0 : CPLXMLNode *OGR_G_ExportToGMLTree( OGRGeometryH hGeometry )
     903                 : 
     904                 : {
     905                 :     char        *pszText;
     906                 :     CPLXMLNode  *psTree;
     907                 : 
     908               0 :     pszText = OGR_G_ExportToGML( hGeometry );
     909               0 :     if( pszText == NULL )
     910               0 :         return NULL;
     911                 : 
     912               0 :     psTree = CPLParseXMLString( pszText );
     913                 : 
     914               0 :     CPLFree( pszText );
     915                 : 
     916               0 :     return psTree;
     917                 : }
     918                 : 
     919                 : /************************************************************************/
     920                 : /*                         OGR_G_ExportToGML()                          */
     921                 : /************************************************************************/
     922                 : 
     923                 : /**
     924                 :  * \brief Convert a geometry into GML format.
     925                 :  *
     926                 :  * The GML geometry is expressed directly in terms of GML basic data
     927                 :  * types assuming the this is available in the gml namespace.  The returned
     928                 :  * string should be freed with CPLFree() when no longer required.
     929                 :  *
     930                 :  * This method is the same as the C++ method OGRGeometry::exportToGML().
     931                 :  *
     932                 :  * @param hGeometry handle to the geometry.
     933                 :  * @return A GML fragment or NULL in case of error.
     934                 :  */
     935                 : 
     936               0 : char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
     937                 : 
     938                 : {
     939               0 :     return OGR_G_ExportToGMLEx(hGeometry, NULL);
     940                 : }
     941                 : 
     942                 : /************************************************************************/
     943                 : /*                        OGR_G_ExportToGMLEx()                         */
     944                 : /************************************************************************/
     945                 : 
     946                 : /**
     947                 :  * \brief Convert a geometry into GML format.
     948                 :  *
     949                 :  * The GML geometry is expressed directly in terms of GML basic data
     950                 :  * types assuming the this is available in the gml namespace.  The returned
     951                 :  * string should be freed with CPLFree() when no longer required.
     952                 :  *
     953                 :  * The supported options in OGR 1.8.0 are :
     954                 :  * <ul>
     955                 :  * <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
     956                 :  * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
     957                 :  *     Otherwise gml:LineString will be used .
     958                 :  * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
     959                 :  *      be written with the "urn:ogc:def:crs:EPSG::" prefix.
     960                 :  *      In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
     961                 :  *      imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
     962                 :  *      If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
     963                 :  * <li> GMLID=astring. If specified, a gml:id attribute will be written in the top-level geometry element with the provided value.
     964                 :  *      Required for GML 3.2 compatibility.
     965                 :  * </ul>
     966                 :  *
     967                 :  * This method is the same as the C++ method OGRGeometry::exportToGML().
     968                 :  *
     969                 :  * @param hGeometry handle to the geometry.
     970                 :  * @param papszOptions NULL-terminated list of options.
     971                 :  * @return A GML fragment or NULL in case of error.
     972                 :  *
     973                 :  * @since OGR 1.8.0
     974                 :  */
     975                 : 
     976              84 : char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
     977                 : 
     978                 : {
     979                 :     char        *pszText;
     980              84 :     int         nLength = 0, nMaxLength = 1;
     981                 : 
     982              84 :     if( hGeometry == NULL )
     983               0 :         return CPLStrdup( "" );
     984                 : 
     985              84 :     pszText = (char *) CPLMalloc(nMaxLength);
     986              84 :     pszText[0] = '\0';
     987                 : 
     988              84 :     const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
     989              84 :     if (pszFormat && EQUAL(pszFormat, "GML3"))
     990                 :     {
     991              34 :         const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
     992              34 :         int bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
     993              34 :         int bLongSRS = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES"));
     994              34 :         const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
     995              34 :         if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
     996                 :                                     &nLength, &nMaxLength, FALSE, bLongSRS, bLineStringAsCurve, pszGMLId ))
     997                 :         {
     998               0 :             CPLFree( pszText );
     999               0 :             return NULL;
    1000                 :         }
    1001                 :         else
    1002              34 :             return pszText;
    1003                 :     }
    1004                 : 
    1005              50 :     if( !OGR2GMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText,
    1006                 :                                 &nLength, &nMaxLength, FALSE ))
    1007                 :     {
    1008               0 :         CPLFree( pszText );
    1009               0 :         return NULL;
    1010                 :     }
    1011                 :     else
    1012              50 :         return pszText;
    1013                 : }

Generated by: LCOV version 1.7