diff -r b758351d191f -r cc9b7e14412b web/lib/django/contrib/gis/geos/geometry.py --- a/web/lib/django/contrib/gis/geos/geometry.py Wed May 19 17:43:59 2010 +0200 +++ b/web/lib/django/contrib/gis/geos/geometry.py Tue May 25 02:43:45 2010 +0200 @@ -21,11 +21,12 @@ # the underlying GEOS library. from django.contrib.gis.geos import prototypes as capi -# Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure -# to prevent potentially malicious input from reaching the underlying C -# library. Not a substitute for good web security programming practices. -hex_regex = re.compile(r'^[0-9A-F]+$', re.I) -wkt_regex = re.compile(r'^(SRID=(?P\d+);)?(?P(POINT|LINESTRING|LINEARRING|POLYGON|MULTIPOINT|MULTILINESTRING|MULTIPOLYGON|GEOMETRYCOLLECTION)[ACEGIMLONPSRUTY\d,\.\-\(\) ]+)$', re.I) +# These functions provide access to a thread-local instance +# of their corresponding GEOS I/O class. +from django.contrib.gis.geos.prototypes.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d + +# For recognizing geometry input. +from django.contrib.gis.geometry.regex import hex_regex, wkt_regex, json_regex class GEOSGeometry(GEOSBase, ListMixin): "A class that, generally, encapsulates a GEOS geometry." @@ -61,13 +62,13 @@ if wkt_m: # Handling WKT input. if wkt_m.group('srid'): srid = int(wkt_m.group('srid')) - g = wkt_r.read(wkt_m.group('wkt')) + g = wkt_r().read(wkt_m.group('wkt')) elif hex_regex.match(geo_input): # Handling HEXEWKB input. - g = wkb_r.read(geo_input) - elif gdal.GEOJSON and gdal.geometries.json_regex.match(geo_input): + g = wkb_r().read(geo_input) + elif gdal.GEOJSON and json_regex.match(geo_input): # Handling GeoJSON input. - g = wkb_r.read(gdal.OGRGeometry(geo_input).wkb) + g = wkb_r().read(gdal.OGRGeometry(geo_input).wkb) else: raise ValueError('String or unicode input unrecognized as WKT EWKT, and HEXEWKB.') elif isinstance(geo_input, GEOM_PTR): @@ -75,7 +76,7 @@ g = geo_input elif isinstance(geo_input, buffer): # When the input is a buffer (WKB). - g = wkb_r.read(geo_input) + g = wkb_r().read(geo_input) elif isinstance(geo_input, GEOSGeometry): g = capi.geom_clone(geo_input.ptr) else: @@ -142,7 +143,7 @@ def __setstate__(self, state): # Instantiating from the tuple state that was pickled. wkb, srid = state - ptr = capi.from_wkb(wkb, len(wkb)) + ptr = wkb_r().read(buffer(wkb)) if not ptr: raise GEOSException('Invalid Geometry loaded from pickled state.') self.ptr = ptr self._post_init(srid) @@ -357,25 +358,45 @@ #### Output Routines #### @property def ewkt(self): - "Returns the EWKT (WKT + SRID) of the Geometry." + """ + Returns the EWKT (WKT + SRID) of the Geometry. Note that Z values + are *not* included in this representation because GEOS does not yet + support serializing them. + """ if self.get_srid(): return 'SRID=%s;%s' % (self.srid, self.wkt) else: return self.wkt @property def wkt(self): - "Returns the WKT (Well-Known Text) of the Geometry." - return wkt_w.write(self) + "Returns the WKT (Well-Known Text) representation of this Geometry." + return wkt_w().write(self) @property def hex(self): """ - Returns the HEX of the Geometry -- please note that the SRID is not - included in this representation, because the GEOS C library uses - -1 by default, even if the SRID is set. + Returns the WKB of this Geometry in hexadecimal form. Please note + that the SRID and Z values are not included in this representation + because it is not a part of the OGC specification (use the `hexewkb` + property instead). """ # A possible faster, all-python, implementation: # str(self.wkb).encode('hex') - return wkb_w.write_hex(self) + return wkb_w().write_hex(self) + + @property + def hexewkb(self): + """ + Returns the EWKB of this Geometry in hexadecimal form. This is an + extension of the WKB specification that includes SRID and Z values + that are a part of this geometry. + """ + if self.hasz: + if not GEOS_PREPARE: + # See: http://trac.osgeo.org/geos/ticket/216 + raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D HEXEWKB.') + return ewkb_w3d().write_hex(self) + else: + return ewkb_w().write_hex(self) @property def json(self): @@ -383,7 +404,7 @@ Returns GeoJSON representation of this Geometry if GDAL 1.5+ is installed. """ - if gdal.GEOJSON: + if gdal.GEOJSON: return self.ogr.json else: raise GEOSException('GeoJSON output only supported on GDAL 1.5+.') @@ -391,8 +412,27 @@ @property def wkb(self): - "Returns the WKB of the Geometry as a buffer." - return wkb_w.write(self) + """ + Returns the WKB (Well-Known Binary) representation of this Geometry + as a Python buffer. SRID and Z values are not included, use the + `ewkb` property instead. + """ + return wkb_w().write(self) + + @property + def ewkb(self): + """ + Return the EWKB representation of this Geometry as a Python buffer. + This is an extension of the WKB specification that includes any SRID + and Z values that are a part of this geometry. + """ + if self.hasz: + if not GEOS_PREPARE: + # See: http://trac.osgeo.org/geos/ticket/216 + raise GEOSException('Upgrade GEOS to 3.1 to get valid 3D EWKB.') + return ewkb_w3d().write(self) + else: + return ewkb_w().write(self) @property def kml(self): @@ -454,7 +494,7 @@ g = gdal.OGRGeometry(self.wkb, srid) g.transform(ct) # Getting a new GEOS pointer - ptr = wkb_r.read(g.wkb) + ptr = wkb_r().read(g.wkb) if clone: # User wants a cloned transformed geometry returned. return GEOSGeometry(ptr, srid=g.srid) @@ -616,9 +656,6 @@ 7 : GeometryCollection, } -# Similarly, import the GEOS I/O instances here to avoid conflicts. -from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w - # If supported, import the PreparedGeometry class. if GEOS_PREPARE: from django.contrib.gis.geos.prepared import PreparedGeometry