Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added `ewkb` and `hexewkb` properties to `GEOSGeometry`. Refs #11433,…

… #12010.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11728 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 36fe303e359bcb33a54d8a5fc8dea8b26df96c70 1 parent f3bb527
@jbronn jbronn authored
View
46 django/contrib/gis/geos/geometry.py
@@ -357,33 +357,49 @@ def set_srid(self, srid):
#### 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."
+ "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.
+ 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)
@property
+ def hexewkb(self):
+ """
+ Returns the HEXEWKB of this Geometry. This is an extension of the WKB
+ specification that includes SRID and Z values taht are a part of this
+ geometry.
+ """
+ if self.hasz:
+ return ewkb_w3d.write_hex(self)
+ else:
+ return ewkb_w.write_hex(self)
+
+ @property
def json(self):
"""
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,10 +407,26 @@ def json(self):
@property
def wkb(self):
- "Returns the WKB of the Geometry as a buffer."
+ """
+ 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:
+ return ewkb_w3d.write(self)
+ else:
+ return ewkb_w.write(self)
+
+ @property
def kml(self):
"Returns the KML representation of this Geometry."
gtype = self.geom_type
@@ -617,7 +649,7 @@ def clone(self):
}
# 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
+from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d
# If supported, import the PreparedGeometry class.
if GEOS_PREPARE:
View
27 django/contrib/gis/geos/io.py
@@ -14,19 +14,19 @@ class IOBase(GEOSBase):
"Base class for GEOS I/O objects."
def __init__(self):
# Getting the pointer with the constructor.
- self.ptr = self.constructor()
+ self.ptr = self._constructor()
def __del__(self):
# Cleaning up with the appropriate destructor.
- if self._ptr: self.destructor(self._ptr)
+ if self._ptr: self._destructor(self._ptr)
### WKT Reading and Writing objects ###
# Non-public class for internal use because its `read` method returns
# _pointers_ instead of a GEOSGeometry object.
class _WKTReader(IOBase):
- constructor = capi.wkt_reader_create
- destructor = capi.wkt_reader_destroy
+ _constructor = capi.wkt_reader_create
+ _destructor = capi.wkt_reader_destroy
ptr_type = capi.WKT_READ_PTR
def read(self, wkt):
@@ -39,8 +39,8 @@ def read(self, wkt):
return GEOSGeometry(super(WKTReader, self).read(wkt))
class WKTWriter(IOBase):
- constructor = capi.wkt_writer_create
- destructor = capi.wkt_writer_destroy
+ _constructor = capi.wkt_writer_create
+ _destructor = capi.wkt_writer_destroy
ptr_type = capi.WKT_WRITE_PTR
def write(self, geom):
@@ -51,8 +51,8 @@ def write(self, geom):
# Non-public class for the same reason as _WKTReader above.
class _WKBReader(IOBase):
- constructor = capi.wkb_reader_create
- destructor = capi.wkb_reader_destroy
+ _constructor = capi.wkb_reader_create
+ _destructor = capi.wkb_reader_destroy
ptr_type = capi.WKB_READ_PTR
def read(self, wkb):
@@ -71,8 +71,8 @@ def read(self, wkb):
return GEOSGeometry(super(WKBReader, self).read(wkb))
class WKBWriter(IOBase):
- constructor = capi.wkb_writer_create
- destructor = capi.wkb_writer_destroy
+ _constructor = capi.wkb_writer_create
+ _destructor = capi.wkb_writer_destroy
ptr_type = capi.WKB_WRITE_PTR
def write(self, geom):
@@ -121,3 +121,10 @@ def _set_include_srid(self, include):
wkt_w = WKTWriter()
wkb_r = _WKBReader()
wkb_w = WKBWriter()
+
+# These instances are for writing EWKB in 2D and 3D.
+ewkb_w = WKBWriter()
+ewkb_w.srid = True
+ewkb_w3d = WKBWriter()
+ewkb_w3d.srid = True
+ewkb_w3d.outdim = 3
View
5 django/contrib/gis/geos/prototypes/geom.py
@@ -62,17 +62,16 @@ def string_from_geom(func):
### ctypes prototypes ###
-# Deprecated creation routines from WKB, HEX, WKT
+# Deprecated creation and output routines from WKB, HEX, WKT
from_hex = bin_constructor(lgeos.GEOSGeomFromHEX_buf)
from_wkb = bin_constructor(lgeos.GEOSGeomFromWKB_buf)
from_wkt = geom_output(lgeos.GEOSGeomFromWKT, [c_char_p])
-# Output routines
to_hex = bin_output(lgeos.GEOSGeomToHEX_buf)
to_wkb = bin_output(lgeos.GEOSGeomToWKB_buf)
to_wkt = string_from_geom(lgeos.GEOSGeomToWKT)
-# The GEOS geometry type, typeid, num_coordites and number of geometries
+# The GEOS geometry type, typeid, num_coordinates and number of geometries
geos_normalize = int_from_geom(lgeos.GEOSNormalize)
geos_type = string_from_geom(lgeos.GEOSGeomType)
geos_typeid = int_from_geom(lgeos.GEOSGeomTypeId)
View
25 django/contrib/gis/geos/tests/test_geos.py
@@ -71,6 +71,31 @@ def test01b_hex(self):
geom = fromstr(g.wkt)
self.assertEqual(g.hex, geom.hex)
+ def test01b_hexewkb(self):
+ "Testing (HEX)EWKB output."
+ from binascii import a2b_hex
+
+ pnt_2d = Point(0, 1, srid=4326)
+ pnt_3d = Point(0, 1, 2, srid=4326)
+
+ # OGC-compliant HEX will not have SRID nor Z value.
+ self.assertEqual(ogc_hex, pnt_2d.hex)
+ self.assertEqual(ogc_hex, pnt_3d.hex)
+
+ # HEXEWKB should be appropriate for its dimension -- have to use an
+ # a WKBWriter w/dimension set accordingly, else GEOS will insert
+ # garbage into 3D coordinate if there is none.
+ self.assertEqual(hexewkb_2d, pnt_2d.hexewkb)
+ self.assertEqual(hexewkb_3d, pnt_3d.hexewkb)
+
+ # Same for EWKB.
+ self.assertEqual(buffer(a2b_hex(hexewkb_2d)), pnt_2d.ewkb)
+ self.assertEqual(buffer(a2b_hex(hexewkb_3d)), pnt_3d.ewkb)
+
+ # Redundant sanity check.
+ self.assertEqual(True, GEOSGeometry(hexewkb_3d).hasz)
+ self.assertEqual(4326, GEOSGeometry(hexewkb_2d).srid)
+
def test01c_kml(self):
"Testing KML output."
for tg in wkt_out:
View
7 django/contrib/gis/tests/geometries.py
@@ -171,3 +171,10 @@ def __init__(self, wkt, **kwargs):
not_equal=True,
),
)
+
+# For testing HEX(EWKB).
+ogc_hex = '01010000000000000000000000000000000000F03F'
+# `SELECT ST_AsHEXEWKB(ST_GeomFromText('POINT(0 1)', 4326));`
+hexewkb_2d = '0101000020E61000000000000000000000000000000000F03F'
+# `SELECT ST_AsHEXEWKB(ST_GeomFromEWKT('SRID=4326;POINT(0 1 2)'));`
+hexewkb_3d = '01010000A0E61000000000000000000000000000000000F03F0000000000000040'
Please sign in to comment.
Something went wrong with that request. Please try again.