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: 2012-04-28 Functions: 11 8 72.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr2gmlgeometry.cpp 23502 2011-12-09 18:49:24Z 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             804 : static void MakeGMLCoordinate( char *pszTarget, 
      54                 :                                double x, double y, double z, int b3D )
      55                 : 
      56                 : {
      57             804 :     OGRMakeWktCoordinate( pszTarget, x, y, z, b3D ? 3 : 2 );
      58           21394 :     while( *pszTarget != '\0' )
      59                 :     {
      60           19786 :         if( *pszTarget == ' ' )
      61            1340 :             *pszTarget = ',';
      62           19786 :         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             804 : }
      91                 : 
      92                 : /************************************************************************/
      93                 : /*                            _GrowBuffer()                             */
      94                 : /************************************************************************/
      95                 : 
      96            2680 : static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
      97                 : 
      98                 : {
      99            2680 :     if( nNeeded+1 >= *pnMaxLength )
     100                 :     {
     101             650 :         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
     102             650 :         *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
     103                 :     }
     104            2680 : }
     105                 : 
     106                 : /************************************************************************/
     107                 : /*                            AppendString()                            */
     108                 : /************************************************************************/
     109                 : 
     110            1020 : static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
     111                 :                           const char *pszTextToAppend )
     112                 : 
     113                 : {
     114                 :     _GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1, 
     115            1020 :                  ppszText, pnMaxLength );
     116                 : 
     117            1020 :     strcat( *ppszText + *pnLength, pszTextToAppend );
     118            1020 :     *pnLength += strlen( *ppszText + *pnLength );
     119            1020 : }
     120                 : 
     121                 : 
     122                 : /************************************************************************/
     123                 : /*                        AppendCoordinateList()                        */
     124                 : /************************************************************************/
     125                 : 
     126              76 : static void AppendCoordinateList( OGRLineString *poLine, 
     127                 :                                   char **ppszText, int *pnLength, 
     128                 :                                   int *pnMaxLength )
     129                 : 
     130                 : {
     131                 :     char        szCoordinate[256];
     132              76 :     int         b3D = (poLine->getGeometryType() & wkb25DBit);
     133                 : 
     134              76 :     *pnLength += strlen(*ppszText + *pnLength);
     135              76 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     136                 : 
     137              76 :     strcat( *ppszText + *pnLength, "<gml:coordinates>" );
     138              76 :     *pnLength += strlen(*ppszText + *pnLength);
     139                 : 
     140                 :     
     141             838 :     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             762 :                            b3D );
     148                 :         _GrowBuffer( *pnLength + strlen(szCoordinate)+1, 
     149             762 :                      ppszText, pnMaxLength );
     150                 : 
     151             762 :         if( iPoint != 0 )
     152             686 :             strcat( *ppszText + *pnLength, " " );
     153                 :             
     154             762 :         strcat( *ppszText + *pnLength, szCoordinate );
     155             762 :         *pnLength += strlen(*ppszText + *pnLength);
     156                 :     }
     157                 :     
     158              76 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     159              76 :     strcat( *ppszText + *pnLength, "</gml:coordinates>" );
     160              76 :     *pnLength += strlen(*ppszText + *pnLength);
     161              76 : }
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                       OGR2GMLGeometryAppend()                        */
     165                 : /************************************************************************/
     166                 : 
     167             180 : 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             180 :     char szAttributes[30] = { 0 };
     180             180 :     int nAttrsLength = 0;
     181                 : 
     182             180 :     const OGRSpatialReference* poSRS = NULL;
     183             180 :     poSRS = poGeometry->getSpatialReference();
     184                 : 
     185             180 :     if( NULL != poSRS && !bIsSubGeometry )
     186                 :     {
     187              36 :         const char* pszAuthName = NULL;
     188              36 :         const char* pszAuthCode = NULL;
     189              36 :         const char* pszTarget = NULL;
     190                 : 
     191              36 :         if (poSRS->IsProjected())
     192              20 :             pszTarget = "PROJCS";
     193                 :         else
     194              16 :             pszTarget = "GEOGCS";
     195                 : 
     196              36 :         pszAuthName = poSRS->GetAuthorityName( pszTarget );
     197              36 :         if( NULL != pszAuthName )
     198                 :         {
     199              16 :             if( EQUAL( pszAuthName, "EPSG" ) )
     200                 :             {
     201              16 :                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
     202              16 :                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
     203                 :                 {
     204                 :                     sprintf( szAttributes, " srsName=\"%s:%s\"",
     205              16 :                             pszAuthName, pszAuthCode );
     206                 : 
     207              16 :                     nAttrsLength = strlen(szAttributes);
     208                 :                 }
     209                 :             }
     210                 :         }
     211                 :     }
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      2D Point                                                        */
     215                 : /* -------------------------------------------------------------------- */
     216             180 :     if( poGeometry->getGeometryType() == wkbPoint )
     217                 :     {
     218                 :         char    szCoordinate[256];
     219              34 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     220                 : 
     221                 :         MakeGMLCoordinate( szCoordinate, 
     222              34 :                            poPoint->getX(), poPoint->getY(), 0.0, FALSE );
     223                 : 
     224                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
     225              34 :                      ppszText, pnMaxLength );
     226                 : 
     227                 :         sprintf( *ppszText + *pnLength, 
     228                 :                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
     229              34 :                  szAttributes, szCoordinate );
     230                 : 
     231              34 :         *pnLength += strlen( *ppszText + *pnLength );
     232                 :     }
     233                 : /* -------------------------------------------------------------------- */
     234                 : /*      3D Point                                                        */
     235                 : /* -------------------------------------------------------------------- */
     236             146 :     else if( poGeometry->getGeometryType() == wkbPoint25D )
     237                 :     {
     238                 :         char    szCoordinate[256];
     239               8 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     240                 : 
     241                 :         MakeGMLCoordinate( szCoordinate, 
     242                 :                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
     243               8 :                            TRUE );
     244                 :                            
     245                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
     246               8 :                      ppszText, pnMaxLength );
     247                 : 
     248                 :         sprintf( *ppszText + *pnLength, 
     249                 :                 "<gml:Point%s><gml:coordinates>%s</gml:coordinates></gml:Point>",
     250               8 :                  szAttributes, szCoordinate );
     251                 : 
     252               8 :         *pnLength += strlen( *ppszText + *pnLength );
     253                 :     }
     254                 : 
     255                 : /* -------------------------------------------------------------------- */
     256                 : /*      LineString and LinearRing                                       */
     257                 : /* -------------------------------------------------------------------- */
     258             230 :     else if( poGeometry->getGeometryType() == wkbLineString 
     259              92 :              || poGeometry->getGeometryType() == wkbLineString25D )
     260                 :     {
     261              76 :         int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
     262                 : 
     263                 :         // Buffer for tag name + srsName attribute if set
     264              76 :         const size_t nLineTagLength = 16;
     265              76 :         char* pszLineTagName = NULL;
     266              76 :         pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
     267                 : 
     268              76 :         if( bRing )
     269                 :         {
     270              46 :             sprintf( pszLineTagName, "<gml:LinearRing%s>", szAttributes );
     271                 : 
     272                 :             AppendString( ppszText, pnLength, pnMaxLength,
     273              46 :                           pszLineTagName );
     274                 :         }
     275                 :         else
     276                 :         {
     277              30 :             sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
     278                 : 
     279                 :             AppendString( ppszText, pnLength, pnMaxLength,
     280              30 :                           pszLineTagName );
     281                 :         }
     282                 : 
     283                 :         // FREE TAG BUFFER
     284              76 :         CPLFree( pszLineTagName );
     285                 : 
     286                 :         AppendCoordinateList( (OGRLineString *) poGeometry, 
     287              76 :                               ppszText, pnLength, pnMaxLength );
     288                 :         
     289              76 :         if( bRing )
     290                 :             AppendString( ppszText, pnLength, pnMaxLength,
     291              46 :                           "</gml:LinearRing>" );
     292                 :         else
     293                 :             AppendString( ppszText, pnLength, pnMaxLength,
     294              30 :                           "</gml:LineString>" );
     295                 :     }
     296                 : 
     297                 : /* -------------------------------------------------------------------- */
     298                 : /*      Polygon                                                         */
     299                 : /* -------------------------------------------------------------------- */
     300             106 :     else if( poGeometry->getGeometryType() == wkbPolygon 
     301              44 :              || poGeometry->getGeometryType() == wkbPolygon25D )
     302                 :     {
     303              42 :         OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
     304                 : 
     305                 :         // Buffer for polygon tag name + srsName attribute if set
     306              42 :         const size_t nPolyTagLength = 13;
     307              42 :         char* pszPolyTagName = NULL;
     308              42 :         pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
     309                 : 
     310                 :         // Compose Polygon tag with or without srsName attribute
     311              42 :         sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
     312                 : 
     313                 :         AppendString( ppszText, pnLength, pnMaxLength,
     314              42 :                       pszPolyTagName );
     315                 : 
     316                 :         // FREE TAG BUFFER
     317              42 :         CPLFree( pszPolyTagName );
     318                 : 
     319                 :         // Don't add srsName to polygon rings
     320                 : 
     321              42 :         if( poPolygon->getExteriorRing() != NULL )
     322                 :         {
     323                 :             AppendString( ppszText, pnLength, pnMaxLength,
     324              42 :                           "<gml:outerBoundaryIs>" );
     325                 : 
     326              42 :             if( !OGR2GMLGeometryAppend( poPolygon->getExteriorRing(), 
     327                 :                                         ppszText, pnLength, pnMaxLength,
     328                 :                                         TRUE ) )
     329                 :             {
     330               0 :                 return FALSE;
     331                 :             }
     332                 :             
     333                 :             AppendString( ppszText, pnLength, pnMaxLength,
     334              42 :                           "</gml:outerBoundaryIs>" );
     335                 :         }
     336                 : 
     337              46 :         for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
     338                 :         {
     339               4 :             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
     340                 : 
     341                 :             AppendString( ppszText, pnLength, pnMaxLength,
     342               4 :                           "<gml:innerBoundaryIs>" );
     343                 :             
     344               4 :             if( !OGR2GMLGeometryAppend( poRing, ppszText, pnLength, 
     345                 :                                         pnMaxLength, TRUE ) )
     346               0 :                 return FALSE;
     347                 :             
     348                 :             AppendString( ppszText, pnLength, pnMaxLength,
     349               4 :                           "</gml:innerBoundaryIs>" );
     350                 :         }
     351                 : 
     352                 :         AppendString( ppszText, pnLength, pnMaxLength,
     353              42 :                       "</gml:Polygon>" );
     354                 :     }
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      MultiPolygon, MultiLineString, MultiPoint, MultiGeometry        */
     358                 : /* -------------------------------------------------------------------- */
     359              54 :     else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon 
     360              16 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
     361              12 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
     362               6 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     363                 :     {
     364              20 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
     365                 :         int             iMember;
     366              20 :         const char *pszElemClose = NULL;
     367              20 :         const char *pszMemberElem = NULL;
     368                 : 
     369                 :         // Buffer for opening tag + srsName attribute
     370              20 :         char* pszElemOpen = NULL;
     371                 : 
     372              20 :         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              16 :         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              12 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
     389                 :         {
     390               6 :             pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
     391               6 :             sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
     392                 : 
     393               6 :             pszElemClose = "MultiPoint>";
     394               6 :             pszMemberElem = "pointMember>";
     395                 :         }
     396                 :         else
     397                 :         {
     398               6 :             pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
     399               6 :             sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
     400                 : 
     401               6 :             pszElemClose = "MultiGeometry>";
     402               6 :             pszMemberElem = "geometryMember>";
     403                 :         }
     404                 : 
     405              20 :         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     406              20 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
     407                 : 
     408              86 :         for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
     409                 :         {
     410              66 :             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
     411                 : 
     412              66 :             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     413              66 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     414                 :             
     415              66 :             if( !OGR2GMLGeometryAppend( poMember, 
     416                 :                                         ppszText, pnLength, pnMaxLength,
     417                 :                                         TRUE ) )
     418                 :             {
     419               0 :                 return FALSE;
     420                 :             }
     421                 :             
     422              66 :             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     423              66 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     424                 :         }
     425                 : 
     426              20 :         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     427              20 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
     428                 : 
     429                 :         // FREE TAG BUFFER
     430              20 :         CPLFree( pszElemOpen );
     431                 :     }
     432                 :     else
     433                 :     {
     434               0 :         return FALSE;
     435                 :     }
     436                 : 
     437             180 :     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              48 : static void AppendGML3CoordinateList( OGRLineString *poLine, int bCoordSwap,
     503                 :                                   char **ppszText, int *pnLength,
     504                 :                                   int *pnMaxLength )
     505                 : 
     506                 : {
     507                 :     char        szCoordinate[256];
     508              48 :     int         b3D = (poLine->getGeometryType() & wkb25DBit);
     509                 : 
     510              48 :     *pnLength += strlen(*ppszText + *pnLength);
     511              48 :     _GrowBuffer( *pnLength + 40, ppszText, pnMaxLength );
     512                 : 
     513              48 :     if (b3D)
     514              24 :         strcat( *ppszText + *pnLength, "<gml:posList srsDimension=\"3\">" );
     515                 :     else
     516              24 :         strcat( *ppszText + *pnLength, "<gml:posList>" );
     517              48 :     *pnLength += strlen(*ppszText + *pnLength);
     518                 : 
     519                 : 
     520             626 :     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     521                 :     {
     522             578 :         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             578 :                            b3D ? 3 : 2 );
     534                 :         _GrowBuffer( *pnLength + strlen(szCoordinate)+1,
     535             578 :                      ppszText, pnMaxLength );
     536                 : 
     537             578 :         if( iPoint != 0 )
     538             530 :             strcat( *ppszText + *pnLength, " " );
     539                 : 
     540             578 :         strcat( *ppszText + *pnLength, szCoordinate );
     541             578 :         *pnLength += strlen(*ppszText + *pnLength);
     542                 :     }
     543                 : 
     544              48 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     545              48 :     strcat( *ppszText + *pnLength, "</gml:posList>" );
     546              48 :     *pnLength += strlen(*ppszText + *pnLength);
     547              48 : }
     548                 : 
     549                 : /************************************************************************/
     550                 : /*                      OGR2GML3GeometryAppend()                        */
     551                 : /************************************************************************/
     552                 : 
     553             116 : 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             116 :     int nAttrsLength = 0;
     571                 : 
     572             116 :     szAttributes[0] = 0;
     573                 : 
     574             116 :     const OGRSpatialReference* poSRS = NULL;
     575             116 :     if (poParentSRS)
     576              20 :         poSRS = poParentSRS;
     577                 :     else
     578              96 :         poParentSRS = poSRS = poGeometry->getSpatialReference();
     579                 : 
     580             116 :     int bCoordSwap = FALSE;
     581                 : 
     582             116 :     if( NULL != poSRS )
     583                 :     {
     584              60 :         const char* pszAuthName = NULL;
     585              60 :         const char* pszAuthCode = NULL;
     586              60 :         const char* pszTarget = NULL;
     587                 : 
     588              60 :         if (poSRS->IsProjected())
     589              42 :             pszTarget = "PROJCS";
     590                 :         else
     591              18 :             pszTarget = "GEOGCS";
     592                 : 
     593              60 :         pszAuthName = poSRS->GetAuthorityName( pszTarget );
     594              60 :         if( NULL != pszAuthName )
     595                 :         {
     596              20 :             if( EQUAL( pszAuthName, "EPSG" ) )
     597                 :             {
     598              20 :                 pszAuthCode = poSRS->GetAuthorityCode( pszTarget );
     599              20 :                 if( NULL != pszAuthCode && strlen(pszAuthCode) < 10 )
     600                 :                 {
     601              20 :                     if (bLongSRS && !((OGRSpatialReference*)poSRS)->EPSGTreatsAsLatLong())
     602                 :                     {
     603              16 :                         OGRSpatialReference oSRS;
     604              16 :                         if (oSRS.importFromEPSGA(atoi(pszAuthCode)) == OGRERR_NONE)
     605                 :                         {
     606              16 :                             if (oSRS.EPSGTreatsAsLatLong())
     607              14 :                                 bCoordSwap = TRUE;
     608              16 :                         }
     609                 :                     }
     610                 : 
     611              20 :                     if (!bIsSubGeometry)
     612                 :                     {
     613              20 :                         if (bLongSRS)
     614                 :                         {
     615                 :                             snprintf( szAttributes, sizeof(szAttributes),
     616                 :                                       " srsName=\"urn:ogc:def:crs:%s::%s\"",
     617              18 :                                       pszAuthName, pszAuthCode );
     618                 :                         }
     619                 :                         else
     620                 :                         {
     621                 :                             snprintf( szAttributes, sizeof(szAttributes),
     622                 :                                       " srsName=\"%s:%s\"",
     623               2 :                                       pszAuthName, pszAuthCode );
     624                 :                         }
     625                 : 
     626              20 :                         nAttrsLength = strlen(szAttributes);
     627                 :                     }
     628                 :                 }
     629                 :             }
     630                 :         }
     631                 :     }
     632                 : 
     633             116 :     if (pszGMLId != NULL && nAttrsLength + 9 + strlen(pszGMLId) + 1 < sizeof(szAttributes))
     634                 :     {
     635               4 :         strcat(szAttributes, " gml:id=\"");
     636               4 :         strcat(szAttributes, pszGMLId);
     637               4 :         strcat(szAttributes, "\"");
     638               4 :         nAttrsLength = strlen(szAttributes);
     639                 :     }
     640                 : 
     641                 : /* -------------------------------------------------------------------- */
     642                 : /*      2D Point                                                        */
     643                 : /* -------------------------------------------------------------------- */
     644             116 :     if( poGeometry->getGeometryType() == wkbPoint )
     645                 :     {
     646                 :         char    szCoordinate[256];
     647              28 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     648                 : 
     649              28 :         if (bCoordSwap)
     650                 :             OGRMakeWktCoordinate( szCoordinate,
     651              14 :                            poPoint->getY(), poPoint->getX(), 0.0, 2 );
     652                 :         else
     653                 :             OGRMakeWktCoordinate( szCoordinate,
     654              14 :                            poPoint->getX(), poPoint->getY(), 0.0, 2 );
     655                 : 
     656                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 60 + nAttrsLength,
     657              28 :                      ppszText, pnMaxLength );
     658                 : 
     659                 :         sprintf( *ppszText + *pnLength,
     660                 :                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
     661              28 :                  szAttributes, szCoordinate );
     662                 : 
     663              28 :         *pnLength += strlen( *ppszText + *pnLength );
     664                 :     }
     665                 : /* -------------------------------------------------------------------- */
     666                 : /*      3D Point                                                        */
     667                 : /* -------------------------------------------------------------------- */
     668              88 :     else if( poGeometry->getGeometryType() == wkbPoint25D )
     669                 :     {
     670                 :         char    szCoordinate[256];
     671               2 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     672                 : 
     673               2 :         if (bCoordSwap)
     674                 :             OGRMakeWktCoordinate( szCoordinate,
     675               0 :                            poPoint->getY(), poPoint->getX(), poPoint->getZ(), 3 );
     676                 :         else
     677                 :             OGRMakeWktCoordinate( szCoordinate,
     678               2 :                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3 );
     679                 : 
     680                 :         _GrowBuffer( *pnLength + strlen(szCoordinate) + 70 + nAttrsLength,
     681               2 :                      ppszText, pnMaxLength );
     682                 : 
     683                 :         sprintf( *ppszText + *pnLength,
     684                 :                 "<gml:Point%s><gml:pos>%s</gml:pos></gml:Point>",
     685               2 :                  szAttributes, szCoordinate );
     686                 : 
     687               2 :         *pnLength += strlen( *ppszText + *pnLength );
     688                 :     }
     689                 : 
     690                 : /* -------------------------------------------------------------------- */
     691                 : /*      LineString and LinearRing                                       */
     692                 : /* -------------------------------------------------------------------- */
     693             148 :     else if( poGeometry->getGeometryType() == wkbLineString
     694              62 :              || poGeometry->getGeometryType() == wkbLineString25D )
     695                 :     {
     696              48 :         int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
     697              56 :         if (!bRing && bLineStringAsCurve)
     698                 :         {
     699                 :             AppendString( ppszText, pnLength, pnMaxLength,
     700               8 :                             "<gml:Curve" );
     701                 :             AppendString( ppszText, pnLength, pnMaxLength,
     702               8 :                             szAttributes );
     703                 :             AppendString( ppszText, pnLength, pnMaxLength,
     704               8 :                             "><gml:segments><gml:LineStringSegment>" );
     705                 :             AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
     706               8 :                                 ppszText, pnLength, pnMaxLength );
     707                 :             AppendString( ppszText, pnLength, pnMaxLength,
     708               8 :                             "</gml:LineStringSegment></gml:segments></gml:Curve>" );
     709                 :         }
     710                 :         else
     711                 :         {
     712                 :             // Buffer for tag name + srsName attribute if set
     713              40 :             const size_t nLineTagLength = 16;
     714              40 :             char* pszLineTagName = NULL;
     715              40 :             pszLineTagName = (char *) CPLMalloc( nLineTagLength + nAttrsLength + 1 );
     716                 : 
     717              40 :             if( bRing )
     718                 :             {
     719                 :                 /* LinearRing isn't supposed to have srsName attribute according to GML3 SF-0 */
     720                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     721              30 :                             "<gml:LinearRing>" );
     722                 :             }
     723                 :             else
     724                 :             {
     725              10 :                 sprintf( pszLineTagName, "<gml:LineString%s>", szAttributes );
     726                 : 
     727                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     728              10 :                             pszLineTagName );
     729                 :             }
     730                 : 
     731                 :             // FREE TAG BUFFER
     732              40 :             CPLFree( pszLineTagName );
     733                 : 
     734                 :             AppendGML3CoordinateList( (OGRLineString *) poGeometry, bCoordSwap,
     735              40 :                                 ppszText, pnLength, pnMaxLength );
     736                 : 
     737              40 :             if( bRing )
     738                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     739              30 :                             "</gml:LinearRing>" );
     740                 :             else
     741                 :                 AppendString( ppszText, pnLength, pnMaxLength,
     742              10 :                             "</gml:LineString>" );
     743                 :         }
     744                 :     }
     745                 : 
     746                 : /* -------------------------------------------------------------------- */
     747                 : /*      Polygon                                                         */
     748                 : /* -------------------------------------------------------------------- */
     749              68 :     else if( poGeometry->getGeometryType() == wkbPolygon
     750              30 :              || poGeometry->getGeometryType() == wkbPolygon25D )
     751                 :     {
     752              28 :         OGRPolygon      *poPolygon = (OGRPolygon *) poGeometry;
     753                 : 
     754                 :         // Buffer for polygon tag name + srsName attribute if set
     755              28 :         const size_t nPolyTagLength = 13;
     756              28 :         char* pszPolyTagName = NULL;
     757              28 :         pszPolyTagName = (char *) CPLMalloc( nPolyTagLength + nAttrsLength + 1 );
     758                 : 
     759                 :         // Compose Polygon tag with or without srsName attribute
     760              28 :         sprintf( pszPolyTagName, "<gml:Polygon%s>", szAttributes );
     761                 : 
     762                 :         AppendString( ppszText, pnLength, pnMaxLength,
     763              28 :                       pszPolyTagName );
     764                 : 
     765                 :         // FREE TAG BUFFER
     766              28 :         CPLFree( pszPolyTagName );
     767                 : 
     768                 :         // Don't add srsName to polygon rings
     769                 : 
     770              28 :         if( poPolygon->getExteriorRing() != NULL )
     771                 :         {
     772                 :             AppendString( ppszText, pnLength, pnMaxLength,
     773              28 :                           "<gml:exterior>" );
     774                 : 
     775              28 :             if( !OGR2GML3GeometryAppend( poPolygon->getExteriorRing(), poSRS,
     776                 :                                         ppszText, pnLength, pnMaxLength,
     777                 :                                         TRUE, bLongSRS, bLineStringAsCurve ) )
     778                 :             {
     779               0 :                 return FALSE;
     780                 :             }
     781                 : 
     782                 :             AppendString( ppszText, pnLength, pnMaxLength,
     783              28 :                           "</gml:exterior>" );
     784                 :         }
     785                 : 
     786              30 :         for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
     787                 :         {
     788               2 :             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
     789                 : 
     790                 :             AppendString( ppszText, pnLength, pnMaxLength,
     791               2 :                           "<gml:interior>" );
     792                 : 
     793               2 :             if( !OGR2GML3GeometryAppend( poRing, poSRS, ppszText, pnLength,
     794                 :                                         pnMaxLength, TRUE, bLongSRS, bLineStringAsCurve ) )
     795               0 :                 return FALSE;
     796                 : 
     797                 :             AppendString( ppszText, pnLength, pnMaxLength,
     798               2 :                           "</gml:interior>" );
     799                 :         }
     800                 : 
     801                 :         AppendString( ppszText, pnLength, pnMaxLength,
     802              28 :                       "</gml:Polygon>" );
     803                 :     }
     804                 : 
     805                 : /* -------------------------------------------------------------------- */
     806                 : /*      MultiPolygon, MultiLineString, MultiPoint, MultiGeometry        */
     807                 : /* -------------------------------------------------------------------- */
     808              24 :     else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon
     809               8 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
     810               4 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
     811               2 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     812                 :     {
     813              10 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeometry;
     814                 :         int             iMember;
     815              10 :         const char *pszElemClose = NULL;
     816              10 :         const char *pszMemberElem = NULL;
     817                 : 
     818                 :         // Buffer for opening tag + srsName attribute
     819              10 :         char* pszElemOpen = NULL;
     820                 : 
     821              10 :         if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
     822                 :         {
     823               2 :             pszElemOpen = (char *) CPLMalloc( 13 + nAttrsLength + 1 );
     824               2 :             sprintf( pszElemOpen, "MultiSurface%s>", szAttributes );
     825                 : 
     826               2 :             pszElemClose = "MultiSurface>";
     827               2 :             pszMemberElem = "surfaceMember>";
     828                 :         }
     829               8 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
     830                 :         {
     831               4 :             pszElemOpen = (char *) CPLMalloc( 16 + nAttrsLength + 1 );
     832               4 :             sprintf( pszElemOpen, "MultiCurve%s>", szAttributes );
     833                 : 
     834               4 :             pszElemClose = "MultiCurve>";
     835               4 :             pszMemberElem = "curveMember>";
     836                 :         }
     837               4 :         else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
     838                 :         {
     839               2 :             pszElemOpen = (char *) CPLMalloc( 11 + nAttrsLength + 1 );
     840               2 :             sprintf( pszElemOpen, "MultiPoint%s>", szAttributes );
     841                 : 
     842               2 :             pszElemClose = "MultiPoint>";
     843               2 :             pszMemberElem = "pointMember>";
     844                 :         }
     845                 :         else
     846                 :         {
     847               2 :             pszElemOpen = (char *) CPLMalloc( 19 + nAttrsLength + 1 );
     848               2 :             sprintf( pszElemOpen, "MultiGeometry%s>", szAttributes );
     849                 : 
     850               2 :             pszElemClose = "MultiGeometry>";
     851               2 :             pszMemberElem = "geometryMember>";
     852                 :         }
     853                 : 
     854              10 :         AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     855              10 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemOpen );
     856                 : 
     857              30 :         for( iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
     858                 :         {
     859              20 :             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
     860                 : 
     861              20 :             AppendString( ppszText, pnLength, pnMaxLength, "<gml:" );
     862              20 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     863                 : 
     864              20 :             char* pszGMLIdSub = NULL;
     865              20 :             if (pszGMLId != NULL)
     866               0 :                 pszGMLIdSub = CPLStrdup(CPLSPrintf("%s.%d", pszGMLId, iMember));
     867                 : 
     868              20 :             if( !OGR2GML3GeometryAppend( poMember, poSRS,
     869                 :                                         ppszText, pnLength, pnMaxLength,
     870                 :                                         TRUE, bLongSRS, bLineStringAsCurve,
     871                 :                                          pszGMLIdSub) )
     872                 :             {
     873               0 :                 CPLFree(pszGMLIdSub);
     874               0 :                 return FALSE;
     875                 :             }
     876                 : 
     877              20 :             CPLFree(pszGMLIdSub);
     878                 : 
     879              20 :             AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     880              20 :             AppendString( ppszText, pnLength, pnMaxLength, pszMemberElem );
     881                 :         }
     882                 : 
     883              10 :         AppendString( ppszText, pnLength, pnMaxLength, "</gml:" );
     884              10 :         AppendString( ppszText, pnLength, pnMaxLength, pszElemClose );
     885                 : 
     886                 :         // FREE TAG BUFFER
     887              10 :         CPLFree( pszElemOpen );
     888                 :     }
     889                 :     else
     890                 :     {
     891               0 :         return FALSE;
     892                 :     }
     893                 : 
     894             116 :     return TRUE;
     895                 : }
     896                 : 
     897                 : /************************************************************************/
     898                 : /*                       OGR_G_ExportToGMLTree()                        */
     899                 : /************************************************************************/
     900                 : 
     901               0 : CPLXMLNode *OGR_G_ExportToGMLTree( OGRGeometryH hGeometry )
     902                 : 
     903                 : {
     904                 :     char        *pszText;
     905                 :     CPLXMLNode  *psTree;
     906                 : 
     907               0 :     pszText = OGR_G_ExportToGML( hGeometry );
     908               0 :     if( pszText == NULL )
     909               0 :         return NULL;
     910                 : 
     911               0 :     psTree = CPLParseXMLString( pszText );
     912                 : 
     913               0 :     CPLFree( pszText );
     914                 : 
     915               0 :     return psTree;
     916                 : }
     917                 : 
     918                 : /************************************************************************/
     919                 : /*                         OGR_G_ExportToGML()                          */
     920                 : /************************************************************************/
     921                 : 
     922                 : /**
     923                 :  * \brief Convert a geometry into GML format.
     924                 :  *
     925                 :  * The GML geometry is expressed directly in terms of GML basic data
     926                 :  * types assuming the this is available in the gml namespace.  The returned
     927                 :  * string should be freed with CPLFree() when no longer required.
     928                 :  *
     929                 :  * This method is the same as the C++ method OGRGeometry::exportToGML().
     930                 :  *
     931                 :  * @param hGeometry handle to the geometry.
     932                 :  * @return A GML fragment or NULL in case of error.
     933                 :  */
     934                 : 
     935               0 : char *OGR_G_ExportToGML( OGRGeometryH hGeometry )
     936                 : 
     937                 : {
     938               0 :     return OGR_G_ExportToGMLEx(hGeometry, NULL);
     939                 : }
     940                 : 
     941                 : /************************************************************************/
     942                 : /*                        OGR_G_ExportToGMLEx()                         */
     943                 : /************************************************************************/
     944                 : 
     945                 : /**
     946                 :  * \brief Convert a geometry into GML format.
     947                 :  *
     948                 :  * The GML geometry is expressed directly in terms of GML basic data
     949                 :  * types assuming the this is available in the gml namespace.  The returned
     950                 :  * string should be freed with CPLFree() when no longer required.
     951                 :  *
     952                 :  * The supported options in OGR 1.8.0 are :
     953                 :  * <ul>
     954                 :  * <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
     955                 :  * <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
     956                 :  *     Otherwise gml:LineString will be used .
     957                 :  * <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
     958                 :  *      be written with the "urn:ogc:def:crs:EPSG::" prefix.
     959                 :  *      In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
     960                 :  *      imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
     961                 :  *      If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
     962                 :  * <li> GMLID=astring. If specified, a gml:id attribute will be written in the top-level geometry element with the provided value.
     963                 :  *      Required for GML 3.2 compatibility.
     964                 :  * </ul>
     965                 :  *
     966                 :  * This method is the same as the C++ method OGRGeometry::exportToGML().
     967                 :  *
     968                 :  * @param hGeometry handle to the geometry.
     969                 :  * @param papszOptions NULL-terminated list of options.
     970                 :  * @return A GML fragment or NULL in case of error.
     971                 :  *
     972                 :  * @since OGR 1.8.0
     973                 :  */
     974                 : 
     975             134 : char *OGR_G_ExportToGMLEx( OGRGeometryH hGeometry, char** papszOptions )
     976                 : 
     977                 : {
     978                 :     char        *pszText;
     979             134 :     int         nLength = 0, nMaxLength = 1;
     980                 : 
     981             134 :     if( hGeometry == NULL )
     982               0 :         return CPLStrdup( "" );
     983                 : 
     984             134 :     pszText = (char *) CPLMalloc(nMaxLength);
     985             134 :     pszText[0] = '\0';
     986                 : 
     987             134 :     const char* pszFormat = CSLFetchNameValue(papszOptions, "FORMAT");
     988             134 :     if (pszFormat && EQUAL(pszFormat, "GML3"))
     989                 :     {
     990              66 :         const char* pszLineStringElement = CSLFetchNameValue(papszOptions, "GML3_LINESTRING_ELEMENT");
     991              66 :         int bLineStringAsCurve = (pszLineStringElement && EQUAL(pszLineStringElement, "curve"));
     992              66 :         int bLongSRS = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "GML3_LONGSRS", "YES"));
     993              66 :         const char* pszGMLId = CSLFetchNameValue(papszOptions, "GMLID");
     994              66 :         if( !OGR2GML3GeometryAppend( (OGRGeometry *) hGeometry, NULL, &pszText,
     995                 :                                     &nLength, &nMaxLength, FALSE, bLongSRS, bLineStringAsCurve, pszGMLId ))
     996                 :         {
     997               0 :             CPLFree( pszText );
     998               0 :             return NULL;
     999                 :         }
    1000                 :         else
    1001              66 :             return pszText;
    1002                 :     }
    1003                 : 
    1004              68 :     if( !OGR2GMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText,
    1005                 :                                 &nLength, &nMaxLength, FALSE ))
    1006                 :     {
    1007               0 :         CPLFree( pszText );
    1008               0 :         return NULL;
    1009                 :     }
    1010                 :     else
    1011              68 :         return pszText;
    1012                 : }

Generated by: LCOV version 1.7