shapely 1.2.14__py2.6-win-amd64.egg → 1.2.18__py2.6-win-amd64.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.
- EGG-INFO/PKG-INFO +451 -380
- EGG-INFO/native_libs.txt +2 -0
- EGG-INFO/not-zip-safe +1 -1
- shapely/DLLs/geos.dll +0 -0
- shapely/DLLs/geos_c.dll +0 -0
- shapely/__init__.py +1 -2
- shapely/__init__.pyc +0 -0
- shapely/affinity.py +252 -0
- shapely/affinity.pyc +0 -0
- shapely/algorithms/__init__.pyc +0 -0
- shapely/algorithms/cga.pyc +0 -0
- shapely/coords.py +15 -0
- shapely/coords.pyc +0 -0
- shapely/ctypes_declarations.py +16 -3
- shapely/ctypes_declarations.pyc +0 -0
- shapely/examples/__init__.pyc +0 -0
- shapely/examples/dissolve.pyc +0 -0
- shapely/examples/geoms.pyc +0 -0
- shapely/examples/intersect.pyc +0 -0
- shapely/examples/world.pyc +0 -0
- shapely/ftools.pyc +0 -0
- shapely/geometry/__init__.py +4 -4
- shapely/geometry/__init__.pyc +0 -0
- shapely/geometry/base.py +127 -38
- shapely/geometry/base.pyc +0 -0
- shapely/geometry/collection.pyc +0 -0
- shapely/geometry/geo.py +2 -2
- shapely/geometry/geo.pyc +0 -0
- shapely/geometry/linestring.py +24 -19
- shapely/geometry/linestring.pyc +0 -0
- shapely/geometry/multilinestring.py +1 -1
- shapely/geometry/multilinestring.pyc +0 -0
- shapely/geometry/multipoint.py +4 -0
- shapely/geometry/multipoint.pyc +0 -0
- shapely/geometry/multipolygon.py +7 -4
- shapely/geometry/multipolygon.pyc +0 -0
- shapely/geometry/point.py +7 -0
- shapely/geometry/point.pyc +0 -0
- shapely/geometry/polygon.py +11 -1
- shapely/geometry/polygon.pyc +0 -0
- shapely/geometry/proxy.py +1 -3
- shapely/geometry/proxy.pyc +0 -0
- shapely/geos.py +45 -14
- shapely/geos.pyc +0 -0
- shapely/impl.py +8 -5
- shapely/impl.pyc +0 -0
- shapely/iterops.pyc +0 -0
- shapely/linref.pyc +0 -0
- shapely/ops.py +125 -3
- shapely/ops.pyc +0 -0
- shapely/predicates.pyc +0 -0
- shapely/prepared.pyc +0 -0
- shapely/speedups/__init__.pyc +0 -0
- shapely/speedups/_speedups.c +5201 -0
- shapely/speedups/_speedups.pyc +0 -0
- shapely/speedups/_speedups.pyd +0 -0
- shapely/tests/Array.txt +86 -0
- shapely/tests/GeoInterface.txt +69 -0
- shapely/tests/IterOps.txt +31 -0
- shapely/tests/LineString.txt +134 -0
- shapely/tests/MultiLineString.txt +81 -0
- shapely/tests/MultiPoint.txt +101 -0
- shapely/tests/MultiPolygon.txt +71 -0
- shapely/tests/Operations.txt +89 -0
- shapely/tests/Operators.txt +18 -0
- shapely/tests/Persist.txt +35 -0
- shapely/tests/Point.txt +148 -0
- shapely/tests/Polygon.txt +143 -0
- shapely/tests/Predicates.txt +51 -0
- shapely/tests/__init__.py +8 -0
- shapely/tests/__init__.pyc +0 -0
- shapely/tests/attribute-chains.txt +38 -0
- shapely/tests/binascii_hex.txt +47 -0
- shapely/tests/cascaded_union.txt +26 -0
- shapely/tests/dimensions.txt +17 -0
- shapely/tests/invalid_intersection.txt +29 -0
- shapely/tests/linemerge.txt +61 -0
- shapely/tests/polygonize.txt +40 -0
- shapely/tests/test_affinity.py +239 -0
- shapely/tests/test_affinity.pyc +0 -0
- shapely/tests/test_box.pyc +0 -0
- shapely/tests/test_cga.pyc +0 -0
- shapely/tests/test_collection.py +15 -0
- shapely/tests/test_collection.pyc +0 -0
- shapely/tests/test_delegated.pyc +0 -0
- shapely/tests/test_dlls.py +1 -1
- shapely/tests/test_dlls.pyc +0 -0
- shapely/tests/test_doctests.pyc +0 -0
- shapely/tests/test_emptiness.py +41 -8
- shapely/tests/test_emptiness.pyc +0 -0
- shapely/tests/test_equality.pyc +0 -0
- shapely/tests/test_geomseq.pyc +0 -0
- shapely/tests/test_getitem.pyc +0 -0
- shapely/tests/test_linear_referencing.pyc +0 -0
- shapely/tests/test_mapping.pyc +0 -0
- shapely/tests/test_ndarrays.py +35 -0
- shapely/tests/test_ndarrays.pyc +0 -0
- shapely/tests/test_pickle.py +15 -0
- shapely/tests/test_pickle.pyc +0 -0
- shapely/tests/test_prepared.pyc +0 -0
- shapely/tests/test_products_z.pyc +0 -0
- shapely/tests/test_singularity.pyc +0 -0
- shapely/tests/test_speedups.pyc +0 -0
- shapely/tests/test_styles.py +17 -0
- shapely/tests/test_styles.pyc +0 -0
- shapely/tests/test_transform.py +61 -0
- shapely/tests/test_transform.pyc +0 -0
- shapely/tests/test_unary_union.py +40 -0
- shapely/tests/test_unary_union.pyc +0 -0
- shapely/tests/test_validation.pyc +0 -0
- shapely/tests/test_xy.pyc +0 -0
- shapely/tests/threading_test.pyc +0 -0
- shapely/tests/wkt_locale.txt +28 -0
- shapely/topology.pyc +0 -0
- shapely/validation.pyc +0 -0
- shapely/wkb.py +3 -17
- shapely/wkb.pyc +0 -0
- shapely/wkt.py +3 -13
- shapely/wkt.pyc +0 -0
- DLLs/geos.dll +0 -0
- DLLs/geos_c.dll +0 -0
shapely/geometry/base.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
"""Base geometry class and utilities
|
|
2
2
|
"""
|
|
3
3
|
|
|
4
|
+
from ctypes import pointer, c_size_t, c_char_p, c_void_p
|
|
4
5
|
import sys
|
|
5
6
|
import warnings
|
|
6
7
|
|
|
7
8
|
from shapely.coords import CoordinateSequence
|
|
8
9
|
from shapely.ftools import wraps
|
|
9
|
-
from shapely.geos import lgeos
|
|
10
|
+
from shapely.geos import lgeos, ReadingError
|
|
10
11
|
from shapely.impl import DefaultImplementation, delegated
|
|
11
|
-
from shapely import wkb, wkt
|
|
12
12
|
|
|
13
13
|
GEOMETRY_TYPES = [
|
|
14
14
|
'Point',
|
|
@@ -34,9 +34,9 @@ def geom_factory(g, parent=None):
|
|
|
34
34
|
geom_type = geometry_type_name(g)
|
|
35
35
|
# TODO: check cost of dynamic import by profiling
|
|
36
36
|
mod = __import__(
|
|
37
|
-
'shapely.geometry',
|
|
38
|
-
globals(),
|
|
39
|
-
locals(),
|
|
37
|
+
'shapely.geometry',
|
|
38
|
+
globals(),
|
|
39
|
+
locals(),
|
|
40
40
|
[geom_type],
|
|
41
41
|
)
|
|
42
42
|
ob.__class__ = getattr(mod, geom_type)
|
|
@@ -48,6 +48,34 @@ def geom_factory(g, parent=None):
|
|
|
48
48
|
ob._ndim = 2
|
|
49
49
|
return ob
|
|
50
50
|
|
|
51
|
+
def geom_from_wkt(data):
|
|
52
|
+
geom = lgeos.GEOSGeomFromWKT(c_char_p(data))
|
|
53
|
+
if not geom:
|
|
54
|
+
raise ReadingError, \
|
|
55
|
+
"Could not create geometry because of errors while reading input."
|
|
56
|
+
return geom_factory(geom)
|
|
57
|
+
|
|
58
|
+
def geom_to_wkt(ob):
|
|
59
|
+
if ob is None or ob._geom is None:
|
|
60
|
+
raise ValueError("Null geometry supports no operations")
|
|
61
|
+
return lgeos.GEOSGeomToWKT(ob._geom)
|
|
62
|
+
|
|
63
|
+
def deserialize_wkb(data):
|
|
64
|
+
geom = lgeos.GEOSGeomFromWKB_buf(c_char_p(data), c_size_t(len(data)));
|
|
65
|
+
if not geom:
|
|
66
|
+
raise ReadingError(
|
|
67
|
+
"Could not create geometry because of errors while reading input.")
|
|
68
|
+
return geom
|
|
69
|
+
|
|
70
|
+
def geom_from_wkb(data):
|
|
71
|
+
return geom_factory(deserialize_wkb(data))
|
|
72
|
+
|
|
73
|
+
def geom_to_wkb(ob):
|
|
74
|
+
if ob is None or ob._geom is None:
|
|
75
|
+
raise ValueError("Null geometry supports no operations")
|
|
76
|
+
size = c_size_t()
|
|
77
|
+
return lgeos.GEOSGeomToWKB_buf(c_void_p(ob._geom), pointer(size))
|
|
78
|
+
|
|
51
79
|
def exceptNull(func):
|
|
52
80
|
"""Decorator which helps avoid GEOS operations on null pointers."""
|
|
53
81
|
@wraps(func)
|
|
@@ -57,7 +85,17 @@ def exceptNull(func):
|
|
|
57
85
|
return func(*args, **kwargs)
|
|
58
86
|
return wrapper
|
|
59
87
|
|
|
60
|
-
|
|
88
|
+
class CAP_STYLE(object):
|
|
89
|
+
round = 1
|
|
90
|
+
flat = 2
|
|
91
|
+
square = 3
|
|
92
|
+
|
|
93
|
+
class JOIN_STYLE(object):
|
|
94
|
+
round = 1
|
|
95
|
+
mitre = 2
|
|
96
|
+
bevel = 3
|
|
97
|
+
|
|
98
|
+
EMPTY = deserialize_wkb('010700000000000000'.decode('hex'))
|
|
61
99
|
|
|
62
100
|
class BaseGeometry(object):
|
|
63
101
|
"""
|
|
@@ -89,7 +127,7 @@ class BaseGeometry(object):
|
|
|
89
127
|
_ndim = None
|
|
90
128
|
_crs = None
|
|
91
129
|
_owned = False
|
|
92
|
-
|
|
130
|
+
|
|
93
131
|
# Backend config
|
|
94
132
|
impl = DefaultImplementation
|
|
95
133
|
|
|
@@ -124,8 +162,12 @@ class BaseGeometry(object):
|
|
|
124
162
|
|
|
125
163
|
def __setstate__(self, state):
|
|
126
164
|
self.empty()
|
|
127
|
-
self.__geom__ =
|
|
128
|
-
|
|
165
|
+
self.__geom__ = deserialize_wkb(state)
|
|
166
|
+
if lgeos.methods['has_z'](self.__geom__):
|
|
167
|
+
self._ndim = 3
|
|
168
|
+
else:
|
|
169
|
+
self._ndim = 2
|
|
170
|
+
|
|
129
171
|
# The _geom property
|
|
130
172
|
def _get_geom(self):
|
|
131
173
|
return self.__geom__
|
|
@@ -134,6 +176,21 @@ class BaseGeometry(object):
|
|
|
134
176
|
self.__geom__ = val
|
|
135
177
|
_geom = property(_get_geom, _set_geom)
|
|
136
178
|
|
|
179
|
+
# Operators
|
|
180
|
+
# ---------
|
|
181
|
+
|
|
182
|
+
def __and__(self, other):
|
|
183
|
+
return self.intersection(other)
|
|
184
|
+
|
|
185
|
+
def __or__(self, other):
|
|
186
|
+
return self.union(other)
|
|
187
|
+
|
|
188
|
+
def __sub__(self, other):
|
|
189
|
+
return self.difference(other)
|
|
190
|
+
|
|
191
|
+
def __xor__(self, other):
|
|
192
|
+
return self.symmetric_difference(other)
|
|
193
|
+
|
|
137
194
|
# Array and ctypes interfaces
|
|
138
195
|
# ---------------------------
|
|
139
196
|
|
|
@@ -194,18 +251,18 @@ class BaseGeometry(object):
|
|
|
194
251
|
|
|
195
252
|
def geometryType(self):
|
|
196
253
|
return geometry_type_name(self._geom)
|
|
197
|
-
|
|
254
|
+
|
|
198
255
|
@property
|
|
199
256
|
def type(self):
|
|
200
257
|
return self.geometryType()
|
|
201
258
|
|
|
202
259
|
def to_wkb(self):
|
|
203
|
-
return
|
|
260
|
+
return geom_to_wkb(self)
|
|
204
261
|
|
|
205
262
|
def to_wkt(self):
|
|
206
|
-
return
|
|
263
|
+
return geom_to_wkt(self)
|
|
207
264
|
|
|
208
|
-
geom_type = property(geometryType,
|
|
265
|
+
geom_type = property(geometryType,
|
|
209
266
|
doc="""Name of the geometry's type, such as 'Point'"""
|
|
210
267
|
)
|
|
211
268
|
wkt = property(to_wkt,
|
|
@@ -236,7 +293,7 @@ class BaseGeometry(object):
|
|
|
236
293
|
@property
|
|
237
294
|
def boundary(self):
|
|
238
295
|
"""Returns a lower dimension geometry that bounds the object
|
|
239
|
-
|
|
296
|
+
|
|
240
297
|
The boundary of a polygon is a line, the boundary of a line is a
|
|
241
298
|
collection of points. The boundary of a point is an empty (null)
|
|
242
299
|
collection.
|
|
@@ -250,7 +307,7 @@ class BaseGeometry(object):
|
|
|
250
307
|
return ()
|
|
251
308
|
else:
|
|
252
309
|
return self.impl['bounds'](self)
|
|
253
|
-
|
|
310
|
+
|
|
254
311
|
@property
|
|
255
312
|
def centroid(self):
|
|
256
313
|
"""Returns the geometric center of the object"""
|
|
@@ -263,12 +320,12 @@ class BaseGeometry(object):
|
|
|
263
320
|
|
|
264
321
|
@property
|
|
265
322
|
def convex_hull(self):
|
|
266
|
-
"""Imagine an elastic band stretched around the geometry: that's a
|
|
323
|
+
"""Imagine an elastic band stretched around the geometry: that's a
|
|
267
324
|
convex hull, more or less
|
|
268
325
|
|
|
269
326
|
The convex hull of a three member multipoint, for example, is a
|
|
270
327
|
triangular polygon.
|
|
271
|
-
"""
|
|
328
|
+
"""
|
|
272
329
|
return geom_factory(self.impl['convex_hull'](self))
|
|
273
330
|
|
|
274
331
|
@property
|
|
@@ -276,16 +333,32 @@ class BaseGeometry(object):
|
|
|
276
333
|
"""A figure that envelopes the geometry"""
|
|
277
334
|
return geom_factory(self.impl['envelope'](self))
|
|
278
335
|
|
|
279
|
-
def buffer(self, distance, resolution=16, quadsegs=None
|
|
280
|
-
|
|
336
|
+
def buffer(self, distance, resolution=16, quadsegs=None,
|
|
337
|
+
cap_style=CAP_STYLE.round, join_style=JOIN_STYLE.round,
|
|
338
|
+
mitre_limit=0):
|
|
339
|
+
"""Returns a geometry with an envelope at a distance from the object's
|
|
281
340
|
envelope
|
|
282
|
-
|
|
341
|
+
|
|
283
342
|
A negative distance has a "shrink" effect. A zero distance may be used
|
|
284
343
|
to "tidy" a polygon. The resolution of the buffer around each vertex of
|
|
285
344
|
the object increases by increasing the resolution keyword parameter
|
|
286
345
|
or second positional parameter. Note: the use of a `quadsegs` parameter
|
|
287
346
|
is deprecated and will be gone from the next major release.
|
|
288
347
|
|
|
348
|
+
The styles of caps are: CAP_STYLE.round (1), CAP_STYLE.flat (2), and
|
|
349
|
+
CAP_STYLE.square (3).
|
|
350
|
+
|
|
351
|
+
The styles of joins between offset segments are: JOIN_STYLE.round (1),
|
|
352
|
+
JOIN_STYLE.mitre (2), and JOIN_STYLE.bevel (3).
|
|
353
|
+
|
|
354
|
+
The mitre limit ratio is used for very sharp corners. The mitre ratio
|
|
355
|
+
is the ratio of the distance from the corner to the end of the mitred
|
|
356
|
+
offset corner. When two line segments meet at a sharp angle, a miter
|
|
357
|
+
join will extend the original geometry. To prevent unreasonable
|
|
358
|
+
geometry, the mitre limit allows controlling the maximum length of the
|
|
359
|
+
join corner. Corners with a ratio which exceed the limit will be
|
|
360
|
+
beveled.
|
|
361
|
+
|
|
289
362
|
Example:
|
|
290
363
|
|
|
291
364
|
>>> from shapely.wkt import loads
|
|
@@ -296,19 +369,35 @@ class BaseGeometry(object):
|
|
|
296
369
|
3.1415138011443009
|
|
297
370
|
>>> g.buffer(1.0, 3).area # triangle approximation
|
|
298
371
|
3.0
|
|
372
|
+
>>> list(g.buffer(1.0, cap_style='square').exterior.coords)
|
|
373
|
+
[(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0)]
|
|
374
|
+
>>> g.buffer(1.0, cap_style='square').area
|
|
375
|
+
4.0
|
|
299
376
|
"""
|
|
377
|
+
|
|
300
378
|
if quadsegs is not None:
|
|
301
379
|
warnings.warn(
|
|
302
|
-
"The `quadsegs` argument is deprecated. Use `resolution`.",
|
|
380
|
+
"The `quadsegs` argument is deprecated. Use `resolution`.",
|
|
303
381
|
DeprecationWarning)
|
|
304
382
|
res = quadsegs
|
|
305
383
|
else:
|
|
306
384
|
res = resolution
|
|
307
|
-
|
|
385
|
+
|
|
386
|
+
if cap_style == CAP_STYLE.round and join_style == JOIN_STYLE.round:
|
|
387
|
+
return geom_factory(self.impl['buffer'](self, distance, res))
|
|
388
|
+
|
|
389
|
+
if 'buffer_with_style' not in self.impl:
|
|
390
|
+
raise NotImplementedError("Styled buffering not available for "
|
|
391
|
+
"GEOS versions < 3.2.")
|
|
392
|
+
|
|
393
|
+
return geom_factory(self.impl['buffer_with_style'](self, distance, res,
|
|
394
|
+
cap_style,
|
|
395
|
+
join_style,
|
|
396
|
+
mitre_limit))
|
|
308
397
|
|
|
309
398
|
@delegated
|
|
310
399
|
def simplify(self, tolerance, preserve_topology=True):
|
|
311
|
-
"""Returns a simplified geometry produced by the Douglas-Puecker
|
|
400
|
+
"""Returns a simplified geometry produced by the Douglas-Puecker
|
|
312
401
|
algorithm
|
|
313
402
|
|
|
314
403
|
Coordinates of the simplified geometry will be no more than the
|
|
@@ -328,13 +417,13 @@ class BaseGeometry(object):
|
|
|
328
417
|
def difference(self, other):
|
|
329
418
|
"""Returns the difference of the geometries"""
|
|
330
419
|
return geom_factory(self.impl['difference'](self, other))
|
|
331
|
-
|
|
420
|
+
|
|
332
421
|
def intersection(self, other):
|
|
333
422
|
"""Returns the intersection of the geometries"""
|
|
334
423
|
return geom_factory(self.impl['intersection'](self, other))
|
|
335
424
|
|
|
336
425
|
def symmetric_difference(self, other):
|
|
337
|
-
"""Returns the symmetric difference of the geometries
|
|
426
|
+
"""Returns the symmetric difference of the geometries
|
|
338
427
|
(Shapely geometry)"""
|
|
339
428
|
return geom_factory(self.impl['symmetric_difference'](self, other))
|
|
340
429
|
|
|
@@ -354,7 +443,7 @@ class BaseGeometry(object):
|
|
|
354
443
|
@property
|
|
355
444
|
def is_empty(self):
|
|
356
445
|
"""True if the set of points in this geometry is empty, else False"""
|
|
357
|
-
return bool(self.impl['is_empty'](self))
|
|
446
|
+
return (self._geom is None) or bool(self.impl['is_empty'](self))
|
|
358
447
|
|
|
359
448
|
@property
|
|
360
449
|
def is_ring(self):
|
|
@@ -363,13 +452,13 @@ class BaseGeometry(object):
|
|
|
363
452
|
|
|
364
453
|
@property
|
|
365
454
|
def is_simple(self):
|
|
366
|
-
"""True if the geometry is simple, meaning that any self-intersections
|
|
455
|
+
"""True if the geometry is simple, meaning that any self-intersections
|
|
367
456
|
are only at boundary points, else False"""
|
|
368
457
|
return bool(self.impl['is_simple'](self))
|
|
369
458
|
|
|
370
459
|
@property
|
|
371
460
|
def is_valid(self):
|
|
372
|
-
"""True if the geometry is valid (definition depends on sub-class),
|
|
461
|
+
"""True if the geometry is valid (definition depends on sub-class),
|
|
373
462
|
else False"""
|
|
374
463
|
return bool(self.impl['is_valid'](self))
|
|
375
464
|
|
|
@@ -377,7 +466,7 @@ class BaseGeometry(object):
|
|
|
377
466
|
# -----------------
|
|
378
467
|
|
|
379
468
|
def relate(self, other):
|
|
380
|
-
"""Returns the DE-9IM intersection matrix for the two geometries
|
|
469
|
+
"""Returns the DE-9IM intersection matrix for the two geometries
|
|
381
470
|
(string)"""
|
|
382
471
|
return self.impl['relate'](self, other)
|
|
383
472
|
|
|
@@ -414,13 +503,13 @@ class BaseGeometry(object):
|
|
|
414
503
|
return bool(self.impl['within'](self, other))
|
|
415
504
|
|
|
416
505
|
def equals_exact(self, other, tolerance):
|
|
417
|
-
"""Returns True if geometries are equal to within a specified
|
|
506
|
+
"""Returns True if geometries are equal to within a specified
|
|
418
507
|
tolerance"""
|
|
419
508
|
# return BinaryPredicateOp('equals_exact', self)(other, tolerance)
|
|
420
509
|
return bool(self.impl['equals_exact'](self, other, tolerance))
|
|
421
510
|
|
|
422
511
|
def almost_equals(self, other, decimal=6):
|
|
423
|
-
"""Returns True if geometries are equal at all coordinates to a
|
|
512
|
+
"""Returns True if geometries are equal at all coordinates to a
|
|
424
513
|
specified decimal place"""
|
|
425
514
|
return self.equals_exact(other, 0.5 * 10**(-decimal))
|
|
426
515
|
|
|
@@ -429,22 +518,22 @@ class BaseGeometry(object):
|
|
|
429
518
|
|
|
430
519
|
@delegated
|
|
431
520
|
def project(self, other, normalized=False):
|
|
432
|
-
"""Returns the distance along this geometry to a point nearest the
|
|
521
|
+
"""Returns the distance along this geometry to a point nearest the
|
|
433
522
|
specified point
|
|
434
|
-
|
|
523
|
+
|
|
435
524
|
If the normalized arg is True, return the distance normalized to the
|
|
436
525
|
length of the linear geometry.
|
|
437
|
-
"""
|
|
526
|
+
"""
|
|
438
527
|
if normalized:
|
|
439
528
|
op = self.impl['project_normalized']
|
|
440
529
|
else:
|
|
441
530
|
op = self.impl['project']
|
|
442
531
|
return op(self, other)
|
|
443
|
-
|
|
532
|
+
|
|
444
533
|
@delegated
|
|
445
534
|
def interpolate(self, distance, normalized=False):
|
|
446
535
|
"""Return a point at the specified distance along a linear geometry
|
|
447
|
-
|
|
536
|
+
|
|
448
537
|
If the normalized arg is True, the distance will be interpreted as a
|
|
449
538
|
fraction of the geometry's length.
|
|
450
539
|
"""
|
|
@@ -537,7 +626,7 @@ class GeometrySequence(object):
|
|
|
537
626
|
def _update(self):
|
|
538
627
|
self._geom = self.__p__._geom
|
|
539
628
|
self._ndim = self.__p__._ndim
|
|
540
|
-
|
|
629
|
+
|
|
541
630
|
def _get_geom_item(self, i):
|
|
542
631
|
g = self.shape_factory()
|
|
543
632
|
g._owned = True
|
|
@@ -597,7 +686,7 @@ class HeterogeneousGeometrySequence(GeometrySequence):
|
|
|
597
686
|
|
|
598
687
|
def _get_geom_item(self, i):
|
|
599
688
|
sub = lgeos.GEOSGetGeometryN(self._geom, i)
|
|
600
|
-
g = geom_factory(sub)
|
|
689
|
+
g = geom_factory(sub, parent=self)
|
|
601
690
|
g._owned = True
|
|
602
691
|
return g
|
|
603
692
|
|
shapely/geometry/base.pyc
CHANGED
|
Binary file
|
shapely/geometry/collection.pyc
CHANGED
|
Binary file
|
shapely/geometry/geo.py
CHANGED
|
@@ -11,14 +11,14 @@ from multipolygon import MultiPolygon, MultiPolygonAdapter
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def box(minx, miny, maxx, maxy, ccw=True):
|
|
14
|
-
"""
|
|
14
|
+
"""Returns a rectangular polygon with configurable normal vector"""
|
|
15
15
|
coords = [(maxx, miny), (maxx, maxy), (minx, maxy), (minx, miny)]
|
|
16
16
|
if not ccw:
|
|
17
17
|
coords = coords[::-1]
|
|
18
18
|
return Polygon(coords)
|
|
19
19
|
|
|
20
20
|
def shape(context):
|
|
21
|
-
"""
|
|
21
|
+
"""Returns a new, independent geometry with coordinates *copied* from the
|
|
22
22
|
context.
|
|
23
23
|
"""
|
|
24
24
|
if hasattr(context, "__geo_interface__"):
|
shapely/geometry/geo.pyc
CHANGED
|
Binary file
|
shapely/geometry/linestring.py
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
from ctypes import c_double, cast, POINTER
|
|
5
5
|
from ctypes import ArgumentError
|
|
6
6
|
|
|
7
|
+
from shapely.coords import required
|
|
7
8
|
from shapely.geos import lgeos, TopologicalError
|
|
8
|
-
from shapely.geometry.base import BaseGeometry, geom_factory
|
|
9
|
+
from shapely.geometry.base import BaseGeometry, geom_factory, JOIN_STYLE
|
|
9
10
|
from shapely.geometry.proxy import CachingGeometryProxy
|
|
10
11
|
|
|
11
12
|
__all__ = ['LineString', 'asLineString']
|
|
@@ -14,7 +15,7 @@ __all__ = ['LineString', 'asLineString']
|
|
|
14
15
|
class LineString(BaseGeometry):
|
|
15
16
|
"""
|
|
16
17
|
A one-dimensional figure comprising one or more line segments
|
|
17
|
-
|
|
18
|
+
|
|
18
19
|
A LineString has non-zero length and zero area. It may approximate a curve
|
|
19
20
|
and need not be straight. Unlike a LinearRing, a LineString is not closed.
|
|
20
21
|
"""
|
|
@@ -56,7 +57,7 @@ class LineString(BaseGeometry):
|
|
|
56
57
|
def array_interface(self):
|
|
57
58
|
"""Provide the Numpy array protocol."""
|
|
58
59
|
return self.coords.array_interface()
|
|
59
|
-
|
|
60
|
+
|
|
60
61
|
__array_interface__ = property(array_interface)
|
|
61
62
|
|
|
62
63
|
# Coordinate access
|
|
@@ -69,9 +70,9 @@ class LineString(BaseGeometry):
|
|
|
69
70
|
@property
|
|
70
71
|
def xy(self):
|
|
71
72
|
"""Separate arrays of X and Y coordinate values
|
|
72
|
-
|
|
73
|
+
|
|
73
74
|
Example:
|
|
74
|
-
|
|
75
|
+
|
|
75
76
|
>>> x, y = LineString(((0, 0), (1, 1))).xy
|
|
76
77
|
>>> list(x)
|
|
77
78
|
[0.0, 1.0]
|
|
@@ -79,22 +80,23 @@ class LineString(BaseGeometry):
|
|
|
79
80
|
[0.0, 1.0]
|
|
80
81
|
"""
|
|
81
82
|
return self.coords.xy
|
|
82
|
-
|
|
83
|
+
|
|
83
84
|
def parallel_offset(
|
|
84
|
-
self, distance, side,
|
|
85
|
-
resolution=16, join_style=
|
|
86
|
-
|
|
85
|
+
self, distance, side,
|
|
86
|
+
resolution=16, join_style=JOIN_STYLE.round, mitre_limit=1.0):
|
|
87
|
+
|
|
87
88
|
"""Returns a LineString or MultiLineString geometry at a distance from
|
|
88
89
|
the object on its right or its left side.
|
|
89
|
-
|
|
90
|
+
|
|
90
91
|
Distance must be a positive float value. The side parameter may be
|
|
91
92
|
'left' or 'right'. The resolution of the buffer around each vertex of
|
|
92
93
|
the object increases by increasing the resolution keyword parameter or
|
|
93
94
|
third positional parameter.
|
|
94
|
-
|
|
95
|
+
|
|
95
96
|
The join style is for outside corners between line segments. Accepted
|
|
96
|
-
values are 1
|
|
97
|
-
|
|
97
|
+
values are JOIN_STYLE.round (1), JOIN_STYLE.mitre (2), and
|
|
98
|
+
JOIN_STYLE.bevel (3).
|
|
99
|
+
|
|
98
100
|
The mitre ratio limit is used for very sharp corners. It is the ratio
|
|
99
101
|
of the distance from the corner to the end of the mitred offset corner.
|
|
100
102
|
When two line segments meet at a sharp angle, a miter join will extend
|
|
@@ -104,11 +106,11 @@ class LineString(BaseGeometry):
|
|
|
104
106
|
|
|
105
107
|
try:
|
|
106
108
|
return geom_factory(self.impl['parallel_offset'](
|
|
107
|
-
self, distance, resolution, join_style, mitre_limit,
|
|
109
|
+
self, distance, resolution, join_style, mitre_limit,
|
|
108
110
|
bool(side=='left')))
|
|
109
111
|
except WindowsError:
|
|
110
112
|
raise TopologicalError()
|
|
111
|
-
|
|
113
|
+
|
|
112
114
|
|
|
113
115
|
class LineStringAdapter(CachingGeometryProxy, LineString):
|
|
114
116
|
|
|
@@ -151,6 +153,9 @@ def asLineString(context):
|
|
|
151
153
|
|
|
152
154
|
|
|
153
155
|
def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
156
|
+
# If numpy is present, we use numpy.require to ensure that we have a
|
|
157
|
+
# C-continguous array that owns its data. View data will be copied.
|
|
158
|
+
ob = required(ob)
|
|
154
159
|
try:
|
|
155
160
|
# From array protocol
|
|
156
161
|
array = ob.__array_interface__
|
|
@@ -194,7 +199,7 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
|
194
199
|
except IndexError:
|
|
195
200
|
raise ValueError("Inconsistent coordinate dimensionality")
|
|
196
201
|
|
|
197
|
-
# Because of a bug in the GEOS C API,
|
|
202
|
+
# Because of a bug in the GEOS C API,
|
|
198
203
|
# always set X before Y
|
|
199
204
|
lgeos.GEOSCoordSeq_setX(cs, i, dx)
|
|
200
205
|
lgeos.GEOSCoordSeq_setY(cs, i, dy)
|
|
@@ -223,11 +228,11 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
|
223
228
|
% update_ndim)
|
|
224
229
|
else:
|
|
225
230
|
cs = lgeos.GEOSCoordSeq_create(m, n)
|
|
226
|
-
|
|
231
|
+
|
|
227
232
|
# add to coordinate sequence
|
|
228
233
|
for i in xrange(m):
|
|
229
234
|
coords = ob[i]
|
|
230
|
-
# Because of a bug in the GEOS C API,
|
|
235
|
+
# Because of a bug in the GEOS C API,
|
|
231
236
|
# always set X before Y
|
|
232
237
|
lgeos.GEOSCoordSeq_setX(cs, i, coords[0])
|
|
233
238
|
lgeos.GEOSCoordSeq_setY(cs, i, coords[1])
|
|
@@ -236,7 +241,7 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
|
236
241
|
lgeos.GEOSCoordSeq_setZ(cs, i, coords[2])
|
|
237
242
|
except IndexError:
|
|
238
243
|
raise ValueError("Inconsistent coordinate dimensionality")
|
|
239
|
-
|
|
244
|
+
|
|
240
245
|
if update_geom is not None:
|
|
241
246
|
return None
|
|
242
247
|
else:
|
shapely/geometry/linestring.pyc
CHANGED
|
Binary file
|
|
Binary file
|
shapely/geometry/multipoint.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from ctypes import byref, c_double, c_void_p, cast, POINTER
|
|
5
5
|
from ctypes import ArgumentError
|
|
6
6
|
|
|
7
|
+
from shapely.coords import required
|
|
7
8
|
from shapely.geos import lgeos
|
|
8
9
|
from shapely.geometry.base import BaseMultipartGeometry, exceptNull
|
|
9
10
|
from shapely.geometry.point import Point, geos_point_from_py
|
|
@@ -128,6 +129,9 @@ def asMultiPoint(context):
|
|
|
128
129
|
|
|
129
130
|
|
|
130
131
|
def geos_multipoint_from_py(ob):
|
|
132
|
+
# If numpy is present, we use numpy.require to ensure that we have a
|
|
133
|
+
# C-continguous array that owns its data. View data will be copied.
|
|
134
|
+
ob = required(ob)
|
|
131
135
|
try:
|
|
132
136
|
# From array protocol
|
|
133
137
|
array = ob.__array_interface__
|
shapely/geometry/multipoint.pyc
CHANGED
|
Binary file
|
shapely/geometry/multipolygon.py
CHANGED
|
@@ -50,7 +50,7 @@ class MultiPolygon(BaseMultipartGeometry):
|
|
|
50
50
|
"""
|
|
51
51
|
super(MultiPolygon, self).__init__()
|
|
52
52
|
|
|
53
|
-
if polygons
|
|
53
|
+
if not polygons:
|
|
54
54
|
# allow creation of empty multipolygons, to support unpickling
|
|
55
55
|
pass
|
|
56
56
|
elif context_type == 'polygons':
|
|
@@ -69,7 +69,7 @@ class MultiPolygon(BaseMultipartGeometry):
|
|
|
69
69
|
coords.append(tuple(geom.exterior.coords))
|
|
70
70
|
for hole in geom.interiors:
|
|
71
71
|
coords.append(tuple(hole.coords))
|
|
72
|
-
allcoords.append(coords)
|
|
72
|
+
allcoords.append(tuple(coords))
|
|
73
73
|
return {
|
|
74
74
|
'type': 'MultiPolygon',
|
|
75
75
|
'coordinates': allcoords
|
|
@@ -109,8 +109,9 @@ def asMultiPolygon(context):
|
|
|
109
109
|
def geos_multipolygon_from_py(ob):
|
|
110
110
|
"""ob must provide Python geo interface coordinates."""
|
|
111
111
|
L = len(ob)
|
|
112
|
-
N = len(ob[0][0][0])
|
|
113
112
|
assert L >= 1
|
|
113
|
+
|
|
114
|
+
N = len(ob[0][0][0])
|
|
114
115
|
assert N == 2 or N == 3
|
|
115
116
|
|
|
116
117
|
subs = (c_void_p * L)()
|
|
@@ -124,12 +125,14 @@ def geos_multipolygon_from_polygons(ob):
|
|
|
124
125
|
"""ob must be either a sequence or array of sequences or arrays."""
|
|
125
126
|
obs = getattr(ob, 'geoms', None) or ob
|
|
126
127
|
L = len(obs)
|
|
128
|
+
assert L >= 1
|
|
129
|
+
|
|
127
130
|
exemplar = obs[0]
|
|
128
131
|
try:
|
|
129
132
|
N = len(exemplar[0][0])
|
|
130
133
|
except TypeError:
|
|
131
134
|
N = exemplar._ndim
|
|
132
|
-
|
|
135
|
+
|
|
133
136
|
assert N == 2 or N == 3
|
|
134
137
|
|
|
135
138
|
subs = (c_void_p * L)()
|
|
Binary file
|
shapely/geometry/point.py
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
from ctypes import c_double
|
|
5
5
|
from ctypes import cast, POINTER
|
|
6
6
|
|
|
7
|
+
from shapely.coords import required
|
|
7
8
|
from shapely.geos import lgeos, DimensionError
|
|
8
9
|
from shapely.geometry.base import BaseGeometry
|
|
9
10
|
from shapely.geometry.proxy import CachingGeometryProxy
|
|
@@ -172,6 +173,9 @@ def geos_point_from_py(ob, update_geom=None, update_ndim=0):
|
|
|
172
173
|
|
|
173
174
|
Returns the GEOS geometry and the number of its dimensions.
|
|
174
175
|
"""
|
|
176
|
+
# If numpy is present, we use numpy.require to ensure that we have a
|
|
177
|
+
# C-continguous array that owns its data. View data will be copied.
|
|
178
|
+
ob = required(ob)
|
|
175
179
|
try:
|
|
176
180
|
# From array protocol
|
|
177
181
|
array = ob.__array_interface__
|
|
@@ -183,6 +187,9 @@ def geos_point_from_py(ob, update_geom=None, update_ndim=0):
|
|
|
183
187
|
da = array['data']
|
|
184
188
|
if type(da) == type((0,)):
|
|
185
189
|
cdata = da[0]
|
|
190
|
+
# If we had numpy, we would do
|
|
191
|
+
# from numpy.ctypeslib import as_ctypes
|
|
192
|
+
# cp = as_ctypes(ob) - check that code?
|
|
186
193
|
cp = cast(cdata, POINTER(c_double))
|
|
187
194
|
dx = c_double(cp[0])
|
|
188
195
|
dy = c_double(cp[1])
|
shapely/geometry/point.pyc
CHANGED
|
Binary file
|
shapely/geometry/polygon.py
CHANGED
|
@@ -6,6 +6,7 @@ from ctypes import ArgumentError
|
|
|
6
6
|
import weakref
|
|
7
7
|
|
|
8
8
|
from shapely.algorithms.cga import signed_area
|
|
9
|
+
from shapely.coords import required
|
|
9
10
|
from shapely.geos import lgeos
|
|
10
11
|
from shapely.geometry.base import BaseGeometry
|
|
11
12
|
from shapely.geometry.linestring import LineString, LineStringAdapter
|
|
@@ -65,9 +66,15 @@ class LinearRing(LineString):
|
|
|
65
66
|
|
|
66
67
|
@property
|
|
67
68
|
def is_ccw(self):
|
|
68
|
-
"""
|
|
69
|
+
"""True is the ring is oriented counter clock-wise"""
|
|
69
70
|
return bool(self.impl['is_ccw'](self))
|
|
70
71
|
|
|
72
|
+
@property
|
|
73
|
+
def is_simple(self):
|
|
74
|
+
"""True if the geometry is simple, meaning that any self-intersections
|
|
75
|
+
are only at boundary points, else False"""
|
|
76
|
+
return LineString(self).is_simple
|
|
77
|
+
|
|
71
78
|
|
|
72
79
|
class LinearRingAdapter(LineStringAdapter):
|
|
73
80
|
|
|
@@ -309,6 +316,9 @@ def orient(polygon, sign=1.0):
|
|
|
309
316
|
return Polygon(rings[0], rings[1:])
|
|
310
317
|
|
|
311
318
|
def geos_linearring_from_py(ob, update_geom=None, update_ndim=0):
|
|
319
|
+
# If numpy is present, we use numpy.require to ensure that we have a
|
|
320
|
+
# C-continguous array that owns its data. View data will be copied.
|
|
321
|
+
ob = required(ob)
|
|
312
322
|
try:
|
|
313
323
|
# From array protocol
|
|
314
324
|
array = ob.__array_interface__
|
shapely/geometry/polygon.pyc
CHANGED
|
Binary file
|
shapely/geometry/proxy.py
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
"""Proxy for coordinates stored outside Shapely geometries
|
|
2
2
|
"""
|
|
3
3
|
|
|
4
|
+
from shapely.geometry.base import deserialize_wkb, EMPTY
|
|
4
5
|
from shapely.geos import lgeos
|
|
5
|
-
from shapely import wkb
|
|
6
|
-
|
|
7
|
-
EMPTY = wkb.deserialize('010700000000000000'.decode('hex'))
|
|
8
6
|
|
|
9
7
|
|
|
10
8
|
class CachingGeometryProxy(object):
|
shapely/geometry/proxy.pyc
CHANGED
|
Binary file
|