web/lib/django/contrib/gis/gdal/geometries.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
    27   >>> mpnt.transform_to(SpatialReference('NAD27'))
    27   >>> mpnt.transform_to(SpatialReference('NAD27'))
    28   >>> print mpnt.proj
    28   >>> print mpnt.proj
    29   +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs
    29   +proj=longlat +ellps=clrk66 +datum=NAD27 +no_defs
    30   >>> print mpnt
    30   >>> print mpnt
    31   MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641)
    31   MULTIPOINT (-89.999930378602485 29.999797886557641,-89.999930378602485 29.999797886557641)
    32   
    32 
    33   The OGRGeomType class is to make it easy to specify an OGR geometry type:
    33   The OGRGeomType class is to make it easy to specify an OGR geometry type:
    34   >>> from django.contrib.gis.gdal import OGRGeomType
    34   >>> from django.contrib.gis.gdal import OGRGeomType
    35   >>> gt1 = OGRGeomType(3) # Using an integer for the type
    35   >>> gt1 = OGRGeomType(3) # Using an integer for the type
    36   >>> gt2 = OGRGeomType('Polygon') # Using a string
    36   >>> gt2 = OGRGeomType('Polygon') # Using a string
    37   >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive
    37   >>> gt3 = OGRGeomType('POLYGON') # It's case-insensitive
    38   >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects
    38   >>> print gt1 == 3, gt1 == 'Polygon' # Equivalence works w/non-OGRGeomType objects
    39   True
    39   True
    40 """
    40 """
    41 # Python library requisites.
    41 # Python library requisites.
    42 import re, sys
    42 import sys
    43 from binascii import a2b_hex
    43 from binascii import a2b_hex
    44 from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
    44 from ctypes import byref, string_at, c_char_p, c_double, c_ubyte, c_void_p
    45 
    45 
    46 # Getting GDAL prerequisites
    46 # Getting GDAL prerequisites
    47 from django.contrib.gis.gdal.base import GDALBase
    47 from django.contrib.gis.gdal.base import GDALBase
    48 from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
    48 from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
    49 from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
    49 from django.contrib.gis.gdal.error import OGRException, OGRIndexError, SRSException
    50 from django.contrib.gis.gdal.geomtype import OGRGeomType
    50 from django.contrib.gis.gdal.geomtype import OGRGeomType
       
    51 from django.contrib.gis.gdal.libgdal import GEOJSON, GDAL_VERSION
    51 from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
    52 from django.contrib.gis.gdal.srs import SpatialReference, CoordTransform
    52 
    53 
    53 # Getting the ctypes prototype functions that interface w/the GDAL C library.
    54 # Getting the ctypes prototype functions that interface w/the GDAL C library.
    54 from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
    55 from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
    55 GEOJSON = capi.GEOJSON
    56 
       
    57 # For recognizing geometry input.
       
    58 from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex
    56 
    59 
    57 # For more information, see the OGR C API source code:
    60 # For more information, see the OGR C API source code:
    58 #  http://www.gdal.org/ogr/ogr__api_8h.html
    61 #  http://www.gdal.org/ogr/ogr__api_8h.html
    59 #
    62 #
    60 # The OGR_G_* routines are relevant here.
    63 # The OGR_G_* routines are relevant here.
    61 
    64 
    62 # Regular expressions for recognizing HEXEWKB and WKT.
       
    63 hex_regex = re.compile(r'^[0-9A-F]+$', re.I)
       
    64 wkt_regex = re.compile(r'^(?P<type>POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+$', re.I)
       
    65 json_regex = re.compile(r'^(\s+)?\{[\s\w,\[\]\{\}\-\."\':]+\}(\s+)?$')
       
    66 
       
    67 #### OGRGeometry Class ####
    65 #### OGRGeometry Class ####
    68 class OGRGeometry(GDALBase):
    66 class OGRGeometry(GDALBase):
    69     "Generally encapsulates an OGR geometry."
    67     "Generally encapsulates an OGR geometry."
    70 
    68 
    71     def __init__(self, geom_input, srs=None):
    69     def __init__(self, geom_input, srs=None):
    76         # If HEX, unpack input to to a binary buffer.
    74         # If HEX, unpack input to to a binary buffer.
    77         if str_instance and hex_regex.match(geom_input):
    75         if str_instance and hex_regex.match(geom_input):
    78             geom_input = buffer(a2b_hex(geom_input.upper()))
    76             geom_input = buffer(a2b_hex(geom_input.upper()))
    79             str_instance = False
    77             str_instance = False
    80 
    78 
    81         # Constructing the geometry, 
    79         # Constructing the geometry,
    82         if str_instance:
    80         if str_instance:
    83             # Checking if unicode
    81             # Checking if unicode
    84             if isinstance(geom_input, unicode):
    82             if isinstance(geom_input, unicode):
    85                 # Encoding to ASCII, WKT or HEX doesn't need any more.
    83                 # Encoding to ASCII, WKT or HEX doesn't need any more.
    86                 geom_input = geom_input.encode('ascii')
    84                 geom_input = geom_input.encode('ascii')
    87 
    85 
    88             wkt_m = wkt_regex.match(geom_input)
    86             wkt_m = wkt_regex.match(geom_input)
    89             json_m = json_regex.match(geom_input)
    87             json_m = json_regex.match(geom_input)
    90             if wkt_m:
    88             if wkt_m:
       
    89                 if wkt_m.group('srid'):
       
    90                     # If there's EWKT, set the SRS w/value of the SRID.
       
    91                     srs = int(wkt_m.group('srid'))
    91                 if wkt_m.group('type').upper() == 'LINEARRING':
    92                 if wkt_m.group('type').upper() == 'LINEARRING':
    92                     # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT.
    93                     # OGR_G_CreateFromWkt doesn't work with LINEARRING WKT.
    93                     #  See http://trac.osgeo.org/gdal/ticket/1992.
    94                     #  See http://trac.osgeo.org/gdal/ticket/1992.
    94                     g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num)
    95                     g = capi.create_geom(OGRGeomType(wkt_m.group('type')).num)
    95                     capi.import_wkt(g, byref(c_char_p(geom_input)))
    96                     capi.import_wkt(g, byref(c_char_p(wkt_m.group('wkt'))))
    96                 else:
    97                 else:
    97                     g = capi.from_wkt(byref(c_char_p(geom_input)), None, byref(c_void_p()))
    98                     g = capi.from_wkt(byref(c_char_p(wkt_m.group('wkt'))), None, byref(c_void_p()))
    98             elif json_m:
    99             elif json_m:
    99                 if GEOJSON:
   100                 if GEOJSON:
   100                     g = capi.from_json(geom_input)
   101                     g = capi.from_json(geom_input)
   101                 else:
   102                 else:
   102                     raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.')
   103                     raise NotImplementedError('GeoJSON input only supported on GDAL 1.5+.')
   127         if bool(srs): self.srs = srs
   128         if bool(srs): self.srs = srs
   128 
   129 
   129         # Setting the class depending upon the OGR Geometry Type
   130         # Setting the class depending upon the OGR Geometry Type
   130         self.__class__ = GEO_CLASSES[self.geom_type.num]
   131         self.__class__ = GEO_CLASSES[self.geom_type.num]
   131 
   132 
       
   133     def __del__(self):
       
   134         "Deletes this Geometry."
       
   135         if self._ptr: capi.destroy_geom(self._ptr)
       
   136 
       
   137     # Pickle routines
       
   138     def __getstate__(self):
       
   139         srs = self.srs
       
   140         if srs:
       
   141             srs = srs.wkt
       
   142         else:
       
   143             srs = None
       
   144         return str(self.wkb), srs
       
   145 
       
   146     def __setstate__(self, state):
       
   147         wkb, srs = state
       
   148         ptr = capi.from_wkb(wkb, None, byref(c_void_p()), len(wkb))
       
   149         if not ptr: raise OGRException('Invalid OGRGeometry loaded from pickled state.')
       
   150         self.ptr = ptr
       
   151         self.srs = srs
       
   152 
   132     @classmethod
   153     @classmethod
   133     def from_bbox(cls, bbox):   
   154     def from_bbox(cls, bbox):
   134         "Constructs a Polygon from a bounding box (4-tuple)."
   155         "Constructs a Polygon from a bounding box (4-tuple)."
   135         x0, y0, x1, y1 = bbox
   156         x0, y0, x1, y1 = bbox
   136         return OGRGeometry( 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' %  (
   157         return OGRGeometry( 'POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))' %  (
   137                 x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) )
   158                 x0, y0, x0, y1, x1, y1, x1, y0, x0, y0) )
   138  
       
   139     def __del__(self):
       
   140         "Deletes this Geometry."
       
   141         if self._ptr: capi.destroy_geom(self._ptr)
       
   142 
   159 
   143     ### Geometry set-like operations ###
   160     ### Geometry set-like operations ###
   144     # g = g1 | g2
   161     # g = g1 | g2
   145     def __or__(self, other):
   162     def __or__(self, other):
   146         "Returns the union of the two geometries."
   163         "Returns the union of the two geometries."
   161         "Return the symmetric difference of this Geometry and the other."
   178         "Return the symmetric difference of this Geometry and the other."
   162         return self.sym_difference(other)
   179         return self.sym_difference(other)
   163 
   180 
   164     def __eq__(self, other):
   181     def __eq__(self, other):
   165         "Is this Geometry equal to the other?"
   182         "Is this Geometry equal to the other?"
   166         return self.equals(other)
   183         if isinstance(other, OGRGeometry):
       
   184             return self.equals(other)
       
   185         else:
       
   186             return False
   167 
   187 
   168     def __ne__(self, other):
   188     def __ne__(self, other):
   169         "Tests for inequality."
   189         "Tests for inequality."
   170         return not self.equals(other)
   190         return not (self == other)
   171 
   191 
   172     def __str__(self):
   192     def __str__(self):
   173         "WKT is used for the string representation."
   193         "WKT is used for the string representation."
   174         return self.wkt
   194         return self.wkt
   175 
   195 
   177     @property
   197     @property
   178     def dimension(self):
   198     def dimension(self):
   179         "Returns 0 for points, 1 for lines, and 2 for surfaces."
   199         "Returns 0 for points, 1 for lines, and 2 for surfaces."
   180         return capi.get_dims(self.ptr)
   200         return capi.get_dims(self.ptr)
   181 
   201 
   182     @property
   202     def _get_coord_dim(self):
   183     def coord_dim(self):
       
   184         "Returns the coordinate dimension of the Geometry."
   203         "Returns the coordinate dimension of the Geometry."
   185         return capi.get_coord_dims(self.ptr)
   204         if isinstance(self, GeometryCollection) and GDAL_VERSION < (1, 5, 2):
       
   205             # On GDAL versions prior to 1.5.2, there exists a bug in which
       
   206             # the coordinate dimension of geometry collections is always 2:
       
   207             #   http://trac.osgeo.org/gdal/ticket/2334
       
   208             # Here we workaround by returning the coordinate dimension of the
       
   209             # first geometry in the collection instead.
       
   210             if len(self):
       
   211                 return capi.get_coord_dim(capi.get_geom_ref(self.ptr, 0))
       
   212         return capi.get_coord_dim(self.ptr)
       
   213 
       
   214     def _set_coord_dim(self, dim):
       
   215         "Sets the coordinate dimension of this Geometry."
       
   216         if not dim in (2, 3):
       
   217             raise ValueError('Geometry dimension must be either 2 or 3')
       
   218         capi.set_coord_dim(self.ptr, dim)
       
   219 
       
   220     coord_dim = property(_get_coord_dim, _set_coord_dim)
   186 
   221 
   187     @property
   222     @property
   188     def geom_count(self):
   223     def geom_count(self):
   189         "The number of elements in this Geometry."
   224         "The number of elements in this Geometry."
   190         return capi.get_geom_count(self.ptr)
   225         return capi.get_geom_count(self.ptr)
   205         return self.point_count
   240         return self.point_count
   206 
   241 
   207     @property
   242     @property
   208     def geom_type(self):
   243     def geom_type(self):
   209         "Returns the Type for this Geometry."
   244         "Returns the Type for this Geometry."
   210         try:
   245         return OGRGeomType(capi.get_geom_type(self.ptr))
   211             return OGRGeomType(capi.get_geom_type(self.ptr))
       
   212         except OGRException:
       
   213             # VRT datasources return an invalid geometry type
       
   214             # number, but a valid name -- we'll try that instead.
       
   215             # See: http://trac.osgeo.org/gdal/ticket/2491
       
   216             return OGRGeomType(capi.get_geom_name(self.ptr))
       
   217 
   246 
   218     @property
   247     @property
   219     def geom_name(self):
   248     def geom_name(self):
   220         "Returns the Name of this Geometry."
   249         "Returns the Name of this Geometry."
   221         return capi.get_geom_name(self.ptr)
   250         return capi.get_geom_name(self.ptr)
   235     def extent(self):
   264     def extent(self):
   236         "Returns the envelope as a 4-tuple, instead of as an Envelope object."
   265         "Returns the envelope as a 4-tuple, instead of as an Envelope object."
   237         return self.envelope.tuple
   266         return self.envelope.tuple
   238 
   267 
   239     #### SpatialReference-related Properties ####
   268     #### SpatialReference-related Properties ####
   240     
   269 
   241     # The SRS property
   270     # The SRS property
   242     def _get_srs(self):
   271     def _get_srs(self):
   243         "Returns the Spatial Reference for this Geometry."
   272         "Returns the Spatial Reference for this Geometry."
   244         try:
   273         try:
   245             srs_ptr = capi.get_geom_srs(self.ptr)
   274             srs_ptr = capi.get_geom_srs(self.ptr)
   247         except SRSException:
   276         except SRSException:
   248             return None
   277             return None
   249 
   278 
   250     def _set_srs(self, srs):
   279     def _set_srs(self, srs):
   251         "Sets the SpatialReference for this geometry."
   280         "Sets the SpatialReference for this geometry."
       
   281         # Do not have to clone the `SpatialReference` object pointer because
       
   282         # when it is assigned to this `OGRGeometry` it's internal OGR
       
   283         # reference count is incremented, and will likewise be released
       
   284         # (decremented) when this geometry's destructor is called.
   252         if isinstance(srs, SpatialReference):
   285         if isinstance(srs, SpatialReference):
   253             srs_ptr = srs_api.clone_srs(srs.ptr)
   286             srs_ptr = srs.ptr
   254         elif isinstance(srs, (int, long, basestring)):
   287         elif isinstance(srs, (int, long, basestring)):
   255             sr = SpatialReference(srs)
   288             sr = SpatialReference(srs)
   256             srs_ptr = srs_api.clone_srs(sr.ptr)
   289             srs_ptr = sr.ptr
   257         else:
   290         else:
   258             raise TypeError('Cannot assign spatial reference with object of type: %s' % type(srs))
   291             raise TypeError('Cannot assign spatial reference with object of type: %s' % type(srs))
   259         capi.assign_srs(self.ptr, srs_ptr)
   292         capi.assign_srs(self.ptr, srs_ptr)
   260 
   293 
   261     srs = property(_get_srs, _set_srs)
   294     srs = property(_get_srs, _set_srs)
   296     def json(self):
   329     def json(self):
   297         """
   330         """
   298         Returns the GeoJSON representation of this Geometry (requires
   331         Returns the GeoJSON representation of this Geometry (requires
   299         GDAL 1.5+).
   332         GDAL 1.5+).
   300         """
   333         """
   301         if GEOJSON: 
   334         if GEOJSON:
   302             return capi.to_json(self.ptr)
   335             return capi.to_json(self.ptr)
   303         else:
   336         else:
   304             raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.')
   337             raise NotImplementedError('GeoJSON output only supported on GDAL 1.5+.')
   305     geojson = json
   338     geojson = json
   306 
   339 
   333 
   366 
   334     @property
   367     @property
   335     def wkt(self):
   368     def wkt(self):
   336         "Returns the WKT representation of the Geometry."
   369         "Returns the WKT representation of the Geometry."
   337         return capi.to_wkt(self.ptr, byref(c_char_p()))
   370         return capi.to_wkt(self.ptr, byref(c_char_p()))
   338     
   371 
       
   372     @property
       
   373     def ewkt(self):
       
   374         "Returns the EWKT representation of the Geometry."
       
   375         srs = self.srs
       
   376         if srs and srs.srid:
       
   377             return 'SRID=%s;%s' % (srs.srid, self.wkt)
       
   378         else:
       
   379             return self.wkt
       
   380 
   339     #### Geometry Methods ####
   381     #### Geometry Methods ####
   340     def clone(self):
   382     def clone(self):
   341         "Clones this OGR Geometry."
   383         "Clones this OGR Geometry."
   342         return OGRGeometry(capi.clone_geom(self.ptr), self.srs)
   384         return OGRGeometry(capi.clone_geom(self.ptr), self.srs)
   343 
   385 
   361         """
   403         """
   362         if clone:
   404         if clone:
   363             klone = self.clone()
   405             klone = self.clone()
   364             klone.transform(coord_trans)
   406             klone.transform(coord_trans)
   365             return klone
   407             return klone
       
   408 
       
   409         # Have to get the coordinate dimension of the original geometry
       
   410         # so it can be used to reset the transformed geometry's dimension
       
   411         # afterwards.  This is done because of GDAL bug (in versions prior
       
   412         # to 1.7) that turns geometries 3D after transformation, see:
       
   413         #  http://trac.osgeo.org/gdal/changeset/17792
       
   414         if GDAL_VERSION < (1, 7):
       
   415             orig_dim = self.coord_dim
       
   416 
       
   417         # Depending on the input type, use the appropriate OGR routine
       
   418         # to perform the transformation.
   366         if isinstance(coord_trans, CoordTransform):
   419         if isinstance(coord_trans, CoordTransform):
   367             capi.geom_transform(self.ptr, coord_trans.ptr)
   420             capi.geom_transform(self.ptr, coord_trans.ptr)
   368         elif isinstance(coord_trans, SpatialReference):
   421         elif isinstance(coord_trans, SpatialReference):
   369             capi.geom_transform_to(self.ptr, coord_trans.ptr)
   422             capi.geom_transform_to(self.ptr, coord_trans.ptr)
   370         elif isinstance(coord_trans, (int, long, basestring)):
   423         elif isinstance(coord_trans, (int, long, basestring)):
   371             sr = SpatialReference(coord_trans)
   424             sr = SpatialReference(coord_trans)
   372             capi.geom_transform_to(self.ptr, sr.ptr)
   425             capi.geom_transform_to(self.ptr, sr.ptr)
   373         else:
   426         else:
   374             raise TypeError('Transform only accepts CoordTransform, SpatialReference, string, and integer objects.')
   427             raise TypeError('Transform only accepts CoordTransform, '
       
   428                             'SpatialReference, string, and integer objects.')
       
   429 
       
   430         # Setting with original dimension, see comment above.
       
   431         if GDAL_VERSION < (1, 7):
       
   432             if isinstance(self, GeometryCollection):
       
   433                 # With geometry collections have to set dimension on
       
   434                 # each internal geometry reference, as the collection
       
   435                 # dimension isn't affected.
       
   436                 for i in xrange(len(self)):
       
   437                     internal_ptr = capi.get_geom_ref(self.ptr, i)
       
   438                     if orig_dim != capi.get_coord_dim(internal_ptr):
       
   439                         capi.set_coord_dim(internal_ptr, orig_dim)
       
   440             else:
       
   441                 if self.coord_dim != orig_dim:
       
   442                     self.coord_dim = orig_dim
   375 
   443 
   376     def transform_to(self, srs):
   444     def transform_to(self, srs):
   377         "For backwards-compatibility."
   445         "For backwards-compatibility."
   378         self.transform(srs)
   446         self.transform(srs)
   379 
   447 
   389         return func(self.ptr, other.ptr)
   457         return func(self.ptr, other.ptr)
   390 
   458 
   391     def intersects(self, other):
   459     def intersects(self, other):
   392         "Returns True if this geometry intersects with the other."
   460         "Returns True if this geometry intersects with the other."
   393         return self._topology(capi.ogr_intersects, other)
   461         return self._topology(capi.ogr_intersects, other)
   394     
   462 
   395     def equals(self, other):
   463     def equals(self, other):
   396         "Returns True if this geometry is equivalent to the other."
   464         "Returns True if this geometry is equivalent to the other."
   397         return self._topology(capi.ogr_equals, other)
   465         return self._topology(capi.ogr_equals, other)
   398 
   466 
   399     def disjoint(self, other):
   467     def disjoint(self, other):
   434         return self._geomgen(capi.get_boundary)
   502         return self._geomgen(capi.get_boundary)
   435 
   503 
   436     @property
   504     @property
   437     def convex_hull(self):
   505     def convex_hull(self):
   438         """
   506         """
   439         Returns the smallest convex Polygon that contains all the points in 
   507         Returns the smallest convex Polygon that contains all the points in
   440         this Geometry.
   508         this Geometry.
   441         """
   509         """
   442         return self._geomgen(capi.geom_convex_hull)
   510         return self._geomgen(capi.geom_convex_hull)
   443 
   511 
   444     def difference(self, other):
   512     def difference(self, other):
   454         geometry and the other.
   522         geometry and the other.
   455         """
   523         """
   456         return self._geomgen(capi.geom_intersection, other)
   524         return self._geomgen(capi.geom_intersection, other)
   457 
   525 
   458     def sym_difference(self, other):
   526     def sym_difference(self, other):
   459         """                                                                                                                                                
   527         """
   460         Returns a new geometry which is the symmetric difference of this
   528         Returns a new geometry which is the symmetric difference of this
   461         geometry and the other.
   529         geometry and the other.
   462         """
   530         """
   463         return self._geomgen(capi.geom_sym_diff, other)
   531         return self._geomgen(capi.geom_sym_diff, other)
   464 
   532 
   543 
   611 
   544     @property
   612     @property
   545     def y(self):
   613     def y(self):
   546         "Returns the Y coordinates in a list."
   614         "Returns the Y coordinates in a list."
   547         return self._listarr(capi.gety)
   615         return self._listarr(capi.gety)
   548     
   616 
   549     @property
   617     @property
   550     def z(self):
   618     def z(self):
   551         "Returns the Z coordinates in a list."
   619         "Returns the Z coordinates in a list."
   552         if self.coord_dim == 3:
   620         if self.coord_dim == 3:
   553             return self._listarr(capi.getz)
   621             return self._listarr(capi.getz)
   608         "Gets the Geometry at the specified index."
   676         "Gets the Geometry at the specified index."
   609         if index < 0 or index >= self.geom_count:
   677         if index < 0 or index >= self.geom_count:
   610             raise OGRIndexError('index out of range: %s' % index)
   678             raise OGRIndexError('index out of range: %s' % index)
   611         else:
   679         else:
   612             return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
   680             return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
   613         
   681 
   614     def __iter__(self):
   682     def __iter__(self):
   615         "Iterates over each Geometry."
   683         "Iterates over each Geometry."
   616         for i in xrange(self.geom_count):
   684         for i in xrange(self.geom_count):
   617             yield self[i]
   685             yield self[i]
   618 
   686 
   656                3 : Polygon,
   724                3 : Polygon,
   657                4 : MultiPoint,
   725                4 : MultiPoint,
   658                5 : MultiLineString,
   726                5 : MultiLineString,
   659                6 : MultiPolygon,
   727                6 : MultiPolygon,
   660                7 : GeometryCollection,
   728                7 : GeometryCollection,
   661                101: LinearRing, 
   729                101: LinearRing,
       
   730                1 + OGRGeomType.wkb25bit : Point,
       
   731                2 + OGRGeomType.wkb25bit : LineString,
       
   732                3 + OGRGeomType.wkb25bit : Polygon,
       
   733                4 + OGRGeomType.wkb25bit : MultiPoint,
       
   734                5 + OGRGeomType.wkb25bit : MultiLineString,
       
   735                6 + OGRGeomType.wkb25bit : MultiPolygon,
       
   736                7 + OGRGeomType.wkb25bit : GeometryCollection,
   662                }
   737                }