Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

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
Justin Bronn authored November 10, 2009
46  django/contrib/gis/geos/geometry.py
@@ -357,33 +357,49 @@ def set_srid(self, srid):
357 357
     #### Output Routines ####
358 358
     @property
359 359
     def ewkt(self):
360  
-        "Returns the EWKT (WKT + SRID) of the Geometry."
  360
+        """
  361
+        Returns the EWKT (WKT + SRID) of the Geometry.  Note that Z values
  362
+        are *not* included in this representation because GEOS does not yet
  363
+        support serializing them.
  364
+        """
361 365
         if self.get_srid(): return 'SRID=%s;%s' % (self.srid, self.wkt)
362 366
         else: return self.wkt
363 367
 
364 368
     @property
365 369
     def wkt(self):
366  
-        "Returns the WKT (Well-Known Text) of the Geometry."
  370
+        "Returns the WKT (Well-Known Text) representation of this Geometry."
367 371
         return wkt_w.write(self)
368 372
 
369 373
     @property
370 374
     def hex(self):
371 375
         """
372 376
         Returns the HEX of the Geometry -- please note that the SRID is not
373  
-        included in this representation, because the GEOS C library uses
374  
-        -1 by default, even if the SRID is set.
  377
+        included in this representation, because it is not a part of the
  378
+        OGC specification (use the `hexewkb` property instead).
375 379
         """
376 380
         # A possible faster, all-python, implementation:
377 381
         #  str(self.wkb).encode('hex')
378 382
         return wkb_w.write_hex(self)
379 383
 
380 384
     @property
  385
+    def hexewkb(self):
  386
+        """
  387
+        Returns the HEXEWKB of this Geometry.  This is an extension of the WKB
  388
+        specification that includes SRID and Z values taht are a part of this
  389
+        geometry.
  390
+        """
  391
+        if self.hasz:
  392
+            return ewkb_w3d.write_hex(self)
  393
+        else:
  394
+            return ewkb_w.write_hex(self)
  395
+
  396
+    @property
381 397
     def json(self):
382 398
         """
383 399
         Returns GeoJSON representation of this Geometry if GDAL 1.5+
384 400
         is installed.
385 401
         """
386  
-        if gdal.GEOJSON: 
  402
+        if gdal.GEOJSON:
387 403
             return self.ogr.json
388 404
         else:
389 405
             raise GEOSException('GeoJSON output only supported on GDAL 1.5+.')
@@ -391,10 +407,26 @@ def json(self):
391 407
 
392 408
     @property
393 409
     def wkb(self):
394  
-        "Returns the WKB of the Geometry as a buffer."
  410
+        """
  411
+        Returns the WKB (Well-Known Binary) representation of this Geometry
  412
+        as a Python buffer.  SRID and Z values are not included, use the
  413
+        `ewkb` property instead.
  414
+        """
395 415
         return wkb_w.write(self)
396 416
 
397 417
     @property
  418
+    def ewkb(self):
  419
+        """
  420
+        Return the EWKB representation of this Geometry as a Python buffer.
  421
+        This is an extension of the WKB specification that includes any SRID
  422
+        and Z values that are a part of this geometry.
  423
+        """
  424
+        if self.hasz:
  425
+            return ewkb_w3d.write(self)
  426
+        else:
  427
+            return ewkb_w.write(self)
  428
+
  429
+    @property
398 430
     def kml(self):
399 431
         "Returns the KML representation of this Geometry."
400 432
         gtype = self.geom_type
@@ -617,7 +649,7 @@ def clone(self):
617 649
                 }
618 650
 
619 651
 # Similarly, import the GEOS I/O instances here to avoid conflicts.
620  
-from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w
  652
+from django.contrib.gis.geos.io import wkt_r, wkt_w, wkb_r, wkb_w, ewkb_w, ewkb_w3d
621 653
 
622 654
 # If supported, import the PreparedGeometry class.
623 655
 if GEOS_PREPARE:
27  django/contrib/gis/geos/io.py
@@ -14,19 +14,19 @@ class IOBase(GEOSBase):
14 14
     "Base class for GEOS I/O objects."
15 15
     def __init__(self):
16 16
         # Getting the pointer with the constructor.
17  
-        self.ptr = self.constructor()
  17
+        self.ptr = self._constructor()
18 18
 
19 19
     def __del__(self):
20 20
         # Cleaning up with the appropriate destructor.
21  
-        if self._ptr: self.destructor(self._ptr)
  21
+        if self._ptr: self._destructor(self._ptr)
22 22
 
23 23
 ### WKT Reading and Writing objects ###
24 24
 
25 25
 # Non-public class for internal use because its `read` method returns
26 26
 # _pointers_ instead of a GEOSGeometry object.
27 27
 class _WKTReader(IOBase):
28  
-    constructor = capi.wkt_reader_create
29  
-    destructor = capi.wkt_reader_destroy
  28
+    _constructor = capi.wkt_reader_create
  29
+    _destructor = capi.wkt_reader_destroy
30 30
     ptr_type = capi.WKT_READ_PTR
31 31
 
32 32
     def read(self, wkt):
@@ -39,8 +39,8 @@ def read(self, wkt):
39 39
         return GEOSGeometry(super(WKTReader, self).read(wkt))
40 40
 
41 41
 class WKTWriter(IOBase):
42  
-    constructor = capi.wkt_writer_create
43  
-    destructor = capi.wkt_writer_destroy
  42
+    _constructor = capi.wkt_writer_create
  43
+    _destructor = capi.wkt_writer_destroy
44 44
     ptr_type = capi.WKT_WRITE_PTR
45 45
 
46 46
     def write(self, geom):
@@ -51,8 +51,8 @@ def write(self, geom):
51 51
 
52 52
 # Non-public class for the same reason as _WKTReader above.
53 53
 class _WKBReader(IOBase):
54  
-    constructor = capi.wkb_reader_create
55  
-    destructor = capi.wkb_reader_destroy
  54
+    _constructor = capi.wkb_reader_create
  55
+    _destructor = capi.wkb_reader_destroy
56 56
     ptr_type = capi.WKB_READ_PTR
57 57
 
58 58
     def read(self, wkb):
@@ -71,8 +71,8 @@ def read(self, wkb):
71 71
         return GEOSGeometry(super(WKBReader, self).read(wkb))
72 72
 
73 73
 class WKBWriter(IOBase):
74  
-    constructor = capi.wkb_writer_create
75  
-    destructor = capi.wkb_writer_destroy
  74
+    _constructor = capi.wkb_writer_create
  75
+    _destructor = capi.wkb_writer_destroy
76 76
     ptr_type = capi.WKB_WRITE_PTR
77 77
 
78 78
     def write(self, geom):
@@ -121,3 +121,10 @@ def _set_include_srid(self, include):
121 121
 wkt_w = WKTWriter()
122 122
 wkb_r = _WKBReader()
123 123
 wkb_w = WKBWriter()
  124
+
  125
+# These instances are for writing EWKB in 2D and 3D.
  126
+ewkb_w = WKBWriter()
  127
+ewkb_w.srid = True
  128
+ewkb_w3d = WKBWriter()
  129
+ewkb_w3d.srid = True
  130
+ewkb_w3d.outdim = 3
5  django/contrib/gis/geos/prototypes/geom.py
@@ -62,17 +62,16 @@ def string_from_geom(func):
62 62
 
63 63
 ### ctypes prototypes ###
64 64
 
65  
-# Deprecated creation routines from WKB, HEX, WKT
  65
+# Deprecated creation and output routines from WKB, HEX, WKT
66 66
 from_hex = bin_constructor(lgeos.GEOSGeomFromHEX_buf)
67 67
 from_wkb = bin_constructor(lgeos.GEOSGeomFromWKB_buf)
68 68
 from_wkt = geom_output(lgeos.GEOSGeomFromWKT, [c_char_p])
69 69
 
70  
-# Output routines
71 70
 to_hex = bin_output(lgeos.GEOSGeomToHEX_buf)
72 71
 to_wkb = bin_output(lgeos.GEOSGeomToWKB_buf)
73 72
 to_wkt = string_from_geom(lgeos.GEOSGeomToWKT)
74 73
 
75  
-# The GEOS geometry type, typeid, num_coordites and number of geometries
  74
+# The GEOS geometry type, typeid, num_coordinates and number of geometries
76 75
 geos_normalize = int_from_geom(lgeos.GEOSNormalize)
77 76
 geos_type = string_from_geom(lgeos.GEOSGeomType)
78 77
 geos_typeid = int_from_geom(lgeos.GEOSGeomTypeId)
25  django/contrib/gis/geos/tests/test_geos.py
@@ -71,6 +71,31 @@ def test01b_hex(self):
71 71
             geom = fromstr(g.wkt)
72 72
             self.assertEqual(g.hex, geom.hex)
73 73
 
  74
+    def test01b_hexewkb(self):
  75
+        "Testing (HEX)EWKB output."
  76
+        from binascii import a2b_hex
  77
+
  78
+        pnt_2d = Point(0, 1, srid=4326)
  79
+        pnt_3d = Point(0, 1, 2, srid=4326)
  80
+        
  81
+        # OGC-compliant HEX will not have SRID nor Z value.
  82
+        self.assertEqual(ogc_hex, pnt_2d.hex)
  83
+        self.assertEqual(ogc_hex, pnt_3d.hex)
  84
+
  85
+        # HEXEWKB should be appropriate for its dimension -- have to use an
  86
+        # a WKBWriter w/dimension set accordingly, else GEOS will insert
  87
+        # garbage into 3D coordinate if there is none.
  88
+        self.assertEqual(hexewkb_2d, pnt_2d.hexewkb)
  89
+        self.assertEqual(hexewkb_3d, pnt_3d.hexewkb)
  90
+
  91
+        # Same for EWKB.
  92
+        self.assertEqual(buffer(a2b_hex(hexewkb_2d)), pnt_2d.ewkb)
  93
+        self.assertEqual(buffer(a2b_hex(hexewkb_3d)), pnt_3d.ewkb)
  94
+        
  95
+        # Redundant sanity check.
  96
+        self.assertEqual(True, GEOSGeometry(hexewkb_3d).hasz)
  97
+        self.assertEqual(4326, GEOSGeometry(hexewkb_2d).srid)
  98
+
74 99
     def test01c_kml(self):
75 100
         "Testing KML output."
76 101
         for tg in wkt_out:
7  django/contrib/gis/tests/geometries.py
@@ -171,3 +171,10 @@ def __init__(self, wkt, **kwargs):
171 171
                        not_equal=True,
172 172
                        ),
173 173
               )
  174
+
  175
+# For testing HEX(EWKB).
  176
+ogc_hex = '01010000000000000000000000000000000000F03F'
  177
+# `SELECT ST_AsHEXEWKB(ST_GeomFromText('POINT(0 1)', 4326));`
  178
+hexewkb_2d = '0101000020E61000000000000000000000000000000000F03F'
  179
+# `SELECT ST_AsHEXEWKB(ST_GeomFromEWKT('SRID=4326;POINT(0 1 2)'));`
  180
+hexewkb_3d = '01010000A0E61000000000000000000000000000000000F03F0000000000000040'

0 notes on commit 36fe303

Please sign in to comment.
Something went wrong with that request. Please try again.