<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#!/usr/bin/env python
# -*- coding: utf-8 -*-
###############################################################################
# $Id$
#
# Project:  GDAL/OGR Test Suite
# Purpose:  Test basic OGR translation of WKT and WKB geometries.
# Author:   Frank Warmerdam &lt;warmerdam@pobox.com&gt;
# 
###############################################################################
# Copyright (c) 2003, Frank Warmerdam &lt;warmerdam@pobox.com&gt;
# Copyright (c) 2009-2014, Even Rouault &lt;even dot rouault at mines-paris dot org&gt;
# 
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
# 
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Library General Public License for more details.
# 
# You should have received a copy of the GNU Library General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
###############################################################################

import os
import sys
import string

sys.path.append( '../pymod' )

import gdaltest
import ogrtest
from osgeo import ogr
from osgeo import osr
from osgeo import gdal

###############################################################################

class gml_geom_unit:
    def __init__(self, unit):
        self.unit = unit

    def gml_geom( self ):
        raw_wkt = open('data/wkb_wkt/' + self.unit + '.wkt').read()

        ######################################################################
        # Convert WKT to GML.

        geom_wkt = ogr.CreateGeometryFromWkt( raw_wkt )

        gml = geom_wkt.ExportToGML()

        if gml is None or len(gml) == 0:
            gdaltest.post_reason( 'Conversion to GML failed.')
            return 'fail'

        ######################################################################
        # Create geometry from GML. 
        
        geom_gml = ogr.CreateGeometryFromGML( gml )

        if ogrtest.check_feature_geometry(geom_wkt, geom_gml, 0.0000000000001) == 1:
            clean_wkt = geom_wkt.ExportToWkt();
            gml_wkt = geom_gml.ExportToWkt()
            gdaltest.post_reason( 'WKT from GML (%s) does not match clean WKT (%s).\ngml was (%s)' % (gml_wkt, clean_wkt, gml) )
            return 'fail'

        geom_wkt.Destroy()
        geom_gml.Destroy()

        return 'success'
        
###############################################################################
# Test geometries with extra spaces at the end, as sometimes are generated
# by ESRI WFS software.

def gml_space_test():
    gml = '&lt;gml:LineString xmlns:foo="http://bar"&gt;&lt;gml:coordinates xmlns:foo="http://bar" decimal="." cs="," ts=" "&gt;189999.99995605,624999.99998375 200000.00005735,624999.99998375 200000.00005735,612499.99997125 195791.3593843,612499.99997125 193327.3749823,612499.99997125 189999.99995605,612499.99997125 189999.99995605,619462.31247125 189999.99995605,624999.99998375 \n&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;'
    geom = ogr.CreateGeometryFromGML( gml )
    if geom is None or geom.GetGeometryType() is not ogr.wkbLineString \
       or geom.GetPointCount() != 8:
        gdaltest.post_reason( 'GML not correctly parsed' )
        return 'fail'

    geom.Destroy()

    return 'success'

###############################################################################
# Test GML 3.x "pos" element for a point.

def gml_pos_point():

    gml = '&lt;gml:Point xmlns:foo="http://bar"&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;'

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POINT (31 29 16)':
        gdaltest.post_reason( '&lt;gml:pos&gt; not correctly parsed' )
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.1.1 "pos" element for a polygon. (ticket #3244)

def gml_pos_polygon():

    gml = '''&lt;gml:Polygon xmlns:foo="http://bar"&gt;
                &lt;gml:exterior xmlns:foo="http://bar"&gt;
                    &lt;gml:LinearRing xmlns:foo="http://bar"&gt;
                        &lt;gml:pos xmlns:foo="http://bar"&gt;0 0&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;4 0&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;4 4&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;0 4&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;0 0&lt;/gml:pos&gt;
                    &lt;/gml:LinearRing&gt;
                &lt;/gml:exterior&gt;
                &lt;gml:interior xmlns:foo="http://bar"&gt;
                    &lt;gml:LinearRing xmlns:foo="http://bar"&gt;
                        &lt;gml:pos&gt;1 1&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;2 1&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;2 2&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;1 2&lt;/gml:pos&gt;
                        &lt;gml:pos&gt;1 1&lt;/gml:pos&gt;
                    &lt;/gml:LinearRing&gt;
                &lt;/gml:interior&gt;
            &lt;/gml:Polygon&gt;'''

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))':
        gdaltest.post_reason( '&lt;gml:Polygon&gt; not correctly parsed' )
        return 'fail'

    return 'success'
    
###############################################################################
# Test GML 3.x "posList" element for a linestring.

def gml_posList_line():

    gml = '&lt;LineString xmlns:foo="http://bar"&gt;&lt;posList xmlns:foo="http://bar"&gt;31 42 53 64 55 76&lt;/posList&gt;&lt;/LineString&gt;'

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'LINESTRING (31 42,53 64,55 76)':
        gdaltest.post_reason( '&lt;gml:posList&gt; not correctly parsed' )
        return 'fail'

    return 'success'


###############################################################################
# Test GML 3.x "posList" element for a 3D linestring.

def gml_posList_line3d():

    gml = '&lt;LineString&gt;&lt;posList xmlns:foo="http://bar" srsDimension="3"&gt;31 42 1 53 64 2 55 76 3&lt;/posList&gt;&lt;/LineString&gt;'

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'LINESTRING (31 42 1,53 64 2,55 76 3)':
        gdaltest.post_reason( '&lt;gml:posList&gt; not correctly parsed' )
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.x "posList" element for a 3D linestring, but with srsDimension
# set on LineString, not posList

def gml_posList_line3d_2():

    gml = '&lt;LineString srsDimension="3"&gt;&lt;posList&gt;31 42 1 53 64 2 55 76 3&lt;/posList&gt;&lt;/LineString&gt;'

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'LINESTRING (31 42 1,53 64 2,55 76 3)':
        gdaltest.post_reason( '&lt;gml:posList&gt; not correctly parsed' )
        return 'fail'

    return 'success'
    
###############################################################################
# Test GML 3.x "polygon" element for a point.

def gml_polygon():

    gml = '&lt;Polygon&gt;&lt;exterior&gt;&lt;LinearRing&gt;&lt;posList&gt;0 0 4 0 4 4 0 4 0 0&lt;/posList&gt;&lt;/LinearRing&gt;&lt;/exterior&gt;&lt;interior xmlns:foo="http://bar"&gt;&lt;LinearRing&gt;&lt;posList xmlns:foo="http://bar"&gt;1 1 2 1 2 2 1 2 1 1&lt;/posList&gt;&lt;/LinearRing&gt;&lt;/interior&gt;&lt;/Polygon&gt;'
    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1))':
        gdaltest.post_reason( '&lt;gml:Polygon&gt; not correctly parsed' )
        return 'fail'

    return 'success'

###############################################################################
# Private utility function to conver WKT to GML with assigned WGS 84 as SRS

def _CreateGMLWithSRSFromWkt(wkt, epsg):

    geom = ogr.CreateGeometryFromWkt( wkt )

    if geom is None:
        gdaltest.post_reason( 'Import geometry from WKT failed' )
        return None

    # Assign SRS from given EPSG code
    srs = osr.SpatialReference()
    srs.ImportFromEPSG( epsg )

    if srs is None:
        gdaltest.post_reason( 'SRS import from EPSG failed' )
        return None

    geom.AssignSpatialReference( srs )

    return geom.ExportToGML()

###############################################################################
# Test of Point geometry with SRS assigned

def gml_out_point_srs():

    wkt = 'POINT(21.675 53.763)'

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'
    
    if gml[0:31] != '&lt;gml:Point srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of Point 3D geometry with SRS assigned

def gml_out_point3d_srs():

    wkt = 'POINT(21.675 53.763 100)'

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'
    
    if gml[0:31] != '&lt;gml:Point srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of LineString geometry with SRS assigned

def gml_out_linestring_srs():
 
    wkt = open('data/wkb_wkt/5.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'
    
    if gml[0:36] != '&lt;gml:LineString srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of Polygon geometry with SRS assigned

def gml_out_polygon_srs():
 
    wkt = open('data/wkb_wkt/6.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'

    if gml[0:33] != '&lt;gml:Polygon srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of MultiPoint geometry with SRS assigned

def gml_out_multipoint_srs():
 
    wkt = open('data/wkb_wkt/11.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'

    if gml[0:36] != '&lt;gml:MultiPoint srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of MultiLineString geometry with SRS assigned

def gml_out_multilinestring_srs():
 
    wkt = open('data/wkb_wkt/2.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'

    if gml[0:41] != '&lt;gml:MultiLineString srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        return 'fail'

    return 'success'

###############################################################################
# Test of MultiPolygon geometry with SRS assigned

def gml_out_multipolygon_srs():
 
    wkt = open('data/wkb_wkt/4.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'

    if gml[0:38] != '&lt;gml:MultiPolygon srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        print(gml)
        return 'fail'

    # Verify we have no other srsName's on subelements.
    if gml[39:].find('srsName') != -1:
        gdaltest.post_reason( 'Got extra srsName attributes on subelements.' )
        print(gml)
        return 'fail'

    return 'success'

###############################################################################
# Test of GeometryCollection with SRS assigned

def gml_out_geometrycollection_srs():
 
    wkt = open('data/wkb_wkt/3.wkt').read()

    gml = _CreateGMLWithSRSFromWkt( wkt, 4326 )

    if gml is None or len(gml) == 0:
        gdaltest.post_reason( 'Conversion to GML failed.')
        return 'fail'

    if gml[0:39] != '&lt;gml:MultiGeometry srsName="EPSG:4326"&gt;':
        gdaltest.post_reason( 'No srsName attribute in GML output')
        print(gml)
        return 'fail'

    return 'success'

###############################################################################
# Test GML Box

def gml_Box():

    gml = """&lt;gml:Box xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
  &lt;gml:coord&gt;
    &lt;gml:X&gt;1&lt;/gml:X&gt;
    &lt;gml:Y&gt;2&lt;/gml:Y&gt;
  &lt;/gml:coord&gt;
  &lt;gml:coord&gt;
    &lt;gml:X&gt;3&lt;/gml:X&gt;
    &lt;gml:Y&gt;4&lt;/gml:Y&gt;
  &lt;/gml:coord&gt;
&lt;/gml:Box&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((1 2 0,3 2 0,3 4 0,1 4 0,1 2 0))':
        gdaltest.post_reason( '&lt;gml:Box&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Envelope

def gml_Envelope():

    gml = """&lt;gml:Envelope xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
    &lt;gml:lowerCorner&gt;1 2&lt;/gml:lowerCorner&gt;
    &lt;gml:upperCorner&gt;3 4&lt;/gml:upperCorner&gt;
&lt;/gml:Envelope&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((1 2,3 2,3 4,1 4,1 2))':
        gdaltest.post_reason( '&lt;gml:Envelope&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Curve

def gml_Curve():

    gml = """&lt;gml:Curve xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
    &lt;gml:segments xmlns:foo="http://bar"&gt;
        &lt;gml:LineStringSegment xmlns:foo="http://bar"&gt;
            &lt;gml:posList&gt;1 2 3 4&lt;/gml:posList&gt;
        &lt;/gml:LineStringSegment&gt;
    &lt;/gml:segments&gt;
&lt;/gml:Curve&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'LINESTRING (1 2,3 4)':
        gdaltest.post_reason( '&lt;gml:Curve&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Curve with pointProperty elements

def gml_Curve_with_pointProperty():

    gml = """&lt;gml:Curve xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
    &lt;gml:segments&gt;
        &lt;gml:LineStringSegment&gt;
            &lt;gml:pos&gt;1 2&lt;/gml:pos&gt;
            &lt;gml:pointProperty&gt;
                &lt;gml:Point&gt;
                    &lt;gml:pos&gt;3 4&lt;/gml:pos&gt;
                &lt;/gml:Point&gt;
            &lt;/gml:pointProperty&gt;
        &lt;/gml:LineStringSegment&gt;
    &lt;/gml:segments&gt;
&lt;/gml:Curve&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'LINESTRING (1 2,3 4)':
        gdaltest.post_reason( '&lt;gml:Curve&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'
    
###############################################################################
# Test GML MultiCurve

def gml_MultiCurve():

    gml = """&lt;gml:MultiCurve xmlns:foo="http://bar" xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
    &lt;gml:curveMember xmlns:foo="http://bar"&gt;
        &lt;gml:LineString&gt;
            &lt;gml:posList&gt;1 2 2 3&lt;/gml:posList&gt;
        &lt;/gml:LineString&gt;
    &lt;/gml:curveMember&gt;
    &lt;gml:curveMember&gt;
        &lt;gml:LineString&gt;
            &lt;gml:posList&gt;3 4 4 5&lt;/gml:posList&gt;
        &lt;/gml:LineString&gt;
    &lt;/gml:curveMember&gt;
&lt;/gml:MultiCurve&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTILINESTRING ((1 2,2 3),(3 4,4 5))':
        gdaltest.post_reason( '&lt;gml:MultiCurve&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML MultiSurface with PolygonPatch

def gml_MultiSurface():

    gml = """&lt;gml:MultiSurface xmlns:gml="http://www.opengis.net/gml" srsName="foo"&gt;
    &lt;gml:surfaceMember xmlns:foo="http://bar" xlink:role="main"&gt;
        &lt;gml:Surface gml:id="id1"&gt;
            &lt;gml:patches xmlns:foo="http://bar"&gt;
                &lt;gml:PolygonPatch xmlns:foo="http://bar" interpolation="planar"&gt;
                    &lt;gml:exterior&gt;
                        &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;1 2 3 4 5 6 1 2&lt;/gml:posList&gt;
                        &lt;/gml:LinearRing&gt;
                    &lt;/gml:exterior&gt;
                    &lt;gml:interior&gt;
                        &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;2 3 4 5 6 7 2 3&lt;/gml:posList&gt;
                        &lt;/gml:LinearRing&gt;
                    &lt;/gml:interior&gt;   
                    &lt;gml:interior&gt;
                        &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;3 4 5 6 7 8 3 4&lt;/gml:posList&gt;
                        &lt;/gml:LinearRing&gt;
                    &lt;/gml:interior&gt;
                &lt;/gml:PolygonPatch&gt;
            &lt;/gml:patches&gt;
        &lt;/gml:Surface&gt;
    &lt;/gml:surfaceMember&gt;
    &lt;gml:surfaceMember&gt;
        &lt;gml:Surface&gt;
            &lt;gml:patches&gt;
                &lt;gml:PolygonPatch interpolation="planar"&gt;
                    &lt;gml:exterior&gt;
                        &lt;gml:Ring&gt;
                            &lt;gml:curveMember&gt;
                                &lt;gml:Curve&gt;
                                    &lt;gml:segments&gt;
                                        &lt;gml:LineStringSegment&gt;
                                            &lt;gml:pos&gt;4 5&lt;/gml:pos&gt;
                                            &lt;gml:pos&gt;6 7&lt;/gml:pos&gt;
                                        &lt;/gml:LineStringSegment&gt;
                                    &lt;/gml:segments&gt;
                                &lt;/gml:Curve&gt;
                            &lt;/gml:curveMember&gt;
                            &lt;gml:curveMember&gt;
                                &lt;gml:Curve&gt;
                                    &lt;gml:segments&gt;
                                        &lt;gml:LineStringSegment&gt;
                                            &lt;gml:pos&gt;8 9&lt;/gml:pos&gt;
                                            &lt;gml:pos&gt;4 5&lt;/gml:pos&gt;
                                        &lt;/gml:LineStringSegment&gt;
                                    &lt;/gml:segments&gt;
                                &lt;/gml:Curve&gt;
                            &lt;/gml:curveMember&gt;
                        &lt;/gml:Ring&gt;
                    &lt;/gml:exterior&gt;
                &lt;/gml:PolygonPatch&gt;
            &lt;/gml:patches&gt;
        &lt;/gml:Surface&gt;
    &lt;/gml:surfaceMember&gt;
&lt;/gml:MultiSurface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOLYGON (((1 2,3 4,5 6,1 2),(2 3,4 5,6 7,2 3),(3 4,5 6,7 8,3 4)),((4 5,6 7,8 9,4 5)))':
        gdaltest.post_reason( '&lt;gml:MultiSurface&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'


###############################################################################
# Test GML MultiSurface with surfaceMembers

def gml_MultiSurface_surfaceMembers():

    gml = """&lt;gml:MultiSurface xmlns:foo="http://bar"&gt;
          &lt;gml:surfaceMembers xmlns:foo="http://bar"&gt;
            &lt;gml:Surface xmlns:foo="http://bar"&gt;
              &lt;gml:patches xmlns:foo="http://bar"&gt;
                &lt;gml:PolygonPatch xmlns:foo="http://bar"&gt;
                  &lt;gml:exterior xmlns:foo="http://bar"&gt;
                      &lt;gml:LinearRing xmlns:foo="http://bar"&gt;
                          &lt;gml:posList&gt;1 2 3 4 5 6 1 2&lt;/gml:posList&gt;
                      &lt;/gml:LinearRing&gt;
                    &lt;/gml:exterior&gt;
                    &lt;gml:interior&gt;
                      &lt;gml:LinearRing&gt;
                          &lt;gml:posList&gt;2 3 4 5 6 7 2 3&lt;/gml:posList&gt;
                      &lt;/gml:LinearRing&gt;
                    &lt;/gml:interior&gt; 
                &lt;/gml:PolygonPatch&gt;
              &lt;/gml:patches&gt;
            &lt;/gml:Surface&gt;
            &lt;gml:Surface&gt;
              &lt;gml:patches&gt;
                &lt;gml:PolygonPatch&gt;
                  &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                      &lt;gml:posList&gt;3 4 5 6 7 8 3 4&lt;/gml:posList&gt;
                    &lt;/gml:LinearRing&gt;
                  &lt;/gml:exterior&gt;
                &lt;/gml:PolygonPatch&gt;
                &lt;gml:PolygonPatch&gt;
                  &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                      &lt;gml:posList&gt;30 40 50 60 70 80 30 40&lt;/gml:posList&gt;
                    &lt;/gml:LinearRing&gt;
                  &lt;/gml:exterior&gt;
                &lt;/gml:PolygonPatch&gt;
              &lt;/gml:patches&gt;
            &lt;/gml:Surface&gt;
          &lt;/gml:surfaceMembers&gt;
        &lt;/gml:MultiSurface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOLYGON (((1 2,3 4,5 6,1 2),(2 3,4 5,6 7,2 3)),((3 4,5 6,7 8,3 4)),((30 40,50 60,70 80,30 40)))':
        gdaltest.post_reason( '&lt;gml:MultiSurface&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'


###############################################################################
# Test GML MultiCurve with curveMembers

def gml_MultiCurve_curveMembers():

    gml = """&lt;gml:MultiCurve xmlns:foo="http://bar"&gt;
          &lt;gml:curveMembers xmlns:foo="http://bar"&gt;
            &lt;gml:LineString xmlns:foo="http://bar"&gt;
                &lt;gml:posList xmlns:foo="http://bar" srsDimension="2"&gt;0 0 1 1&lt;/gml:posList&gt;
              &lt;/gml:LineString&gt;
            &lt;/gml:curveMembers&gt;
          &lt;/gml:MultiCurve&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTILINESTRING ((0 0,1 1))':
        gdaltest.post_reason( '&lt;gml:MultiCurve&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML MultiPoint with pointMembers

def gml_MultiCurve_pointMembers():

    gml = """&lt;gml:MultiPoint xmlns:foo="http://bar"&gt;
          &lt;gml:pointMembers xmlns:foo="http://bar"&gt;
              &lt;gml:Point xmlns:foo="http://bar"&gt;
                &lt;gml:pos xmlns:foo="http://bar"&gt;0 0&lt;/gml:pos&gt;
              &lt;/gml:Point&gt;
              &lt;gml:Point&gt;
                &lt;gml:pos&gt;1 1&lt;/gml:pos&gt;
              &lt;/gml:Point&gt;
            &lt;/gml:pointMembers&gt;
          &lt;/gml:MultiPoint&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOINT (0 0,1 1)':
        gdaltest.post_reason( '&lt;gml:MultiPoint&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'
###############################################################################
# Test GML Solid

def gml_Solid():

    gml = """&lt;gml:Solid xmlns:foo="http://bar" gml:id="UUID_cc5a9513-2d85-4f1a-869a-620400182e1f"&gt;
          &lt;gml:exterior xmlns:foo="http://bar"&gt;
            &lt;gml:CompositeSurface xmlns:foo="http://bar" gml:id="UUID_2c83341e-a9ce-4abe-9c40-b5208eed5588"&gt;
              &lt;gml:surfaceMember xmlns:foo="http://bar"&gt;
                &lt;gml:Polygon xmlns:foo="http://bar" gml:id="UUID_d8e4b04b-ce0a-441e-b940-5ab99fcf6112"&gt;
                  &lt;gml:exterior xmlns:foo="http://bar"&gt;
                    &lt;gml:LinearRing xmlns:foo="http://bar" gml:id="UUID_d8e4b04b-ce0a-441e-b940-5ab99fcf6112_0"&gt;
                      &lt;gml:posList xmlns:foo="http://bar" srsDimension="3"&gt;1 2 0 3 4 0 5 6 0 1 2 0&lt;/gml:posList&gt;
                    &lt;/gml:LinearRing&gt;
                  &lt;/gml:exterior&gt;
                &lt;/gml:Polygon&gt;
              &lt;/gml:surfaceMember&gt;
            &lt;/gml:CompositeSurface&gt;
          &lt;/gml:exterior&gt;
        &lt;/gml:Solid&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOLYGON (((1 2 0,3 4 0,5 6 0,1 2 0)))':
        gdaltest.post_reason( '&lt;gml:Solid&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML OrientableSurface

def gml_OrientableSurface():

    gml = """&lt;gml:OrientableSurface xmlns:foo="http://bar" orientation="+"&gt;
                                            &lt;gml:baseSurface xmlns:foo="http://bar"&gt;
                                                &lt;gml:Polygon&gt;
                                                  &lt;gml:exterior&gt;
                                                  &lt;gml:LinearRing&gt;
                                                  &lt;gml:posList srsDimension="3"&gt;-213.475 24.989 0
                                                  -213.475 24.989 8.0 -215.704 25.077 8.0 -215.704
                                                  25.077 0 -213.475 24.989 0 &lt;/gml:posList&gt;
                                                  &lt;/gml:LinearRing&gt;
                                                  &lt;/gml:exterior&gt;
                                                &lt;/gml:Polygon&gt;
                                            &lt;/gml:baseSurface&gt;
                                        &lt;/gml:OrientableSurface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((-213.475 24.989 0,-213.475 24.989 8,-215.704 25.077 8,-215.704 25.077 0,-213.475 24.989 0))':
        gdaltest.post_reason( '&lt;gml:OrientableSurface&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Triangle

def gml_Triangle():

    gml = """&lt;gml:Triangle xmlns:foo="http://bar"&gt;
                &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                        &lt;gml:posList&gt;0 0 0 1 1 1 0 0&lt;/gml:posList&gt;
                     &lt;/gml:LinearRing&gt;
                &lt;/gml:exterior&gt;
             &lt;/gml:Triangle&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,0 1,1 1,0 0))':
        gdaltest.post_reason( '&lt;gml:Triangle&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Rectangle

def gml_Rectangle():

    gml = """&lt;gml:Rectangle xmlns:foo="http://bar"&gt;
                &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                        &lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;
                     &lt;/gml:LinearRing&gt;
                &lt;/gml:exterior&gt;
             &lt;/gml:Rectangle&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,0 1,1 1,1 0,0 0))':
        gdaltest.post_reason( '&lt;gml:Rectangle&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Tin

def gml_Tin():

    gml = """&lt;gml:Tin xmlns:foo="http://bar"&gt;
                &lt;gml:patches xmlns:foo="http://bar"&gt;
                    &lt;gml:Triangle xmlns:foo="http://bar"&gt;
                        &lt;gml:exterior xmlns:foo="http://bar"&gt;
                            &lt;gml:LinearRing xmlns:foo="http://bar"&gt;
                                &lt;gml:posList srsDimension="3"&gt;0 0 1 0 1 1 1 1 1 1 0 1 0 0 1 &lt;/gml:posList&gt;
                            &lt;/gml:LinearRing&gt;
                        &lt;/gml:exterior&gt;
                     &lt;/gml:Triangle&gt;
                 &lt;/gml:patches&gt;
             &lt;/gml:Tin&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0 1,0 1 1,1 1 1,1 0 1,0 0 1))':
        gdaltest.post_reason( '&lt;gml:Tin&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML Arc

def gml_Arc():

    poslist_list = [
("1 0 0 1 -1 0", 'LINESTRING (1 0,0.707106781186548 0.707106781186547,0.0 1.0,-0.707106781186547 0.707106781186548,-1.0 0.0)' ),
("1 0 0 -1 -1 0", 'LINESTRING (1 0,0.707106781186548 -0.707106781186547,0.0 -1.0,-0.707106781186547 -0.707106781186548,-1.0 -0.0)' ),
("1 0 -1 0 0 -1 ", 'LINESTRING (1 0,0.707106781186548 0.707106781186547,0.0 1.0,-0.707106781186547 0.707106781186548,-1.0 0.0,-0.707106781186548 -0.707106781186547,-0.0 -1.0)' ),
("1 0 -1 0 0 1 ", 'LINESTRING (1 0,0.707106781186548 -0.707106781186547,0.0 -1.0,-0.707106781186547 -0.707106781186548,-1.0 -0.0,-0.707106781186548 0.707106781186547,-0.0 1.0)' ),
("1 0  0 0 -1 0 ", 'LINESTRING (1 0,0 0,-1 0)' ),
("0 1 1 0 0 -1", 'LINESTRING (0.0 1.0,0.707106781186548 0.707106781186547,1 0,0.707106781186548 -0.707106781186547,0.0 -1.0)' ),
("0 1 -1 0 0 -1", 'LINESTRING (0.0 1.0,-0.707106781186547 0.707106781186548,-1.0 0.0,-0.707106781186548 -0.707106781186547,-0.0 -1.0)' ),
("-1 0 0 1 1 0", 'LINESTRING (-1.0 0.0,-0.707106781186547 0.707106781186548,0.0 1.0,0.707106781186548 0.707106781186547,1 0)' ),
("-1 0 0 1 -0.707106781186547 -0.707106781186548", 'LINESTRING (-1 0,-0.707106781186547 0.707106781186548,0 1,0.923879532511287 0.38268343236509,0.923879532511287 -0.38268343236509,0.38268343236509 -0.923879532511287,-0.707106781186547 -0.707106781186548)' )
    ]

    for (poslist, expected_wkt) in poslist_list:

        gml = "&lt;gml:Arc&gt;&lt;gml:posList&gt;%s&lt;/gml:posList&gt;&lt;/gml:Arc&gt;" % poslist
        gdal.SetConfigOption('OGR_ARC_STEPSIZE','45')
        geom = ogr.CreateGeometryFromGML( gml )
        gdal.SetConfigOption('OGR_ARC_STEPSIZE',None)

        if ogrtest.check_feature_geometry(geom, ogr.CreateGeometryFromWkt(expected_wkt)) != 0:
            print(gml)
            print(geom)
            return 'fail'

    return 'success'

###############################################################################
# Test GML Circle

def gml_Circle():

    gml = """&lt;gml:PolygonPatch&gt;
                &lt;gml:exterior&gt;
                    &lt;gml:Ring&gt;
                        &lt;gml:curveMember&gt;
                            &lt;gml:Curve&gt;
                                &lt;gml:segments&gt;
                                    &lt;gml:Circle&gt;
                                        &lt;gml:posList&gt;-1 0 0 1 -0.707106781186547 -0.707106781186548&lt;/gml:posList&gt;
                                    &lt;/gml:Circle&gt;
                                &lt;/gml:segments&gt;
                            &lt;/gml:Curve&gt;
                        &lt;/gml:curveMember&gt;
                    &lt;/gml:Ring&gt;
                &lt;/gml:exterior&gt;
            &lt;/gml:PolygonPatch&gt;"""

    gdal.SetConfigOption('OGR_ARC_STEPSIZE','45')
    geom = ogr.CreateGeometryFromGML( gml )
    gdal.SetConfigOption('OGR_ARC_STEPSIZE',None)

    expected_wkt = 'POLYGON ((-1 0,-0.707106781186547 0.707106781186548,0 1,0.923879532511287 0.38268343236509,0.923879532511287 -0.38268343236509,0.38268343236509 -0.923879532511287,-0.707106781186547 -0.707106781186548,-1.0 -0.0,-1 0))'
    if ogrtest.check_feature_geometry(geom, ogr.CreateGeometryFromWkt(expected_wkt)) != 0:
        print(geom)
        return 'fail'

    return 'success'

###############################################################################
# Test concatenated sections (#4451)

def gml_ConcatenatedDeduplication():

    gml = """&lt;gml:Surface&gt;
       &lt;gml:patches&gt;
        &lt;gml:PolygonPatch interpolation="planar"&gt;
         &lt;gml:exterior&gt;
          &lt;gml:Ring&gt;
           &lt;gml:curveMember&gt;
            &lt;gml:Curve&gt;
             &lt;gml:segments&gt;
              &lt;gml:LineStringSegment interpolation="linear"&gt;
               &lt;gml:pos&gt;0 -1&lt;/gml:pos&gt;
               &lt;gml:pos&gt;0 1&lt;/gml:pos&gt;
              &lt;/gml:LineStringSegment&gt;
              &lt;gml:Arc interpolation="circularArc3Points" numArc="1"&gt;
               &lt;gml:pos&gt;0 1&lt;/gml:pos&gt;
               &lt;gml:pos&gt;1 0&lt;/gml:pos&gt;
               &lt;gml:pos&gt;0 -1&lt;/gml:pos&gt;
              &lt;/gml:Arc&gt;
             &lt;/gml:segments&gt;
            &lt;/gml:Curve&gt;
           &lt;/gml:curveMember&gt;
          &lt;/gml:Ring&gt;&lt;/gml:exterior&gt;
         &lt;/gml:PolygonPatch&gt;
        &lt;/gml:patches&gt;
       &lt;/gml:Surface&gt;"""

    gdal.SetConfigOption('OGR_ARC_STEPSIZE','45')
    geom = ogr.CreateGeometryFromGML( gml )
    gdal.SetConfigOption('OGR_ARC_STEPSIZE',None)

    expected_wkt = 'POLYGON ((0 -1,0 1,0.707106781186548 0.707106781186547,1 0,0.707106781186548 -0.707106781186547,0.0 -1.0))'
    if ogrtest.check_feature_geometry(geom, ogr.CreateGeometryFromWkt(expected_wkt)) != 0:
        print(geom)
        return 'fail'

    if ogrtest.have_geos() and not geom.IsValid():
        gdaltest.post_reason( 'geometry not valid' )
        return 'fail'

    return 'success'

###############################################################################
# Test OGRFormatDouble() to check for rounding errors (would also apply for KML output, or ogrinfo output)

def gml_out_precision():
    
    geom = ogr.CreateGeometryFromWkt('POINT(93538.15 1.23456789)')
    expected_gml = '&lt;gml:Point&gt;&lt;gml:coordinates&gt;93538.15,1.23456789&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;'
    got_gml = geom.ExportToGML()
    if got_gml != expected_gml:
        gdaltest.post_reason('did not get expected gml')
        print(got_gml)
        return 'fail'

    geom = ogr.CreateGeometryFromWkt('POINT(93538.55 1234567.89)')
    expected_gml = '&lt;gml:Point&gt;&lt;gml:coordinates&gt;93538.55,1234567.89&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;'
    got_gml = geom.ExportToGML()
    if got_gml != expected_gml:
        gdaltest.post_reason('did not get expected gml')
        print(got_gml)
        return 'fail'

    return 'success'

###############################################################################
# Test various error cases of gml2ogrgeometry.cpp

def gml_invalid_geoms():

    gml_expected_wkt_list = [
        ('&lt;?xml version="1.0" encoding="UTF-8"?&gt;', None),
        ('&lt;!-- bla --&gt;', None),
        ('&lt;foo/&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates/&gt;&lt;/gml:Point&gt;', 'POINT EMPTY'), # This is valid GML actually
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;0&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;0 1&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (0 1)'), # Support for uncommon formatting of coordinates
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;0 1 2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (0 1 2)'), # Support for uncommon formatting of coordinates
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;0,1 2,3&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:pos&gt;0&lt;/gml:pos&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:pos/&gt;&lt;/gml:Point&gt;', 'POINT EMPTY'), # This is valid GML actually
        ('&lt;gml:Point/&gt;', None),
        ('&lt;gml:Point&gt;&lt;foo/&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:LineString/&gt;', None),
        ('&lt;gml:LineString&gt;&lt;foo/&gt;&lt;/gml:LineString&gt;', None),
        ('&lt;gml:LineString&gt;&lt;gml:posList&gt;&lt;/gml:posList&gt;&lt;/gml:LineString&gt;', 'LINESTRING EMPTY'), # This is valid GML actually
        ('&lt;gml:LineString&gt;&lt;gml:posList&gt;0&lt;/gml:posList&gt;&lt;/gml:LineString&gt;', None),
        ('&lt;gml:LineString&gt;&lt;gml:posList srsDimension="4"&gt;0 1 2 3&lt;/gml:posList&gt;&lt;/gml:LineString&gt;', None),
        ('&lt;gml:LineString&gt;&lt;gml:posList srsDimension="3"&gt;0 1 2 3&lt;/gml:posList&gt;&lt;/gml:LineString&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:coord&gt;&lt;/gml:coord&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:coord&gt;&lt;gml:X/&gt;&lt;gml:Y/&gt;&lt;/gml:coord&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Point&gt;&lt;gml:coord&gt;&lt;gml:X&gt;0&lt;/gml:X&gt;&lt;/gml:coord&gt;&lt;/gml:Point&gt;', None),
        ('&lt;gml:Polygon/&gt;', 'POLYGON EMPTY'), # valid GML3, but invalid GML2. Be tolerant
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs/&gt;&lt;/gml:Polygon&gt;', 'POLYGON EMPTY'), # valid GML2
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;foo/&gt;&lt;/gml:outerBoundaryIs&gt;&lt;/gml:Polygon&gt;', None),
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:outerBoundaryIs&gt;&lt;/gml:Polygon&gt;', None),
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;0 1 2 3 4 5 0 1&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:outerBoundaryIs&gt;&lt;gml:innerBoundaryIs/&gt;&lt;/gml:Polygon&gt;', None),
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;gml:LinearRing/&gt;&lt;/gml:outerBoundaryIs&gt;&lt;gml:innerBoundaryIs/&gt;&lt;/gml:Polygon&gt;', None),
        ('&lt;gml:Polygon&gt;&lt;gml:outerBoundaryIs&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;0 1 2 3 4 5 0 1&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:outerBoundaryIs&gt;&lt;gml:innerBoundaryIs&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:innerBoundaryIs&gt;&lt;/gml:Polygon&gt;', None),
        ('&lt;gml:Ring/&gt;', 'LINEARRING EMPTY'), # Probably illegal GML
        ('&lt;gml:Ring&gt;&lt;foo/&gt;&lt;/gml:Ring&gt;', 'LINEARRING EMPTY'), # Probably illegal GML
        ('&lt;gml:Ring&gt;&lt;gml:curveMember/&gt;&lt;/gml:Ring&gt;', None),
        ('&lt;gml:Ring&gt;&lt;gml:curveMember&gt;&lt;foo/&gt;&lt;/gml:curveMember&gt;&lt;/gml:Ring&gt;', None),
        ('&lt;gml:Ring&gt;&lt;gml:curveMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:curveMember&gt;&lt;/gml:Ring&gt;', None),
        ('&lt;gml:Box/&gt;', None),
        ('&lt;gml:Box&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Box&gt;', None),
        ('&lt;gml:MultiPolygon/&gt;', 'MULTIPOLYGON EMPTY'), # valid GML3, but invalid GML2. Be tolerant
        ('&lt;gml:MultiPolygon&gt;&lt;foo/&gt;&lt;/gml:MultiPolygon&gt;', 'MULTIPOLYGON EMPTY'), # illegal GML, but we are tolerant
        ('&lt;gml:MultiPolygon&gt;&lt;gml:polygonMember/&gt;&lt;/gml:MultiPolygon&gt;', 'MULTIPOLYGON EMPTY'), # valid in GML3 (accepted by PostGIS too)
        ('&lt;gml:MultiPolygon&gt;&lt;gml:polygonMember&gt;&lt;foo/&gt;&lt;/gml:polygonMember&gt;&lt;/gml:MultiPolygon&gt;', None),
        ('&lt;gml:MultiPolygon&gt;&lt;gml:polygonMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:polygonMember&gt;&lt;/gml:MultiPolygon&gt;', None),
        ('&lt;gml:MultiSurface&gt;&lt;gml:surfaceMembers/&gt;&lt;/gml:MultiSurface&gt;', 'MULTIPOLYGON EMPTY'), # valid GML
        ('&lt;gml:MultiSurface&gt;&lt;gml:surfaceMembers&gt;&lt;foo/&gt;&lt;/gml:surfaceMembers&gt;&lt;/gml:MultiSurface&gt;', 'MULTIPOLYGON EMPTY'), # illegal GML, but we are tolerant
        ('&lt;gml:MultiSurface&gt;&lt;gml:surfaceMembers&gt;&lt;gml:Polygon/&gt;&lt;/gml:surfaceMembers&gt;&lt;/gml:MultiSurface&gt;', 'MULTIPOLYGON EMPTY'), # valid GML3
        ('&lt;gml:MultiPoint/&gt;', 'MULTIPOINT EMPTY'),
        ('&lt;gml:MultiPoint&gt;&lt;foo/&gt;&lt;/gml:MultiPoint&gt;', 'MULTIPOINT EMPTY'),
        ('&lt;gml:MultiPoint&gt;&lt;gml:pointMember/&gt;&lt;/gml:MultiPoint&gt;', 'MULTIPOINT EMPTY'), # valid in GML3 (accepted by PostGIS too)
        ('&lt;gml:MultiPoint&gt;&lt;gml:pointMember&gt;&lt;gml:LineString&gt;&lt;gml:posList&gt;0 1 2 3&lt;/gml:posList&gt;&lt;/gml:LineString&gt;&lt;/gml:pointMember&gt;&lt;/gml:MultiPoint&gt;', None),
        ('&lt;gml:MultiPoint&gt;&lt;gml:pointMembers&gt;&lt;/gml:pointMembers&gt;&lt;/gml:MultiPoint&gt;', 'MULTIPOINT EMPTY'),
        ('&lt;gml:MultiPoint&gt;&lt;gml:pointMembers&gt;&lt;foo/&gt;&lt;/gml:pointMembers&gt;&lt;/gml:MultiPoint&gt;', 'MULTIPOINT EMPTY'),
        ('&lt;gml:MultiPoint&gt;&lt;gml:pointMembers&gt;&lt;gml:Point/&gt;&lt;/gml:pointMembers&gt;&lt;/gml:MultiPoint&gt;', None),
        ('&lt;gml:MultiLineString/&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiLineString&gt;&lt;foo/&gt;&lt;/gml:MultiLineString&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiLineString&gt;&lt;gml:lineStringMember/&gt;&lt;/gml:MultiLineString&gt;', None),
        ('&lt;gml:MultiLineString&gt;&lt;gml:lineStringMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:lineStringMember&gt;&lt;/gml:MultiLineString&gt;', None),
        ('&lt;gml:MultiCurve/&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiCurve&gt;&lt;foo/&gt;&lt;/gml:MultiCurve&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMember/&gt;&lt;/gml:MultiCurve&gt;', 'MULTILINESTRING EMPTY'), # valid in GML3 (accepted by PostGIS too)
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;foo/&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;', None),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;gml:Curve/&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;', None),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;gml:Curve&gt;&lt;foo/&gt;&lt;/gml:Curve&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;', None),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;gml:Curve&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:Curve&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;', None),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMembers&gt;&lt;/gml:curveMembers&gt;&lt;/gml:MultiCurve&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMembers&gt;&lt;foo/&gt;&lt;/gml:curveMembers&gt;&lt;/gml:MultiCurve&gt;', 'MULTILINESTRING EMPTY'),
        ('&lt;gml:MultiCurve&gt;&lt;gml:curveMembers&gt;&lt;gml:LineString/&gt;&lt;/gml:curveMembers&gt;&lt;/gml:MultiCurve&gt;', None),
        ('&lt;gml:Curve/&gt;', None),
        ('&lt;gml:Curve&gt;&lt;foo/&gt;&lt;/gml:Curve&gt;', None),
        ('&lt;gml:Curve&gt;&lt;gml:segments/&gt;&lt;/gml:Curve&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;foo/&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:Arc/&gt;', None),
        ('&lt;gml:Arc&gt;&lt;gml:posList&gt;0 0 0 1&lt;/gml:posList&gt;&lt;/gml:Arc&gt;', None),
        ('&lt;gml:segments/&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:segments&gt;&lt;foo/&gt;&lt;/gml:segments&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:segments&gt;&lt;gml:LineStringSegment/&gt;&lt;/gml:segments&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;foo/&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;31 29 16&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;', 'LINESTRING EMPTY'),
        ('&lt;gml:MultiGeometry/&gt;', 'GEOMETRYCOLLECTION EMPTY'),
        ('&lt;gml:MultiGeometry&gt;&lt;foo/&gt;&lt;/gml:MultiGeometry&gt;', 'GEOMETRYCOLLECTION EMPTY'),
        ('&lt;gml:MultiGeometry&gt;&lt;gml:geometryMember/&gt;&lt;/gml:MultiGeometry&gt;', 'GEOMETRYCOLLECTION EMPTY'), # valid in GML3 (accepted by PostGIS too)
        ('&lt;gml:MultiGeometry&gt;&lt;gml:geometryMember&gt;&lt;foo/&gt;&lt;/gml:geometryMember&gt;&lt;/gml:MultiGeometry&gt;', None),
        ('&lt;gml:Surface/&gt;', 'POLYGON EMPTY'), # valid GML3
        ('&lt;gml:Surface&gt;&lt;foo/&gt;&lt;/gml:Surface&gt;', 'POLYGON EMPTY'), # invalid GML3, but we are tolerant
        ('&lt;gml:Surface&gt;&lt;gml:patches/&gt;&lt;/gml:Surface&gt;', 'POLYGON EMPTY'), # valid GML3
        ('&lt;gml:Surface&gt;&lt;gml:patches&gt;&lt;foo/&gt;&lt;/gml:patches&gt;&lt;/gml:Surface&gt;', None),
        ('&lt;gml:Surface&gt;&lt;gml:patches&gt;&lt;gml:PolygonPatch/&gt;&lt;/gml:patches&gt;&lt;/gml:Surface&gt;', 'POLYGON EMPTY'), # valid GML3
        ('&lt;gml:Solid/&gt;', 'POLYGON EMPTY'), # valid GML3
        ('&lt;gml:Solid&gt;&lt;foo/&gt;&lt;/gml:Solid&gt;', 'POLYGON EMPTY'), # invalid GML3, but we are tolerant
        ('&lt;gml:Solid&gt;&lt;gml:exterior/&gt;&lt;/gml:Solid&gt;', 'POLYGON EMPTY'), # valid GML3
        ('&lt;gml:Solid&gt;&lt;gml:exterior&gt;&lt;foo/&gt;&lt;/gml:exterior&gt;&lt;/gml:Solid&gt;', None),
        ('&lt;gml:Solid&gt;&lt;gml:exterior&gt;&lt;Polygon&gt;&lt;exterior&gt;&lt;LinearRing&gt;&lt;posList&gt;0 0 4 0 4 4 0 4 0 0&lt;/posList&gt;&lt;/LinearRing&gt;&lt;/exterior&gt;&lt;/Polygon&gt;&lt;/gml:exterior&gt;&lt;gml:interior/&gt;&lt;/gml:Solid&gt;', 'POLYGON ((0 0,4 0,4 4,0 4,0 0))'),
        ('&lt;gml:OrientableSurface/&gt;', None),
        ('&lt;gml:OrientableSurface&gt;&lt;foo/&gt;&lt;/gml:OrientableSurface&gt;', None),
        ('&lt;gml:OrientableSurface&gt;&lt;gml:baseSurface/&gt;&lt;/gml:OrientableSurface&gt;', None),
        ('&lt;gml:OrientableSurface&gt;&lt;gml:baseSurface&gt;&lt;foo/&gt;&lt;/gml:baseSurface&gt;&lt;/gml:OrientableSurface&gt;', None),
        ('&lt;gmlce:SimplePolygon/&gt;',None), #invalid
        ('&lt;gmlce:SimplePolygon&gt;&lt;foo/&gt;&lt;/gmlce:SimplePolygon&gt;',None), # invalid GML3, but we are tolerant
        ('&lt;gmlce:SimplePolygon&gt;&lt;gml:posList/&gt;&lt;/gmlce:SimplePolygon&gt;','POLYGON EMPTY'), # validates the schema
        ('&lt;gmlce:SimpleMultiPoint/&gt;',None), #invalid
        ('&lt;gmlce:SimpleMultiPoint&gt;&lt;foo/&gt;&lt;/gmlce:SimpleMultiPoint&gt;',None), # invalid GML3, but we are tolerant
        ('&lt;gmlce:SimpleMultiPoint&gt;&lt;gml:posList/&gt;&lt;/gmlce:SimpleMultiPoint&gt;','MULTIPOINT EMPTY'), # validates the schema
        ('&lt;gml:Envelope/&gt;',None),
        ('&lt;gml:Envelope&gt;&lt;gml:lowerCorner/&gt;&lt;gml:upperCorner/&gt;&lt;/gml:Envelope&gt;',None),
        ('&lt;gml:Envelope&gt;&lt;gml:lowerCorner&gt;1&lt;/gml:lowerCorner&gt;&lt;gml:upperCorner&gt;3 4&lt;/gml:upperCorner/&gt;&lt;/gml:Envelope&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs="bla"&gt;1bla2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs=""&gt;1bla2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs="0"&gt;1bla2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates ts="bla"&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates ts=""&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates ts="0"&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates decimal="bla"&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates decimal=""&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
        ('&lt;gml:Point&gt;&lt;gml:coordinates decimal="0"&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;',None),
    ]

    for (gml, expected_wkt) in gml_expected_wkt_list:
        gdal.PushErrorHandler('CPLQuietErrorHandler')
        #print gml
        geom = ogr.CreateGeometryFromGML(gml)
        gdal.PopErrorHandler()
        if geom is None:
            if expected_wkt is not None:
                gdaltest.post_reason('did not get expected result for %s. Got None instead of %s' % (gml, expected_wkt))
                return 'fail'
        else:
            wkt = geom.ExportToWkt()
            if expected_wkt is None:
                gdaltest.post_reason('did not get expected result for %s. Got %s instead of None' % (gml, wkt))
                return 'fail'
            else:
                if wkt != expected_wkt:
                    gdaltest.post_reason('did not get expected result for %s. Got %s instead of %s' % (gml, wkt, expected_wkt))
                    return 'fail'

    return 'success'

###############################################################################
# Test write support for GML3

def gml_write_gml3_geometries():

    gml_list = [ '&lt;gml:Point&gt;&lt;gml:pos&gt;2 3&lt;/gml:pos&gt;&lt;/gml:Point&gt;',
             '&lt;gml:Point&gt;&lt;gml:pos&gt;2 3 4&lt;/gml:pos&gt;&lt;/gml:Point&gt;',
             '&lt;gml:LineString&gt;&lt;gml:posList&gt;2 3 4 5&lt;/gml:posList&gt;&lt;/gml:LineString&gt;',
             '&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;gml:posList&gt;2 3 4 5&lt;/gml:posList&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;',
             '&lt;gml:LineString&gt;&lt;gml:posList srsDimension="3"&gt;2 3 10 4 5 20&lt;/gml:posList&gt;&lt;/gml:LineString&gt;',
             '&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;gml:posList srsDimension="3"&gt;2 3 10 4 5 20&lt;/gml:posList&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;',
             '&lt;gml:Polygon&gt;&lt;gml:exterior&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:exterior&gt;&lt;/gml:Polygon&gt;',
             '&lt;gml:Polygon&gt;&lt;gml:exterior&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:exterior&gt;&lt;gml:interior&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;10 10 10 11 11 11 10 10&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:interior&gt;&lt;/gml:Polygon&gt;',
             '&lt;gml:MultiPoint&gt;&lt;gml:pointMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;2 3&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:pointMember&gt;&lt;gml:pointMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;4 5&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:pointMember&gt;&lt;/gml:MultiPoint&gt;',
             '&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;gml:LineString&gt;&lt;gml:posList&gt;0 1 2 3 4 5&lt;/gml:posList&gt;&lt;/gml:LineString&gt;&lt;/gml:curveMember&gt;&lt;gml:curveMember&gt;&lt;gml:LineString&gt;&lt;gml:posList&gt;6 7 8 9 10 11&lt;/gml:posList&gt;&lt;/gml:LineString&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;',
             '&lt;gml:MultiCurve&gt;&lt;gml:curveMember&gt;&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;gml:posList&gt;0 1 2 3 4 5&lt;/gml:posList&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;&lt;/gml:curveMember&gt;&lt;gml:curveMember&gt;&lt;gml:Curve&gt;&lt;gml:segments&gt;&lt;gml:LineStringSegment&gt;&lt;gml:posList&gt;6 7 8 9 10 11&lt;/gml:posList&gt;&lt;/gml:LineStringSegment&gt;&lt;/gml:segments&gt;&lt;/gml:Curve&gt;&lt;/gml:curveMember&gt;&lt;/gml:MultiCurve&gt;',
             '&lt;gml:MultiSurface&gt;&lt;gml:surfaceMember&gt;&lt;gml:Polygon&gt;&lt;gml:exterior&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;0 1 2 3 4 5 0 1&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:exterior&gt;&lt;/gml:Polygon&gt;&lt;/gml:surfaceMember&gt;&lt;gml:surfaceMember&gt;&lt;gml:Polygon&gt;&lt;gml:exterior&gt;&lt;gml:LinearRing&gt;&lt;gml:posList&gt;6 7 8 9 10 11 6 7&lt;/gml:posList&gt;&lt;/gml:LinearRing&gt;&lt;/gml:exterior&gt;&lt;/gml:Polygon&gt;&lt;/gml:surfaceMember&gt;&lt;/gml:MultiSurface&gt;',
             '&lt;gml:MultiGeometry&gt;&lt;gml:geometryMember&gt;&lt;gml:Point&gt;&lt;gml:pos&gt;0 1&lt;/gml:pos&gt;&lt;/gml:Point&gt;&lt;/gml:geometryMember&gt;&lt;gml:geometryMember&gt;&lt;gml:LineString&gt;&lt;gml:posList&gt;2 3 4 5&lt;/gml:posList&gt;&lt;/gml:LineString&gt;&lt;/gml:geometryMember&gt;&lt;/gml:MultiGeometry&gt;' ]

    for gml_in in gml_list:
        geom = ogr.CreateGeometryFromGML(gml_in)
        if gml_in.find('&lt;gml:Curve') != -1:
            gml_out = geom.ExportToGML( ['FORMAT=GML3', 'GML3_LINESTRING_ELEMENT=curve'] )
        else:
            gml_out = geom.ExportToGML( ['FORMAT=GML3'] )
        if gml_out != gml_in:
            gdaltest.post_reason('got %s, instead of %s' % (gml_out, gml_in))
            return 'fail'

    return 'success'

###############################################################################
# Test write support for GML3 SRS

def gml_write_gml3_srs():

    sr32631 = osr.SpatialReference()
    sr32631.SetFromUserInput("EPSG:32631")

    srlonglat = osr.SpatialReference()
    srlonglat.SetFromUserInput("EPSG:4326")

    srlatlong = osr.SpatialReference()
    srlatlong.SetFromUserInput("EPSGA:4326")

    geom = ogr.CreateGeometryFromWkt('POINT(500000 4500000)')
    geom.AssignSpatialReference(sr32631)
    gml3 = geom.ExportToGML( options = ['FORMAT=GML3'] )
    expected_gml = '&lt;gml:Point srsName="urn:ogc:def:crs:EPSG::32631"&gt;&lt;gml:pos&gt;500000 4500000&lt;/gml:pos&gt;&lt;/gml:Point&gt;'
    if gml3 != expected_gml:
        gdaltest.post_reason('got %s, instead of %s' % (gml3, expected_gml))
        return 'fail'

    # Should perform the needed coordinate order swapping
    geom = ogr.CreateGeometryFromWkt('POINT(2 49)')
    geom.AssignSpatialReference(srlonglat)
    gml3 = geom.ExportToGML( options = ['FORMAT=GML3'] )
    expected_gml = '&lt;gml:Point srsName="urn:ogc:def:crs:EPSG::4326"&gt;&lt;gml:pos&gt;49 2&lt;/gml:pos&gt;&lt;/gml:Point&gt;'
    if gml3 != expected_gml:
        gdaltest.post_reason('got %s, instead of %s' % (gml3, expected_gml))
        return 'fail'

    # Shouldn't change the coordinate order
    geom = ogr.CreateGeometryFromWkt('POINT(49 2)')
    geom.AssignSpatialReference(srlatlong)
    gml3 = geom.ExportToGML( options = ['FORMAT=GML3'] )
    expected_gml = '&lt;gml:Point srsName="urn:ogc:def:crs:EPSG::4326"&gt;&lt;gml:pos&gt;49 2&lt;/gml:pos&gt;&lt;/gml:Point&gt;'
    if gml3 != expected_gml:
        gdaltest.post_reason('got %s, instead of %s' % (gml3, expected_gml))
        return 'fail'

    # Legacy SRS format
    geom = ogr.CreateGeometryFromWkt('POINT(2 49)')
    geom.AssignSpatialReference(srlonglat)
    gml3 = geom.ExportToGML( options = ['FORMAT=GML3', 'GML3_LONGSRS=NO'] )
    expected_gml = '&lt;gml:Point srsName="EPSG:4326"&gt;&lt;gml:pos&gt;2 49&lt;/gml:pos&gt;&lt;/gml:Point&gt;'
    if gml3 != expected_gml:
        gdaltest.post_reason('got %s, instead of %s' % (gml3, expected_gml))
        return 'fail'

    return 'success'

###############################################################################
# Test that importing too nested GML doesn't cause stack overflows

def gml_nested():

    gml = ''
    for i in range(31):
        gml = gml + '&lt;gml:MultiGeometry&gt;&lt;gml:geometryMember&gt;'
    gml = gml + '&lt;gml:MultiPolygon&gt;&lt;/gml:MultiPolygon&gt;'
    for i in range(31):
        gml = gml +  '&lt;/gml:geometryMember&gt;&lt;/gml:MultiGeometry&gt;'

    geom = ogr.CreateGeometryFromGML(gml)
    if geom is None:
        gdaltest.post_reason('expected a geometry')
        return 'fail'

    gml = ''
    for i in range(32):
        gml = gml + '&lt;gml:MultiGeometry&gt;&lt;gml:geometryMember&gt;'
    gml = gml + '&lt;gml:MultiPolygon&gt;&lt;/gml:MultiPolygon&gt;'
    for i in range(32):
        gml = gml +  '&lt;/gml:geometryMember&gt;&lt;/gml:MultiGeometry&gt;'

    gdal.PushErrorHandler('CPLQuietErrorHandler')
    geom = ogr.CreateGeometryFromGML(gml)
    gdal.PopErrorHandler()
    if geom is not None:
        gdaltest.post_reason('expected None')
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.3 SimplePolygon

def gml_SimplePolygon():

    gml = """&lt;gmlce:SimplePolygon&gt;&lt;gml:posList&gt;0 0 1 0 1 1 0 1&lt;/gml:posList&gt;&lt;/gmlce:SimplePolygon&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,1 0,1 1,0 1,0 0))':
        gdaltest.post_reason( '&lt;gmlce:SimplePolygon&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.3 SimpleRectangle

def gml_SimpleRectangle():

    gml = """&lt;gmlce:SimpleRectangle&gt;&lt;gml:posList&gt;0 0 1 0 1 1 0 1&lt;/gml:posList&gt;&lt;/gmlce:SimpleRectangle&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,1 0,1 1,0 1,0 0))':
        gdaltest.post_reason( '&lt;gmlce:SimpleRectangle&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.3 SimpleTriangle

def gml_SimpleTriangle():

    gml = """&lt;gmlce:SimpleTriangle&gt;&lt;gml:posList&gt;0 0 1 0 1 1&lt;/gml:posList&gt;&lt;/gmlce:SimpleTriangle&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,1 0,1 1,0 0))':
        gdaltest.post_reason( '&lt;gmlce:SimpleTriangle&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test GML 3.3 SimpleMultiPoint

def gml_SimpleMultiPoint():

    gml = """&lt;gmlce:SimpleMultiPoint&gt;&lt;gml:posList&gt;0 1 2 3&lt;/gml:posList&gt;&lt;/gmlce:SimpleMultiPoint&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOINT (0 1,2 3)':
        gdaltest.post_reason( '&lt;gmlce:SimpleMultiPoint&gt; not correctly parsed' )
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test  gml:CompositeCurve&gt; in &lt;gml:Ring&gt;

def gml_CompositeCurveInRing():

    gml = """&lt;gml:Surface&gt;
    &lt;gml:patches&gt;
        &lt;gml:PolygonPatch interpolation="planar"&gt;
            &lt;gml:exterior&gt;
                &lt;gml:Ring&gt;
                    &lt;gml:curveMember&gt;
                        &lt;gml:CompositeCurve&gt;
                            &lt;gml:curveMember&gt;
                                &lt;gml:Curve&gt;
                                    &lt;gml:segments&gt;
                                        &lt;gml:LineStringSegment&gt;
                                            &lt;gml:pos&gt;0 0&lt;/gml:pos&gt;
                                            &lt;gml:pos&gt;0 1&lt;/gml:pos&gt;
                                        &lt;/gml:LineStringSegment&gt;
                                    &lt;/gml:segments&gt;
                                &lt;/gml:Curve&gt;
                            &lt;/gml:curveMember&gt;
                            &lt;gml:curveMember&gt;
                                &lt;gml:Curve&gt;
                                    &lt;gml:segments&gt;
                                        &lt;gml:LineStringSegment&gt;
                                            &lt;gml:pos&gt;0 1&lt;/gml:pos&gt;
                                            &lt;gml:pos&gt;1 1&lt;/gml:pos&gt;
                                        &lt;/gml:LineStringSegment&gt;
                                    &lt;/gml:segments&gt;
                                &lt;/gml:Curve&gt;
                            &lt;/gml:curveMember&gt;
                            &lt;gml:curveMember&gt;
                                &lt;gml:Curve&gt;
                                    &lt;gml:segments&gt;
                                        &lt;gml:LineStringSegment&gt;
                                            &lt;gml:pos&gt;1 1&lt;/gml:pos&gt;
                                            &lt;gml:pos&gt;0 0&lt;/gml:pos&gt;
                                        &lt;/gml:LineStringSegment&gt;
                                    &lt;/gml:segments&gt;
                                &lt;/gml:Curve&gt;
                            &lt;/gml:curveMember&gt;
                        &lt;/gml:CompositeCurve&gt;
                    &lt;/gml:curveMember&gt;
                &lt;/gml:Ring&gt;
            &lt;/gml:exterior&gt;
        &lt;/gml:PolygonPatch&gt;
    &lt;/gml:patches&gt;
&lt;/gml:Surface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'POLYGON ((0 0,0 1,1 1,0 0))':
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test &lt;gml:CompositeSurface&gt; in &lt;gml:surfaceMembers&gt; (#5369)

def gml_CompositeSurface_in_surfaceMembers():

    gml = """&lt;gml:MultiSurface&gt;
          &lt;gml:surfaceMembers&gt;
            &lt;gml:CompositeSurface&gt;
              &lt;gml:surfaceMember&gt;
                &lt;gml:Polygon&gt;
                  &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                      &lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;
                    &lt;/gml:LinearRing&gt;
                  &lt;/gml:exterior&gt;
                &lt;/gml:Polygon&gt;
              &lt;/gml:surfaceMember&gt;
              &lt;gml:surfaceMember&gt;
                &lt;gml:Polygon&gt;
                  &lt;gml:exterior&gt;
                    &lt;gml:LinearRing&gt;
                      &lt;gml:posList&gt;2 0 2 1 3 1 3 0 2 0&lt;/gml:posList&gt;
                    &lt;/gml:LinearRing&gt;
                  &lt;/gml:exterior&gt;
                &lt;/gml:Polygon&gt;
              &lt;/gml:surfaceMember&gt;
            &lt;/gml:CompositeSurface&gt;
          &lt;/gml:surfaceMembers&gt;
        &lt;/gml:MultiSurface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0)),((2 0,2 1,3 1,3 0,2 0)))':
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test &lt;gml:PolygonPatch&gt; with only Interior ring (#5421)

def gml_MultiSurfaceOfSurfaceOfPolygonPatchWithInteriorRing():
 
    gml = """&lt;gml:MultiSurface&gt;
               &lt;gml:surfaceMember&gt;
                 &lt;gml:Surface&gt;
                    &lt;gml:patches&gt;
                      &lt;gml:PolygonPatch&gt;
                        &lt;gml:exterior&gt;
                          &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;
                          &lt;/gml:LinearRing&gt;
                        &lt;/gml:exterior&gt;
                      &lt;/gml:PolygonPatch&gt;
                    &lt;/gml:patches&gt;
                  &lt;/gml:Surface&gt;
                &lt;/gml:surfaceMember&gt;
                &lt;gml:surfaceMember&gt;
                  &lt;gml:Surface&gt;
                    &lt;gml:patches&gt;
                      &lt;gml:PolygonPatch&gt;
                        &lt;gml:interior&gt;
                          &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.25 0.25 0.25&lt;/gml:posList&gt;
                          &lt;/gml:LinearRing&gt;
                        &lt;/gml:interior&gt;
                      &lt;/gml:PolygonPatch&gt;
                    &lt;/gml:patches&gt;
                  &lt;/gml:Surface&gt;
                &lt;/gml:surfaceMember&gt;
               &lt;gml:surfaceMember&gt;
                 &lt;gml:Surface&gt;
                    &lt;gml:patches&gt;
                      &lt;gml:PolygonPatch&gt;
                        &lt;gml:exterior&gt;
                          &lt;gml:LinearRing&gt;
                            &lt;gml:posList&gt;0 0 0 -1 -1 -1 -1 0 0 0&lt;/gml:posList&gt;
                          &lt;/gml:LinearRing&gt;
                        &lt;/gml:exterior&gt;
                      &lt;/gml:PolygonPatch&gt;
                    &lt;/gml:patches&gt;
                  &lt;/gml:Surface&gt;
                &lt;/gml:surfaceMember&gt;
              &lt;/gml:MultiSurface&gt;"""

    geom = ogr.CreateGeometryFromGML( gml )

    if geom.ExportToWkt() != 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25)),((0 0,0 -1,-1 -1,-1 0,0 0)))':
        print(geom.ExportToWkt())
        return 'fail'

    return 'success'

###############################################################################
# Test ts, cs and decimal attributes of gml:coordinates

def gml_Coordinates_ts_cs_decimal():

    gml_expected_wkt_list = [
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'), # default values
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs="," ts=" " decimal="."&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'), # default values
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs="," ts=" " decimal="."&gt;1,2,3&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2 3)'), # default values
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs="," ts=" " decimal="."&gt;  1,2  &lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'), # we accept that...
        ('&lt;gml:Point&gt;&lt;gml:coordinates&gt;1 2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'), # this is completely out of specification ! but we accept that too !
        ('&lt;gml:Point&gt;&lt;gml:coordinates cs=";"&gt;1;2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'),
        ('&lt;gml:Point&gt;&lt;gml:coordinates decimal="," cs=";"&gt;1,2;3,4&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1.2 3.4)'), 
        ('&lt;gml:Point&gt;&lt;gml:coordinates decimal="," cs=";"&gt;1,2;3,4;5,6&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1.2 3.4 5.6)'), 
        ('&lt;gml:LineString&gt;&lt;gml:coordinates&gt;1,2 3,4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2,3 4)'), # default values
        ('&lt;gml:LineString&gt;&lt;gml:coordinates cs="," ts=" " decimal="."&gt;1,2 3,4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2,3 4)'), # default values
        ('&lt;gml:LineString&gt;&lt;gml:coordinates cs="," ts=" " decimal="."&gt;1,2,2.5 3,4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2 2.5,3 4 0)'), # default values
        ('&lt;gml:LineString&gt;&lt;gml:coordinates ts="-"&gt;1,2-3,4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2,3 4)'),
        ('&lt;gml:LineString&gt;&lt;gml:coordinates cs=" " ts=","&gt;1 2,3 4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2,3 4)'),
        ('&lt;gml:LineString&gt;&lt;gml:coordinates cs=" " ts=","&gt;1 2 2.5,3 4&lt;/gml:coordinates&gt;&lt;/gml:LineString&gt;', 'LINESTRING (1 2 2.5,3 4 0)'),
    ]

    for (gml, expected_wkt) in gml_expected_wkt_list:
        geom = ogr.CreateGeometryFromGML(gml)
        wkt = geom.ExportToWkt()
        if expected_wkt is None:
            gdaltest.post_reason('did not get expected result for %s. Got %s instead of None' % (gml, wkt))
            return 'fail'
        else:
            if wkt != expected_wkt:
                gdaltest.post_reason('did not get expected result for %s. Got %s instead of %s' % (gml, wkt, expected_wkt))
                return 'fail'

    return 'success'

###############################################################################
# Test gml with XML header and comments

def gml_with_xml_header_and_comments():

    gml_expected_wkt_list = [
        ('&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;!-- comment --&gt;&lt;gml:Point&gt; &lt;!-- comment --&gt; &lt;gml:coordinates&gt;1,2&lt;/gml:coordinates&gt;&lt;/gml:Point&gt;', 'POINT (1 2)'),
        ("""&lt;gml:MultiSurface&gt;&lt;!-- comment --&gt;
               &lt;gml:surfaceMember&gt;&lt;!-- comment --&gt;
                 &lt;gml:Surface&gt;&lt;!-- comment --&gt;
                    &lt;gml:patches&gt;&lt;!-- comment --&gt;
                      &lt;gml:PolygonPatch&gt;&lt;!-- comment --&gt;
                        &lt;gml:exterior&gt;&lt;!-- comment --&gt;
                          &lt;gml:LinearRing&gt;&lt;!-- comment --&gt;
                            &lt;gml:posList&gt;0 0 0 1 1 1 1 0 0 0&lt;/gml:posList&gt;
                          &lt;/gml:LinearRing&gt;
                        &lt;/gml:exterior&gt;
                        &lt;!-- comment --&gt;
                        &lt;gml:interior&gt;&lt;!-- comment --&gt;
                          &lt;gml:LinearRing&gt;&lt;!-- comment --&gt;
                            &lt;gml:posList&gt;0.25 0.25 0.25 0.75 0.75 0.75 0.75 0.25 0.25 0.25&lt;/gml:posList&gt;
                          &lt;/gml:LinearRing&gt;
                        &lt;/gml:interior&gt;
                      &lt;/gml:PolygonPatch&gt;
                    &lt;/gml:patches&gt;
                  &lt;/gml:Surface&gt;
                &lt;/gml:surfaceMember&gt;
              &lt;/gml:MultiSurface&gt;""", 'MULTIPOLYGON (((0 0,0 1,1 1,1 0,0 0),(0.25 0.25,0.25 0.75,0.75 0.75,0.75 0.25,0.25 0.25)))'),
    ]

    for (gml, expected_wkt) in gml_expected_wkt_list:
        geom = ogr.CreateGeometryFromGML(gml)
        wkt = geom.ExportToWkt()
        if expected_wkt is None:
            gdaltest.post_reason('did not get expected result for %s. Got %s instead of None' % (gml, wkt))
            return 'fail'
        else:
            if wkt != expected_wkt:
                gdaltest.post_reason('did not get expected result for %s. Got %s instead of %s' % (gml, wkt, expected_wkt))
                return 'fail'

    return 'success'

###############################################################################
# When imported build a list of units based on the files available.

#print 'hit enter'
#sys.stdin.readline()

gdaltest_list = []

files = os.listdir('data/wkb_wkt')
for filename in files:
    if filename[-4:] == '.wkt':
        ut = gml_geom_unit( filename[:-4] )
        gdaltest_list.append( (ut.gml_geom, ut.unit) )

gdaltest_list.append( gml_space_test )
gdaltest_list.append( gml_pos_point )
gdaltest_list.append( gml_pos_polygon )
gdaltest_list.append( gml_posList_line )
gdaltest_list.append( gml_posList_line3d )
gdaltest_list.append( gml_posList_line3d_2 )
gdaltest_list.append( gml_polygon )
gdaltest_list.append( gml_out_point_srs )
gdaltest_list.append( gml_out_point3d_srs )
gdaltest_list.append( gml_out_linestring_srs )
gdaltest_list.append( gml_out_polygon_srs )
gdaltest_list.append( gml_out_multipoint_srs )
gdaltest_list.append( gml_out_multilinestring_srs )
gdaltest_list.append( gml_out_multipolygon_srs )
gdaltest_list.append( gml_out_geometrycollection_srs )
gdaltest_list.append( gml_Box )
gdaltest_list.append( gml_Envelope )
gdaltest_list.append( gml_Curve )
gdaltest_list.append( gml_Curve_with_pointProperty )
gdaltest_list.append( gml_MultiCurve )
gdaltest_list.append( gml_MultiSurface )
gdaltest_list.append( gml_MultiSurface_surfaceMembers )
gdaltest_list.append( gml_MultiCurve_curveMembers )
gdaltest_list.append( gml_MultiCurve_pointMembers )
gdaltest_list.append( gml_Solid )
gdaltest_list.append( gml_OrientableSurface )
gdaltest_list.append( gml_Triangle )
gdaltest_list.append( gml_Rectangle )
gdaltest_list.append( gml_Tin )
gdaltest_list.append( gml_Arc )
gdaltest_list.append( gml_Circle )
gdaltest_list.append( gml_ConcatenatedDeduplication )
#gdaltest_list.append( gml_out_precision )
gdaltest_list.append( gml_invalid_geoms )
gdaltest_list.append( gml_write_gml3_geometries )
gdaltest_list.append( gml_write_gml3_srs )
gdaltest_list.append( gml_nested )
gdaltest_list.append( gml_SimplePolygon )
gdaltest_list.append( gml_SimpleRectangle )
gdaltest_list.append( gml_SimpleTriangle )
gdaltest_list.append( gml_SimpleMultiPoint )
gdaltest_list.append( gml_CompositeCurveInRing )
gdaltest_list.append( gml_CompositeSurface_in_surfaceMembers )
gdaltest_list.append( gml_MultiSurfaceOfSurfaceOfPolygonPatchWithInteriorRing )
gdaltest_list.append( gml_Coordinates_ts_cs_decimal )
gdaltest_list.append( gml_with_xml_header_and_comments )

if __name__ == '__main__':

    gdaltest.setup_run( 'ogr_gml_geom' )

    gdaltest.run_tests( gdaltest_list )

    gdaltest.summarize()

</pre></body></html>