Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #16594 -- Added wkt 3D support for GEOS geometries

This requires GEOS >= 3.3.0 to function properly. On previous
versions, the Z dimension will simply not appear in the wkt.
Disabled OpenLayers editing for 3D geometries (unsupported).
  • Loading branch information...
commit 5e80571bf92d93c177bea9e5ee7d89153ecadbad 1 parent 8a92139
Claude Paroz authored September 21, 2012
5  django/contrib/gis/admin/options.py
@@ -51,9 +51,10 @@ def media(self):
51 51
     def formfield_for_dbfield(self, db_field, **kwargs):
52 52
         """
53 53
         Overloaded from ModelAdmin so that an OpenLayersWidget is used
54  
-        for viewing/editing GeometryFields.
  54
+        for viewing/editing 2D GeometryFields (OpenLayers 2 does not support
  55
+        3D editing).
55 56
         """
56  
-        if isinstance(db_field, models.GeometryField):
  57
+        if isinstance(db_field, models.GeometryField) and db_field.dim < 3:
57 58
             request = kwargs.pop('request', None)
58 59
             # Setting the widget with the newly defined widget.
59 60
             kwargs['widget'] = self.get_map_widget(db_field)
2  django/contrib/gis/geos/geometry.py
@@ -382,7 +382,7 @@ def ewkt(self):
382 382
     @property
383 383
     def wkt(self):
384 384
         "Returns the WKT (Well-Known Text) representation of this Geometry."
385  
-        return wkt_w().write(self).decode()
  385
+        return wkt_w(self.hasz and 3 or 2).write(self).decode()
386 386
 
387 387
     @property
388 388
     def hex(self):
26  django/contrib/gis/geos/prototypes/io.py
@@ -45,6 +45,18 @@ class WKBWriter_st(Structure): pass
45 45
 wkt_writer_write.restype = geos_char_p
46 46
 wkt_writer_write.errcheck = check_string
47 47
 
  48
+try:
  49
+    wkt_writer_get_outdim = GEOSFunc('GEOSWKTWriter_getOutputDimension')
  50
+    wkt_writer_get_outdim.argtypes = [WKT_WRITE_PTR]
  51
+    wkt_writer_get_outdim.restype = c_int
  52
+    wkt_writer_set_outdim = GEOSFunc('GEOSWKTWriter_setOutputDimension')
  53
+    wkt_writer_set_outdim.argtypes = [WKT_WRITE_PTR, c_int]
  54
+except AttributeError:
  55
+    # GEOSWKTWriter_get/setOutputDimension has been introduced in GEOS 3.3.0
  56
+    # Always return 2 if not available
  57
+    wkt_writer_get_outdim = lambda ptr: 2
  58
+    wkt_writer_set_outdim = lambda ptr, dim: None
  59
+
48 60
 ### WKBReader routines ###
49 61
 wkb_reader_create = GEOSFunc('GEOSWKBReader_create')
50 62
 wkb_reader_create.restype = WKB_READ_PTR
@@ -151,6 +163,17 @@ def write(self, geom):
151 163
         "Returns the WKT representation of the given geometry."
152 164
         return wkt_writer_write(self.ptr, geom.ptr)
153 165
 
  166
+    @property
  167
+    def outdim(self):
  168
+        return wkt_writer_get_outdim(self.ptr)
  169
+
  170
+    @outdim.setter
  171
+    def outdim(self, new_dim):
  172
+        if not new_dim in (2, 3):
  173
+            raise ValueError('WKT output dimension must be 2 or 3')
  174
+        wkt_writer_set_outdim(self.ptr, new_dim)
  175
+
  176
+
154 177
 class WKBWriter(IOBase):
155 178
     _constructor = wkb_writer_create
156 179
     _destructor = wkb_writer_destroy
@@ -217,9 +240,10 @@ def wkt_r():
217 240
         thread_context.wkt_r = _WKTReader()
218 241
     return thread_context.wkt_r
219 242
 
220  
-def wkt_w():
  243
+def wkt_w(dim=2):
221 244
     if not thread_context.wkt_w:
222 245
         thread_context.wkt_w = WKTWriter()
  246
+    thread_context.wkt_w.outdim = dim
223 247
     return thread_context.wkt_w
224 248
 
225 249
 def wkb_r():
3  django/contrib/gis/geos/tests/test_geos.py
@@ -80,7 +80,8 @@ def test_wkt(self):
80 80
         "Testing WKT output."
81 81
         for g in self.geometries.wkt_out:
82 82
             geom = fromstr(g.wkt)
83  
-            self.assertEqual(g.ewkt, geom.wkt)
  83
+            if geom.hasz and geos_version_info()['version'] >= '3.3.0':
  84
+                self.assertEqual(g.ewkt, geom.wkt)
84 85
 
85 86
     def test_hex(self):
86 87
         "Testing HEX output."
4  django/contrib/gis/tests/data/geometries.json
@@ -20,6 +20,7 @@
20 20
   ],
21 21
   "wkt_out": [
22 22
     {"wkt": "POINT (110 130)", "ewkt": "POINT (110.0000000000000000 130.0000000000000000)", "kml": "<Point><coordinates>110.0,130.0,0</coordinates></Point>", "gml": "<gml:Point><gml:coordinates>110,130</gml:coordinates></gml:Point>"},
  23
+    {"wkt": "POINT (110 130 85)", "ewkt": "POINT Z (110.0000000000000000 130.0000000000000000 85.0000000000000000)", "kml": "<Point><coordinates>110.0,130.0,85.0</coordinates></Point>", "gml": "<gml:Point><gml:coordinates>110,130,85</gml:coordinates></gml:Point>"},
23 24
     {"wkt": "LINESTRING (40 40,50 130,130 130)", "ewkt": "LINESTRING (40.0000000000000000 40.0000000000000000, 50.0000000000000000 130.0000000000000000, 130.0000000000000000 130.0000000000000000)", "kml": "<LineString><coordinates>40.0,40.0,0 50.0,130.0,0 130.0,130.0,0</coordinates></LineString>", "gml": "<gml:LineString><gml:coordinates>40,40 50,130 130,130</gml:coordinates></gml:LineString>"},
24 25
     {"wkt": "POLYGON ((150 150,410 150,280 20,20 20,150 150),(170 120,330 120,260 50,100 50,170 120))", "ewkt": "POLYGON ((150.0000000000000000 150.0000000000000000, 410.0000000000000000 150.0000000000000000, 280.0000000000000000 20.0000000000000000, 20.0000000000000000 20.0000000000000000, 150.0000000000000000 150.0000000000000000), (170.0000000000000000 120.0000000000000000, 330.0000000000000000 120.0000000000000000, 260.0000000000000000 50.0000000000000000, 100.0000000000000000 50.0000000000000000, 170.0000000000000000 120.0000000000000000))", "kml": "<Polygon><outerBoundaryIs><LinearRing><coordinates>150.0,150.0,0 410.0,150.0,0 280.0,20.0,0 20.0,20.0,0 150.0,150.0,0</coordinates></LinearRing></outerBoundaryIs><innerBoundaryIs><LinearRing><coordinates>170.0,120.0,0 330.0,120.0,0 260.0,50.0,0 100.0,50.0,0 170.0,120.0,0</coordinates></LinearRing></innerBoundaryIs></Polygon>", "gml": "<gml:Polygon><gml:outerBoundaryIs><gml:LinearRing><gml:coordinates>150,150 410,150 280,20 20,20 150,150</gml:coordinates></gml:LinearRing></gml:outerBoundaryIs><gml:innerBoundaryIs><gml:LinearRing><gml:coordinates>170,120 330,120 260,50 100,50 170,120</gml:coordinates></gml:LinearRing></gml:innerBoundaryIs></gml:Polygon>"},
25 26
     {"wkt": "MULTIPOINT (10 80,110 170,110 120)", "ewkt": "MULTIPOINT (10.0000000000000000 80.0000000000000000, 110.0000000000000000 170.0000000000000000, 110.0000000000000000 120.0000000000000000)", "kml": "<MultiGeometry><Point><coordinates>10.0,80.0,0</coordinates></Point><Point><coordinates>110.0,170.0,0</coordinates></Point><Point><coordinates>110.0,120.0,0</coordinates></Point></MultiGeometry>", "gml": "<gml:MultiPoint><gml:pointMember><gml:Point><gml:coordinates>10,80</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>110,170</gml:coordinates></gml:Point></gml:pointMember><gml:pointMember><gml:Point><gml:coordinates>110,120</gml:coordinates></gml:Point></gml:pointMember></gml:MultiPoint>"},
@@ -29,6 +30,7 @@
29 30
   ],
30 31
   "hex_wkt": [
31 32
     {"wkt": "POINT(0 1)", "hex": "01010000000000000000000000000000000000F03F"},
  33
+    {"wkt": "POINT(0 1 5)", "hex": "01010000800000000000000000000000000000F03F0000000000001440"},
32 34
     {"wkt": "LINESTRING(0 1, 2 3, 4 5)", "hex": "0102000000030000000000000000000000000000000000F03F0000000000000040000000000000084000000000000010400000000000001440"},
33 35
     {"wkt": "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))", "hex": "010300000001000000050000000000000000000000000000000000000000000000000024400000000000000000000000000000244000000000000024400000000000000000000000000000244000000000000000000000000000000000"},
34 36
     {"wkt": "MULTIPOINT(0 0, 10 0, 10 10, 0 10, 0 0)", "hex": "010400000005000000010100000000000000000000000000000000000000010100000000000000000024400000000000000000010100000000000000000024400000000000002440010100000000000000000000000000000000002440010100000000000000000000000000000000000000"},
@@ -118,4 +120,4 @@
118 120
       {"wkt": "POLYGON ((-5 0,-5 10,5 10,5 5,10 5,10 -5,0 -5,0 0,-5 0))"},
119 121
       {"wkt": "POLYGON ((2 0, 2 15, 18 15, 18 0, 2 0))"}
120 122
   ]
121  
-}
  123
+}

0 notes on commit 5e80571

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