LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/kml - ogr2kmlgeometry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 170 105 61.8 %
Date: 2012-04-28 Functions: 8 6 75.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogr2kmlgeometry.cpp 21019 2010-10-30 11:37:54Z rouault $
       3                 :  *
       4                 :  * Project:  KML Driver
       5                 :  * Purpose:  Implementation of OGR -> KML geometries writer.
       6                 :  * Author:   Christopher Condit, condit@sdsc.edu
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2006, Christopher Condit
      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
      22                 :  * OR 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                 : #include "cpl_minixml.h"
      30                 : #include "ogr_geometry.h"
      31                 : #include "ogr_api.h"
      32                 : #include "ogr_p.h"
      33                 : #include "cpl_error.h"
      34                 : #include "cpl_conv.h"
      35                 : 
      36                 : 
      37                 : #define EPSILON 1e-8
      38                 : 
      39                 : /************************************************************************/
      40                 : /*                        MakeKMLCoordinate()                           */
      41                 : /************************************************************************/
      42                 : 
      43             120 : static void MakeKMLCoordinate( char *pszTarget, 
      44                 :                                double x, double y, double z, int b3D )
      45                 : 
      46                 : {
      47             120 :     if (y < -90 || y > 90)
      48                 :     {
      49               0 :         if (y > 90 && y < 90 + EPSILON)
      50                 :         {
      51               0 :             y = 90;
      52                 :         }
      53               0 :         else if (y > -90 - EPSILON  && y < -90)
      54                 :         {
      55               0 :             y = -90;
      56                 :         }
      57                 :         else
      58                 :         {
      59                 :             static int bFirstWarning = TRUE;
      60               0 :             if (bFirstWarning)
      61                 :             {
      62                 :                 CPLError(CE_Failure, CPLE_AppDefined,
      63                 :                         "Latitude %f is invalid. Valid range is [-90,90]. This warning will not be issued any more",
      64               0 :                         y);
      65               0 :                 bFirstWarning = FALSE;
      66                 :             }
      67                 :         }
      68                 :     }
      69                 : 
      70             120 :     if (x < -180 || x > 180)
      71                 :     {
      72               0 :         if (x > 180 && x < 180 + EPSILON)
      73                 :         {
      74               0 :             x = 180;
      75                 :         }
      76               0 :         else if (x > -180 - EPSILON  && x < -180)
      77                 :         {
      78               0 :             x = -180;
      79                 :         }
      80                 :         else
      81                 :         {
      82                 :             static int bFirstWarning = TRUE;
      83               0 :             if (bFirstWarning)
      84                 :             {
      85                 :                 CPLError(CE_Warning, CPLE_AppDefined,
      86                 :                         "Longitude %f has been modified to fit into range [-180,180]. This warning will not be issued any more",
      87               0 :                         x);
      88               0 :                 bFirstWarning = FALSE;
      89                 :             }
      90                 :     
      91               0 :             if (x > 180)
      92               0 :                 x -= ((int) ((x+180)/360)*360);
      93               0 :             else if (x < -180)
      94               0 :                 x += ((int) (180 - x)/360)*360;
      95                 :         }
      96                 :     }
      97                 : 
      98             120 :     OGRMakeWktCoordinate( pszTarget, x, y, z, b3D ? 3 : 2 );
      99             780 :     while( *pszTarget != '\0' )
     100                 :     {
     101             540 :         if( *pszTarget == ' ' )
     102             124 :             *pszTarget = ',';
     103             540 :         pszTarget++;
     104                 :     }
     105                 : 
     106                 : #ifdef notdef
     107                 :     if( !b3D )
     108                 :     {
     109                 :         if( x == (int) x && y == (int) y )
     110                 :             sprintf( pszTarget, "%d,%d", (int) x, (int) y );
     111                 :         else if( fabs(x) < 370 && fabs(y) < 370 )
     112                 :             sprintf( pszTarget, "%.16g,%.16g", x, y );
     113                 :         else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 )
     114                 :             sprintf( pszTarget, "%.16g,%.16g", x, y );
     115                 :         else
     116                 :             sprintf( pszTarget, "%.3f,%.3f", x, y );
     117                 :     }
     118                 :     else
     119                 :     {
     120                 :         if( x == (int) x && y == (int) y && z == (int) z )
     121                 :             sprintf( pszTarget, "%d,%d,%d", (int) x, (int) y, (int) z );
     122                 :         else if( fabs(x) < 370 && fabs(y) < 370 )
     123                 :             sprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
     124                 :         else if( fabs(x) > 100000000.0 || fabs(y) > 100000000.0 
     125                 :                  || fabs(z) > 100000000.0 )
     126                 :             sprintf( pszTarget, "%.16g,%.16g,%.16g", x, y, z );
     127                 :         else
     128                 :             sprintf( pszTarget, "%.3f,%.3f,%.3f", x, y, z );
     129                 :     }
     130                 : #endif
     131             120 : }
     132                 : 
     133                 : /************************************************************************/
     134                 : /*                            _GrowBuffer()                             */
     135                 : /************************************************************************/
     136                 : 
     137             346 : static void _GrowBuffer( int nNeeded, char **ppszText, int *pnMaxLength )
     138                 : 
     139                 : {
     140             346 :     if( nNeeded+1 >= *pnMaxLength )
     141                 :     {
     142              96 :         *pnMaxLength = MAX(*pnMaxLength * 2,nNeeded+1);
     143              96 :         *ppszText = (char *) CPLRealloc(*ppszText, *pnMaxLength);
     144                 :     }
     145             346 : }
     146                 : 
     147                 : /************************************************************************/
     148                 : /*                            AppendString()                            */
     149                 : /************************************************************************/
     150                 : 
     151             170 : static void AppendString( char **ppszText, int *pnLength, int *pnMaxLength,
     152                 :                           const char *pszTextToAppend )
     153                 : 
     154                 : {
     155                 :     _GrowBuffer( *pnLength + strlen(pszTextToAppend) + 1,
     156             170 :                  ppszText, pnMaxLength );
     157                 : 
     158             170 :     strcat( *ppszText + *pnLength, pszTextToAppend );
     159             170 :     *pnLength += strlen( *ppszText + *pnLength );
     160             170 : }
     161                 : 
     162                 : 
     163                 : /************************************************************************/
     164                 : /*                        AppendCoordinateList()                        */
     165                 : /************************************************************************/
     166                 : 
     167              28 : static void AppendCoordinateList( OGRLineString *poLine, 
     168                 :                                   char **ppszText, int *pnLength, 
     169                 :                                   int *pnMaxLength )
     170                 : 
     171                 : {
     172              28 :     char szCoordinate[256]= { 0 };
     173              28 :     int b3D = (poLine->getGeometryType() & wkb25DBit);
     174                 : 
     175              28 :     *pnLength += strlen(*ppszText + *pnLength);
     176              28 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     177                 : 
     178              28 :     strcat( *ppszText + *pnLength, "<coordinates>" );
     179              28 :     *pnLength += strlen(*ppszText + *pnLength);
     180                 : 
     181             124 :     for( int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++ )
     182                 :     {
     183                 :         MakeKMLCoordinate( szCoordinate, 
     184                 :                            poLine->getX(iPoint),
     185                 :                            poLine->getY(iPoint),
     186                 :                            poLine->getZ(iPoint),
     187              96 :                            b3D );
     188                 :         _GrowBuffer( *pnLength + strlen(szCoordinate)+1, 
     189              96 :             ppszText, pnMaxLength );
     190                 : 
     191              96 :         if( iPoint != 0 )
     192              68 :             strcat( *ppszText + *pnLength, " " );
     193                 : 
     194              96 :         strcat( *ppszText + *pnLength, szCoordinate );
     195              96 :         *pnLength += strlen(*ppszText + *pnLength);
     196                 :     }
     197                 : 
     198              28 :     _GrowBuffer( *pnLength + 20, ppszText, pnMaxLength );
     199              28 :     strcat( *ppszText + *pnLength, "</coordinates>" );
     200              28 :     *pnLength += strlen(*ppszText + *pnLength);
     201              28 : }
     202                 : 
     203                 : /************************************************************************/
     204                 : /*                       OGR2KMLGeometryAppend()                        */
     205                 : /************************************************************************/
     206                 : 
     207              70 : static int OGR2KMLGeometryAppend( OGRGeometry *poGeometry, 
     208                 :                                   char **ppszText, int *pnLength, 
     209                 :                                   int *pnMaxLength, char * szAltitudeMode )
     210                 : 
     211                 : {
     212                 : /* -------------------------------------------------------------------- */
     213                 : /*      2D Point                                                        */
     214                 : /* -------------------------------------------------------------------- */
     215              70 :     if( poGeometry->getGeometryType() == wkbPoint )
     216                 :     {
     217              20 :         char szCoordinate[256] = { 0 };
     218              20 :         OGRPoint* poPoint = static_cast<OGRPoint*>(poGeometry);
     219                 : 
     220              20 :         if (poPoint->getCoordinateDimension() == 0)
     221                 :         {
     222                 :             _GrowBuffer( *pnLength + 10, 
     223               0 :                      ppszText, pnMaxLength );
     224               0 :             strcat( *ppszText + *pnLength, "<Point/>");
     225               0 :             *pnLength += strlen( *ppszText + *pnLength );
     226                 :         }
     227                 :         else
     228                 :         {
     229                 :             MakeKMLCoordinate( szCoordinate, 
     230              20 :                             poPoint->getX(), poPoint->getY(), 0.0, FALSE );
     231                 : 
     232                 :             _GrowBuffer( *pnLength + strlen(szCoordinate) + 60, 
     233              20 :                         ppszText, pnMaxLength );
     234                 : 
     235                 :             sprintf( *ppszText + *pnLength, 
     236                 :                     "<Point><coordinates>%s</coordinates></Point>",
     237              20 :                     szCoordinate );
     238                 : 
     239              20 :             *pnLength += strlen( *ppszText + *pnLength );
     240                 :         }
     241                 :     }
     242                 : /* -------------------------------------------------------------------- */
     243                 : /*      3D Point                                                        */
     244                 : /* -------------------------------------------------------------------- */
     245              50 :     else if( poGeometry->getGeometryType() == wkbPoint25D )
     246                 :     {
     247               4 :         char szCoordinate[256] = { 0 };
     248               4 :         OGRPoint *poPoint = static_cast<OGRPoint*>(poGeometry);
     249                 : 
     250                 :         MakeKMLCoordinate( szCoordinate, 
     251                 :                            poPoint->getX(), poPoint->getY(), poPoint->getZ(), 
     252               4 :                            TRUE );
     253                 :                            
     254               4 :         if (NULL == szAltitudeMode) 
     255                 :         { 
     256                 :             _GrowBuffer( *pnLength + strlen(szCoordinate) + 70, 
     257               0 :                          ppszText, pnMaxLength );
     258                 : 
     259                 :             sprintf( *ppszText + *pnLength,  
     260                 :                      "<Point><coordinates>%s</coordinates></Point>",
     261               0 :                      szCoordinate );
     262                 :         }
     263                 :         else
     264                 :         { 
     265                 :             _GrowBuffer( *pnLength + strlen(szCoordinate) 
     266                 :                          + strlen(szAltitudeMode) + 70, 
     267               4 :                          ppszText, pnMaxLength );
     268                 : 
     269                 :             sprintf( *ppszText + *pnLength,  
     270                 :                      "<Point>%s<coordinates>%s</coordinates></Point>", 
     271               4 :                      szAltitudeMode, szCoordinate ); 
     272                 :         }
     273                 : 
     274               4 :         *pnLength += strlen( *ppszText + *pnLength );
     275                 :     }
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      LineString and LinearRing                                       */
     278                 : /* -------------------------------------------------------------------- */
     279              64 :     else if( poGeometry->getGeometryType() == wkbLineString 
     280              18 :              || poGeometry->getGeometryType() == wkbLineString25D )
     281                 :     {
     282              28 :         int bRing = EQUAL(poGeometry->getGeometryName(),"LINEARRING");
     283                 : 
     284              28 :         if( bRing )
     285                 :             AppendString( ppszText, pnLength, pnMaxLength,
     286              20 :                           "<LinearRing>" );
     287                 :         else
     288                 :             AppendString( ppszText, pnLength, pnMaxLength,
     289               8 :                           "<LineString>" );
     290                 : 
     291              28 :         if (NULL != szAltitudeMode) 
     292                 :         { 
     293              28 :             AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
     294                 :         }
     295                 : 
     296                 :         AppendCoordinateList( (OGRLineString *) poGeometry, 
     297              28 :                               ppszText, pnLength, pnMaxLength );
     298                 :         
     299              28 :         if( bRing )
     300                 :             AppendString( ppszText, pnLength, pnMaxLength,
     301              20 :                           "</LinearRing>" );
     302                 :         else
     303                 :             AppendString( ppszText, pnLength, pnMaxLength,
     304               8 :                           "</LineString>" );
     305                 :     }
     306                 : 
     307                 : /* -------------------------------------------------------------------- */
     308                 : /*      Polygon                                                         */
     309                 : /* -------------------------------------------------------------------- */
     310              26 :     else if( poGeometry->getGeometryType() == wkbPolygon 
     311               8 :              || poGeometry->getGeometryType() == wkbPolygon25D )
     312                 :     {
     313              10 :         OGRPolygon* poPolygon = static_cast<OGRPolygon*>(poGeometry);
     314                 : 
     315              10 :         AppendString( ppszText, pnLength, pnMaxLength, "<Polygon>" );
     316                 : 
     317              10 :         if (NULL != szAltitudeMode) 
     318                 :         { 
     319              10 :             AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
     320                 :         }
     321                 : 
     322              10 :         if( poPolygon->getExteriorRing() != NULL )
     323                 :         {
     324                 :             AppendString( ppszText, pnLength, pnMaxLength,
     325              10 :                           "<outerBoundaryIs>" );
     326                 : 
     327              10 :             if( !OGR2KMLGeometryAppend( poPolygon->getExteriorRing(), 
     328                 :                                         ppszText, pnLength, pnMaxLength, szAltitudeMode ) )
     329                 :             {
     330               0 :                 return FALSE;
     331                 :             }
     332                 :             AppendString( ppszText, pnLength, pnMaxLength,
     333              10 :                           "</outerBoundaryIs>" );
     334                 :         }
     335                 : 
     336              20 :         for( int iRing = 0; iRing < poPolygon->getNumInteriorRings(); iRing++ )
     337                 :         {
     338              10 :             OGRLinearRing *poRing = poPolygon->getInteriorRing(iRing);
     339                 : 
     340                 :             AppendString( ppszText, pnLength, pnMaxLength,
     341              10 :                           "<innerBoundaryIs>" );
     342                 :             
     343              10 :             if( !OGR2KMLGeometryAppend( poRing, ppszText, pnLength, 
     344                 :                                         pnMaxLength, szAltitudeMode ) )
     345                 :             {
     346               0 :                 return FALSE;
     347                 :             }
     348                 :             AppendString( ppszText, pnLength, pnMaxLength,
     349              10 :                           "</innerBoundaryIs>" );
     350                 :         }
     351                 : 
     352                 :         AppendString( ppszText, pnLength, pnMaxLength,
     353              10 :                       "</Polygon>" );
     354                 :     }
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      MultiPolygon                                                    */
     358                 : /* -------------------------------------------------------------------- */
     359              20 :     else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon 
     360               6 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString
     361               4 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint
     362               2 :              || wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection )
     363                 :     {
     364               8 :         OGRGeometryCollection* poGC = NULL;
     365               8 :         poGC = static_cast<OGRGeometryCollection*>(poGeometry);
     366                 : 
     367               8 :         AppendString( ppszText, pnLength, pnMaxLength, "<MultiGeometry>" );
     368                 : 
     369                 :         // XXX - mloskot
     370                 :         //if (NULL != szAltitudeMode) 
     371                 :         //{ 
     372                 :         //    AppendString( ppszText, pnLength, pnMaxLength, szAltitudeMode); 
     373                 :         //}
     374                 : 
     375              24 :         for( int iMember = 0; iMember < poGC->getNumGeometries(); iMember++)
     376                 :         {
     377              16 :             OGRGeometry *poMember = poGC->getGeometryRef( iMember );
     378                 : 
     379              16 :             if( !OGR2KMLGeometryAppend( poMember, ppszText, pnLength, pnMaxLength, szAltitudeMode ) )
     380                 :             {
     381               0 :                 return FALSE;
     382                 :             }
     383                 :         }
     384                 : 
     385               8 :     AppendString( ppszText, pnLength, pnMaxLength, "</MultiGeometry>" );
     386                 :     }
     387                 :     else
     388                 :     {
     389               0 :         return FALSE;
     390                 :     }
     391                 : 
     392              70 :     return TRUE;
     393                 : }
     394                 : 
     395                 : /************************************************************************/
     396                 : /*                   OGR_G_ExportEnvelopeToKMLTree()                    */
     397                 : /*                                                                      */
     398                 : /*      Export the envelope of a geometry as a KML:Box.                 */
     399                 : /************************************************************************/
     400                 : 
     401               0 : CPLXMLNode* OGR_G_ExportEnvelopeToKMLTree( OGRGeometryH hGeometry )
     402                 : {
     403               0 :     VALIDATE_POINTER1( hGeometry, "OGR_G_ExportEnvelopeToKMLTree", NULL );
     404                 : 
     405               0 :     CPLXMLNode* psBox = NULL;
     406               0 :     CPLXMLNode* psCoord = NULL;
     407               0 :     OGREnvelope sEnvelope;
     408               0 :     char szCoordinate[256] = { 0 };
     409               0 :     char* pszY = NULL;
     410                 : 
     411               0 :     memset( &sEnvelope, 0, sizeof(sEnvelope) );
     412               0 :     ((OGRGeometry*)(hGeometry))->getEnvelope( &sEnvelope );
     413                 : 
     414               0 :     if( sEnvelope.MinX == 0 && sEnvelope.MaxX == 0 
     415                 :         && sEnvelope.MaxX == 0 && sEnvelope.MaxY == 0 )
     416                 :     {
     417                 :         /* there is apparently a special way of representing a null box
     418                 :            geometry ... we should use it here eventually. */
     419                 : 
     420               0 :         return NULL;
     421                 :     }
     422                 : 
     423               0 :     psBox = CPLCreateXMLNode( NULL, CXT_Element, "Box" );
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      Add minxy coordinate.                                           */
     427                 : /* -------------------------------------------------------------------- */
     428               0 :     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
     429                 :     
     430                 :     MakeKMLCoordinate( szCoordinate, sEnvelope.MinX, sEnvelope.MinY, 0.0, 
     431               0 :                        FALSE );
     432               0 :     pszY = strstr(szCoordinate,",") + 1;
     433               0 :     pszY[-1] = '\0';
     434                 : 
     435               0 :     CPLCreateXMLElementAndValue( psCoord, "X", szCoordinate );
     436               0 :     CPLCreateXMLElementAndValue( psCoord, "Y", pszY );
     437                 : 
     438                 : /* -------------------------------------------------------------------- */
     439                 : /*      Add maxxy coordinate.                                           */
     440                 : /* -------------------------------------------------------------------- */
     441               0 :     psCoord = CPLCreateXMLNode( psBox, CXT_Element, "coord" );
     442                 :     
     443                 :     MakeKMLCoordinate( szCoordinate, sEnvelope.MaxX, sEnvelope.MaxY, 0.0, 
     444               0 :                        FALSE );
     445               0 :     pszY = strstr(szCoordinate,",") + 1;
     446               0 :     pszY[-1] = '\0';
     447                 : 
     448               0 :     CPLCreateXMLElementAndValue( psCoord, "X", szCoordinate );
     449               0 :     CPLCreateXMLElementAndValue( psCoord, "Y", pszY );
     450                 : 
     451               0 :     return psBox;
     452                 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                         OGR_G_ExportToKML()                          */
     456                 : /************************************************************************/
     457                 : 
     458                 : /**
     459                 :  * \brief Convert a geometry into KML format.
     460                 :  *
     461                 :  * The returned string should be freed with CPLFree() when no longer required.
     462                 :  *
     463                 :  * This method is the same as the C++ method OGRGeometry::exportToKML().
     464                 :  *
     465                 :  * @param hGeometry handle to the geometry.
     466                 :  * @param pszAltitudeMode value to write in altitudeMode element, or NULL.
     467                 :  * @return A KML fragment or NULL in case of error.
     468                 :  */
     469                 : 
     470              34 : char *OGR_G_ExportToKML( OGRGeometryH hGeometry, const char *pszAltitudeMode )
     471                 : {
     472              34 :     char* pszText = NULL;
     473              34 :     int nLength = 0;
     474              34 :     int nMaxLength = 1;
     475                 :     char szAltitudeMode[128]; 
     476                 : 
     477                 :     // TODO - mloskot: Shouldn't we use VALIDATE_POINTER1 here?
     478              34 :     if( hGeometry == NULL )
     479               0 :         return CPLStrdup( "" );
     480                 : 
     481              34 :     pszText = (char *) CPLMalloc(nMaxLength);
     482              34 :     pszText[0] = '\0';
     483                 : 
     484              34 :     if (NULL != pszAltitudeMode && strlen(pszAltitudeMode) < 128 - (29 + 1))
     485                 :     {
     486               0 :         sprintf(szAltitudeMode, "<altitudeMode>%s</altitudeMode>", pszAltitudeMode); 
     487                 :     }
     488                 :     else 
     489                 :     {
     490              34 :         szAltitudeMode[0] = 0; 
     491                 :     }
     492                 : 
     493              34 :     if( !OGR2KMLGeometryAppend( (OGRGeometry *) hGeometry, &pszText, 
     494                 :                                 &nLength, &nMaxLength, szAltitudeMode ))
     495                 :     {
     496               0 :         CPLFree( pszText );
     497               0 :         return NULL;
     498                 :     }
     499                 :     
     500              34 :     return pszText;
     501                 : }
     502                 : 
     503                 : /************************************************************************/
     504                 : /*                       OGR_G_ExportToKMLTree()                        */
     505                 : /************************************************************************/
     506                 : 
     507               0 : CPLXMLNode *OGR_G_ExportToKMLTree( OGRGeometryH hGeometry )
     508                 : {
     509               0 :     char        *pszText = NULL;
     510               0 :     CPLXMLNode  *psTree = NULL;
     511                 : 
     512                 :     // TODO - mloskot: If passed geometry is null the pszText is non-null,
     513                 :     // so the condition below is false.
     514               0 :     pszText = OGR_G_ExportToKML( hGeometry, NULL );
     515               0 :     if( pszText == NULL )
     516               0 :         return NULL;
     517                 : 
     518               0 :     psTree = CPLParseXMLString( pszText );
     519                 : 
     520               0 :     CPLFree( pszText );
     521                 : 
     522               0 :     return psTree;
     523                 : }
     524                 : 

Generated by: LCOV version 1.7