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 :
|