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/base.py DELETED
@@ -1,415 +0,0 @@
1
- """
2
- Base geometry class and utilities.
3
- """
4
-
5
- from ctypes import string_at, byref, c_int, c_size_t, c_char_p, c_double
6
- import sys
7
-
8
- from shapely.geos import lgeos, free, allocated_c_char_p
9
- from shapely.predicates import BinaryPredicate, UnaryPredicate
10
- from shapely.topology import BinaryTopologicalOp, UnaryTopologicalOp
11
-
12
-
13
- GEOMETRY_TYPES = [
14
- 'Point',
15
- 'LineString',
16
- 'LinearRing',
17
- 'Polygon',
18
- 'MultiPoint',
19
- 'MultiLineString',
20
- 'MultiPolygon',
21
- 'GeometryCollection'
22
- ]
23
-
24
- def geometry_type_name(g):
25
- if g is None:
26
- raise ValueError, "Null geometry has no type"
27
- return GEOMETRY_TYPES[lgeos.GEOSGeomTypeId(g)]
28
-
29
- # Abstract geometry factory for use with topological methods below
30
-
31
- def geom_factory(g):
32
- if not g:
33
- raise ValueError, "No Shapely geometry can be created from this null value"
34
- ob = BaseGeometry()
35
- geom_type = geometry_type_name(g)
36
- # TODO: check cost of dynamic import by profiling
37
- mod = __import__(
38
- 'shapely.geometry',
39
- globals(),
40
- locals(),
41
- [geom_type],
42
- )
43
- ob.__class__ = getattr(mod, geom_type)
44
- ob._geom = g
45
- ob._ndim = 2 # callers should be all from 2D worlds
46
- return ob
47
-
48
-
49
- class CoordinateSequence(object):
50
-
51
- _cseq = None
52
- _ndim = None
53
- _length = 0
54
- index = 0
55
-
56
- def __init__(self, geom):
57
- self._cseq = lgeos.GEOSGeom_getCoordSeq(geom._geom)
58
- self._ndim = geom._ndim
59
-
60
- def __iter__(self):
61
- self.index = 0
62
- self._length = self.__len__()
63
- return self
64
-
65
- def next(self):
66
- dx = c_double()
67
- dy = c_double()
68
- dz = c_double()
69
- i = self.index
70
- if i < self._length:
71
- lgeos.GEOSCoordSeq_getX(self._cseq, i, byref(dx))
72
- lgeos.GEOSCoordSeq_getY(self._cseq, i, byref(dy))
73
- if self._ndim == 3: # TODO: use hasz
74
- lgeos.GEOSCoordSeq_getZ(self._cseq, i, byref(dz))
75
- self.index += 1
76
- return (dx.value, dy.value, dz.value)
77
- else:
78
- self.index += 1
79
- return (dx.value, dy.value)
80
- else:
81
- raise StopIteration
82
-
83
- def __len__(self):
84
- cs_len = c_int(0)
85
- lgeos.GEOSCoordSeq_getSize(self._cseq, byref(cs_len))
86
- return cs_len.value
87
-
88
- def __getitem__(self, i):
89
- M = self.__len__()
90
- if i + M < 0 or i >= M:
91
- raise IndexError, "index out of range"
92
- if i < 0:
93
- ii = M + i
94
- else:
95
- ii = i
96
- dx = c_double()
97
- dy = c_double()
98
- dz = c_double()
99
- lgeos.GEOSCoordSeq_getX(self._cseq, ii, byref(dx))
100
- lgeos.GEOSCoordSeq_getY(self._cseq, ii, byref(dy))
101
- if self._ndim == 3: # TODO: use hasz
102
- lgeos.GEOSCoordSeq_getZ(self._cseq, ii, byref(dz))
103
- return (dx.value, dy.value, dz.value)
104
- else:
105
- return (dx.value, dy.value)
106
-
107
-
108
- class GeometrySequence(object):
109
-
110
- _factory = None
111
- _geom = None
112
- _ndim = None
113
- _index = 0
114
- _length = 0
115
-
116
- def __init__(self, geom, type):
117
- self._factory = type
118
- self._geom = geom._geom
119
- self._ndim = geom._ndim
120
-
121
- def __iter__(self):
122
- self._index = 0
123
- self._length = self.__len__()
124
- return self
125
-
126
- def next(self):
127
- if self._index < self.__len__():
128
- g = self._factory()
129
- g._owned = True
130
- g._geom = lgeos.GEOSGetGeometryN(self._geom, self._index)
131
- self._index += 1
132
- return g
133
- else:
134
- raise StopIteration
135
-
136
- def __len__(self):
137
- return lgeos.GEOSGetNumGeometries(self._geom)
138
-
139
- def __getitem__(self, i):
140
- M = self.__len__()
141
- if i + M < 0 or i >= M:
142
- raise IndexError, "index out of range"
143
- if i < 0:
144
- ii = M + i
145
- else:
146
- ii = i
147
- g = self._factory()
148
- g._owned = True
149
- g._geom = lgeos.GEOSGetGeometryN(self._geom, ii)
150
- return g
151
-
152
- @property
153
- def _longest(self):
154
- max = 0
155
- for g in iter(self):
156
- l = len(g.coords)
157
- if l > max:
158
- max = l
159
-
160
-
161
- def exceptNull(func):
162
- """Decorator which helps avoid GEOS operations on null pointers."""
163
- def wrapper(*args, **kwargs):
164
- # self is the first arg
165
- if args[0]._geom is None:
166
- raise ValueError, "Null geometry supports no operations"
167
- return func(*args, **kwargs)
168
- return wrapper
169
-
170
- def exceptEitherNull(func):
171
- """Decorator which avoids GEOS operations on one or more null pointers."""
172
- def wrapper(*args, **kwargs):
173
- # self is the first arg
174
- if args[0]._geom is None or args[1]._geom is None:
175
- raise ValueError, "Null geometry supports no operations"
176
- return func(*args, **kwargs)
177
- return wrapper
178
-
179
-
180
- class BaseGeometry(object):
181
-
182
- """Provides GEOS spatial predicates and topological operations.
183
- """
184
-
185
- __geom = None # See _geom property below
186
- _ctypes_data = None
187
- _ndim = None
188
- _crs = None
189
- _owned = False
190
-
191
- def __init__(self):
192
- self.__geom = None
193
-
194
- def __del__(self):
195
- if self.__geom is not None and not self._owned:
196
- lgeos.GEOSGeom_destroy(self.__geom)
197
-
198
- def __str__(self):
199
- return self.to_wkt()
200
-
201
- def __eq__(self, other):
202
- return self.equals(other)
203
-
204
- def __ne__(self, other):
205
- return not self.equals(other)
206
-
207
- # To support pickling
208
-
209
- def __reduce__(self):
210
- return (self.__class__, (), self.to_wkb())
211
-
212
- def __setstate__(self, state):
213
- self.__geom = lgeos.GEOSGeomFromWKB_buf(
214
- c_char_p(state),
215
- c_size_t(len(state))
216
- )
217
-
218
- # _geom has been made a property with the GEOS geometry pointer stored
219
- # in __geom so that geometries and geometry adapters can share __del__
220
-
221
- def get_geom(self):
222
- return self.__geom
223
- def set_geom(self, val):
224
- self.__geom = val
225
- _geom = property(get_geom, set_geom)
226
-
227
- # Array and ctypes interfaces
228
-
229
- @property
230
- def ctypes(self):
231
- """Return a ctypes representation.
232
-
233
- To be overridden by extension classes."""
234
- raise NotImplementedError
235
-
236
- @property
237
- def array_interface_base(self):
238
- if sys.byteorder == 'little':
239
- typestr = '<f8'
240
- elif sys.byteorder == 'big':
241
- typestr = '>f8'
242
- else:
243
- raise ValueError, "Unsupported byteorder: neither little nor big-endian"
244
- return {
245
- 'version': 3,
246
- 'typestr': typestr,
247
- 'data': self.ctypes,
248
- }
249
-
250
- @property
251
- def __array_interface__(self):
252
- """Provide the Numpy array protocol."""
253
- raise NotImplementedError
254
-
255
- @exceptNull
256
- def get_coords(self):
257
- return CoordinateSequence(self)
258
-
259
- def set_coords(self, ob):
260
- raise NotImplementedError, \
261
- "set_coords must be provided by derived classes"
262
-
263
- coords = property(get_coords, set_coords)
264
-
265
- # Python feature protocol
266
-
267
- @property
268
- def __geo_interface__(self):
269
- raise NotImplementedError
270
-
271
- @property
272
- def type(self):
273
- return self.geometryType()
274
-
275
- # Type of geometry and its representations
276
-
277
- @exceptNull
278
- def geometryType(self):
279
- """Returns a string representing the geometry type, e.g. 'Polygon'."""
280
- return geometry_type_name(self._geom)
281
-
282
- @exceptNull
283
- def to_wkb(self):
284
- """Returns a WKB byte string representation of the geometry."""
285
- func = lgeos.GEOSGeomToWKB_buf
286
- size = c_int()
287
- def errcheck(result, func, argtuple):
288
- retval = string_at(result, size.value)[:]
289
- free(result)
290
- return retval
291
- func.errcheck = errcheck
292
- return func(self._geom, byref(size))
293
-
294
- @exceptNull
295
- def to_wkt(self):
296
- """Returns a WKT string representation of the geometry."""
297
- func = lgeos.GEOSGeomToWKT
298
- def errcheck(result, func, argtuple):
299
- retval = result.value
300
- free(result)
301
- return retval
302
- func.restype = allocated_c_char_p
303
- func.errcheck = errcheck
304
- return lgeos.GEOSGeomToWKT(self._geom)
305
-
306
- geom_type = property(geometryType)
307
- wkt = property(to_wkt)
308
- wkb = property(to_wkb)
309
-
310
- # Basic geometry properties
311
-
312
- @property
313
- @exceptNull
314
- def area(self):
315
- a = c_double()
316
- retval = lgeos.GEOSArea(self._geom, byref(a))
317
- return a.value
318
-
319
- @property
320
- @exceptNull
321
- def length(self):
322
- len = c_double()
323
- retval = lgeos.GEOSLength(self._geom, byref(len))
324
- return len.value
325
-
326
- @exceptEitherNull
327
- def distance(self, other):
328
- d = c_double()
329
- retval = lgeos.GEOSDistance(self._geom, other._geom, byref(d))
330
- return d.value
331
-
332
- # Topology operations
333
- #
334
- # These use descriptors to reduce the amount of boilerplate.
335
-
336
- envelope = UnaryTopologicalOp(lgeos.GEOSEnvelope, geom_factory)
337
- intersection = BinaryTopologicalOp(lgeos.GEOSIntersection, geom_factory)
338
- convex_hull = UnaryTopologicalOp(lgeos.GEOSConvexHull, geom_factory)
339
- difference = BinaryTopologicalOp(lgeos.GEOSDifference, geom_factory)
340
- symmetric_difference = BinaryTopologicalOp(lgeos.GEOSSymDifference,
341
- geom_factory)
342
- boundary = UnaryTopologicalOp(lgeos.GEOSBoundary, geom_factory)
343
- union = BinaryTopologicalOp(lgeos.GEOSUnion, geom_factory)
344
- centroid = UnaryTopologicalOp(lgeos.GEOSGetCentroid, geom_factory)
345
-
346
- # Buffer has a unique distance argument, so not a descriptor
347
- @exceptNull
348
- def buffer(self, distance, quadsegs=16):
349
- return geom_factory(
350
- lgeos.GEOSBuffer(self._geom, c_double(distance), c_int(quadsegs))
351
- )
352
-
353
- # Relate has a unique string return value
354
- @exceptNull
355
- def relate(self, other):
356
- func = lgeos.GEOSRelate
357
- def errcheck(result, func, argtuple):
358
- retval = result.value
359
- free(result)
360
- return retval
361
- func.restype = allocated_c_char_p
362
- func.errcheck = errcheck
363
- return lgeos.GEOSRelate(self._geom, other._geom)
364
-
365
- # Binary predicates
366
- #
367
- # These use descriptors to reduce the amount of boilerplate.
368
-
369
- # TODO: Relate Pattern?
370
- disjoint = BinaryPredicate(lgeos.GEOSDisjoint)
371
- touches = BinaryPredicate(lgeos.GEOSTouches)
372
- intersects = BinaryPredicate(lgeos.GEOSIntersects)
373
- crosses = BinaryPredicate(lgeos.GEOSCrosses)
374
- within = BinaryPredicate(lgeos.GEOSWithin)
375
- contains = BinaryPredicate(lgeos.GEOSContains)
376
- overlaps = BinaryPredicate(lgeos.GEOSOverlaps)
377
- equals = BinaryPredicate(lgeos.GEOSEquals)
378
-
379
- # Unary predicates
380
- #
381
- # These use descriptors to reduce the amount of boilerplate.
382
-
383
- is_empty = UnaryPredicate(lgeos.GEOSisEmpty)
384
- is_valid = UnaryPredicate(lgeos.GEOSisValid)
385
- is_simple = UnaryPredicate(lgeos.GEOSisSimple)
386
- is_ring = UnaryPredicate(lgeos.GEOSisRing)
387
- has_z = UnaryPredicate(lgeos.GEOSHasZ)
388
-
389
- @property
390
- @exceptNull
391
- def bounds(self):
392
- env = self.envelope
393
- if env.geom_type != 'Polygon':
394
- raise ValueError, env.wkt
395
- cs = lgeos.GEOSGeom_getCoordSeq(env.exterior._geom)
396
- cs_len = c_int(0)
397
- lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len))
398
-
399
- minx = 1.e+20
400
- maxx = -1e+20
401
- miny = 1.e+20
402
- maxy = -1e+20
403
- temp = c_double()
404
- for i in xrange(cs_len.value):
405
- lgeos.GEOSCoordSeq_getX(cs, i, byref(temp))
406
- x = temp.value
407
- if x < minx: minx = x
408
- if x > maxx: maxx = x
409
- lgeos.GEOSCoordSeq_getY(cs, i, byref(temp))
410
- y = temp.value
411
- if y < miny: miny = y
412
- if y > maxy: maxy = y
413
-
414
- return (minx, miny, maxx, maxy)
415
-
shapely/geometry/base.pyc DELETED
Binary file
@@ -1,24 +0,0 @@
1
- """
2
- Geometry collections.
3
- """
4
-
5
- from shapely.geometry.base import BaseGeometry
6
-
7
- class GeometryCollection(BaseGeometry):
8
-
9
- """A geometry collection.
10
- """
11
-
12
- def __init__(self):
13
- BaseGeometry.__init__(self)
14
-
15
-
16
- # Test runner
17
- def _test():
18
- import doctest
19
- doctest.testmod()
20
-
21
-
22
- if __name__ == "__main__":
23
- _test()
24
-
Binary file
shapely/geometry/geo.py DELETED
@@ -1,35 +0,0 @@
1
-
2
- from point import PointAdapter
3
- from linestring import LineStringAdapter
4
- from polygon import PolygonAdapter
5
- from multipoint import MultiPointAdapter
6
- from multilinestring import MultiLineStringAdapter
7
- from multipolygon import MultiPolygonAdapter
8
-
9
-
10
- def asShape(context):
11
- """Adapts the context to a geometry interface. The coordinates remain
12
- stored in the context.
13
- """
14
- if hasattr(context, "__geo_interface__"):
15
- ob = context.__geo_interface__
16
- else:
17
- ob = context
18
-
19
- geom_type = ob.get("type").lower()
20
-
21
- if geom_type == "point":
22
- return PointAdapter(ob["coordinates"])
23
- elif geom_type == "linestring":
24
- return LineStringAdapter(ob["coordinates"])
25
- elif geom_type == "polygon":
26
- return PolygonAdapter(ob["coordinates"][0], ob["coordinates"][1:])
27
- elif geom_type == "multipoint":
28
- return MultiPointAdapter(ob["coordinates"])
29
- elif geom_type == "multilinestring":
30
- return MultiLineStringAdapter(ob["coordinates"])
31
- elif geom_type == "multipolygon":
32
- return MultiPolygonAdapter(ob["coordinates"])
33
- else:
34
- raise ValueError, "Unknown geometry type: %s" % geom_type
35
-
shapely/geometry/geo.pyc DELETED
Binary file
@@ -1,234 +0,0 @@
1
- """
2
- Line strings.
3
- """
4
-
5
- from ctypes import byref, c_double, c_int, cast, POINTER, pointer
6
- from ctypes import ArgumentError
7
-
8
- from shapely.geos import lgeos
9
- from shapely.geometry.base import BaseGeometry, exceptNull
10
-
11
-
12
- def geos_linestring_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
- # Create a coordinate sequence
29
- if update_geom is not None:
30
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
31
- if n != update_ndim:
32
- raise ValueError, \
33
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
34
- % update_ndim
35
- else:
36
- cs = lgeos.GEOSCoordSeq_create(m, n)
37
-
38
- # add to coordinate sequence
39
- for i in xrange(m):
40
- dx = c_double(cp[n*i])
41
- dy = c_double(cp[n*i+1])
42
- dz = None
43
- if n == 3:
44
- dz = c_double(cp[n*i+2])
45
-
46
- # Because of a bug in the GEOS C API,
47
- # always set X before Y
48
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
49
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
50
- if n == 3:
51
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
52
-
53
- except AttributeError:
54
- # Fall back on list
55
- m = len(ob)
56
- n = len(ob[0])
57
- assert m >= 2
58
- assert n == 2 or n == 3
59
-
60
- # Create a coordinate sequence
61
- if update_geom is not None:
62
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
63
- if n != update_ndim:
64
- raise ValueError, \
65
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
66
- % update_ndim
67
- else:
68
- cs = lgeos.GEOSCoordSeq_create(m, n)
69
-
70
- # add to coordinate sequence
71
- for i in xrange(m):
72
- coords = ob[i]
73
- dx = c_double(coords[0])
74
- dy = c_double(coords[1])
75
- dz = None
76
- if n == 3:
77
- dz = c_double(coords[2])
78
-
79
- # Because of a bug in the GEOS C API,
80
- # always set X before Y
81
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
82
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
83
- if n == 3:
84
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
85
-
86
- if update_geom is not None:
87
- return None
88
- else:
89
- return lgeos.GEOSGeom_createLineString(cs), n
90
-
91
- def update_linestring_from_py(geom, ob):
92
- geos_linestring_from_py(ob, geom._geom, geom._ndim)
93
-
94
-
95
- class LineString(BaseGeometry):
96
-
97
- """A line string, also known as a polyline.
98
-
99
- """
100
-
101
- def __init__(self, coordinates=None):
102
- """Initialize.
103
-
104
- Parameters
105
- ----------
106
-
107
- coordinates : sequence or array
108
- This may be an object that satisfies the numpy array protocol,
109
- providing an M x 2 or M x 3 (with z) array, or it may be a sequence
110
- of x, y (,z) coordinate sequences.
111
-
112
- Example
113
- -------
114
-
115
- >>> line = LineString([[0.0, 0.0], [1.0, 2.0]])
116
- >>> line = LineString(array([[0.0, 0.0], [1.0, 2.0]]))
117
-
118
- Each result in a line string from (0.0, 0.0) to (1.0, 2.0).
119
- """
120
- BaseGeometry.__init__(self)
121
- self._init_geom(coordinates)
122
-
123
- def _init_geom(self, coordinates):
124
- if coordinates is None:
125
- # allow creation of null lines, to support unpickling
126
- pass
127
- else:
128
- self._geom, self._ndim = geos_linestring_from_py(coordinates)
129
-
130
- @property
131
- def __geo_interface__(self):
132
- return {
133
- 'type': 'LineString',
134
- 'coordinates': tuple(self.coords)
135
- }
136
-
137
- @property
138
- @exceptNull
139
- def ctypes(self):
140
- if not self._ctypes_data:
141
- cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
142
- cs_len = c_int(0)
143
- lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len))
144
- temp = c_double()
145
- n = self._ndim
146
- m = cs_len.value
147
- array_type = c_double * (m * n)
148
- data = array_type()
149
- for i in xrange(m):
150
- lgeos.GEOSCoordSeq_getX(cs, i, byref(temp))
151
- data[n*i] = temp.value
152
- lgeos.GEOSCoordSeq_getY(cs, i, byref(temp))
153
- data[n*i+1] = temp.value
154
- if n == 3: # TODO: use hasz
155
- lgeos.GEOSCoordSeq_getZ(cs, i, byref(temp))
156
- data[n*i+2] = temp.value
157
- self._ctypes_data = data
158
- return self._ctypes_data
159
-
160
- def array_interface(self):
161
- """Provide the Numpy array protocol."""
162
- ai = self.array_interface_base
163
- ai.update({'shape': (len(self.coords), self._ndim)})
164
- return ai
165
- __array_interface__ = property(array_interface)
166
-
167
- # Coordinate access
168
-
169
- def set_coords(self, coordinates):
170
- if self._geom is None:
171
- self._init_geom(coordinates)
172
- update_linestring_from_py(self, coordinates)
173
-
174
- coords = property(BaseGeometry.get_coords, set_coords)
175
-
176
-
177
- class LineStringAdapter(LineString):
178
-
179
- """Adapts a Python coordinate pair or a numpy array to the line string
180
- interface.
181
- """
182
-
183
- context = None
184
- __geom = None
185
- _owned = False
186
-
187
- def __init__(self, context):
188
- self.context = context
189
-
190
- @property
191
- def _ndim(self):
192
- try:
193
- # From array protocol
194
- array = self.context.__array_interface__
195
- n = array['shape'][1]
196
- assert n == 2 or n == 3
197
- return n
198
- except AttributeError:
199
- # Fall back on list
200
- return len(self.context[0])
201
-
202
- @property
203
- def _geom(self):
204
- """Keeps the GEOS geometry in synch with the context."""
205
- if self.__geom is not None:
206
- lgeos.GEOSGeom_destroy(self.__geom)
207
- self.__geom, n = geos_linestring_from_py(self.context)
208
- return self.__geom
209
-
210
- @property
211
- def __array_interface__(self):
212
- """Provide the Numpy array protocol."""
213
- try:
214
- return self.context.__array_interface__
215
- except AttributeError:
216
- return self.array_interface()
217
-
218
- coords = property(BaseGeometry.get_coords)
219
-
220
-
221
- def asLineString(context):
222
- """Factory for PointAdapter instances."""
223
- return LineStringAdapter(context)
224
-
225
-
226
- # Test runner
227
- def _test():
228
- import doctest
229
- doctest.testmod()
230
-
231
-
232
- if __name__ == "__main__":
233
- _test()
234
-