LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/nas - gml3ogrgeometry.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 265
Code covered: 20.8 % Executed lines: 55

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

Generated by: LTP GCOV extension version 1.5