shapely 1.0__py2.4.egg

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ """
2
+ Multi-part collection of polygons.
3
+ """
4
+
5
+ from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
6
+
7
+ from shapely.geos import lgeos
8
+ from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
+ from shapely.geometry.polygon import Polygon, geos_polygon_from_py
10
+
11
+
12
+ def geos_multipolygon_from_py(ob):
13
+ """ob must be either a sequence or array of sequences or arrays."""
14
+ L = len(ob)
15
+ N = len(ob[0][0][0])
16
+ assert L >= 1
17
+ assert N == 2 or N == 3
18
+
19
+ subs = (c_void_p * L)()
20
+ for l in xrange(L):
21
+ geom, ndims = geos_polygon_from_py(ob[l][0], ob[l][1])
22
+ subs[l] = cast(geom, c_void_p)
23
+
24
+ return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
25
+
26
+
27
+ class MultiPolygon(BaseGeometry):
28
+
29
+ """a multiple polygon geometry.
30
+ """
31
+
32
+ def __init__(self, polygons=None):
33
+ """Initialize.
34
+
35
+ Parameters
36
+ ----------
37
+
38
+ polygons : sequence
39
+ A sequence of (shell, holes) tuples where shell is the sequence
40
+ representation of a linear ring (see linearring.py) and holes is
41
+ a sequence of such linear rings.
42
+
43
+ Example
44
+ -------
45
+ >>> geom = MultiPolygon( [
46
+ ... (
47
+ ... ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0)),
48
+ ... [((0.1,0.1), (0.1,0.2), (0.2,0.2), (0.2,0.1))]
49
+ ... )
50
+ ... ] )
51
+ """
52
+ BaseGeometry.__init__(self)
53
+
54
+ if polygons is None:
55
+ # allow creation of null collections, to support unpickling
56
+ pass
57
+ else:
58
+ self._geom, self._ndim = geos_multipolygon_from_py(polygons)
59
+
60
+ @property
61
+ def __geo_interface__(self):
62
+ allcoords = []
63
+ for geom in self.geoms:
64
+ coords = []
65
+ coords.append(tuple(geom.exterior.coords))
66
+ for hole in geom.interiors:
67
+ coords.append(tuple(hole.coords))
68
+ allcoords.append(coords)
69
+ return {
70
+ 'type': 'MultiPolygon',
71
+ 'coordinates': allcoords
72
+ }
73
+
74
+ @property
75
+ def ctypes(self):
76
+ raise NotImplementedError, \
77
+ "Multi-part geometries have no ctypes representations"
78
+
79
+ @property
80
+ def __array_interface__(self):
81
+ """Provide the Numpy array protocol."""
82
+ raise NotImplementedError, \
83
+ "Multi-part geometries do not themselves provide the array interface"
84
+
85
+ @property
86
+ def coords(self):
87
+ raise NotImplementedError, \
88
+ "Multi-part geometries do not provide a coordinate sequence"
89
+
90
+ @property
91
+ @exceptNull
92
+ def geoms(self):
93
+ return GeometrySequence(self, Polygon)
94
+
95
+
96
+ class MultiPolygonAdapter(MultiPolygon):
97
+
98
+ """Adapts sequences of sequences or numpy arrays to the multipolygon
99
+ interface.
100
+ """
101
+
102
+ context = None
103
+ __geom = None
104
+ _owned = False
105
+
106
+ def __init__(self, context):
107
+ self.context = context
108
+
109
+ @property
110
+ def _ndim(self):
111
+ try:
112
+ # From array protocol
113
+ array = self.context[0][0].__array_interface__
114
+ n = array['shape'][1]
115
+ assert n == 2 or n == 3
116
+ return n
117
+ except AttributeError:
118
+ # Fall back on list
119
+ return len(self.context[0][0][0])
120
+
121
+ @property
122
+ def _geom(self):
123
+ """Keeps the GEOS geometry in synch with the context."""
124
+ if self.__geom is not None:
125
+ lgeos.GEOSGeom_destroy(self.__geom)
126
+ self.__geom = geos_multipolygon_from_py(self.context)[0]
127
+ return self.__geom
128
+
129
+
130
+ def asMultiPolygon(context):
131
+ """Factory for MultiLineStringAdapter instances."""
132
+ return MultiPolygonAdapter(context)
133
+
134
+
135
+ # Test runner
136
+ def _test():
137
+ import doctest
138
+ doctest.testmod()
139
+
140
+
141
+ if __name__ == "__main__":
142
+ _test()
143
+
Binary file
@@ -0,0 +1,259 @@
1
+ """
2
+ Points.
3
+ """
4
+
5
+ from ctypes import string_at, create_string_buffer, \
6
+ c_char_p, c_double, c_float, c_int, c_uint, c_size_t, c_ubyte, \
7
+ c_void_p, byref
8
+ from ctypes import cast, POINTER
9
+
10
+ from shapely.geos import lgeos, DimensionError
11
+ from shapely.geometry.base import BaseGeometry, CoordinateSequence
12
+ from shapely.geometry.base import exceptNull
13
+
14
+
15
+ def geos_point_from_py(ob, update_geom=None, update_ndim=0):
16
+ """Create a GEOS geom from an object that is a coordinate sequence
17
+ or that provides the array interface.
18
+
19
+ Returns the GEOS geometry and the number of its dimensions.
20
+ """
21
+ try:
22
+ # From array protocol
23
+ array = ob.__array_interface__
24
+ assert len(array['shape']) == 1
25
+ n = array['shape'][0]
26
+ assert n == 2 or n == 3
27
+
28
+ cdata = array['data'][0]
29
+ cp = cast(cdata, POINTER(c_double))
30
+ dx = c_double(cp[0])
31
+ dy = c_double(cp[1])
32
+ dz = None
33
+ if n == 3:
34
+ dz = c_double(cp[2])
35
+ ndim = 3
36
+ except AttributeError:
37
+ # Fall back on the case of Python sequence data
38
+ # Accept either (x, y) or [(x, y)]
39
+ if type(ob[0]) == type(tuple()):
40
+ coords = ob[0]
41
+ else:
42
+ coords = ob
43
+ n = len(coords)
44
+ dx = c_double(coords[0])
45
+ dy = c_double(coords[1])
46
+ dz = None
47
+ if n == 3:
48
+ dz = c_double(coords[2])
49
+
50
+ if update_geom:
51
+ cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
52
+ if n != update_ndim:
53
+ raise ValueError, \
54
+ "Wrong coordinate dimensions; this geometry has dimensions: %d" \
55
+ % update_ndim
56
+ else:
57
+ cs = lgeos.GEOSCoordSeq_create(1, n)
58
+
59
+ # Because of a bug in the GEOS C API, always set X before Y
60
+ lgeos.GEOSCoordSeq_setX(cs, 0, dx)
61
+ lgeos.GEOSCoordSeq_setY(cs, 0, dy)
62
+ if n == 3:
63
+ lgeos.GEOSCoordSeq_setZ(cs, 0, dz)
64
+
65
+ if update_geom:
66
+ return None
67
+ else:
68
+ return lgeos.GEOSGeom_createPoint(cs), n
69
+
70
+ def update_point_from_py(geom, ob):
71
+ geos_point_from_py(ob, geom._geom, geom._ndim)
72
+
73
+
74
+ class Point(BaseGeometry):
75
+
76
+ """A point geometry.
77
+
78
+ Attributes
79
+ ----------
80
+ x, y, z : float
81
+ Coordinate values
82
+
83
+ Example
84
+ -------
85
+ >>> p = Point(1.0, -1.0)
86
+ >>> str(p)
87
+ 'POINT (1.0000000000000000 -1.0000000000000000)'
88
+ >>> p.y = 0.0
89
+ >>> p.y
90
+ 0.0
91
+ >>> p.x
92
+ 1.0
93
+ >>> p.array
94
+ [[1.0, 0.0]]
95
+ """
96
+
97
+ def __init__(self, *args):
98
+ """This *copies* the given data to a new GEOS geometry.
99
+
100
+ Parameters
101
+ ----------
102
+
103
+ There are 2 cases:
104
+
105
+ 1) 1 parameter: this must satisfy the numpy array protocol.
106
+ 2) 2 or more parameters: x, y, z : float
107
+ Easting, northing, and elevation.
108
+ """
109
+ BaseGeometry.__init__(self)
110
+ self._init_geom(*args)
111
+
112
+ def _init_geom(self, *args):
113
+ if len(args) == 0:
114
+ # allow creation of null points, to support unpickling
115
+ pass
116
+ else:
117
+ if len(args) == 1:
118
+ self._geom, self._ndim = geos_point_from_py(args[0])
119
+ else:
120
+ self._geom, self._ndim = geos_point_from_py(tuple(args))
121
+
122
+ # Coordinate getters and setters
123
+
124
+ @property
125
+ @exceptNull
126
+ def x(self):
127
+ """Return x coordinate."""
128
+ cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
129
+ d = c_double()
130
+ lgeos.GEOSCoordSeq_getX(cs, 0, byref(d))
131
+ return d.value
132
+
133
+ @property
134
+ @exceptNull
135
+ def y(self):
136
+ """Return y coordinate."""
137
+ cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
138
+ d = c_double()
139
+ lgeos.GEOSCoordSeq_getY(cs, 0, byref(d))
140
+ return d.value
141
+
142
+ @property
143
+ @exceptNull
144
+ def z(self):
145
+ """Return z coordinate."""
146
+ if self._ndim != 3:
147
+ raise DimensionError, "This point has no z coordinate."
148
+ cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
149
+ d = c_double()
150
+ lgeos.GEOSCoordSeq_getZ(cs, 0, byref(d))
151
+ return d.value
152
+
153
+ @property
154
+ @exceptNull
155
+ def __geo_interface__(self):
156
+ return {
157
+ 'type': 'Point',
158
+ 'coordinates': self.coords[0]
159
+ }
160
+
161
+ @property
162
+ @exceptNull
163
+ def ctypes(self):
164
+ if not self._ctypes_data:
165
+ array_type = c_double * self._ndim
166
+ array = array_type()
167
+ array[0] = self.x
168
+ array[1] = self.y
169
+ if self._ndim == 3:
170
+ array[2] = self.z
171
+ self._ctypes_data = array
172
+ return self._ctypes_data
173
+
174
+ def array_interface(self):
175
+ """Provide the Numpy array protocol."""
176
+ ai = self.array_interface_base
177
+ ai.update({'shape': (self._ndim,)})
178
+ return ai
179
+ __array_interface__ = property(array_interface)
180
+
181
+ @property
182
+ @exceptNull
183
+ def bounds(self):
184
+ cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
185
+ x = c_double()
186
+ y = c_double()
187
+ lgeos.GEOSCoordSeq_getX(cs, 0, byref(x))
188
+ lgeos.GEOSCoordSeq_getY(cs, 0, byref(y))
189
+ return (x.value, y.value, x.value, y.value)
190
+
191
+ # Coordinate access
192
+
193
+ def set_coords(self, coordinates):
194
+ if self._geom is None:
195
+ self._init_geom(coordinates)
196
+ else:
197
+ update_point_from_py(self, coordinates)
198
+
199
+ coords = property(BaseGeometry.get_coords, set_coords)
200
+
201
+
202
+ class PointAdapter(Point):
203
+
204
+ """Adapts a Python coordinate pair or a numpy array to the point interface.
205
+ """
206
+
207
+ context = None
208
+ __geom = None
209
+ _owned = False
210
+
211
+ def __init__(self, context):
212
+ self.context = context
213
+
214
+ @property
215
+ def _ndim(self):
216
+ try:
217
+ # From array protocol
218
+ array = self.context.__array_interface__
219
+ n = array['shape'][0]
220
+ assert n == 2 or n == 3
221
+ return n
222
+ except AttributeError:
223
+ # Fall back on list
224
+ return len(self.context)
225
+
226
+ @property
227
+ def _geom(self):
228
+ """Keeps the GEOS geometry in synch with the context."""
229
+ if self.__geom is not None:
230
+ lgeos.GEOSGeom_destroy(self.__geom)
231
+ self.__geom, n = geos_point_from_py(self.context)
232
+ return self.__geom
233
+
234
+ # TODO: reimplement x, y, z properties without calling invoking _geom
235
+
236
+ @property
237
+ def __array_interface__(self):
238
+ """Provide the Numpy array protocol."""
239
+ try:
240
+ return self.context.__array_interface__
241
+ except AttributeError:
242
+ return self.array_interface()
243
+
244
+ coords = property(BaseGeometry.get_coords)
245
+
246
+
247
+ def asPoint(context):
248
+ """Factory for PointAdapter instances."""
249
+ return PointAdapter(context)
250
+
251
+
252
+ # Test runner
253
+ def _test():
254
+ import doctest
255
+ doctest.testmod()
256
+
257
+ if __name__ == "__main__":
258
+ _test()
259
+
Binary file