Loading django/contrib/gis/geos/geometry.py +39 −7 Original line number Diff line number Diff line Loading @@ -357,26 +357,42 @@ class GEOSGeometry(GEOSBase, ListMixin): #### 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): """ Loading @@ -391,9 +407,25 @@ class GEOSGeometry(GEOSBase, ListMixin): @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." Loading Loading @@ -617,7 +649,7 @@ GEOS_CLASSES = {0 : Point, } # 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: Loading django/contrib/gis/geos/io.py +17 −10 Original line number Diff line number Diff line Loading @@ -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): Loading @@ -39,8 +39,8 @@ class WKTReader(_WKTReader): 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): Loading @@ -51,8 +51,8 @@ class WKTWriter(IOBase): # 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): Loading @@ -71,8 +71,8 @@ class WKBReader(_WKBReader): 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): Loading Loading @@ -121,3 +121,10 @@ wkt_r = _WKTReader() 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 django/contrib/gis/geos/prototypes/geom.py +2 −3 Original line number Diff line number Diff line Loading @@ -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) Loading django/contrib/gis/geos/tests/test_geos.py +25 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,31 @@ class GEOSTest(unittest.TestCase): 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: Loading django/contrib/gis/tests/geometries.py +7 −0 Original line number Diff line number Diff line Loading @@ -171,3 +171,10 @@ json_geoms = (TestGeom('POINT(100 0)', json='{ "type": "Point", "coordinates": [ 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' Loading
django/contrib/gis/geos/geometry.py +39 −7 Original line number Diff line number Diff line Loading @@ -357,26 +357,42 @@ class GEOSGeometry(GEOSBase, ListMixin): #### 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): """ Loading @@ -391,9 +407,25 @@ class GEOSGeometry(GEOSBase, ListMixin): @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." Loading Loading @@ -617,7 +649,7 @@ GEOS_CLASSES = {0 : Point, } # 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: Loading
django/contrib/gis/geos/io.py +17 −10 Original line number Diff line number Diff line Loading @@ -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): Loading @@ -39,8 +39,8 @@ class WKTReader(_WKTReader): 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): Loading @@ -51,8 +51,8 @@ class WKTWriter(IOBase): # 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): Loading @@ -71,8 +71,8 @@ class WKBReader(_WKBReader): 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): Loading Loading @@ -121,3 +121,10 @@ wkt_r = _WKTReader() 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
django/contrib/gis/geos/prototypes/geom.py +2 −3 Original line number Diff line number Diff line Loading @@ -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) Loading
django/contrib/gis/geos/tests/test_geos.py +25 −0 Original line number Diff line number Diff line Loading @@ -71,6 +71,31 @@ class GEOSTest(unittest.TestCase): 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: Loading
django/contrib/gis/tests/geometries.py +7 −0 Original line number Diff line number Diff line Loading @@ -171,3 +171,10 @@ json_geoms = (TestGeom('POINT(100 0)', json='{ "type": "Point", "coordinates": [ 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'