1 """ |
1 """ |
2 Module that holds classes for performing I/O operations on GEOS geometry |
2 Module that holds classes for performing I/O operations on GEOS geometry |
3 objects. Specifically, this has Python implementations of WKB/WKT |
3 objects. Specifically, this has Python implementations of WKB/WKT |
4 reader and writer classes. |
4 reader and writer classes. |
5 """ |
5 """ |
6 from ctypes import byref, c_size_t |
|
7 from django.contrib.gis.geos.base import GEOSBase |
|
8 from django.contrib.gis.geos.error import GEOSException |
|
9 from django.contrib.gis.geos.geometry import GEOSGeometry |
6 from django.contrib.gis.geos.geometry import GEOSGeometry |
10 from django.contrib.gis.geos.libgeos import GEOM_PTR |
7 from django.contrib.gis.geos.prototypes.io import _WKTReader, _WKBReader, WKBWriter, WKTWriter |
11 from django.contrib.gis.geos.prototypes import io as capi |
|
12 |
8 |
13 class IOBase(GEOSBase): |
9 # Public classes for (WKB|WKT)Reader, which return GEOSGeometry |
14 "Base class for GEOS I/O objects." |
10 class WKBReader(_WKBReader): |
15 def __init__(self): |
11 def read(self, wkb): |
16 # Getting the pointer with the constructor. |
12 "Returns a GEOSGeometry for the given WKB buffer." |
17 self.ptr = self.constructor() |
13 return GEOSGeometry(super(WKBReader, self).read(wkb)) |
18 |
|
19 def __del__(self): |
|
20 # Cleaning up with the appropriate destructor. |
|
21 if self._ptr: self.destructor(self._ptr) |
|
22 |
|
23 ### WKT Reading and Writing objects ### |
|
24 |
|
25 # Non-public class for internal use because its `read` method returns |
|
26 # _pointers_ instead of a GEOSGeometry object. |
|
27 class _WKTReader(IOBase): |
|
28 constructor = capi.wkt_reader_create |
|
29 destructor = capi.wkt_reader_destroy |
|
30 ptr_type = capi.WKT_READ_PTR |
|
31 |
|
32 def read(self, wkt): |
|
33 if not isinstance(wkt, basestring): raise TypeError |
|
34 return capi.wkt_reader_read(self.ptr, wkt) |
|
35 |
14 |
36 class WKTReader(_WKTReader): |
15 class WKTReader(_WKTReader): |
37 def read(self, wkt): |
16 def read(self, wkt): |
38 "Returns a GEOSGeometry for the given WKT string." |
17 "Returns a GEOSGeometry for the given WKT string." |
39 return GEOSGeometry(super(WKTReader, self).read(wkt)) |
18 return GEOSGeometry(super(WKTReader, self).read(wkt)) |
40 |
19 |
41 class WKTWriter(IOBase): |
|
42 constructor = capi.wkt_writer_create |
|
43 destructor = capi.wkt_writer_destroy |
|
44 ptr_type = capi.WKT_WRITE_PTR |
|
45 |
20 |
46 def write(self, geom): |
|
47 "Returns the WKT representation of the given geometry." |
|
48 return capi.wkt_writer_write(self.ptr, geom.ptr) |
|
49 |
|
50 ### WKB Reading and Writing objects ### |
|
51 |
|
52 # Non-public class for the same reason as _WKTReader above. |
|
53 class _WKBReader(IOBase): |
|
54 constructor = capi.wkb_reader_create |
|
55 destructor = capi.wkb_reader_destroy |
|
56 ptr_type = capi.WKB_READ_PTR |
|
57 |
|
58 def read(self, wkb): |
|
59 "Returns a _pointer_ to C GEOS Geometry object from the given WKB." |
|
60 if isinstance(wkb, buffer): |
|
61 wkb_s = str(wkb) |
|
62 return capi.wkb_reader_read(self.ptr, wkb_s, len(wkb_s)) |
|
63 elif isinstance(wkb, basestring): |
|
64 return capi.wkb_reader_read_hex(self.ptr, wkb, len(wkb)) |
|
65 else: |
|
66 raise TypeError |
|
67 |
|
68 class WKBReader(_WKBReader): |
|
69 def read(self, wkb): |
|
70 "Returns a GEOSGeometry for the given WKB buffer." |
|
71 return GEOSGeometry(super(WKBReader, self).read(wkb)) |
|
72 |
|
73 class WKBWriter(IOBase): |
|
74 constructor = capi.wkb_writer_create |
|
75 destructor = capi.wkb_writer_destroy |
|
76 ptr_type = capi.WKB_WRITE_PTR |
|
77 |
|
78 def write(self, geom): |
|
79 "Returns the WKB representation of the given geometry." |
|
80 return buffer(capi.wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t()))) |
|
81 |
|
82 def write_hex(self, geom): |
|
83 "Returns the HEXEWKB representation of the given geometry." |
|
84 return capi.wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t())) |
|
85 |
|
86 ### WKBWriter Properties ### |
|
87 |
|
88 # Property for getting/setting the byteorder. |
|
89 def _get_byteorder(self): |
|
90 return capi.wkb_writer_get_byteorder(self.ptr) |
|
91 |
|
92 def _set_byteorder(self, order): |
|
93 if not order in (0, 1): raise ValueError('Byte order parameter must be 0 (Big Endian) or 1 (Little Endian).') |
|
94 capi.wkb_writer_set_byteorder(self.ptr, order) |
|
95 |
|
96 byteorder = property(_get_byteorder, _set_byteorder) |
|
97 |
|
98 # Property for getting/setting the output dimension. |
|
99 def _get_outdim(self): |
|
100 return capi.wkb_writer_get_outdim(self.ptr) |
|
101 |
|
102 def _set_outdim(self, new_dim): |
|
103 if not new_dim in (2, 3): raise ValueError('WKB output dimension must be 2 or 3') |
|
104 capi.wkb_writer_set_outdim(self.ptr, new_dim) |
|
105 |
|
106 outdim = property(_get_outdim, _set_outdim) |
|
107 |
|
108 # Property for getting/setting the include srid flag. |
|
109 def _get_include_srid(self): |
|
110 return bool(ord(capi.wkb_writer_get_include_srid(self.ptr))) |
|
111 |
|
112 def _set_include_srid(self, include): |
|
113 if bool(include): flag = chr(1) |
|
114 else: flag = chr(0) |
|
115 capi.wkb_writer_set_include_srid(self.ptr, flag) |
|
116 |
|
117 srid = property(_get_include_srid, _set_include_srid) |
|
118 |
|
119 # Instances of the WKT and WKB reader/writer objects. |
|
120 wkt_r = _WKTReader() |
|
121 wkt_w = WKTWriter() |
|
122 wkb_r = _WKBReader() |
|
123 wkb_w = WKBWriter() |
|