|
0
|
1 |
""" |
|
|
2 |
Module that holds classes for performing I/O operations on GEOS geometry |
|
|
3 |
objects. Specifically, this has Python implementations of WKB/WKT |
|
|
4 |
reader and writer classes. |
|
|
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 |
|
|
10 |
from django.contrib.gis.geos.libgeos import GEOM_PTR |
|
|
11 |
from django.contrib.gis.geos.prototypes import io as capi |
|
|
12 |
|
|
|
13 |
class IOBase(GEOSBase): |
|
|
14 |
"Base class for GEOS I/O objects." |
|
|
15 |
def __init__(self): |
|
|
16 |
# Getting the pointer with the constructor. |
|
|
17 |
self.ptr = self.constructor() |
|
|
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 |
|
|
|
36 |
class WKTReader(_WKTReader): |
|
|
37 |
def read(self, wkt): |
|
|
38 |
"Returns a GEOSGeometry for the given WKT string." |
|
|
39 |
return GEOSGeometry(super(WKTReader, self).read(wkt)) |
|
|
40 |
|
|
|
41 |
class WKTWriter(IOBase): |
|
|
42 |
constructor = capi.wkt_writer_create |
|
|
43 |
destructor = capi.wkt_writer_destroy |
|
|
44 |
ptr_type = capi.WKT_WRITE_PTR |
|
|
45 |
|
|
|
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() |