LTP GCOV extension - code coverage report
Current view: directory - ogr - gml2ogrgeometry.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 535
Code covered: 49.5 % Executed lines: 265

       1                 : /******************************************************************************
       2                 :  * $Id: gml2ogrgeometry.cpp 20010 2010-07-10 23:04:05Z 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             467 : static const char *BareGMLElement( const char *pszInput )
      57                 : 
      58                 : {
      59                 :     const char *pszReturn;
      60                 : 
      61             467 :     pszReturn = strchr( pszInput, ':' );
      62             467 :     if( pszReturn == NULL )
      63             162 :         pszReturn = pszInput;
      64                 :     else
      65             305 :         pszReturn++;
      66                 : 
      67             467 :     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                 : static const CPLXMLNode *FindBareXMLChild( const CPLXMLNode *psParent, 
      78             175 :                                            const char *pszBareName )
      79                 : 
      80                 : {
      81             175 :     const CPLXMLNode *psCandidate = psParent->psChild;
      82                 : 
      83             432 :     while( psCandidate != NULL )
      84                 :     {
      85             216 :         if( psCandidate->eType == CXT_Element
      86                 :             && EQUAL(BareGMLElement(psCandidate->pszValue), pszBareName) )
      87             134 :             return psCandidate;
      88                 : 
      89              82 :         psCandidate = psCandidate->psNext;
      90                 :     }
      91                 : 
      92              41 :     return NULL;
      93                 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                           GetElementText()                           */
      97                 : /************************************************************************/
      98                 : 
      99             137 : static const char *GetElementText( const CPLXMLNode *psElement )
     100                 : 
     101                 : {
     102             137 :     if( psElement == NULL )
     103               0 :         return NULL;
     104                 : 
     105             137 :     const CPLXMLNode *psChild = psElement->psChild;
     106                 : 
     107             281 :     while( psChild != NULL )
     108                 :     {
     109             144 :         if( psChild->eType == CXT_Text )
     110             137 :             return psChild->pszValue;
     111                 : 
     112               7 :         psChild = psChild->psNext;
     113                 :     }
     114                 :     
     115               0 :     return NULL;
     116                 : }
     117                 : 
     118                 : /************************************************************************/
     119                 : /*                    GetElementOrientation()                           */
     120                 : /*     Returns true for positive orientation.                           */
     121                 : /************************************************************************/
     122                 : 
     123               0 : int GetElementOrientation( const CPLXMLNode *psElement )
     124                 : {
     125               0 :     if( psElement == NULL )
     126               0 :         return TRUE;
     127                 : 
     128               0 :     const CPLXMLNode *psChild = psElement->psChild;
     129                 : 
     130               0 :     while( psChild != NULL )
     131                 :     {
     132               0 :         if( psChild->eType == CXT_Attribute &&
     133                 :             EQUAL(psChild->pszValue,"orientation") )
     134               0 :                 return EQUAL(psChild->psChild->pszValue,"+");
     135                 : 
     136               0 :         psChild = psChild->psNext;
     137                 :     }
     138                 :     
     139               0 :     return TRUE;
     140                 : }
     141                 : 
     142                 : /************************************************************************/
     143                 : /*                              AddPoint()                              */
     144                 : /*                                                                      */
     145                 : /*      Add a point to the passed geometry.                             */
     146                 : /************************************************************************/
     147                 : 
     148                 : static int AddPoint( OGRGeometry *poGeometry, 
     149             389 :                      double dfX, double dfY, double dfZ, int nDimension )
     150                 : 
     151                 : {
     152             389 :     if( poGeometry->getGeometryType() == wkbPoint 
     153                 :         || poGeometry->getGeometryType() == wkbPoint25D )
     154                 :     {
     155              73 :         OGRPoint *poPoint = (OGRPoint *) poGeometry;
     156                 : 
     157              73 :         if( poPoint->getX() != 0.0 || poPoint->getY() != 0.0 )
     158                 :         {
     159                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     160               0 :                       "More than one coordinate for <Point> element.");
     161               0 :             return FALSE;
     162                 :         }
     163                 :             
     164              73 :         poPoint->setX( dfX );
     165              73 :         poPoint->setY( dfY );
     166              73 :         if( nDimension == 3 )
     167               4 :             poPoint->setZ( dfZ );
     168                 : 
     169              73 :         return TRUE;
     170                 :     }
     171                 :                 
     172             316 :     else if( poGeometry->getGeometryType() == wkbLineString
     173                 :              || poGeometry->getGeometryType() == wkbLineString25D )
     174                 :     {
     175             316 :         if( nDimension == 3 )
     176              24 :             ((OGRLineString *) poGeometry)->addPoint( dfX, dfY, dfZ );
     177                 :         else
     178             292 :             ((OGRLineString *) poGeometry)->addPoint( dfX, dfY );
     179                 : 
     180             316 :         return TRUE;
     181                 :     }
     182                 : 
     183                 :     else
     184                 :     {
     185               0 :         CPLAssert( FALSE );
     186               0 :         return FALSE;                                                   
     187                 :     }
     188                 : }
     189                 : 
     190                 : /************************************************************************/
     191                 : /*                        ParseGMLCoordinates()                         */
     192                 : /************************************************************************/
     193                 : 
     194             119 : static int ParseGMLCoordinates( const CPLXMLNode *psGeomNode, OGRGeometry *poGeometry )
     195                 : 
     196                 : {
     197             119 :     const CPLXMLNode *psCoordinates = FindBareXMLChild( psGeomNode, "coordinates" );
     198             119 :     int iCoord = 0;
     199                 : 
     200                 : /* -------------------------------------------------------------------- */
     201                 : /*      Handle <coordinates> case.                                      */
     202                 : /* -------------------------------------------------------------------- */
     203             119 :     if( psCoordinates != NULL )
     204                 :     {
     205              90 :         const char *pszCoordString = GetElementText( psCoordinates );
     206                 : 
     207              90 :         if( pszCoordString == NULL )
     208                 :         {
     209                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     210               0 :                       "<coordinates> element missing value." );
     211               0 :             return FALSE;
     212                 :         }
     213                 : 
     214             490 :         while( *pszCoordString != '\0' )
     215                 :         {
     216             310 :             double dfX, dfY, dfZ = 0.0;
     217             310 :             int nDimension = 2;
     218                 : 
     219                 :             // parse out 2 or 3 tuple. 
     220             310 :             dfX = OGRFastAtof( pszCoordString );
     221            3500 :             while( *pszCoordString != '\0'
     222                 :                    && *pszCoordString != ','
     223                 :                    && !isspace((unsigned char)*pszCoordString) )
     224            2880 :                 pszCoordString++;
     225                 : 
     226             310 :             if( *pszCoordString == '\0' || isspace((unsigned char)*pszCoordString) )
     227                 :             {
     228                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     229               0 :                           "Corrupt <coordinates> value." );
     230               0 :                 return FALSE;
     231                 :             }
     232                 : 
     233             310 :             pszCoordString++;
     234             310 :             dfY = OGRFastAtof( pszCoordString );
     235            3571 :             while( *pszCoordString != '\0' 
     236                 :                    && *pszCoordString != ','
     237                 :                    && !isspace((unsigned char)*pszCoordString) )
     238            2951 :                 pszCoordString++;
     239                 : 
     240             310 :             if( *pszCoordString == ',' )
     241                 :             {
     242              24 :                 pszCoordString++;
     243              24 :                 dfZ = OGRFastAtof( pszCoordString );
     244              24 :                 nDimension = 3;
     245              72 :                 while( *pszCoordString != '\0' 
     246                 :                        && *pszCoordString != ','
     247                 :                        && !isspace((unsigned char)*pszCoordString) )
     248              24 :                 pszCoordString++;
     249                 :             }
     250                 : 
     251             869 :             while( isspace((unsigned char)*pszCoordString) )
     252             249 :                 pszCoordString++;
     253                 : 
     254             310 :             if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
     255               0 :                 return FALSE;
     256                 : 
     257             310 :             iCoord++;
     258                 :         }
     259                 : 
     260              90 :         return iCoord > 0;
     261                 :     }
     262                 : 
     263                 : /* -------------------------------------------------------------------- */
     264                 : /*      Is this a "pos"?  GML 3 construct.                              */
     265                 : /*      Parse if it exist a series of pos elements (this would allow    */
     266                 : /*      the correct parsing of gml3.1.1 geomtries such as linestring    */
     267                 : /*      defined with pos elements.                                      */
     268                 : /* -------------------------------------------------------------------- */
     269                 :     const CPLXMLNode *psPos;
     270                 :     
     271              29 :     int bHasFoundPosElement = FALSE;
     272              71 :     for( psPos = psGeomNode->psChild; 
     273                 :          psPos != NULL;
     274                 :          psPos = psPos->psNext )
     275                 :     {
     276              42 :         if( psPos->eType != CXT_Element 
     277                 :             || !EQUAL(BareGMLElement(psPos->pszValue),"pos") )
     278              20 :             continue;
     279                 :         
     280                 :         char **papszTokens = CSLTokenizeStringComplex( 
     281              22 :             GetElementText( psPos ), " ,", FALSE, FALSE );
     282              22 :         int bSuccess = FALSE;
     283                 : 
     284              22 :         if( CSLCount( papszTokens ) > 2 )
     285                 :         {
     286                 :             bSuccess = AddPoint( poGeometry, 
     287                 :                                  OGRFastAtof(papszTokens[0]), 
     288                 :                                  OGRFastAtof(papszTokens[1]),
     289               1 :                                  OGRFastAtof(papszTokens[2]), 3 );
     290                 :         }
     291              21 :         else if( CSLCount( papszTokens ) > 1 )
     292                 :         {
     293                 :             bSuccess = AddPoint( poGeometry, 
     294                 :                                  OGRFastAtof(papszTokens[0]), 
     295                 :                                  OGRFastAtof(papszTokens[1]),
     296              21 :                                  0.0, 2 );
     297                 :         }
     298                 :         else
     299                 :         {
     300                 :             CPLError( CE_Failure, CPLE_AppDefined,
     301                 :                       "Did not get 2+ values in <gml:pos>%s</gml:pos> tuple.",
     302               0 :                       GetElementText( psPos ) );
     303                 :         }
     304                 : 
     305              22 :         CSLDestroy( papszTokens );
     306                 :         
     307              22 :         if (bSuccess)
     308              22 :             bHasFoundPosElement = TRUE;
     309                 :         else
     310               0 :             return FALSE;
     311                 :     }
     312                 :     
     313              29 :     if (bHasFoundPosElement)
     314              12 :         return TRUE;
     315                 :     
     316                 : 
     317                 : /* -------------------------------------------------------------------- */
     318                 : /*      Is this a "posList"?  GML 3 construct (SF profile).             */
     319                 : /* -------------------------------------------------------------------- */
     320              17 :     const CPLXMLNode *psPosList = FindBareXMLChild( psGeomNode, "posList" );
     321                 :     
     322              17 :     if( psPosList != NULL )
     323                 :     {
     324                 :         char **papszTokens;
     325              16 :         int bSuccess = FALSE;
     326              16 :         int i=0, nCount=0;
     327                 :         const CPLXMLNode* psChild;
     328              16 :         int nDimension = 2;
     329                 : 
     330                 :         /* Try to detect the presence of an srsDimension attribute */
     331                 :         /* This attribute is only availabe for gml3.1.1 but not */
     332                 :         /* available for gml3.1 SF*/
     333              16 :         psChild = psPosList->psChild;
     334              32 :         while (psChild != NULL)
     335                 :         {
     336              16 :             if (psChild->eType == CXT_Attribute &&
     337                 :                 EQUAL(psChild->pszValue, "srsDimension"))
     338                 :             {
     339               1 :                 nDimension = atoi(psChild->psChild->pszValue);
     340               1 :                 break;
     341                 :             }
     342              15 :             else if (psChild->eType != CXT_Attribute)
     343                 :             {
     344              15 :                 break;
     345                 :             }
     346               0 :             psChild = psChild->psNext;
     347                 :         }
     348                 : 
     349              16 :         if (nDimension != 2 && nDimension != 3)
     350                 :         {
     351                 :             CPLError( CE_Failure, CPLE_AppDefined,
     352               0 :                       "srsDimension = %d not supported", nDimension);
     353               0 :             return FALSE;
     354                 :         }
     355                 : 
     356                 :         papszTokens = CSLTokenizeStringComplex( 
     357              16 :             GetElementText( psPosList ), " ,", FALSE, FALSE );
     358                 : 
     359              16 :         nCount = CSLCount( papszTokens );
     360                 : 
     361              17 :         if (nCount < nDimension  || (nCount % nDimension) != 0)
     362                 :         {
     363                 :             CPLError( CE_Failure, CPLE_AppDefined,
     364                 :                       "Did not get at least %d values or invalid number of \n"
     365                 :                       "set of coordinates <gml:posList>%s</gml:posList>",
     366               1 :                       nDimension, GetElementText( psPosList ) );
     367                 :         }
     368                 :         else
     369                 :         {
     370              15 :             i=0;
     371              85 :             while (i<nCount)
     372                 :             {
     373                 :                 bSuccess = AddPoint( poGeometry, 
     374                 :                                      OGRFastAtof(papszTokens[i]), 
     375                 :                                      OGRFastAtof(papszTokens[i+1]),
     376              55 :                                      (nDimension == 3) ? OGRFastAtof(papszTokens[i+2]) : 0.0, nDimension );
     377              55 :                 i+=nDimension;
     378                 :             }
     379                 :         }
     380              16 :         CSLDestroy( papszTokens );
     381                 : 
     382              16 :         return bSuccess;
     383                 :     }
     384                 :     
     385                 : 
     386                 : /* -------------------------------------------------------------------- */
     387                 : /*      Handle form with a list of <coord> items each with an <X>,      */
     388                 : /*      and <Y> element.                                                */
     389                 : /* -------------------------------------------------------------------- */
     390                 :     const CPLXMLNode *psCoordNode;
     391                 : 
     392               5 :     for( psCoordNode = psGeomNode->psChild; 
     393                 :          psCoordNode != NULL;
     394                 :          psCoordNode = psCoordNode->psNext )
     395                 :     {
     396               4 :         if( psCoordNode->eType != CXT_Element 
     397                 :             || !EQUAL(BareGMLElement(psCoordNode->pszValue),"coord") )
     398               2 :             continue;
     399                 : 
     400                 :         const CPLXMLNode *psXNode, *psYNode, *psZNode;
     401               2 :         double dfX, dfY, dfZ = 0.0;
     402               2 :         int nDimension = 2;
     403                 : 
     404               2 :         psXNode = FindBareXMLChild( psCoordNode, "X" );
     405               2 :         psYNode = FindBareXMLChild( psCoordNode, "Y" );
     406               2 :         psZNode = FindBareXMLChild( psCoordNode, "Z" );
     407                 : 
     408               2 :         if( psXNode == NULL || psYNode == NULL 
     409                 :             || GetElementText(psXNode) == NULL
     410                 :             || GetElementText(psYNode) == NULL
     411                 :             || (psZNode != NULL && GetElementText(psZNode) == NULL) )
     412                 :         {
     413                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     414               0 :                       "Corrupt <coord> element, missing <X> or <Y> element?" );
     415               0 :             return FALSE;
     416                 :         }
     417                 : 
     418               2 :         dfX = OGRFastAtof( GetElementText(psXNode) );
     419               2 :         dfY = OGRFastAtof( GetElementText(psYNode) );
     420                 : 
     421               2 :         if( psZNode != NULL && GetElementText(psZNode) != NULL )
     422                 :         {
     423               0 :             dfZ = OGRFastAtof( GetElementText(psZNode) );
     424               0 :             nDimension = 3;
     425                 :         }
     426                 : 
     427               2 :         if( !AddPoint( poGeometry, dfX, dfY, dfZ, nDimension ) )
     428               0 :             return FALSE;
     429                 : 
     430               2 :         iCoord++;
     431                 :     }
     432                 : 
     433               1 :     return iCoord > 0.0;
     434                 : }
     435                 : 
     436                 : /************************************************************************/
     437                 : /*                      GML2OGRGeometry_XMLNode()                       */
     438                 : /*                                                                      */
     439                 : /*      Translates the passed XMLnode and it's children into an         */
     440                 : /*      OGRGeometry.  This is used recursively for geometry             */
     441                 : /*      collections.                                                    */
     442                 : /************************************************************************/
     443                 : 
     444                 : static OGRGeometry *GML2OGRGeometry_XMLNode( const CPLXMLNode *psNode,
     445                 :                                              int bIgnoreGSG = FALSE,
     446             153 :                                              int bOrientation = TRUE )
     447                 : 
     448                 : {
     449             153 :     const char *pszBaseGeometry = BareGMLElement( psNode->pszValue );
     450                 :     int bGetSecondaryGeometry =
     451                 :             bIgnoreGSG ? FALSE :
     452             153 :             CSLTestBoolean(CPLGetConfigOption("GML_GET_SECONDARY_GEOM", "NO"));
     453                 : 
     454             153 :     if( bGetSecondaryGeometry )
     455               0 :         if( !( EQUAL(pszBaseGeometry,"directedEdge") ||
     456                 :                EQUAL(pszBaseGeometry,"TopoCurve") ) )
     457               0 :             return NULL;
     458                 : 
     459                 : /* -------------------------------------------------------------------- */
     460                 : /*      Polygon                                                         */
     461                 : /* -------------------------------------------------------------------- */
     462             153 :     if( EQUAL(pszBaseGeometry,"Polygon") ||
     463                 :         EQUAL(pszBaseGeometry,"PolygonPatch") )
     464                 :     {
     465                 :         const CPLXMLNode *psChild;
     466              17 :         OGRPolygon *poPolygon = new OGRPolygon();
     467                 :         OGRLinearRing *poRing;
     468                 : 
     469                 :         // Find outer ring.
     470              17 :         psChild = FindBareXMLChild( psNode, "outerBoundaryIs" );
     471              17 :         if (psChild == NULL)
     472               7 :            psChild = FindBareXMLChild( psNode, "exterior");
     473                 : 
     474              17 :         if( psChild == NULL || psChild->psChild == NULL )
     475                 :         {
     476                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     477               0 :                       "Missing outerBoundaryIs property on Polygon." );
     478               0 :             delete poPolygon;
     479               0 :             return NULL;
     480                 :         }
     481                 : 
     482                 :         // Translate outer ring and add to polygon.
     483                 :         poRing = (OGRLinearRing *) 
     484              17 :             GML2OGRGeometry_XMLNode( psChild->psChild );
     485              17 :         if( poRing == NULL )
     486                 :         {
     487               0 :             CPLError( CE_Failure, CPLE_AppDefined, "Invalid exterior ring");
     488               0 :             delete poPolygon;
     489               0 :             return NULL;
     490                 :         }
     491                 : 
     492              17 :         if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
     493                 :         {
     494                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     495                 :                       "Polygon: Got %.500s geometry as outerBoundaryIs instead of LINEARRING.",
     496               0 :                       poRing->getGeometryName() );
     497               0 :             delete poPolygon;
     498               0 :             delete poRing;
     499               0 :             return NULL;
     500                 :         }
     501                 : 
     502              17 :         poPolygon->addRingDirectly( poRing );
     503                 : 
     504                 :         // Find all inner rings 
     505              45 :         for( psChild = psNode->psChild; 
     506                 :              psChild != NULL;
     507                 :              psChild = psChild->psNext ) 
     508                 :         {
     509              28 :             if( psChild->eType == CXT_Element
     510                 :                 && (EQUAL(BareGMLElement(psChild->pszValue),"innerBoundaryIs") ||
     511                 :                     EQUAL(BareGMLElement(psChild->pszValue),"interior")))
     512                 :             {
     513               6 :                 if (psChild->psChild != NULL)
     514                 :                     poRing = (OGRLinearRing *) 
     515               6 :                         GML2OGRGeometry_XMLNode( psChild->psChild );
     516                 :                 else
     517               0 :                     poRing = NULL;
     518               6 :                 if (poRing == NULL)
     519                 :                 {
     520               0 :                     CPLError( CE_Failure, CPLE_AppDefined, "Invalid interior ring");
     521               0 :                     delete poPolygon;
     522               0 :                     return NULL;
     523                 :                 }
     524               6 :                 if( !EQUAL(poRing->getGeometryName(),"LINEARRING") )
     525                 :                 {
     526                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     527                 :                               "Polygon: Got %.500s geometry as innerBoundaryIs instead of LINEARRING.",
     528               0 :                               poRing->getGeometryName() );
     529               0 :                     delete poPolygon;
     530               0 :                     delete poRing;
     531               0 :                     return NULL;
     532                 :                 }
     533                 : 
     534               6 :                 poPolygon->addRingDirectly( poRing );
     535                 :             }
     536                 :         }
     537                 : 
     538              17 :         return poPolygon;
     539                 :     }
     540                 : 
     541                 : /* -------------------------------------------------------------------- */
     542                 : /*      LinearRing                                                      */
     543                 : /* -------------------------------------------------------------------- */
     544             136 :     if( EQUAL(pszBaseGeometry,"LinearRing") )
     545                 :     {
     546              22 :         OGRLinearRing   *poLinearRing = new OGRLinearRing();
     547                 :         
     548              22 :         if( !ParseGMLCoordinates( psNode, poLinearRing ) )
     549                 :         {
     550               0 :             delete poLinearRing;
     551               0 :             return NULL;
     552                 :         }
     553                 : 
     554              22 :         return poLinearRing;
     555                 :     }
     556                 : 
     557                 : /* -------------------------------------------------------------------- */
     558                 : /*      Ring GML3                                                       */
     559                 : /* -------------------------------------------------------------------- */
     560             114 :     if( EQUAL(pszBaseGeometry,"Ring") )
     561                 :     {
     562               1 :         OGRLinearRing   *poLinearRing = new OGRLinearRing();
     563                 :         const CPLXMLNode *psChild;
     564                 : 
     565               3 :         for( psChild = psNode->psChild; 
     566                 :              psChild != NULL; psChild = psChild->psNext )
     567                 :         {
     568               2 :             if( psChild->eType == CXT_Element
     569                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
     570                 :             {
     571                 :                 OGRLineString *poLS;
     572               2 :                 if (psChild->psChild)
     573                 :                     poLS = (OGRLineString *) 
     574               2 :                         GML2OGRGeometry_XMLNode( psChild->psChild );
     575                 :                 else
     576               0 :                     poLS = NULL;
     577                 : 
     578               2 :                 if( poLS == NULL 
     579                 :                     || wkbFlatten(poLS->getGeometryType()) != wkbLineString )
     580                 :                 {
     581               0 :                     delete poLS;
     582               0 :                     delete poLinearRing;
     583               0 :                     return NULL;
     584                 :                 }
     585                 : 
     586                 :                 // we might need to take steps to avoid duplicate points...
     587               2 :                 poLinearRing->addSubLineString( poLS );
     588               2 :                 delete poLS;
     589                 :             }
     590                 :         }
     591                 : 
     592               1 :         return poLinearRing;
     593                 :     }
     594                 : 
     595                 : /* -------------------------------------------------------------------- */
     596                 : /*      LineString                                                      */
     597                 : /* -------------------------------------------------------------------- */
     598             113 :     if( EQUAL(pszBaseGeometry,"LineString")
     599                 :         || EQUAL(pszBaseGeometry,"LineStringSegment") )
     600                 :     {
     601              23 :         OGRLineString   *poLine = new OGRLineString();
     602                 :         
     603              23 :         if( !ParseGMLCoordinates( psNode, poLine ) )
     604                 :         {
     605               1 :             delete poLine;
     606               1 :             return NULL;
     607                 :         }
     608                 : 
     609              22 :         return poLine;
     610                 :     }
     611                 : 
     612                 : /* -------------------------------------------------------------------- */
     613                 : /*      PointType                                                       */
     614                 : /* -------------------------------------------------------------------- */
     615              90 :     if( EQUAL(pszBaseGeometry,"PointType") 
     616                 :         || EQUAL(pszBaseGeometry,"Point")
     617                 :         || EQUAL(pszBaseGeometry,"ConnectionPoint") )
     618                 :     {
     619              73 :         OGRPoint *poPoint = new OGRPoint();
     620                 :         
     621              73 :         if( !ParseGMLCoordinates( psNode, poPoint ) )
     622                 :         {
     623               0 :             delete poPoint;
     624               0 :             return NULL;
     625                 :         }
     626                 : 
     627              73 :         return poPoint;
     628                 :     }
     629                 : 
     630                 : /* -------------------------------------------------------------------- */
     631                 : /*      Box                                                             */
     632                 : /* -------------------------------------------------------------------- */
     633              17 :     if( EQUAL(pszBaseGeometry,"BoxType") || EQUAL(pszBaseGeometry,"Box") )
     634                 :     {
     635               1 :         OGRLineString  oPoints;
     636                 : 
     637               1 :         if( !ParseGMLCoordinates( psNode, &oPoints ) )
     638               1 :             return NULL;
     639                 : 
     640               1 :         if( oPoints.getNumPoints() < 2 )
     641               0 :             return NULL;
     642                 : 
     643               1 :         OGRLinearRing *poBoxRing = new OGRLinearRing();
     644               2 :         OGRPolygon *poBoxPoly = new OGRPolygon();
     645                 : 
     646               1 :         poBoxRing->setNumPoints( 5 );
     647                 :         poBoxRing->setPoint( 
     648               1 :             0, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
     649                 :         poBoxRing->setPoint( 
     650               1 :             1, oPoints.getX(1), oPoints.getY(0), oPoints.getZ(0) );
     651                 :         poBoxRing->setPoint( 
     652               1 :             2, oPoints.getX(1), oPoints.getY(1), oPoints.getZ(1) );
     653                 :         poBoxRing->setPoint( 
     654               1 :             3, oPoints.getX(0), oPoints.getY(1), oPoints.getZ(0) );
     655                 :         poBoxRing->setPoint( 
     656               1 :             4, oPoints.getX(0), oPoints.getY(0), oPoints.getZ(0) );
     657                 : 
     658               1 :         poBoxPoly->addRingDirectly( poBoxRing );
     659                 : 
     660               1 :         return poBoxPoly;
     661                 :     }
     662                 : 
     663                 : /* -------------------------------------------------------------------- */
     664                 : /*      MultiPolygon                                                    */
     665                 : /* -------------------------------------------------------------------- */
     666              16 :     if( EQUAL(pszBaseGeometry,"MultiPolygon") ||
     667                 :         EQUAL(pszBaseGeometry,"MultiSurface") )
     668                 :     {
     669                 :         const CPLXMLNode *psChild;
     670               2 :         OGRMultiPolygon *poMPoly = new OGRMultiPolygon();
     671                 : 
     672                 :         // Find all inner rings 
     673               8 :         for( psChild = psNode->psChild; 
     674                 :              psChild != NULL;
     675                 :              psChild = psChild->psNext ) 
     676                 :         {
     677               6 :             if( psChild->eType == CXT_Element
     678                 :                 && (EQUAL(BareGMLElement(psChild->pszValue),"polygonMember") ||
     679                 :                     EQUAL(BareGMLElement(psChild->pszValue),"surfaceMember")) )
     680                 :             {
     681                 :                 OGRPolygon *poPolygon;
     682                 : 
     683               4 :                 if (psChild->psChild != NULL)
     684                 :                     poPolygon = (OGRPolygon *) 
     685               4 :                         GML2OGRGeometry_XMLNode( psChild->psChild );
     686                 :                 else
     687               0 :                     poPolygon = NULL;
     688                 : 
     689               4 :                 if( poPolygon == NULL )
     690                 :                 {
     691                 :                     CPLError( CE_Failure, CPLE_AppDefined, "Invalid %s",
     692               0 :                               BareGMLElement(psChild->pszValue));
     693               0 :                     delete poMPoly;
     694               0 :                     return NULL;
     695                 :                 }
     696                 : 
     697               4 :                 if( !EQUAL(poPolygon->getGeometryName(),"POLYGON") )
     698                 :                 {
     699                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     700                 :                               "Got %.500s geometry as polygonMember instead of MULTIPOLYGON.",
     701               0 :                               poPolygon->getGeometryName() );
     702               0 :                     delete poPolygon;
     703               0 :                     delete poMPoly;
     704               0 :                     return NULL;
     705                 :                 }
     706                 : 
     707               4 :                 poMPoly->addGeometryDirectly( poPolygon );
     708                 :             }
     709                 :         }
     710                 : 
     711               2 :         return poMPoly;
     712                 :     }
     713                 : 
     714                 : /* -------------------------------------------------------------------- */
     715                 : /*      MultiPoint                                                      */
     716                 : /* -------------------------------------------------------------------- */
     717              14 :     if( EQUAL(pszBaseGeometry,"MultiPoint") )
     718                 :     {
     719                 :         const CPLXMLNode *psChild;
     720               2 :         OGRMultiPoint *poMP = new OGRMultiPoint();
     721                 : 
     722                 :         // collect points.
     723               8 :         for( psChild = psNode->psChild; 
     724                 :              psChild != NULL;
     725                 :              psChild = psChild->psNext ) 
     726                 :         {
     727               6 :             if( psChild->eType == CXT_Element
     728                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"pointMember") )
     729                 :             {
     730                 :                 OGRPoint *poPoint;
     731                 : 
     732               6 :                 if (psChild->psChild != NULL)
     733                 :                     poPoint = (OGRPoint *) 
     734               6 :                         GML2OGRGeometry_XMLNode( psChild->psChild );
     735                 :                 else
     736               0 :                     poPoint = NULL;
     737               6 :                 if( poPoint == NULL 
     738                 :                     || wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
     739                 :                 {
     740                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     741                 :                               "MultiPoint: Got %.500s geometry as pointMember instead of MULTIPOINT",
     742               0 :                               poPoint ? poPoint->getGeometryName() : "NULL" );
     743               0 :                     delete poPoint;
     744               0 :                     delete poMP;
     745               0 :                     return NULL;
     746                 :                 }
     747                 : 
     748               6 :                 poMP->addGeometryDirectly( poPoint );
     749                 :             }
     750                 :         }
     751                 : 
     752               2 :         return poMP;
     753                 :     }
     754                 : 
     755                 : /* -------------------------------------------------------------------- */
     756                 : /*      MultiLineString                                                 */
     757                 : /* -------------------------------------------------------------------- */
     758              12 :     if( EQUAL(pszBaseGeometry,"MultiLineString") )
     759                 :     {
     760                 :         const CPLXMLNode *psChild;
     761               1 :         OGRMultiLineString *poMLS = new OGRMultiLineString();
     762                 : 
     763                 :         // collect lines
     764               5 :         for( psChild = psNode->psChild; 
     765                 :              psChild != NULL;
     766                 :              psChild = psChild->psNext ) 
     767                 :         {
     768               4 :             if( psChild->eType == CXT_Element
     769                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"lineStringMember") )
     770                 :             {
     771                 :                 OGRGeometry *poGeom;
     772                 : 
     773               4 :                 if (psChild->psChild != NULL)
     774               4 :                     poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
     775                 :                 else
     776               0 :                     poGeom = NULL;
     777               4 :                 if( poGeom == NULL 
     778                 :                     || wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
     779                 :                 {
     780                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     781                 :                               "MultiLineString: Got %.500s geometry as Member instead of LINESTRING.",
     782               0 :                               poGeom ? poGeom->getGeometryName() : "NULL" );
     783               0 :                     delete poGeom;
     784               0 :                     delete poMLS;
     785               0 :                     return NULL;
     786                 :                 }
     787                 : 
     788               4 :                 poMLS->addGeometryDirectly( poGeom );
     789                 :             }
     790                 :         }
     791                 : 
     792               1 :         return poMLS;
     793                 :     }
     794                 : 
     795                 : 
     796                 : /* -------------------------------------------------------------------- */
     797                 : /*      MultiCurve                                                      */
     798                 : /* -------------------------------------------------------------------- */
     799              11 :     if( EQUAL(pszBaseGeometry,"MultiCurve") )
     800                 :     {
     801                 :         const CPLXMLNode *psChild, *psCurve;
     802               1 :         OGRMultiLineString *poMLS = new OGRMultiLineString();
     803                 : 
     804                 :         // collect curveMembers
     805               5 :         for( psChild = psNode->psChild; 
     806                 :              psChild != NULL;
     807                 :              psChild = psChild->psNext ) 
     808                 :         {
     809               4 :             if( psChild->eType == CXT_Element
     810                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"curveMember") )
     811                 :             {
     812                 :                 OGRGeometry *poGeom;
     813                 : 
     814                 :                 // There can be only one curve under a curveMember.
     815                 :                 // Currently "Curve" and "LineString" are handled.
     816               2 :                 psCurve = FindBareXMLChild( psChild, "Curve" );
     817               2 :                 if( psCurve == NULL )
     818               2 :                     psCurve = FindBareXMLChild( psChild, "LineString" );
     819               2 :                 if( psCurve == NULL )
     820                 :                 {
     821                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     822               0 :                               "Failed to get curve element in curveMember" );
     823               0 :                     delete poMLS;
     824               0 :                     return NULL;
     825                 :                 }
     826               2 :                 poGeom = GML2OGRGeometry_XMLNode( psCurve );
     827               2 :                 if( poGeom == NULL ||
     828                 :                     ( wkbFlatten(poGeom->getGeometryType()) != wkbLineString ) )
     829                 :                 {
     830                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     831                 :                               "MultiCurve: Got %.500s geometry as Member instead of LINESTRING.",
     832               0 :                               poGeom ? poGeom->getGeometryName() : "NULL" );
     833               0 :                     if( poGeom != NULL ) delete poGeom;
     834               0 :                     delete poMLS;
     835               0 :                     return NULL;
     836                 :                 }
     837                 : 
     838               2 :                 poMLS->addGeometryDirectly( (OGRLineString *)poGeom );
     839                 :             }
     840                 :         }
     841               1 :         return poMLS;
     842                 :     }
     843                 : 
     844                 : /* -------------------------------------------------------------------- */
     845                 : /*      Curve                                                      */
     846                 : /* -------------------------------------------------------------------- */
     847              10 :     if( EQUAL(pszBaseGeometry,"Curve") )
     848                 :     {
     849                 :         const CPLXMLNode *psChild;
     850                 : 
     851               3 :         psChild = FindBareXMLChild( psNode, "segments");
     852               3 :         if( psChild == NULL )
     853                 :         {
     854                 :             CPLError( CE_Failure, CPLE_AppDefined,
     855               0 :                       "GML3 Curve geometry lacks segments element." );
     856               0 :             return NULL;
     857                 :         }
     858                 : 
     859                 :         OGRGeometry *poGeom;
     860                 : 
     861               3 :         poGeom = GML2OGRGeometry_XMLNode( psChild );
     862               3 :         if( poGeom == NULL ||
     863                 :             wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
     864                 :         {
     865                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     866                 :                 "Curve: Got %.500s geometry as Member instead of segments.",
     867               0 :                 poGeom ? poGeom->getGeometryName() : "NULL" );
     868               0 :             if( poGeom != NULL ) delete poGeom;
     869               0 :             return NULL;
     870                 :         }
     871                 : 
     872               3 :         return poGeom;
     873                 :     }
     874                 : 
     875                 : /* -------------------------------------------------------------------- */
     876                 : /*      segments                                                        */
     877                 : /* -------------------------------------------------------------------- */
     878               7 :     if( EQUAL(pszBaseGeometry,"segments") )
     879                 :     {
     880                 :         const CPLXMLNode *psChild;
     881               3 :         OGRLineString *poLS = new OGRLineString();
     882                 : 
     883               6 :         for( psChild = psNode->psChild; 
     884                 :              psChild != NULL;
     885                 :              psChild = psChild->psNext ) 
     886                 : 
     887                 :         {
     888               3 :             if( psChild->eType == CXT_Element
     889                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"LineStringSegment") )
     890                 :             {
     891                 :                 OGRGeometry *poGeom;
     892                 : 
     893               3 :                 poGeom = GML2OGRGeometry_XMLNode( psChild );
     894               3 :                 if( poGeom != NULL &&
     895                 :                     wkbFlatten(poGeom->getGeometryType()) != wkbLineString )
     896                 :                 {
     897                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     898                 :                               "segments: Got %.500s geometry as Member instead of LINESTRING.",
     899               0 :                               poGeom ? poGeom->getGeometryName() : "NULL" );
     900               0 :                     delete poGeom;
     901               0 :                     delete poLS;
     902               0 :                     return NULL;
     903                 :                 }
     904               3 :                 if( poGeom != NULL )
     905                 :                 {
     906               3 :                     poLS->addSubLineString( (OGRLineString *)poGeom );
     907               3 :                     delete poGeom;
     908                 :                 }
     909                 :             }
     910                 :         }
     911                 : 
     912               3 :         return poLS;
     913                 :     }
     914                 : 
     915                 : /* -------------------------------------------------------------------- */
     916                 : /*      GeometryCollection                                              */
     917                 : /* -------------------------------------------------------------------- */
     918               4 :     if( EQUAL(pszBaseGeometry,"GeometryCollection") )
     919                 :     {
     920                 :         const CPLXMLNode *psChild;
     921               2 :         OGRGeometryCollection *poGC = new OGRGeometryCollection();
     922                 : 
     923                 :         // collect geoms
     924              10 :         for( psChild = psNode->psChild; 
     925                 :              psChild != NULL;
     926                 :              psChild = psChild->psNext ) 
     927                 :         {
     928               8 :             if( psChild->eType == CXT_Element
     929                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"geometryMember") )
     930                 :             {
     931                 :                 OGRGeometry *poGeom;
     932                 : 
     933               8 :                 if (psChild->psChild != NULL)
     934               8 :                     poGeom = GML2OGRGeometry_XMLNode( psChild->psChild );
     935                 :                 else
     936               0 :                     poGeom = NULL;
     937               8 :                 if( poGeom == NULL )
     938                 :                 {
     939                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     940               0 :                               "GeometryCollection: Failed to get geometry in geometryMember" );
     941               0 :                     delete poGeom;
     942               0 :                     delete poGC;
     943               0 :                     return NULL;
     944                 :                 }
     945                 : 
     946               8 :                 poGC->addGeometryDirectly( poGeom );
     947                 :             }
     948                 :         }
     949                 : 
     950               2 :         return poGC;
     951                 :     }
     952                 : 
     953                 : /* -------------------------------------------------------------------- */
     954                 : /*      Directed Edge                                              */
     955                 : /* -------------------------------------------------------------------- */
     956               2 :     if( EQUAL(pszBaseGeometry,"directedEdge") )
     957                 :     {
     958                 :         const CPLXMLNode *psEdge,
     959                 :                          *psdirectedNode,
     960                 :                          *psNodeElement,
     961                 :                          *pspointProperty,
     962                 :                          *psPoint,
     963                 :                          *psCurveProperty,
     964                 :                          *psCurve;
     965               0 :         int               bEdgeOrientation = TRUE,
     966               0 :                           bNodeOrientation = TRUE;
     967                 :         OGRGeometry      *poGeom;
     968                 :         OGRLineString    *poLineString;
     969               0 :         OGRPoint         *poPositiveNode = NULL, *poNegativeNode = NULL;
     970                 :         OGRMultiPoint    *poMP;
     971                 :     
     972               0 :         bEdgeOrientation = GetElementOrientation(psNode);
     973                 : 
     974                 :         //collect edge
     975               0 :         psEdge = FindBareXMLChild(psNode,"Edge");
     976               0 :         if( psEdge == NULL )
     977                 :         {
     978                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     979               0 :                       "Failed to get Edge element in directedEdge" );
     980               0 :             return NULL;
     981                 :         }
     982                 : 
     983               0 :         if( bGetSecondaryGeometry )
     984                 :         {
     985               0 :             psdirectedNode = FindBareXMLChild(psEdge,"directedNode");
     986               0 :             if( psdirectedNode == NULL ) goto nonode;
     987                 : 
     988               0 :             bNodeOrientation = GetElementOrientation( psdirectedNode );
     989                 : 
     990               0 :             psNodeElement = FindBareXMLChild(psdirectedNode,"Node");
     991               0 :             if( psNodeElement == NULL ) goto nonode;
     992                 : 
     993               0 :             pspointProperty = FindBareXMLChild(psNodeElement,"pointProperty");
     994               0 :             if( pspointProperty == NULL )
     995               0 :                 pspointProperty = FindBareXMLChild(psNodeElement,"connectionPointProperty");
     996               0 :             if( pspointProperty == NULL ) goto nonode;
     997                 : 
     998               0 :             psPoint = FindBareXMLChild(pspointProperty,"Point");
     999               0 :             if( psPoint == NULL )
    1000               0 :                 psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
    1001               0 :             if( psPoint == NULL ) goto nonode;
    1002                 : 
    1003               0 :             poGeom = GML2OGRGeometry_XMLNode( psPoint, TRUE );
    1004               0 :             if( poGeom == NULL
    1005                 :                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
    1006                 :             {
    1007                 : /*                CPLError( CE_Failure, CPLE_AppDefined, 
    1008                 :                       "Got %.500s geometry as Member instead of POINT.",
    1009                 :                       poGeom ? poGeom->getGeometryName() : "NULL" );*/
    1010               0 :                 if( poGeom != NULL) delete poGeom;
    1011               0 :                 goto nonode;
    1012                 :             }
    1013                 : 
    1014               0 :             if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
    1015               0 :                 poPositiveNode = (OGRPoint *)poGeom;
    1016                 :             else
    1017               0 :                 poNegativeNode = (OGRPoint *)poGeom;
    1018                 : 
    1019                 :             // look for the other node
    1020               0 :             psdirectedNode = psdirectedNode->psNext;
    1021               0 :             while( psdirectedNode != NULL &&
    1022                 :                    !EQUAL( psdirectedNode->pszValue, "directedNode" ) )
    1023               0 :                 psdirectedNode = psdirectedNode->psNext;
    1024               0 :             if( psdirectedNode == NULL ) goto nonode;
    1025                 : 
    1026               0 :             if( GetElementOrientation( psdirectedNode ) == bNodeOrientation )
    1027               0 :                 goto nonode;
    1028                 : 
    1029               0 :             psNodeElement = FindBareXMLChild(psEdge,"Node");
    1030               0 :             if( psNodeElement == NULL ) goto nonode;
    1031                 : 
    1032               0 :             pspointProperty = FindBareXMLChild(psNodeElement,"pointProperty");
    1033               0 :             if( pspointProperty == NULL )
    1034               0 :                 pspointProperty = FindBareXMLChild(psNodeElement,"connectionPointProperty");
    1035               0 :             if( pspointProperty == NULL ) goto nonode;
    1036                 : 
    1037               0 :             psPoint = FindBareXMLChild(pspointProperty,"Point");
    1038               0 :             if( psPoint == NULL )
    1039               0 :                 psPoint = FindBareXMLChild(pspointProperty,"ConnectionPoint");
    1040               0 :             if( psPoint == NULL ) goto nonode;
    1041                 : 
    1042               0 :             poGeom = GML2OGRGeometry_XMLNode( psPoint, TRUE );
    1043               0 :             if( poGeom == NULL
    1044                 :                 || wkbFlatten(poGeom->getGeometryType()) != wkbPoint )
    1045                 :             {
    1046                 : /*                CPLError( CE_Failure, CPLE_AppDefined, 
    1047                 :                       "Got %.500s geometry as Member instead of POINT.",
    1048                 :                       poGeom ? poGeom->getGeometryName() : "NULL" );*/
    1049               0 :                 if( poGeom != NULL) delete poGeom;
    1050               0 :                 goto nonode;
    1051                 :             }
    1052                 : 
    1053               0 :             if( ( bNodeOrientation == bEdgeOrientation ) != bOrientation )
    1054               0 :                 poNegativeNode = (OGRPoint *)poGeom;
    1055                 :             else
    1056               0 :                 poPositiveNode = (OGRPoint *)poGeom;
    1057                 : 
    1058               0 :             poMP = new OGRMultiPoint();
    1059               0 :             poMP->addGeometryDirectly( poNegativeNode );
    1060               0 :             poMP->addGeometryDirectly( poPositiveNode );
    1061                 :             
    1062               0 :             return poMP;
    1063                 : 
    1064               0 :             nonode:;
    1065                 :         }
    1066                 : 
    1067                 :         // collect curveproperty
    1068               0 :         psCurveProperty = FindBareXMLChild(psEdge,"curveProperty");
    1069               0 :         if( psCurveProperty == NULL )
    1070                 :         {
    1071                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1072               0 :                         "directedEdge: Failed to get curveProperty in Edge" );
    1073               0 :             return NULL;
    1074                 :         }
    1075                 : 
    1076               0 :         psCurve = FindBareXMLChild(psCurveProperty,"LineString");
    1077               0 :         if( psCurve == NULL )
    1078                 :         {
    1079                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1080               0 :                       "directedEdge: Failed to get LineString geometry in curveProperty" );
    1081               0 :             return NULL;
    1082                 :         }
    1083                 : 
    1084               0 :         poLineString = (OGRLineString *)GML2OGRGeometry_XMLNode( psCurve, TRUE );
    1085               0 :         if( poLineString == NULL 
    1086                 :             || wkbFlatten(poLineString->getGeometryType()) != wkbLineString )
    1087                 :         {
    1088                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1089                 :                       "Got %.500s geometry as Member instead of LINESTRING.",
    1090               0 :                       poLineString ? poLineString->getGeometryName() : "NULL" );
    1091               0 :             if( poLineString != NULL )
    1092               0 :                 delete poLineString;
    1093               0 :             return NULL;
    1094                 :         }
    1095                 : 
    1096               0 :         if( bGetSecondaryGeometry )
    1097                 :         {
    1098                 :             // choose a point based on the orientation
    1099               0 :             poNegativeNode = new OGRPoint();
    1100               0 :             poPositiveNode = new OGRPoint();
    1101               0 :             if( bEdgeOrientation == bOrientation )
    1102                 :             {
    1103               0 :                 poLineString->StartPoint( poNegativeNode );
    1104               0 :                 poLineString->EndPoint( poPositiveNode );
    1105                 :             }
    1106                 :             else
    1107                 :             {
    1108               0 :                 poLineString->StartPoint( poPositiveNode );
    1109               0 :                 poLineString->EndPoint( poNegativeNode );
    1110                 :             }
    1111               0 :             delete poLineString;
    1112                 : 
    1113               0 :             poMP = new OGRMultiPoint();
    1114               0 :             poMP->addGeometryDirectly( poNegativeNode );
    1115               0 :             poMP->addGeometryDirectly( poPositiveNode );
    1116                 : 
    1117               0 :             return poMP;
    1118                 :         }
    1119                 : 
    1120                 :         // correct orientation of the line string
    1121               0 :         if( bEdgeOrientation != bOrientation )
    1122                 :         {
    1123               0 :             int iStartCoord = 0, iEndCoord = poLineString->getNumPoints() - 1;
    1124               0 :             OGRPoint *poTempStartPoint = new OGRPoint();
    1125               0 :             OGRPoint *poTempEndPoint = new OGRPoint();
    1126               0 :             while( iStartCoord < iEndCoord )
    1127                 :             {
    1128               0 :                 poLineString->getPoint( iStartCoord, poTempStartPoint );
    1129               0 :                 poLineString->getPoint( iEndCoord, poTempEndPoint );
    1130               0 :                 poLineString->setPoint( iStartCoord, poTempEndPoint );
    1131               0 :                 poLineString->setPoint( iEndCoord, poTempStartPoint );
    1132               0 :                 iStartCoord++;
    1133               0 :                 iEndCoord--;
    1134                 :             }
    1135               0 :             delete poTempStartPoint;
    1136               0 :             delete poTempEndPoint;
    1137                 :         }
    1138               0 :         return poLineString;
    1139                 :     }
    1140                 : 
    1141                 : /* -------------------------------------------------------------------- */
    1142                 : /*      TopoCurve                                                       */
    1143                 : /* -------------------------------------------------------------------- */
    1144               2 :     if( EQUAL(pszBaseGeometry,"TopoCurve") )
    1145                 :     {
    1146                 :         const CPLXMLNode *psChild;
    1147               0 :         OGRMultiLineString *poMLS = NULL;
    1148               0 :         OGRMultiPoint *poMP = NULL;
    1149                 : 
    1150               0 :         if( bGetSecondaryGeometry )
    1151               0 :             poMP = new OGRMultiPoint();
    1152                 :         else
    1153               0 :             poMLS = new OGRMultiLineString();
    1154                 : 
    1155                 :         // collect directedEdges
    1156               0 :         for( psChild = psNode->psChild; 
    1157                 :              psChild != NULL;
    1158                 :              psChild = psChild->psNext ) 
    1159                 :         {
    1160               0 :             if( psChild->eType == CXT_Element
    1161                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"directedEdge"))
    1162                 :             {
    1163                 :                 OGRGeometry *poGeom;
    1164                 : 
    1165               0 :                 poGeom = GML2OGRGeometry_XMLNode( psChild );
    1166               0 :                 if( poGeom == NULL )
    1167                 :                 {
    1168                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
    1169               0 :                               "Failed to get geometry in directedEdge" );
    1170               0 :                     delete poGeom;
    1171               0 :                     if( bGetSecondaryGeometry )
    1172               0 :                         delete poMP;
    1173                 :                     else
    1174               0 :                         delete poMLS;
    1175               0 :                     return NULL;
    1176                 :                 }
    1177                 : 
    1178                 :                 //Add the two points corresponding to the two nodes to poMP
    1179               0 :                 if( bGetSecondaryGeometry &&
    1180                 :                      wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint )
    1181                 :                 {
    1182                 :                     //TODO: TopoCurve geometries with more than one
    1183                 :                     //      directedEdge elements were not tested.
    1184               0 :                     if( poMP->getNumGeometries() <= 0 ||
    1185                 :                         !(poMP->getGeometryRef( poMP->getNumGeometries() - 1 )->Equals(((OGRMultiPoint *)poGeom)->getGeometryRef( 0 ) ) ))
    1186                 :                     {
    1187                 :                         poMP->addGeometry(
    1188               0 :                             ( (OGRMultiPoint *)poGeom )->getGeometryRef( 0 ) );
    1189                 :                     }
    1190                 :                     poMP->addGeometry(
    1191               0 :                             ( (OGRMultiPoint *)poGeom )->getGeometryRef( 1 ) );
    1192               0 :                     delete poGeom;
    1193                 :                 }
    1194               0 :                 else if( !bGetSecondaryGeometry &&
    1195                 :                      wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
    1196                 :                 {
    1197               0 :                     poMLS->addGeometryDirectly( poGeom );
    1198                 :                 }
    1199                 :                 else
    1200                 :                 {
    1201                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
    1202                 :                               "Got %.500s geometry as Member instead of %s.",
    1203                 :                               poGeom ? poGeom->getGeometryName() : "NULL",
    1204               0 :                               bGetSecondaryGeometry?"MULTIPOINT":"LINESTRING");
    1205               0 :                     delete poGeom;
    1206               0 :                     if( bGetSecondaryGeometry )
    1207               0 :                         delete poMP;
    1208                 :                     else
    1209               0 :                         delete poMLS;
    1210               0 :                     return NULL;
    1211                 :                 }
    1212                 :             }
    1213                 :         }
    1214                 : 
    1215               0 :         if( bGetSecondaryGeometry )
    1216               0 :             return poMP;
    1217                 :         else
    1218               0 :             return poMLS;
    1219                 :     }
    1220                 : 
    1221                 : /* -------------------------------------------------------------------- */
    1222                 : /*      TopoSurface                                                     */
    1223                 : /* -------------------------------------------------------------------- */
    1224               2 :     if( EQUAL(pszBaseGeometry,"TopoSurface") )
    1225                 :     {
    1226               0 :         if( bGetSecondaryGeometry )
    1227               0 :             return NULL;
    1228                 :         const CPLXMLNode *psChild, *psFaceChild, *psDirectedEdgeChild;
    1229               0 :         int bFaceOrientation = TRUE;
    1230               0 :         OGRPolygon *poTS = new OGRPolygon();
    1231                 : 
    1232                 :         // collect directed faces
    1233               0 :         for( psChild = psNode->psChild; 
    1234                 :              psChild != NULL;
    1235                 :              psChild = psChild->psNext ) 
    1236                 :         {
    1237               0 :           if( psChild->eType == CXT_Element
    1238                 :               && EQUAL(BareGMLElement(psChild->pszValue),"directedFace") )
    1239                 :           {
    1240               0 :             OGRLinearRing *poFaceGeom = new OGRLinearRing();
    1241                 : 
    1242               0 :             bFaceOrientation = GetElementOrientation(psChild);
    1243                 : 
    1244                 :             // collect next face (psChild->psChild)
    1245               0 :             psFaceChild = psChild->psChild;
    1246               0 :             while( psFaceChild != NULL &&
    1247                 :                    !EQUAL(BareGMLElement(psFaceChild->pszValue),"Face") )
    1248               0 :                     psFaceChild = psFaceChild->psNext;
    1249                 : 
    1250               0 :             if( psFaceChild == NULL )
    1251               0 :               continue;
    1252                 : 
    1253                 :             // collect directed edges of the face
    1254               0 :             for( psDirectedEdgeChild = psFaceChild->psChild;
    1255                 :                  psDirectedEdgeChild != NULL;
    1256                 :                  psDirectedEdgeChild = psDirectedEdgeChild->psNext )
    1257                 :             {
    1258               0 :               if( psDirectedEdgeChild->eType == CXT_Element &&
    1259                 :                   EQUAL(BareGMLElement(psDirectedEdgeChild->pszValue),"directedEdge") )
    1260                 :               {
    1261                 :                 OGRGeometry *poEdgeGeom;
    1262                 : 
    1263                 :                 poEdgeGeom = GML2OGRGeometry_XMLNode( psDirectedEdgeChild,
    1264                 :                                                       TRUE,
    1265               0 :                                                       bFaceOrientation );
    1266                 : 
    1267               0 :                 if( poEdgeGeom == NULL ||
    1268                 :                     wkbFlatten(poEdgeGeom->getGeometryType()) != wkbLineString )
    1269                 :                 {
    1270                 :                   CPLError( CE_Failure, CPLE_AppDefined, 
    1271               0 :                             "Failed to get geometry in geometryMember" );
    1272               0 :                   delete poEdgeGeom;
    1273               0 :                   return NULL;
    1274                 :                 }
    1275                 : 
    1276               0 :                 if( !bFaceOrientation )
    1277                 :                 {
    1278               0 :                   if( poFaceGeom->getNumPoints() > 0 )
    1279               0 :                     ((OGRLinearRing *)poEdgeGeom)->addSubLineString( (OGRLineString *)poFaceGeom );
    1280               0 :                   poFaceGeom->empty();
    1281                 :                 }
    1282               0 :                 poFaceGeom->addSubLineString( (OGRLinearRing *)poEdgeGeom );
    1283               0 :                 delete poEdgeGeom;
    1284                 :               }
    1285                 :             }
    1286                 : 
    1287                 : /*            if( poFaceGeom == NULL )
    1288                 :             {
    1289                 :               CPLError( CE_Failure, CPLE_AppDefined, 
    1290                 :                         "Failed to get Face geometry in directedFace" );
    1291                 :               delete poFaceGeom;
    1292                 :               return NULL;
    1293                 :             }*/
    1294                 : 
    1295               0 :             poTS->addRingDirectly( poFaceGeom );
    1296                 :           }
    1297                 :         }
    1298                 : 
    1299                 : /*        if( poTS == NULL )
    1300                 :         {
    1301                 :           CPLError( CE_Failure, CPLE_AppDefined, 
    1302                 :                     "Failed to get TopoSurface geometry" );
    1303                 :           delete poTS;
    1304                 :           return NULL;
    1305                 :         }*/
    1306                 : 
    1307               0 :         return poTS;
    1308                 :     }
    1309                 : 
    1310                 : /* -------------------------------------------------------------------- */
    1311                 : /*      Surface                                                         */
    1312                 : /* -------------------------------------------------------------------- */
    1313               2 :     if( EQUAL(pszBaseGeometry,"Surface") )
    1314                 :     {
    1315                 :         const CPLXMLNode *psChild;
    1316               2 :         OGRGeometry *poResult = NULL;
    1317                 : 
    1318                 :         // Find outer ring.
    1319               2 :         psChild = FindBareXMLChild( psNode, "patches" );
    1320               2 :         if( psChild == NULL )
    1321               0 :             psChild = FindBareXMLChild( psNode, "polygonPatches" );
    1322                 : 
    1323               2 :         if( psChild == NULL || psChild->psChild == NULL )
    1324                 :         {
    1325                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1326               0 :                       "Missing <patches> for Surface." );
    1327               0 :             return NULL;
    1328                 :         }
    1329                 : 
    1330               4 :         for( psChild = psChild->psChild; 
    1331                 :              psChild != NULL; psChild = psChild->psNext )
    1332                 :         {
    1333               2 :             if( psChild->eType == CXT_Element
    1334                 :                 && EQUAL(BareGMLElement(psChild->pszValue),"PolygonPatch") )
    1335                 :             {
    1336                 :                 OGRPolygon *poPolygon = (OGRPolygon *) 
    1337               2 :                     GML2OGRGeometry_XMLNode( psChild );
    1338               2 :                 if( poPolygon == NULL )
    1339               0 :                     return NULL;
    1340                 :                 
    1341               2 :                 if( poResult == NULL )
    1342               2 :                     poResult = poPolygon;
    1343               0 :                 else if( wkbFlatten(poResult->getGeometryType()) == wkbPolygon )
    1344                 :                 {
    1345               0 :                     OGRMultiPolygon *poMP = new OGRMultiPolygon();
    1346               0 :                     poMP->addGeometryDirectly( poResult );
    1347               0 :                     poMP->addGeometryDirectly( poPolygon );
    1348               0 :                     poResult = poMP;
    1349                 :                 }
    1350                 :                 else
    1351                 :                 {
    1352               0 :                     ((OGRMultiPolygon *) poResult)->addGeometryDirectly( poPolygon );
    1353                 :                 }
    1354                 :             }
    1355                 :         }
    1356                 :         
    1357               2 :         return poResult;
    1358                 :     }
    1359                 : 
    1360                 :     CPLError( CE_Failure, CPLE_AppDefined, 
    1361                 :               "Unrecognised geometry type <%.500s>.", 
    1362               0 :               pszBaseGeometry );
    1363                 : 
    1364               0 :     return NULL;
    1365                 : }
    1366                 : 
    1367                 : /************************************************************************/
    1368                 : /*                      OGR_G_CreateFromGMLTree()                       */
    1369                 : /************************************************************************/
    1370                 : 
    1371               4 : OGRGeometryH OGR_G_CreateFromGMLTree( const CPLXMLNode *psTree )
    1372                 : 
    1373                 : {
    1374               4 :     return (OGRGeometryH) GML2OGRGeometry_XMLNode( psTree );
    1375                 : }
    1376                 : 
    1377                 : /************************************************************************/
    1378                 : /*                        OGR_G_CreateFromGML()                         */
    1379                 : /************************************************************************/
    1380                 : 
    1381              92 : OGRGeometryH OGR_G_CreateFromGML( const char *pszGML )
    1382                 : 
    1383                 : {
    1384              92 :     if( pszGML == NULL || strlen(pszGML) == 0 )
    1385                 :     {
    1386                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1387               0 :                   "GML Geometry is empty in GML2OGRGeometry()." );
    1388               0 :         return NULL;
    1389                 :     }
    1390                 : 
    1391                 : /* ------------------------------------------------------------ -------- */
    1392                 : /*      Try to parse the XML snippet using the MiniXML API.  If this    */
    1393                 : /*      fails, we assume the minixml api has already posted a CPL       */
    1394                 : /*      error, and just return NULL.                                    */
    1395                 : /* -------------------------------------------------------------------- */
    1396              92 :     CPLXMLNode *psGML = CPLParseXMLString( pszGML );
    1397                 : 
    1398              92 :     if( psGML == NULL )
    1399               0 :         return NULL;
    1400                 : 
    1401                 : /* -------------------------------------------------------------------- */
    1402                 : /*      Convert geometry recursively.                                   */
    1403                 : /* -------------------------------------------------------------------- */
    1404                 :     OGRGeometry *poGeometry;
    1405                 : 
    1406              92 :     poGeometry = GML2OGRGeometry_XMLNode( psGML );
    1407                 : 
    1408              92 :     CPLDestroyXMLNode( psGML );
    1409                 :     
    1410              92 :     return (OGRGeometryH) poGeometry;
    1411                 : }
    1412                 : 
    1413                 : 

Generated by: LTP GCOV extension version 1.5