LCOV - code coverage report
Current view: directory - ogr - gml2ogrgeometry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 275 185 67.3 %
Date: 2010-01-09 Functions: 8 8 100.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gml2ogrgeometry.cpp 18085 2009-11-23 19:02:18Z rouault $
       3                 :  *
       4                 :  * Project:  GML Reader
       5                 :  * Purpose:  Code to translate between GML and OGR geometry forms.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, Frank Warmerdam
      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 with any kind of input data.
      33                 :  *
      34                 :  * Security Audit 2003/03/28 warmerda:
      35                 :  *   Completed security audit.  I believe that this module may be safely used 
      36                 :  *   to parse, arbitrary GML potentially provided by a hostile source without
      37                 :  *   compromising the system.
      38                 :  *
      39                 :  */
      40                 : 
      41                 : #include "cpl_minixml.h"
      42                 : #include "ogr_geometry.h"
      43                 : #include "ogr_api.h"
      44                 : #include "cpl_error.h"
      45                 : #include "cpl_string.h"
      46                 : #include <ctype.h>
      47                 : #include "ogr_p.h"
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                           BareGMLElement()                           */
      51                 : /*                                                                      */
      52                 : /*      Returns the passed string with any namespace prefix             */
      53                 : /*      stripped off.                                                   */
      54                 : /************************************************************************/
      55                 : 
      56             349 : static const char *BareGMLElement( const char *pszInput )
      57                 : 
      58                 : {
      59                 :     const char *pszReturn;
      60                 : 
      61             349 :     pszReturn = strchr( pszInput, ':' );
      62             349 :     if( pszReturn == NULL )
      63             146 :         pszReturn = pszInput;
      64                 :     else
      65             203 :         pszReturn++;
      66                 : 
      67             349 :     return pszReturn;
      68                 : }
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                          FindBareXMLChild()                          */
      72                 : /*                                                                      */
      73                 : /*      Find a child node with the indicated "bare" name, that is       */
      74                 : /*      after any namespace qualifiers have been stripped off.          */
      75                 : /************************************************************************/
      76                 : 
      77             133 : static const CPLXMLNode *FindBareXMLChild( const CPLXMLNode *psParent, 
      78                 :                                            const char *pszBareName )
      79                 : 
      80                 : {
      81             133 :     const CPLXMLNode *psCandidate = psParent->psChild;
      82                 : 
      83             307 :     while( psCandidate != NULL )
      84                 :     {
      85             151 :         if( psCandidate->eType == CXT_Element
      86                 :             && EQUAL(BareGMLElement(psCandidate->pszValue), pszBareName) )
      87             110 :             return psCandidate;
      88                 : 
      89              41 :         psCandidate = psCandidate->psNext;
      90                 :     }
      91                 : 
      92              23 :     return NULL;
      93                 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                           GetElementText()                           */
      97                 : /************************************************************************/
      98                 : 
      99             112 : static const char *GetElementText( const CPLXMLNode *psElement )
     100                 : 
     101                 : {
     102             112 :     if( psElement == NULL )
     103               0 :         return NULL;
     104                 : 
     105             112 :     const CPLXMLNode *psChild = psElement->psChild;
     106                 : 
     107             231 :     while( psChild != NULL )
     108                 :     {
     109             119 :         if( psChild->eType == CXT_Text )
     110             112 :             return psChild->pszValue;
     111                 : 
     112               7 :         psChild = psChild->psNext;
     113                 :     }
     114                 :     
     115               0 :     return NULL;
     116                 : }
     117                 : 
     118                 : /************************************************************************/
     119                 : /*                              AddPoint()                              */
     120                 : /*                                                                      */
     121                 : /*      Add a point to the passed geometry.                             */
     122                 : /************************************************************************/
     123                 : 
     124             358 : static int AddPoint( OGRGeometry *poGeometry, 
     125                 :                      double dfX, double dfY, double dfZ, int nDimension )
     126                 : 
     127                 : {
     128             650 :     if( poGeometry->getGeometryType() == wkbPoint 
     129             292 :         || poGeometry->getGeometryType() == wkbPoint25D )
     130                 :     {
     131              66 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     132                 : 
     133              66 :         if( poPoint->getX() != 0.0 || poPoint->getY() != 0.0 )
     134                 :         {
     135                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     136               0 :                       "More than one coordinate for <Point> element.");
     137               0 :             return FALSE;
     138                 :         }
     139                 :             
     140              66 :         poPoint->setX( dfX );
     141              66 :         poPoint->setY( dfY );
     142              66 :         if( nDimension == 3 )
     143               4 :             poPoint->setZ( dfZ );
     144                 : 
     145              66 :         return TRUE;
     146                 :     }
     147                 :                 
     148             310 :     else if( poGeometry->getGeometryType() == wkbLineString
     149              18 :              || poGeometry->getGeometryType() == wkbLineString25D )
     150                 :     {
     151             292 :         if( nDimension == 3 )
     152              24 :             ((OGRLineString *) poGeometry)->addPoint( dfX, dfY, dfZ );
     153                 :         else
     154             268 :             ((OGRLineString *) poGeometry)->addPoint( dfX, dfY );
     155                 : 
     156             292 :         return TRUE;
     157                 :     }
     158                 : 
     159                 :     else
     160                 :     {
     161                 :         CPLAssert( FALSE );
     162               0 :         return FALSE;                                                   
     163                 :     }
     164                 : }
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                        ParseGMLCoordinates()                         */
     168                 : /************************************************************************/
     169                 : 
     170             103 : static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeometry )
     171                 : 
     172                 : {
     173             103 :     const CPLXMLNode *psCoordinates = FindBareXMLChild( psGeomNode, "coordinates" );
     174             103 :     int iCoord = 0;
     175                 : 
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*      Handle <coordinates> case.                                      */
     178                 : /* -------------------------------------------------------------------- */
     179             103 :     if( psCoordinates != NULL )
     180                 :     {
     181              85 :         const char *pszCoordString = GetElementText( psCoordinates );
     182                 : 
     183              85 :         if( pszCoordString == NULL )
     184                 :         {
     185                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     186               0 :                       "<coordinates> element missing value." );
     187               0 :             return FALSE;
     188                 :         }
     189                 : 
     190             475 :         while( *pszCoordString != '\0' )
     191                 :         {
     192             305 :             double dfX, dfY, dfZ = 0.0;
     193             305 :             int nDimension = 2;
     194                 : 
     195                 :             // parse out 2 or 3 tuple. 
     196             305 :             dfX = OGRFastAtof( pszCoordString );
     197            3461 :             while( *pszCoordString != '\0'
     198                 :                    && *pszCoordString != ','
     199                 :                    && !isspace((unsigned char)*pszCoordString) )
     200            2851 :                 pszCoordString++;
     201                 : 
     202             305 :             if( *pszCoordString == '\0' || isspace((unsigned char)*pszCoordString) )
     203                 :             {
     204                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     205               0 :                           "Corrupt <coordinates> value." );
     206               0 :                 return FALSE;
     207                 :             }
     208                 : 
     209             305 :             pszCoordString++;
     210             305 :             dfY = OGRFastAtof( pszCoordString );
     211            3532 :             while( *pszCoordString != '\0' 
     212                 :                    && *pszCoordString != ','
     213                 :                    && !isspace((unsigned char)*pszCoordString) )
     214            2922 :                 pszCoordString++;
     215                 : 
     216             305 :             if( *pszCoordString == ',' )
     217                 :             {
     218              24 :                 pszCoordString++;
     219              24 :                 dfZ = OGRFastAtof( pszCoordString );
     220              24 :                 nDimension = 3;
     221              72 :                 while( *pszCoordString != '\0' 
     222                 :                        && *pszCoordString != ','
     223                 :                        && !isspace((unsigned char)*pszCoordString) )
     224              24 :                 pszCoordString++;
     225                 :             }
     226                 : 
     227             833 :             while( isspace((unsigned char)*pszCoordString) )
     228             223 :                 pszCoordString++;
     229                 : 
     230             305 :             if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
     231               0 :                 return FALSE;
     232                 : 
     233             305 :             iCoord++;
     234                 :         }
     235                 : 
     236              85 :         return iCoord > 0;
     237                 :     }
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Is this a "pos"?  GML 3 construct.                              */
     241                 : /*      Parse if it exist a series of pos elements (this would allow    */
     242                 : /*      the correct parsing of gml3.1.1 geomtries such as linestring    */
     243                 : /*      defined with pos elements.                                      */
     244                 : /* -------------------------------------------------------------------- */
     245                 :     const CPLXMLNode *psPos;
     246                 :     
     247              18 :     int bHasFoundPosElement = FALSE;
     248              44 :     for( psPos = psGeomNode->psChild; 
     249                 :          psPos != NULL;
     250                 :          psPos = psPos->psNext )
     251                 :     {
     252              26 :         if( psPos->eType != CXT_Element 
     253                 :             || !EQUAL(BareGMLElement(psPos->pszValue),"pos") )
     254              10 :             continue;
     255                 :         
     256                 :         char **papszTokens = CSLTokenizeStringComplex( 
     257              16 :             GetElementText( psPos ), " ,", FALSE, FALSE );
     258              16 :         int bSuccess = FALSE;
     259                 : 
     260              16 :         if( CSLCount( papszTokens ) > 2 )
     261                 :         {
     262                 :             bSuccess = AddPoint( poGeometry, 
     263               1 :                                  OGRFastAtof(papszTokens[0]), 
     264               1 :                                  OGRFastAtof(papszTokens[1]),
     265               3 :                                  OGRFastAtof(papszTokens[2]), 3 );
     266                 :         }
     267              15 :         else if( CSLCount( papszTokens ) > 1 )
     268                 :         {
     269                 :             bSuccess = AddPoint( poGeometry, 
     270              15 :                                  OGRFastAtof(papszTokens[0]), 
     271              15 :                                  OGRFastAtof(papszTokens[1]),
     272              45 :                                  0.0, 2 );
     273                 :         }
     274                 :         else
     275                 :         {
     276                 :             CPLError( CE_Failure, CPLE_AppDefined,
     277                 :                       "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.",
     278               0 :                       GetElementText( psPos ) );
     279                 :         }
     280                 : 
     281              16 :         CSLDestroy( papszTokens );
     282                 :         
     283              16 :         if (bSuccess)
     284              16 :             bHasFoundPosElement = TRUE;
     285                 :         else
     286               0 :             return FALSE;
     287                 :     }
     288                 :     
     289              18 :     if (bHasFoundPosElement)
     290               8 :         return TRUE;
     291                 :     
     292                 : 
     293                 : /* -------------------------------------------------------------------- */
     294                 : /*      Is this a "posList"?  GML 3 construct (SF profile).             */
     295                 : /* -------------------------------------------------------------------- */
     296              10 :     const CPLXMLNode *psPosList = FindBareXMLChild( psGeomNode, "posList" );
     297                 :     
     298              10 :     if( psPosList != NULL )
     299                 :     {
     300                 :         char **papszTokens;
     301              10 :         int bSuccess = FALSE;
     302              10 :         int i=0, nCount=0;
     303                 :         const CPLXMLNode* psChild;
     304              10 :         int nDimension = 2;
     305                 : 
     306                 :         /* Try to detect the presence of an srsDimension attribute */
     307                 :         /* This attribute is only availabe for gml3.1.1 but not */
     308                 :         /* available for gml3.1 SF*/
     309              10 :         psChild = psPosList->psChild;
     310              20 :         while (psChild != NULL)
     311                 :         {
     312              10 :             if (psChild->eType == CXT_Attribute &&
     313                 :                 EQUAL(psChild->pszValue, "srsDimension"))
     314                 :             {
     315               1 :                 nDimension = atoi(psChild->psChild->pszValue);
     316               1 :                 break;
     317                 :             }
     318               9 :             else if (psChild->eType != CXT_Attribute)
     319                 :             {
     320               9 :                 break;
     321                 :             }
     322               0 :             psChild = psChild->psNext;
     323                 :         }
     324                 : 
     325              10 :         if (nDimension != 2 && nDimension != 3)
     326                 :         {
     327                 :             CPLError( CE_Failure, CPLE_AppDefined,
     328               0 :                       "srsDimension = %d not supported", nDimension);
     329               0 :             return FALSE;
     330                 :         }
     331                 : 
     332                 :         papszTokens = CSLTokenizeStringComplex( 
     333              10 :             GetElementText( psPosList ), " ,", FALSE, FALSE );
     334                 : 
     335              10 :         nCount = CSLCount( papszTokens );
     336                 : 
     337              11 :         if (nCount < nDimension  || (nCount % nDimension) != 0)
     338                 :         {
     339                 :             CPLError( CE_Failure, CPLE_AppDefined,
     340                 :                       "Did not get at least %d values or invalid number of \n"
     341                 :                       "set of coordinates <gml:posList>%s</gml:posList>",
     342               1 :                       nDimension, GetElementText( psPosList ) );
     343                 :         }
     344                 :         else
     345                 :         {
     346               9 :             i=0;
     347              55 :             while (i<nCount)
     348                 :             {
     349                 :                 bSuccess = AddPoint( poGeometry, 
     350              37 :                                      OGRFastAtof(papszTokens[i]), 
     351              37 :                                      OGRFastAtof(papszTokens[i+1]),
     352             111 :                                      (nDimension == 3) ? OGRFastAtof(papszTokens[i+2]) : 0.0, nDimension );
     353              37 :                 i+=nDimension;
     354                 :             }
     355                 :         }
     356              10 :         CSLDestroy( papszTokens );
     357                 : 
     358              10 :         return bSuccess;
     359                 :     }
     360                 :     
     361                 : 
     362                 : /* -------------------------------------------------------------------- */
     363                 : /*      Handle form with a list of <coord> items each with an <X>,      */
     364                 : /*      and <Y> element.                                                */
     365                 : /* -------------------------------------------------------------------- */
     366                 :     const CPLXMLNode *psCoordNode;
     367                 : 
     368               0 :     for( psCoordNode = psGeomNode->psChild; 
     369                 :          psCoordNode != NULL;
     370                 :          psCoordNode = psCoordNode->psNext )
     371                 :     {
     372               0 :         if( psCoordNode->eType != CXT_Element 
     373                 :             || !EQUAL(BareGMLElement(psCoordNode->pszValue),"coord") )
     374               0 :             continue;
     375                 : 
     376                 :         const CPLXMLNode *psXNode, *psYNode, *psZNode;
     377               0 :         double dfX, dfY, dfZ = 0.0;
     378               0 :         int nDimension = 2;
     379                 : 
     380               0 :         psXNode = FindBareXMLChild( psCoordNode, "X" );
     381               0 :         psYNode = FindBareXMLChild( psCoordNode, "Y" );
     382               0 :         psZNode = FindBareXMLChild( psCoordNode, "Z" );
     383                 : 
     384               0 :         if( psXNode == NULL || psYNode == NULL 
     385                 :             || GetElementText(psXNode) == NULL
     386                 :             || GetElementText(psYNode) == NULL
     387                 :             || (psZNode != NULL && GetElementText(psZNode) == NULL) )
     388                 :         {
     389                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     390               0 :                       "Corrupt <coord> element, missing <X> or <Y> element?" );
     391               0 :             return FALSE;
     392                 :         }
     393                 : 
     394               0 :         dfX = OGRFastAtof( GetElementText(psXNode) );
     395               0 :         dfY = OGRFastAtof( GetElementText(psYNode) );
     396                 : 
     397               0 :         if( psZNode != NULL && GetElementText(psZNode) != NULL )
     398                 :         {
     399               0 :             dfZ = OGRFastAtof( GetElementText(psZNode) );
     400               0 :             nDimension = 3;
     401                 :         }
     402                 : 
     403               0 :         if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
     404               0 :             return FALSE;
     405                 : 
     406               0 :         iCoord++;
     407                 :     }
     408                 : 
     409               0 :     return iCoord > 0.0;
     410                 : }
     411                 : 
     412                 : /************************************************************************/
     413                 : /*                      GML2OGRGeometry_XMLNode()                       */
     414                 : /*                                                                      */
     415                 : /*      Translates the passed XMLnode and it's children into an         */
     416                 : /*      OGRGeometry.  This is used recursively for geometry             */
     417                 : /*      collections.                                                    */
     418                 : /************************************************************************/
     419                 : 
     420             124 : static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode )
     421                 : 
     422                 : {
     423             124 :     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      Polygon                                                         */
     427                 : /* -------------------------------------------------------------------- */
     428             124 :     if( EQUAL(pszBaseGeometry,"Polygon") )
     429                 :     {
     430                 :         const CPLXMLNode *psChild;
     431              15 :         OGRPolygon *poPolygon = new OGRPolygon();
     432                 :         OGRLinearRing *poRing;
     433                 : 
     434                 :         // Find outer ring.
     435              15 :         psChild = FindBareXMLChild( psNode, "outerBoundaryIs" );
     436              15 :         if (psChild == NULL)
     437               5 :            psChild = FindBareXMLChild( psNode, "exterior");
     438                 : 
     439              15 :         if( psChild == NULL || psChild->psChild == NULL )
     440                 :         {
     441                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     442               0 :                       "Missing outerBoundaryIs property on Polygon." );
     443               0 :             delete poPolygon;
     444               0 :             return NULL;
     445                 :         }
     446                 : 
     447                 :         // Translate outer ring and add to polygon.
     448                 :         poRing = (OGRLinearRing *) 
     449              15 :             GML2OGRGeometry_XMLNode( psChild->psChild );
     450              15 :         if( poRing == NULL )
     451                 :         {
     452               0 :             delete poPolygon;
     453               0 :             return NULL;
     454                 :         }
     455                 : 
     456              15 :         if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
     457                 :         {
     458                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     459                 :                       "Got %.500s geometry as outerBoundaryIs instead of LINEARRING.",
     460               0 :                       poRing->getGeometryName() );
     461               0 :             delete poPolygon;
     462               0 :             delete poRing;
     463               0 :             return NULL;
     464                 :         }
     465                 : 
     466              15 :         poPolygon->addRingDirectly( poRing );
     467                 : 
     468                 :         // Find all inner rings 
     469              37 :         for( psChild = psNode->psChild; 
     470                 :              psChild != NULL;
     471                 :              psChild = psChild->psNext ) 
     472                 :         {
     473              22 :             if( psChild->eType == CXT_Element
     474                 :                 && (EQUAL(BareGMLElement(psChild->pszValue),"innerBoundaryIs") ||
     475                 :                     EQUAL(BareGMLElement(psChild->pszValue),"interior")))
     476                 :             {
     477                 :                 poRing = (OGRLinearRing *) 
     478               4 :                     GML2OGRGeometry_XMLNode( psChild->psChild );
     479               4 :                 if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
     480                 :                 {
     481                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     482                 :                               "Got %.500s geometry as innerBoundaryIs instead of LINEARRING.",
     483               0 :                               poRing->getGeometryName() );
     484               0 :                     delete poPolygon;
     485               0 :                     delete poRing;
     486               0 :                     return NULL;
     487                 :                 }
     488                 : 
     489               4 :                 poPolygon->addRingDirectly( poRing );
     490                 :             }
     491                 :         }
     492                 : 
     493              15 :         return poPolygon;
     494                 :     }
     495                 : 
     496                 : /* -------------------------------------------------------------------- */
     497                 : /*      LinearRing                                                      */
     498                 : /* -------------------------------------------------------------------- */
     499             109 :     if( EQUAL(pszBaseGeometry,"LinearRing") )
     500                 :     {
     501              19 :         OGRLinearRing   *poLinearRing = new OGRLinearRing();
     502                 :         
     503              19 :         if( !ParseGMLCoordinates( psNode, poLinearRing ) )
     504                 :         {
     505               0 :             delete poLinearRing;
     506               0 :             return NULL;
     507                 :         }
     508                 : 
     509              19 :         return poLinearRing;
     510                 :     }
     511                 : 
     512                 : /* -------------------------------------------------------------------- */
     513                 : /*      LineString                                                      */
     514                 : /* -------------------------------------------------------------------- */
     515              90 :     if( EQUAL(pszBaseGeometry,"LineString") )
     516                 :     {
     517              18 :         OGRLineString   *poLine = new OGRLineString();
     518                 :         
     519              18 :         if( !ParseGMLCoordinates( psNode, poLine ) )
     520                 :         {
     521               1 :             delete poLine;
     522               1 :             return NULL;
     523                 :         }
     524                 : 
     525              17 :         return poLine;
     526                 :     }
     527                 : 
     528                 : /* -------------------------------------------------------------------- */
     529                 : /*      PointType                                                       */
     530                 : /* -------------------------------------------------------------------- */
     531              72 :     if( EQUAL(pszBaseGeometry,"PointType") 
     532                 :         || EQUAL(pszBaseGeometry,"Point") )
     533                 :     {
     534              66 :         OGRPoint *poPoint = new OGRPoint();
     535                 :         
     536              66 :         if( !ParseGMLCoordinates( psNode, poPoint ) )
     537                 :         {
     538               0 :             delete poPoint;
     539               0 :             return NULL;
     540                 :         }
     541                 : 
     542              66 :         return poPoint;
     543                 :     }
     544                 : 
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Box                                                             */
     547                 : /* -------------------------------------------------------------------- */
     548               6 :     if( EQUAL(pszBaseGeometry,"BoxType") || EQUAL(pszBaseGeometry,"Box") )
     549                 :     {
     550               0 :         OGRLineString  oPoints;
     551                 : 
     552               0 :         if( !ParseGMLCoordinates( psNode, &oPoints ) )
     553               0 :             return NULL;
     554                 : 
     555               0 :         if( oPoints.getNumPoints() < 2 )
     556               0 :             return NULL;
     557                 : 
     558               0 :         OGRLinearRing *poBoxRing = new OGRLinearRing();
     559               0 :         OGRPolygon *poBoxPoly = new OGRPolygon();
     560                 : 
     561               0 :         poBoxRing->setNumPoints( 5 );
     562                 :         poBoxRing->setPoint( 
     563               0 :             0, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
     564                 :         poBoxRing->setPoint( 
     565               0 :             1, oPoints.getX(1), oPoints.getY(0), oPoints.getZ(0) );
     566                 :         poBoxRing->setPoint( 
     567               0 :             2, oPoints.getX(1), oPoints.getY(1), oPoints.getZ(1) );
     568                 :         poBoxRing->setPoint( 
     569               0 :             3, oPoints.getX(0), oPoints.getY(1), oPoints.getZ(0) );
     570                 :         poBoxRing->setPoint( 
     571               0 :             4, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
     572                 : 
     573               0 :         poBoxPoly->addRingDirectly( poBoxRing );
     574                 : 
     575               0 :         return poBoxPoly;
     576                 :     }
     577                 : 
     578                 : /* -------------------------------------------------------------------- */
     579                 : /*      MultiPolygon                                                    */
     580                 : /* -------------------------------------------------------------------- */
     581               6 :     if( EQUAL(pszBaseGeometry,"MultiPolygon") ||
     582                 :         EQUAL(pszBaseGeometry,"MultiSurface") )
     583                 :     {
     584                 :         const CPLXMLNode *psChild;
     585               1 :         OGRMultiPolygon *poMPoly = new OGRMultiPolygon();
     586                 : 
     587                 :         // Find all inner rings 
     588               3 :         for( psChild = psNode->psChild; 
     589                 :              psChild != NULL;
     590                 :              psChild = psChild->psNext ) 
     591                 :         {
     592               2 :             if( psChild->eType == CXT_Element
     593                 :                 && (EQUAL(BareGMLElement(psChild->pszValue),"polygonMember") ||
     594                 :                     EQUAL(BareGMLElement(psChild->pszValue),"surfaceMember")) )
     595                 :             {
     596                 :                 OGRPolygon *poPolygon;
     597                 : 
     598                 :                 poPolygon = (OGRPolygon *) 
     599               2 :                     GML2OGRGeometry_XMLNode( psChild->psChild );
     600                 : 
     601               2 :                 if( poPolygon == NULL )
     602                 :                 {
     603               0 :                     delete poMPoly;
     604               0 :                     return NULL;
     605                 :                 }
     606                 : 
     607               2 :                 if( !EQUAL(poPolygon->getGeometryName(),"POLYGON") )
     608                 :                 {
     609                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     610                 :                               "Got %.500s geometry as polygonMember instead of MULTIPOLYGON.",
     611               0 :                               poPolygon->getGeometryName() );
     612               0 :                     delete poPolygon;
     613               0 :                     delete poMPoly;
     614               0 :                     return NULL;
     615                 :                 }
     616                 : 
     617               2 :                 poMPoly->addGeometryDirectly( poPolygon );
     618                 :             }
     619                 :         }
     620                 : 
     621               1 :         return poMPoly;
     622                 :     }
     623                 : 
     624                 : /* -------------------------------------------------------------------- */
     625                 : /*      MultiPoint                                                      */
     626                 : /* -------------------------------------------------------------------- */
     627               5 :     if( EQUAL(pszBaseGeometry,"MultiPoint") )
     628                 :     {
     629                 :         const CPLXMLNode *psChild;
     630               2 :         OGRMultiPoint *poMP = new OGRMultiPoint();
     631                 : 
     632                 :         // collect points.
     633               8 :         for( psChild = psNode->psChild; 
     634                 :              psChild != NULL;
     635                 :              psChild = psChild->psNext ) 
     636                 :         {
     637               6 :             if( psChild->eType == CXT_Element
     638                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"pointMember") )
     639                 :             {
     640                 :                 OGRPoint *poPoint;
     641                 : 
     642                 :                 poPoint = (OGRPoint *) 
     643               6 :                     GML2OGRGeometry_XMLNode( psChild->psChild );
     644              12 :                 if( poPoint == NULL 
     645               6 :                     || wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
     646                 :                 {
     647                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     648                 :                               "Got %.500s geometry as pointMember instead of MULTIPOINT",
     649               0 :                               poPoint ? poPoint->getGeometryName() : "NULL" );
     650               0 :                     delete poPoint;
     651               0 :                     delete poMP;
     652               0 :                     return NULL;
     653                 :                 }
     654                 : 
     655               6 :                 poMP->addGeometryDirectly( poPoint );
     656                 :             }
     657                 :         }
     658                 : 
     659               2 :         return poMP;
     660                 :     }
     661                 : 
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      MultiLineString                                                 */
     664                 : /* -------------------------------------------------------------------- */
     665               3 :     if( EQUAL(pszBaseGeometry,"MultiLineString") )
     666                 :     {
     667                 :         const CPLXMLNode *psChild;
     668               1 :         OGRMultiLineString *poMP = new OGRMultiLineString();
     669                 : 
     670                 :         // collect lines
     671               5 :         for( psChild = psNode->psChild; 
     672                 :              psChild != NULL;
     673                 :              psChild = psChild->psNext ) 
     674                 :         {
     675               4 :             if( psChild->eType == CXT_Element
     676                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"lineStringMember") )
     677                 :             {
     678                 :                 OGRGeometry *poGeom;
     679                 : 
     680               4 :                 poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
     681               8 :                 if( poGeom == NULL 
     682               4 :                     || wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
     683                 :                 {
     684                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     685                 :                               "Got %.500s geometry as Member instead of LINESTRING.",
     686               0 :                               poGeom ? poGeom->getGeometryName() : "NULL" );
     687               0 :                     delete poGeom;
     688               0 :                     delete poMP;
     689               0 :                     return NULL;
     690                 :                 }
     691                 : 
     692               4 :                 poMP->addGeometryDirectly( poGeom );
     693                 :             }
     694                 :         }
     695                 : 
     696               1 :         return poMP;
     697                 :     }
     698                 : 
     699                 : /* -------------------------------------------------------------------- */
     700                 : /*      GeometryCollection                                              */
     701                 : /* -------------------------------------------------------------------- */
     702               2 :     if( EQUAL(pszBaseGeometry,"GeometryCollection") )
     703                 :     {
     704                 :         const CPLXMLNode *psChild;
     705               2 :         OGRGeometryCollection *poGC = new OGRGeometryCollection();
     706                 : 
     707                 :         // collect geoms
     708              10 :         for( psChild = psNode->psChild; 
     709                 :              psChild != NULL;
     710                 :              psChild = psChild->psNext ) 
     711                 :         {
     712               8 :             if( psChild->eType == CXT_Element
     713                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"geometryMember") )
     714                 :             {
     715                 :                 OGRGeometry *poGeom;
     716                 : 
     717               8 :                 poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
     718               8 :                 if( poGeom == NULL )
     719                 :                 {
     720                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     721               0 :                               "Failed to get geometry in geometryMember" );
     722               0 :                     delete poGeom;
     723               0 :                     delete poGC;
     724               0 :                     return NULL;
     725                 :                 }
     726                 : 
     727               8 :                 poGC->addGeometryDirectly( poGeom );
     728                 :             }
     729                 :         }
     730                 : 
     731               2 :         return poGC;
     732                 :     }
     733                 : 
     734                 :     CPLError( CE_Failure, CPLE_AppDefined, 
     735                 :               "Unrecognised geometry type <%.500s>.", 
     736               0 :               pszBaseGeometry );
     737                 : 
     738               0 :     return NULL;
     739                 : }
     740                 : 
     741                 : /************************************************************************/
     742                 : /*                      OGR_G_CreateFromGMLTree()                       */
     743                 : /************************************************************************/
     744                 : 
     745               2 : OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
     746                 : 
     747                 : {
     748               2 :     return (OGRGeometryH) GML2OGRGeometry_XMLNode( psTree );
     749                 : }
     750                 : 
     751                 : /************************************************************************/
     752                 : /*                        OGR_G_CreateFromGML()                         */
     753                 : /************************************************************************/
     754                 : 
     755              83 : OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
     756                 : 
     757                 : {
     758              83 :     if( pszGML == NULL || strlen(pszGML) == 0 )
     759                 :     {
     760                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     761               0 :                   "GML Geometry is empty in GML2OGRGeometry()." );
     762               0 :         return NULL;
     763                 :     }
     764                 : 
     765                 : /* ------------------------------------------------------------ -------- */
     766                 : /*      Try to parse the XML snippet using the MiniXML API.  If this    */
     767                 : /*      fails, we assume the minixml api has already posted a CPL       */
     768                 : /*      error, and just return NULL.                                    */
     769                 : /* -------------------------------------------------------------------- */
     770              83 :     CPLXMLNode *psGML = CPLParseXMLString( pszGML );
     771                 : 
     772              83 :     if( psGML == NULL )
     773               0 :         return NULL;
     774                 : 
     775                 : /* -------------------------------------------------------------------- */
     776                 : /*      Convert geometry recursively.                                   */
     777                 : /* -------------------------------------------------------------------- */
     778                 :     OGRGeometry *poGeometry;
     779                 : 
     780              83 :     poGeometry = GML2OGRGeometry_XMLNode( psGML );
     781                 : 
     782              83 :     CPLDestroyXMLNode( psGML );
     783                 :     
     784              83 :     return (OGRGeometryH) poGeometry;
     785                 : }

Generated by: LCOV version 1.7