shapely 1.0__py2.4.egg → 1.0b1__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.
shapely/geometry/point.py DELETED
@@ -1,259 +0,0 @@
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
@@ -1,429 +0,0 @@
1
- """
2
- Polygons and their linear ring components.
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, exceptNull
9
- from shapely.geometry.linestring import LineString, LineStringAdapter
10
-
11
-
12
- def geos_linearring_from_py(ob, update_geom=None, update_ndim=0):
13
- try:
14
- # From array protocol
15
- array = ob.__array_interface__
16
- assert len(array['shape']) == 2
17
- m = array['shape'][0]
18
- n = array['shape'][1]
19
- assert m >= 2
20
- assert n == 2 or n == 3
21
-
22
- # Make pointer to the coordinate array
23
- try:
24
- cp = cast(array['data'][0], POINTER(c_double))
25
- except ArgumentError:
26
- cp = array['data']
27
-
28
- # Add closing coordinates to sequence?
29
- if cp[0] != cp[m*n-n] or cp[1] != cp[m*n-n+1]:
30
- M = m + 1
31
- else:
32
- M = m
33
-
34
- # Create a coordinate sequence
35
- if update_geom is not None:
36
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
37
- if n != update_ndim:
38
- raise ValueError, \
39
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
40
- % update_ndim
41
- else:
42
- cs = lgeos.GEOSCoordSeq_create(M, n)
43
-
44
- # add to coordinate sequence
45
- for i in xrange(m):
46
- dx = c_double(cp[n*i])
47
- dy = c_double(cp[n*i+1])
48
- dz = None
49
- if n == 3:
50
- dz = c_double(cp[n*i+2])
51
-
52
- # Because of a bug in the GEOS C API,
53
- # always set X before Y
54
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
55
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
56
- if n == 3:
57
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
58
-
59
- # Add closing coordinates to sequence?
60
- if M > m:
61
- dx = c_double(cp[0])
62
- dy = c_double(cp[1])
63
- dz = None
64
- if n == 3:
65
- dz = c_double(cp[2])
66
-
67
- # Because of a bug in the GEOS C API,
68
- # always set X before Y
69
- lgeos.GEOSCoordSeq_setX(cs, M-1, dx)
70
- lgeos.GEOSCoordSeq_setY(cs, M-1, dy)
71
- if n == 3:
72
- lgeos.GEOSCoordSeq_setZ(cs, M-1, dz)
73
-
74
- except AttributeError:
75
- # Fall back on list
76
- m = len(ob)
77
- n = len(ob[0])
78
- assert m >= 2
79
- assert n == 2 or n == 3
80
-
81
- # Add closing coordinates if not provided
82
- if ob[0][0] != ob[-1][0] or ob[0][1] != ob[-1][1]:
83
- M = m + 1
84
- else:
85
- M = m
86
-
87
- # Create a coordinate sequence
88
- if update_geom is not None:
89
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
90
- if n != update_ndim:
91
- raise ValueError, \
92
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
93
- % update_ndim
94
- else:
95
- cs = lgeos.GEOSCoordSeq_create(M, n)
96
-
97
- # add to coordinate sequence
98
- for i in xrange(m):
99
- coords = ob[i]
100
- dx = c_double(coords[0])
101
- dy = c_double(coords[1])
102
- dz = None
103
- if n == 3:
104
- dz = c_double(coords[2])
105
-
106
- # Because of a bug in the GEOS C API,
107
- # always set X before Y
108
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
109
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
110
- if n == 3:
111
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
112
-
113
- # Add closing coordinates to sequence?
114
- if M > m:
115
- coords = ob[0]
116
- dx = c_double(coords[0])
117
- dy = c_double(coords[1])
118
- dz = None
119
- if n == 3:
120
- dz = c_double(coords[2])
121
-
122
- # Because of a bug in the GEOS C API,
123
- # always set X before Y
124
- lgeos.GEOSCoordSeq_setX(cs, M-1, dx)
125
- lgeos.GEOSCoordSeq_setY(cs, M-1, dy)
126
- if n == 3:
127
- lgeos.GEOSCoordSeq_setZ(cs, M-1, dz)
128
-
129
- if update_geom is not None:
130
- return None
131
- else:
132
- return lgeos.GEOSGeom_createLinearRing(cs), n
133
-
134
- def update_linearring_from_py(geom, ob):
135
- geos_linearring_from_py(ob, geom._geom, geom._ndim)
136
-
137
-
138
- class LinearRing(LineString):
139
-
140
- """A linear ring.
141
- """
142
-
143
- _ndim = 2
144
- __geom = None
145
- _owned = False
146
-
147
- def __init__(self, coordinates=None):
148
- """Initialize.
149
-
150
- Parameters
151
- ----------
152
- coordinates : sequence or array
153
- This may be an object that satisfies the numpy array protocol,
154
- providing an M x 2 or M x 3 (with z) array, or it may be a sequence
155
- of x, y (,z) coordinate sequences.
156
-
157
- Rings are implicitly closed. There is no need to specific a final
158
- coordinate pair identical to the first.
159
-
160
- Example
161
- -------
162
- >>> ring = LinearRing( ((0.,0.), (0.,1.), (1.,1.), (1.,0.)) )
163
-
164
- Produces a 1x1 square.
165
- """
166
- BaseGeometry.__init__(self)
167
- self._init_geom(coordinates)
168
-
169
- def _init_geom(self, coordinates):
170
- if coordinates is None:
171
- # allow creation of null lines, to support unpickling
172
- pass
173
- else:
174
- self._geom, self._ndims = geos_linearring_from_py(coordinates)
175
-
176
- @property
177
- def __geo_interface__(self):
178
- return {
179
- 'type': 'LinearRing',
180
- 'coordinates': tuple(self.coords)
181
- }
182
-
183
- # Coordinate access
184
-
185
- def set_coords(self, coordinates):
186
- if self._geom is None:
187
- self._init_geom(coordinates)
188
- update_linearring_from_py(self, coordinates)
189
-
190
- coords = property(BaseGeometry.get_coords, set_coords)
191
-
192
-
193
- class LinearRingAdapter(LineStringAdapter):
194
-
195
- context = None
196
- __geom = None
197
- _owned = False
198
-
199
- @property
200
- def _geom(self):
201
- """Keeps the GEOS geometry in synch with the context."""
202
- if self.__geom is not None:
203
- lgeos.GEOSGeom_destroy(self.__geom)
204
- self.__geom, n = geos_linearring_from_py(self.context)
205
- return self.__geom
206
-
207
- @property
208
- def __geo_interface__(self):
209
- return {
210
- 'type': 'LinearRing',
211
- 'coordinates': tuple(self.coords)
212
- }
213
-
214
- coords = property(BaseGeometry.get_coords)
215
-
216
-
217
- def asLinearRing(context):
218
- return LinearRingAdapter(context)
219
-
220
-
221
- class InteriorRingSequence(object):
222
-
223
- _factory = None
224
- _geom = None
225
- _ndim = None
226
- _index = 0
227
- _length = 0
228
-
229
- def __init__(self, geom):
230
- self._geom = geom._geom
231
- self._ndim = geom._ndim
232
-
233
- def __iter__(self):
234
- self._index = 0
235
- self._length = self.__len__()
236
- return self
237
-
238
- def next(self):
239
- if self._index < self._length:
240
- g = LinearRing()
241
- g._owned = True
242
- g._geom = lgeos.GEOSGetInteriorRingN(self._geom, self._index)
243
- self._index += 1
244
- return g
245
- else:
246
- raise StopIteration
247
-
248
- def __len__(self):
249
- return lgeos.GEOSGetNumInteriorRings(self._geom)
250
-
251
- def __getitem__(self, i):
252
- M = self.__len__()
253
- if i + M < 0 or i >= M:
254
- raise IndexError, "index out of range"
255
- if i < 0:
256
- ii = M + i
257
- else:
258
- ii = i
259
- g = LinearRing()
260
- g._owned = True
261
- g._geom = lgeos.GEOSGetInteriorRingN(self._geom, ii)
262
- return g
263
-
264
- @property
265
- def _longest(self):
266
- max = 0
267
- for g in iter(self):
268
- l = len(g.coords)
269
- if l > max:
270
- max = l
271
-
272
-
273
- def geos_polygon_from_py(shell, holes=None):
274
- if shell is not None:
275
- geos_shell, ndims = geos_linearring_from_py(shell)
276
- if holes:
277
- ob = holes
278
- L = len(ob)
279
- try:
280
- N = len(ob[0][0])
281
- except:
282
- import pdb; pdb.set_trace()
283
- assert L >= 1
284
- assert N == 2 or N == 3
285
-
286
- # Array of pointers to ring geometries
287
- geos_holes = (c_void_p * L)()
288
-
289
- # add to coordinate sequence
290
- for l in xrange(L):
291
- geom, ndims = geos_linearring_from_py(ob[l])
292
- geos_holes[l] = cast(geom, c_void_p)
293
-
294
- else:
295
- geos_holes = POINTER(c_void_p)()
296
- L = 0
297
-
298
- return (
299
- lgeos.GEOSGeom_createPolygon(
300
- c_void_p(geos_shell),
301
- geos_holes,
302
- L
303
- ),
304
- ndims
305
- )
306
-
307
- class Polygon(BaseGeometry):
308
-
309
- """A line string, also known as a polyline.
310
- """
311
-
312
- _exterior = None
313
- _interiors = []
314
- _ndim = 2
315
- __geom = None
316
- _owned = False
317
-
318
- def __init__(self, shell=None, holes=None):
319
- """Initialize.
320
-
321
- Parameters
322
- ----------
323
- exterior : sequence or array
324
- This may be an object that satisfies the numpy array protocol,
325
- providing an M x 2 or M x 3 (with z) array, or it may be a sequence
326
- of x, y (,z) coordinate sequences.
327
-
328
- Example
329
- -------
330
- >>> coords = ((0., 0.), (0., 1.), (1., 1.), (1., 0.), (0., 0.))
331
- >>> polygon = Polygon(coords)
332
- """
333
- BaseGeometry.__init__(self)
334
-
335
- if shell is not None:
336
- self._geom, self._ndims = geos_polygon_from_py(shell, holes)
337
-
338
- @property
339
- @exceptNull
340
- def exterior(self):
341
- if self._exterior is None:
342
- # A polygon created from the abstract factory will have a null
343
- # _exterior attribute.
344
- ring = lgeos.GEOSGetExteriorRing(self._geom)
345
- self._exterior = LinearRing()
346
- self._exterior._geom = ring
347
- self._exterior._owned = True
348
- return self._exterior
349
-
350
- @property
351
- @exceptNull
352
- def interiors(self):
353
- return InteriorRingSequence(self)
354
-
355
- @property
356
- def ctypes(self):
357
- if not self._ctypes_data:
358
- self._ctypes_data = self.exterior.ctypes
359
- return self._ctypes_data
360
-
361
- @property
362
- def __array_interface__(self):
363
- raise NotImplementedError, \
364
- "A polygon does not itself provide the array interface. Its rings do."
365
-
366
- @property
367
- def coords(self):
368
- raise NotImplementedError, \
369
- "Component rings have coordinate sequences, but the polygon does not"
370
-
371
- @property
372
- def __geo_interface__(self):
373
- coords = [tuple(self.exterior.coords)]
374
- for hole in self.interiors:
375
- coords.append(tuple(hole.coords))
376
- return {
377
- 'type': 'Polygon',
378
- 'coordinates': tuple(coords)
379
- }
380
-
381
-
382
- class PolygonAdapter(Polygon):
383
-
384
- """Adapts sequences of sequences or numpy arrays to the polygon
385
- interface.
386
- """
387
-
388
- context = None
389
- __geom = None
390
- _owned = False
391
-
392
- def __init__(self, shell, holes=None):
393
- self.shell = shell
394
- self.holes = holes
395
-
396
- @property
397
- def _ndim(self):
398
- try:
399
- # From array protocol
400
- array = self.shell.__array_interface__
401
- n = array['shape'][1]
402
- assert n == 2 or n == 3
403
- return n
404
- except AttributeError:
405
- # Fall back on list
406
- return len(self.shell[0])
407
-
408
- @property
409
- def _geom(self):
410
- """Keeps the GEOS geometry in synch with the context."""
411
- if self.__geom is not None:
412
- lgeos.GEOSGeom_destroy(self.__geom)
413
- self.__geom = geos_polygon_from_py(self.shell, self.holes)[0]
414
- return self.__geom
415
-
416
-
417
- def asPolygon(shell, holes=None):
418
- """Factory for PolygonAdapter instances."""
419
- return PolygonAdapter(shell, holes)
420
-
421
-
422
- # Test runner
423
- def _test():
424
- import doctest
425
- doctest.testmod()
426
-
427
- if __name__ == "__main__":
428
- _test()
429
-
Binary file
File without changes