shapely 1.0.3__tar.gz → 1.0.5__tar.gz

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.
Files changed (62) hide show
  1. Shapely-1.0.5/CHANGES.txt +24 -0
  2. {Shapely-1.0.3 → Shapely-1.0.5}/PKG-INFO +1 -1
  3. {Shapely-1.0.3 → Shapely-1.0.5}/Shapely.egg-info/PKG-INFO +1 -1
  4. {Shapely-1.0.3 → Shapely-1.0.5}/Shapely.egg-info/SOURCES.txt +3 -0
  5. {Shapely-1.0.3 → Shapely-1.0.5}/manual/manual.txt +35 -7
  6. {Shapely-1.0.3 → Shapely-1.0.5}/setup.py +1 -1
  7. {Shapely-1.0.3 → Shapely-1.0.5}/setup_windows.py +1 -1
  8. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/__init__.py +1 -2
  9. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/base.py +46 -8
  10. Shapely-1.0.5/shapely/geometry/collection.py +38 -0
  11. Shapely-1.0.5/shapely/geometry/geo.py +64 -0
  12. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/linestring.py +24 -18
  13. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/multilinestring.py +3 -11
  14. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/multipoint.py +3 -11
  15. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/multipolygon.py +3 -11
  16. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/point.py +3 -12
  17. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geometry/polygon.py +10 -17
  18. Shapely-1.0.5/shapely/geometry/proxy.py +48 -0
  19. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/iterops.py +2 -2
  20. Shapely-1.0.5/shapely/ops.py +29 -0
  21. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/predicates.py +2 -2
  22. {Shapely-1.0.3 → Shapely-1.0.5}/tests/LineString.txt +2 -2
  23. {Shapely-1.0.3 → Shapely-1.0.5}/tests/MultiPoint.txt +2 -2
  24. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Point.txt +4 -4
  25. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Polygon.txt +6 -0
  26. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Predicates.txt +1 -7
  27. Shapely-1.0.5/tests/polygonize.txt +29 -0
  28. Shapely-1.0.3/CHANGES.txt +0 -10
  29. Shapely-1.0.3/shapely/geometry/collection.py +0 -24
  30. Shapely-1.0.3/shapely/geometry/geo.py +0 -35
  31. {Shapely-1.0.3 → Shapely-1.0.5}/CREDITS.txt +0 -0
  32. {Shapely-1.0.3 → Shapely-1.0.5}/HISTORY.txt +0 -0
  33. {Shapely-1.0.3 → Shapely-1.0.5}/LICENSE.txt +0 -0
  34. {Shapely-1.0.3 → Shapely-1.0.5}/README.txt +0 -0
  35. {Shapely-1.0.3 → Shapely-1.0.5}/Shapely.egg-info/dependency_links.txt +0 -0
  36. {Shapely-1.0.3 → Shapely-1.0.5}/Shapely.egg-info/requires.txt +0 -0
  37. {Shapely-1.0.3 → Shapely-1.0.5}/Shapely.egg-info/top_level.txt +0 -0
  38. {Shapely-1.0.3 → Shapely-1.0.5}/examples/geoms.py +0 -0
  39. {Shapely-1.0.3 → Shapely-1.0.5}/examples/world.py +0 -0
  40. {Shapely-1.0.3 → Shapely-1.0.5}/manual/style.css +0 -0
  41. {Shapely-1.0.3 → Shapely-1.0.5}/setup.cfg +0 -0
  42. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/__init__.py +0 -0
  43. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/geos.py +0 -0
  44. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/kml.py +0 -0
  45. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/topology.py +0 -0
  46. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/wkb.py +0 -0
  47. {Shapely-1.0.3 → Shapely-1.0.5}/shapely/wkt.py +0 -0
  48. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Array.txt +0 -0
  49. {Shapely-1.0.3 → Shapely-1.0.5}/tests/GeoInterface.txt +0 -0
  50. {Shapely-1.0.3 → Shapely-1.0.5}/tests/IterOps.txt +0 -0
  51. {Shapely-1.0.3 → Shapely-1.0.5}/tests/MultiLineString.txt +0 -0
  52. {Shapely-1.0.3 → Shapely-1.0.5}/tests/MultiPolygon.txt +0 -0
  53. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Operations.txt +0 -0
  54. {Shapely-1.0.3 → Shapely-1.0.5}/tests/Persist.txt +0 -0
  55. {Shapely-1.0.3 → Shapely-1.0.5}/tests/__init__.py +0 -0
  56. {Shapely-1.0.3 → Shapely-1.0.5}/tests/attribute-chains.txt +0 -0
  57. {Shapely-1.0.3 → Shapely-1.0.5}/tests/binascii_hex.txt +0 -0
  58. {Shapely-1.0.3 → Shapely-1.0.5}/tests/invalid_intersection.txt +0 -0
  59. {Shapely-1.0.3 → Shapely-1.0.5}/tests/rungrind.dist +0 -0
  60. {Shapely-1.0.3 → Shapely-1.0.5}/tests/test_doctests.py +0 -0
  61. {Shapely-1.0.3 → Shapely-1.0.5}/tests/test_threads.py +0 -0
  62. {Shapely-1.0.3 → Shapely-1.0.5}/tests/valgrind-python.supp +0 -0
@@ -0,0 +1,24 @@
1
+ All tickets are children of http://trac.gispython.org/projects/PCL/ticket/
2
+
3
+ 1.0.5 (2008-05-20)
4
+ ------------------
5
+ - Added access to GEOS polygonizer function.
6
+ - Raise exception when insufficient coordinate tuples are passed to LinearRing
7
+ constructor (#164).
8
+
9
+ 1.0.4 (2008-05-01)
10
+ ------------------
11
+ - Disentangle Python and topological equality (#163).
12
+ - Add shape(), a factory that copies coordinates from a geo interface provider.
13
+ To be used instead of asShape() unless you really need to store coordinates
14
+ outside shapely for efficient use in other code.
15
+ - Cache GEOS geometries in adapters (#163).
16
+
17
+ 1.0.3 (2008-04-09)
18
+ ------------------
19
+ - Do not release GIL when calling GEOS functions (#158).
20
+ - Prevent faults when chaining multiple GEOS operators (#159).
21
+
22
+ 1.0.2 (2008-02-26)
23
+ ------------------
24
+ - Fix loss of dimensionality in polygon rings (#155).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: Geospatial geometries, predicates, and operations
5
5
  Home-page: http://trac.gispython.org/projects/PCL/wiki/Shapely
6
6
  Author: Sean Gillies
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.0.3
3
+ Version: 1.0.5
4
4
  Summary: Geospatial geometries, predicates, and operations
5
5
  Home-page: http://trac.gispython.org/projects/PCL/wiki/Shapely
6
6
  Author: Sean Gillies
@@ -18,6 +18,7 @@ shapely/__init__.py
18
18
  shapely/geos.py
19
19
  shapely/iterops.py
20
20
  shapely/kml.py
21
+ shapely/ops.py
21
22
  shapely/predicates.py
22
23
  shapely/topology.py
23
24
  shapely/wkb.py
@@ -32,6 +33,7 @@ shapely/geometry/multipoint.py
32
33
  shapely/geometry/multipolygon.py
33
34
  shapely/geometry/point.py
34
35
  shapely/geometry/polygon.py
36
+ shapely/geometry/proxy.py
35
37
  tests/Array.txt
36
38
  tests/GeoInterface.txt
37
39
  tests/IterOps.txt
@@ -48,6 +50,7 @@ tests/__init__.py
48
50
  tests/attribute-chains.txt
49
51
  tests/binascii_hex.txt
50
52
  tests/invalid_intersection.txt
53
+ tests/polygonize.txt
51
54
  tests/rungrind.dist
52
55
  tests/test_doctests.py
53
56
  tests/test_threads.py
@@ -4,16 +4,15 @@ The Shapely Manual
4
4
 
5
5
  :Author: Sean Gillies
6
6
  :address: sgillies@frii.com
7
- http://zcologia.com/sgillies
8
-
9
- :revision: 1.0
10
- :date: 2 January 2008
11
-
12
- :copyright: This work is licensed under a `Creative Commons Attribution 3.0 United States License`__.
7
+ :revision: 1.0.5
8
+ :date: 20 May 2008
9
+ :copyright: This work is licensed under a `Creative Commons Attribution 3.0
10
+ United States License`__.
13
11
 
14
12
  .. __: http://creativecommons.org/licenses/by/3.0/us/
15
13
 
16
- :abstract: This document describes the Shapely Python package for programming with geospatial geometries.
14
+ :abstract: This document describes the Shapely Python package for programming
15
+ with geospatial geometries.
17
16
 
18
17
  .. sectnum::
19
18
 
@@ -342,6 +341,32 @@ not:
342
341
  <shapely.geometry.polygon.Polygon object at ...>
343
342
 
344
343
 
344
+ Other Operations
345
+ ----------------
346
+
347
+ Polygonization
348
+ ++++++++++++++
349
+
350
+ shapely.ops.polygonize(lines) : iterator
351
+ Returns an iterator over polygons constructed from the *lines* iterator. The
352
+ elements of *lines* may be Shapely geometries, objects that provide the geo
353
+ interface, or Numpy arrays or Python sequences shaped like LineStrings.
354
+
355
+ .. code-block:: python
356
+
357
+ >>> from shapely.ops import polygonize
358
+ >>> lines = [
359
+ ... ((0, 0), (1, 1)),
360
+ ... ((0, 0), (0, 1)),
361
+ ... ((0, 1), (1, 1)),
362
+ ... ((1, 1), (1, 0)),
363
+ ... ((1, 0), (0, 0))
364
+ ... ]
365
+ >>> result = polygonize(lines)
366
+ >>> list(result.geoms)
367
+ [<shapely.geometry.polygon.Polygon object at ...>, <shapely.geometry.polygon.Polygon object at ...>]
368
+
369
+
345
370
  Unary Spatial Predicates
346
371
  ------------------------
347
372
 
@@ -798,6 +823,9 @@ Or a simple placemark-type object:
798
823
  >>> list(shape.coords)
799
824
  [(0.0, 0.0)]
800
825
 
826
+ If you want to copy coordinate data to a new geometry, use the
827
+ *shapely.geometry.shape* function instead.
828
+
801
829
  .. _Python geo interface: http://trac.gispython.org/projects/PCL/wiki/PythonGeoInterface
802
830
 
803
831
 
@@ -11,7 +11,7 @@ if version_info[:2] < (2,5):
11
11
  readme_text = file('README.txt', 'rb').read()
12
12
 
13
13
  setup(name = 'Shapely',
14
- version = '1.0.3',
14
+ version = '1.0.5',
15
15
  description = 'Geospatial geometries, predicates, and operations',
16
16
  license = 'BSD',
17
17
  keywords = 'geometry topology',
@@ -11,7 +11,7 @@ if version_info[:2] < (2,5):
11
11
  readme_text = file('README.txt', 'rb').read()
12
12
 
13
13
  setup(name = 'Shapely',
14
- version = '1.0.3',
14
+ version = '1.0.5',
15
15
  description = 'Geospatial geometries, predicates, and operations',
16
16
  license = 'BSD',
17
17
  keywords = 'geometry topology',
@@ -1,4 +1,4 @@
1
- from geo import asShape
1
+ from geo import shape, asShape
2
2
  from point import Point, asPoint
3
3
  from linestring import LineString, asLineString
4
4
  from polygon import Polygon, asPolygon
@@ -6,4 +6,3 @@ from multipoint import MultiPoint, asMultiPoint
6
6
  from multilinestring import MultiLineString, asMultiLineString
7
7
  from multipolygon import MultiPolygon, asMultiPolygon
8
8
  from collection import GeometryCollection
9
-
@@ -207,11 +207,29 @@ class GeometrySequence(object):
207
207
  max = l
208
208
 
209
209
 
210
+ class HeterogeneousGeometrySequence(GeometrySequence):
211
+
212
+ def __init__(self, parent):
213
+ self.__p__ = parent
214
+ self._geom = parent._geom
215
+ self._ndim = parent._ndim
216
+
217
+ def next(self):
218
+ if self._index < self.__len__():
219
+ sub = lgeos.GEOSGetGeometryN(self._geom, self._index)
220
+ g = geom_factory(sub)
221
+ g._owned = True
222
+ self._index += 1
223
+ return g
224
+ else:
225
+ raise StopIteration
226
+
227
+
210
228
  def exceptNull(func):
211
229
  """Decorator which helps avoid GEOS operations on null pointers."""
212
230
  def wrapper(*args, **kwargs):
213
231
  # self is the first arg
214
- if args[0]._geom is None:
232
+ if not args[0]._geom:
215
233
  raise ValueError, "Null geometry supports no operations"
216
234
  return func(*args, **kwargs)
217
235
  return wrapper
@@ -220,7 +238,7 @@ def exceptEitherNull(func):
220
238
  """Decorator which avoids GEOS operations on one or more null pointers."""
221
239
  def wrapper(*args, **kwargs):
222
240
  # self is the first arg
223
- if args[0]._geom is None or args[1]._geom is None:
241
+ if not args[0]._geom or not args[1]._geom:
224
242
  raise ValueError, "Null geometry supports no operations"
225
243
  return func(*args, **kwargs)
226
244
  return wrapper
@@ -248,12 +266,6 @@ class BaseGeometry(object):
248
266
  def __str__(self):
249
267
  return self.to_wkt()
250
268
 
251
- def __eq__(self, other):
252
- return self.equals(other)
253
-
254
- def __ne__(self, other):
255
- return not self.equals(other)
256
-
257
269
  # To support pickling
258
270
 
259
271
  def __reduce__(self):
@@ -465,3 +477,29 @@ class BaseGeometry(object):
465
477
 
466
478
  return (minx, miny, maxx, maxy)
467
479
 
480
+
481
+ class BaseMultiPartGeometry(BaseGeometry):
482
+
483
+ @property
484
+ def ctypes(self):
485
+ raise NotImplementedError, \
486
+ "Multi-part geometries have no ctypes representations"
487
+
488
+ @property
489
+ def __array_interface__(self):
490
+ """Provide the Numpy array protocol."""
491
+ raise NotImplementedError, \
492
+ "Multi-part geometries do not themselves provide the array interface"
493
+
494
+ def _get_coords(self):
495
+ raise NotImplementedError, \
496
+ "Sub-geometries may have coordinate sequences, but collections do not"
497
+
498
+ def _set_coords(self, ob):
499
+ raise NotImplementedError, \
500
+ "Sub-geometries may have coordinate sequences, but collections do not"
501
+
502
+ @property
503
+ def coords(self):
504
+ raise NotImplementedError, \
505
+ "Multi-part geometries do not provide a coordinate sequence"
@@ -0,0 +1,38 @@
1
+ """
2
+ Geometry collections.
3
+ """
4
+
5
+ from shapely.geometry.base import BaseMultiPartGeometry
6
+ from shapely.geometry.base import HeterogeneousGeometrySequence, exceptNull
7
+
8
+
9
+ class GeometryCollection(BaseMultiPartGeometry):
10
+
11
+ """A geometry collection.
12
+ """
13
+
14
+ def __init__(self):
15
+ BaseMultiPartGeometry.__init__(self)
16
+
17
+ @property
18
+ def __geo_interface__(self):
19
+ geometries = []
20
+ for geom in self.geoms:
21
+ geometries.append(geom.__geo_interface__)
22
+ return dict(type='GeometryCollection', geometries=geometries)
23
+
24
+ @property
25
+ @exceptNull
26
+ def geoms(self):
27
+ return HeterogeneousGeometrySequence(self)
28
+
29
+
30
+ # Test runner
31
+ def _test():
32
+ import doctest
33
+ doctest.testmod()
34
+
35
+
36
+ if __name__ == "__main__":
37
+ _test()
38
+
@@ -0,0 +1,64 @@
1
+ """
2
+ Geometry factories based on the geo interface.
3
+ """
4
+
5
+ from point import Point, asPoint
6
+ from linestring import LineString, asLineString
7
+ from polygon import Polygon, asPolygon
8
+ from multipoint import MultiPoint, asMultiPoint
9
+ from multilinestring import MultiLineString, asMultiLineString
10
+ from multipolygon import MultiPolygon, asMultiPolygon
11
+
12
+
13
+ def shape(context):
14
+ """Return a new, independent geometry with coordinates *copied* from the
15
+ context.
16
+ """
17
+ if hasattr(context, "__geo_interface__"):
18
+ ob = context.__geo_interface__
19
+ else:
20
+ ob = context
21
+ geom_type = ob.get("type").lower()
22
+ if geom_type == "point":
23
+ return Point(ob["coordinates"])
24
+ elif geom_type == "linestring":
25
+ return LineString(ob["coordinates"])
26
+ elif geom_type == "polygon":
27
+ return Polygon(ob["coordinates"][0], ob["coordinates"][1:])
28
+ elif geom_type == "multipoint":
29
+ return MultiPoint(ob["coordinates"])
30
+ elif geom_type == "multilinestring":
31
+ return MultiLineString(ob["coordinates"])
32
+ elif geom_type == "multipolygon":
33
+ return MultiPolygon(ob["coordinates"])
34
+ else:
35
+ raise ValueError, "Unknown geometry type: %s" % geom_type
36
+
37
+ def asShape(context):
38
+ """Adapts the context to a geometry interface. The coordinates remain
39
+ stored in the context.
40
+ """
41
+ if hasattr(context, "__geo_interface__"):
42
+ ob = context.__geo_interface__
43
+ else:
44
+ ob = context
45
+
46
+ try:
47
+ geom_type = ob.get("type").lower()
48
+ except AttributeError:
49
+ raise ValueError, "Context does not provide geo interface"
50
+
51
+ if geom_type == "point":
52
+ return asPoint(ob["coordinates"])
53
+ elif geom_type == "linestring":
54
+ return asLineString(ob["coordinates"])
55
+ elif geom_type == "polygon":
56
+ return asPolygon(ob["coordinates"][0], ob["coordinates"][1:])
57
+ elif geom_type == "multipoint":
58
+ return asMultiPoint(ob["coordinates"])
59
+ elif geom_type == "multilinestring":
60
+ return asMultiLineString(ob["coordinates"])
61
+ elif geom_type == "multipolygon":
62
+ return asMultiPolygon(ob["coordinates"])
63
+ else:
64
+ raise ValueError, "Unknown geometry type: %s" % geom_type
@@ -7,6 +7,7 @@ from ctypes import ArgumentError
7
7
 
8
8
  from shapely.geos import lgeos
9
9
  from shapely.geometry.base import BaseGeometry, exceptNull
10
+ from shapely.geometry.proxy import CachingGeometryProxy
10
11
 
11
12
 
12
13
  def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
@@ -15,8 +16,12 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
15
16
  array = ob.__array_interface__
16
17
  assert len(array['shape']) == 2
17
18
  m = array['shape'][0]
18
- n = array['shape'][1]
19
- assert m >= 2
19
+ if m < 2:
20
+ raise ValueError, "LineStrings must have at least 2 coordinate tuples"
21
+ try:
22
+ n = array['shape'][1]
23
+ except IndexError:
24
+ raise ValueError, "Input %s is the wrong shape for a LineString" % str(ob)
20
25
  assert n == 2 or n == 3
21
26
 
22
27
  # Make pointer to the coordinate array
@@ -41,8 +46,11 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
41
46
  dy = c_double(cp[n*i+1])
42
47
  dz = None
43
48
  if n == 3:
44
- dz = c_double(cp[n*i+2])
45
-
49
+ try:
50
+ dz = c_double(cp[n*i+2])
51
+ except IndexError:
52
+ raise ValueError, "Inconsistent coordinate dimensionality"
53
+
46
54
  # Because of a bug in the GEOS C API,
47
55
  # always set X before Y
48
56
  lgeos.GEOSCoordSeq_setX(cs, i, dx)
@@ -53,8 +61,12 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
53
61
  except AttributeError:
54
62
  # Fall back on list
55
63
  m = len(ob)
56
- n = len(ob[0])
57
- assert m >= 2
64
+ if m < 2:
65
+ raise ValueError, "LineStrings must have at least 2 coordinate tuples"
66
+ try:
67
+ n = len(ob[0])
68
+ except TypeError:
69
+ raise ValueError, "Input %s is the wrong shape for a LineString" % str(ob)
58
70
  assert n == 2 or n == 3
59
71
 
60
72
  # Create a coordinate sequence
@@ -74,7 +86,10 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
74
86
  dy = c_double(coords[1])
75
87
  dz = None
76
88
  if n == 3:
77
- dz = c_double(coords[2])
89
+ try:
90
+ dz = c_double(coords[2])
91
+ except IndexError:
92
+ raise ValueError, "Inconsistent coordinate dimensionality"
78
93
 
79
94
  # Because of a bug in the GEOS C API,
80
95
  # always set X before Y
@@ -157,18 +172,18 @@ class LineString(BaseGeometry):
157
172
  coords = property(BaseGeometry._get_coords, _set_coords)
158
173
 
159
174
 
160
- class LineStringAdapter(LineString):
175
+ class LineStringAdapter(CachingGeometryProxy, LineString):
161
176
 
162
177
  """Adapts a Python coordinate pair or a numpy array to the line string
163
178
  interface.
164
179
  """
165
180
 
166
181
  context = None
167
- #__geom = None
168
182
  _owned = False
169
183
 
170
184
  def __init__(self, context):
171
185
  self.context = context
186
+ self.factory = geos_linestring_from_py
172
187
 
173
188
  @property
174
189
  def _ndim(self):
@@ -182,14 +197,6 @@ class LineStringAdapter(LineString):
182
197
  # Fall back on list
183
198
  return len(self.context[0])
184
199
 
185
- @property
186
- def _geom(self):
187
- """Keeps the GEOS geometry in synch with the context."""
188
- if self.__geom__ is not None:
189
- lgeos.GEOSGeom_destroy(self.__geom__)
190
- self.__geom__, n = geos_linestring_from_py(self.context)
191
- return self.__geom__
192
-
193
200
  @property
194
201
  def __array_interface__(self):
195
202
  """Provide the Numpy array protocol."""
@@ -220,4 +227,3 @@ def _test():
220
227
 
221
228
  if __name__ == "__main__":
222
229
  _test()
223
-
@@ -7,6 +7,7 @@ from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
7
7
  from shapely.geos import lgeos
8
8
  from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
9
  from shapely.geometry.linestring import LineString, geos_linestring_from_py
10
+ from shapely.geometry.proxy import CachingGeometryProxy
10
11
 
11
12
 
12
13
  def geos_multilinestring_from_py(ob):
@@ -115,18 +116,18 @@ class MultiLineString(BaseGeometry):
115
116
  return GeometrySequence(self, LineString)
116
117
 
117
118
 
118
- class MultiLineStringAdapter(MultiLineString):
119
+ class MultiLineStringAdapter(CachingGeometryProxy, MultiLineString):
119
120
 
120
121
  """Adapts sequences of sequences or numpy arrays to the multilinestring
121
122
  interface.
122
123
  """
123
124
 
124
125
  context = None
125
- #__geom = None
126
126
  _owned = False
127
127
 
128
128
  def __init__(self, context):
129
129
  self.context = context
130
+ self.factory = geos_multilinestring_from_py
130
131
 
131
132
  @property
132
133
  def _ndim(self):
@@ -140,14 +141,6 @@ class MultiLineStringAdapter(MultiLineString):
140
141
  # Fall back on list
141
142
  return len(self.context[0][0])
142
143
 
143
- @property
144
- def _geom(self):
145
- """Keeps the GEOS geometry in synch with the context."""
146
- if self.__geom__ is not None:
147
- lgeos.GEOSGeom_destroy(self.__geom__)
148
- self.__geom__ = geos_multilinestring_from_py(self.context)[0]
149
- return self.__geom__
150
-
151
144
 
152
145
  def asMultiLineString(context):
153
146
  """Factory for MultiLineStringAdapter instances."""
@@ -162,4 +155,3 @@ def _test():
162
155
 
163
156
  if __name__ == "__main__":
164
157
  _test()
165
-
@@ -7,6 +7,7 @@ from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
7
7
  from shapely.geos import lgeos
8
8
  from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
9
  from shapely.geometry.point import Point, geos_point_from_py
10
+ from shapely.geometry.proxy import CachingGeometryProxy
10
11
 
11
12
 
12
13
  def geos_multipoint_from_py(ob):
@@ -137,18 +138,18 @@ class MultiPoint(BaseGeometry):
137
138
  return GeometrySequence(self, Point)
138
139
 
139
140
 
140
- class MultiPointAdapter(MultiPoint):
141
+ class MultiPointAdapter(CachingGeometryProxy, MultiPoint):
141
142
 
142
143
  """Adapts a Python coordinate pair or a numpy array to the multipoint
143
144
  interface.
144
145
  """
145
146
 
146
147
  context = None
147
- #__geom__ = None
148
148
  _owned = False
149
149
 
150
150
  def __init__(self, context):
151
151
  self.context = context
152
+ self.factory = geos_multipoint_from_py
152
153
 
153
154
  @property
154
155
  def _ndim(self):
@@ -162,14 +163,6 @@ class MultiPointAdapter(MultiPoint):
162
163
  # Fall back on list
163
164
  return len(self.context[0])
164
165
 
165
- @property
166
- def _geom(self):
167
- """Keeps the GEOS geometry in synch with the context."""
168
- if self.__geom__ is not None:
169
- lgeos.GEOSGeom_destroy(self.__geom__)
170
- self.__geom__, n = geos_multipoint_from_py(self.context)
171
- return self.__geom__
172
-
173
166
  @property
174
167
  def __array_interface__(self):
175
168
  """Provide the Numpy array protocol."""
@@ -192,4 +185,3 @@ def _test():
192
185
 
193
186
  if __name__ == "__main__":
194
187
  _test()
195
-
@@ -7,6 +7,7 @@ from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
7
7
  from shapely.geos import lgeos
8
8
  from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
9
  from shapely.geometry.polygon import Polygon, geos_polygon_from_py
10
+ from shapely.geometry.proxy import CachingGeometryProxy
10
11
 
11
12
 
12
13
  def geos_multipolygon_from_py(ob):
@@ -101,18 +102,18 @@ class MultiPolygon(BaseGeometry):
101
102
  return GeometrySequence(self, Polygon)
102
103
 
103
104
 
104
- class MultiPolygonAdapter(MultiPolygon):
105
+ class MultiPolygonAdapter(CachingGeometryProxy, MultiPolygon):
105
106
 
106
107
  """Adapts sequences of sequences or numpy arrays to the multipolygon
107
108
  interface.
108
109
  """
109
110
 
110
111
  context = None
111
- #__geom = None
112
112
  _owned = False
113
113
 
114
114
  def __init__(self, context):
115
115
  self.context = context
116
+ self.factory = geos_multipolygon_from_py
116
117
 
117
118
  @property
118
119
  def _ndim(self):
@@ -126,14 +127,6 @@ class MultiPolygonAdapter(MultiPolygon):
126
127
  # Fall back on list
127
128
  return len(self.context[0][0][0])
128
129
 
129
- @property
130
- def _geom(self):
131
- """Keeps the GEOS geometry in synch with the context."""
132
- if self.__geom__ is not None:
133
- lgeos.GEOSGeom_destroy(self.__geom__)
134
- self.__geom__ = geos_multipolygon_from_py(self.context)[0]
135
- return self.__geom__
136
-
137
130
 
138
131
  def asMultiPolygon(context):
139
132
  """Factory for MultiLineStringAdapter instances."""
@@ -148,4 +141,3 @@ def _test():
148
141
 
149
142
  if __name__ == "__main__":
150
143
  _test()
151
-
@@ -10,6 +10,7 @@ from ctypes import cast, POINTER
10
10
  from shapely.geos import lgeos, DimensionError
11
11
  from shapely.geometry.base import BaseGeometry, CoordinateSequence
12
12
  from shapely.geometry.base import exceptNull
13
+ from shapely.geometry.proxy import CachingGeometryProxy
13
14
 
14
15
 
15
16
  def geos_point_from_py(ob, update_geom=None, update_ndim=0):
@@ -199,17 +200,16 @@ class Point(BaseGeometry):
199
200
  coords = property(BaseGeometry._get_coords, _set_coords)
200
201
 
201
202
 
202
- class PointAdapter(Point):
203
+ class PointAdapter(CachingGeometryProxy, Point):
203
204
 
204
205
  """Adapts a Python coordinate pair or a numpy array to the point interface.
205
206
  """
206
207
 
207
- context = None
208
- __geom = None
209
208
  _owned = False
210
209
 
211
210
  def __init__(self, context):
212
211
  self.context = context
212
+ self.factory = geos_point_from_py
213
213
 
214
214
  @property
215
215
  def _ndim(self):
@@ -223,14 +223,6 @@ class PointAdapter(Point):
223
223
  # Fall back on list
224
224
  return len(self.context)
225
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
226
  # TODO: reimplement x, y, z properties without calling invoking _geom
235
227
 
236
228
  @property
@@ -262,4 +254,3 @@ def _test():
262
254
 
263
255
  if __name__ == "__main__":
264
256
  _test()
265
-
@@ -7,6 +7,7 @@ from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
7
7
  from shapely.geos import lgeos
8
8
  from shapely.geometry.base import BaseGeometry, exceptNull
9
9
  from shapely.geometry.linestring import LineString, LineStringAdapter
10
+ from shapely.geometry.proxy import PolygonProxy
10
11
 
11
12
 
12
13
  def geos_linearring_from_py(ob, update_geom=None, update_ndim=0):
@@ -16,7 +17,8 @@ def geos_linearring_from_py(ob, update_geom=None, update_ndim=0):
16
17
  assert len(array['shape']) == 2
17
18
  m = array['shape'][0]
18
19
  n = array['shape'][1]
19
- assert m >= 2
20
+ if m < 3:
21
+ raise ValueError, "A LinearRing must have at least 3 coordinate tuples"
20
22
  assert n == 2 or n == 3
21
23
 
22
24
  # Make pointer to the coordinate array
@@ -75,8 +77,9 @@ def geos_linearring_from_py(ob, update_geom=None, update_ndim=0):
75
77
  # Fall back on list
76
78
  m = len(ob)
77
79
  n = len(ob[0])
78
- assert m >= 2
79
- assert n == 2 or n == 3
80
+ if m < 3:
81
+ raise ValueError, "A LinearRing must have at least 3 coordinate tuples"
82
+ assert (n == 2 or n == 3)
80
83
 
81
84
  # Add closing coordinates if not provided
82
85
  if ob[0][0] != ob[-1][0] or ob[0][1] != ob[-1][1]:
@@ -282,10 +285,7 @@ def geos_polygon_from_py(shell, holes=None):
282
285
  if holes:
283
286
  ob = holes
284
287
  L = len(ob)
285
- try:
286
- N = len(ob[0][0])
287
- except:
288
- import pdb; pdb.set_trace()
288
+ N = len(ob[0][0])
289
289
  assert L >= 1
290
290
  assert N == 2 or N == 3
291
291
 
@@ -395,7 +395,7 @@ class Polygon(BaseGeometry):
395
395
  }
396
396
 
397
397
 
398
- class PolygonAdapter(Polygon):
398
+ class PolygonAdapter(PolygonProxy, Polygon):
399
399
 
400
400
  """Adapts sequences of sequences or numpy arrays to the polygon
401
401
  interface.
@@ -408,6 +408,8 @@ class PolygonAdapter(Polygon):
408
408
  def __init__(self, shell, holes=None):
409
409
  self.shell = shell
410
410
  self.holes = holes
411
+ self.context = (shell, holes)
412
+ self.factory = geos_polygon_from_py
411
413
 
412
414
  @property
413
415
  def _ndim(self):
@@ -421,14 +423,6 @@ class PolygonAdapter(Polygon):
421
423
  # Fall back on list
422
424
  return len(self.shell[0])
423
425
 
424
- @property
425
- def _geom(self):
426
- """Keeps the GEOS geometry in synch with the context."""
427
- if self.__geom__ is not None:
428
- lgeos.GEOSGeom_destroy(self.__geom__)
429
- self.__geom__ = geos_polygon_from_py(self.shell, self.holes)[0]
430
- return self.__geom__
431
-
432
426
 
433
427
  def asPolygon(shell, holes=None):
434
428
  """Factory for PolygonAdapter instances."""
@@ -442,4 +436,3 @@ def _test():
442
436
 
443
437
  if __name__ == "__main__":
444
438
  _test()
445
-
@@ -0,0 +1,48 @@
1
+ """
2
+ Proxy for coordinates stored outside Shapely geometries.
3
+ """
4
+
5
+ from shapely.geos import lgeos
6
+
7
+
8
+ class CachingGeometryProxy(object):
9
+
10
+ context = None
11
+ factory = None
12
+ __geom__ = None
13
+ _gtag = None
14
+
15
+ def __init__(self, context):
16
+ self.context = context
17
+
18
+ @property
19
+ def _geom(self):
20
+ """Keeps the GEOS geometry in synch with the context."""
21
+ gtag = self.gtag()
22
+ if gtag != self._gtag:
23
+ if self.__geom__ is not None:
24
+ lgeos.GEOSGeom_destroy(self.__geom__)
25
+ self.__geom__, n = self.factory(self.context)
26
+ elif self.__geom__ is None:
27
+ self.__geom__, n = self.factory(self.context)
28
+ self._gtag = gtag
29
+ return self.__geom__
30
+
31
+ def gtag(self):
32
+ return hash(repr(self.context))
33
+
34
+
35
+ class PolygonProxy(CachingGeometryProxy):
36
+
37
+ @property
38
+ def _geom(self):
39
+ """Keeps the GEOS geometry in synch with the context."""
40
+ gtag = self.gtag()
41
+ if gtag != self._gtag:
42
+ if self.__geom__ is not None:
43
+ lgeos.GEOSGeom_destroy(self.__geom__)
44
+ self.__geom__, n = self.factory(self.context[0], self.context[1])
45
+ elif self.__geom__ is None:
46
+ self.__geom__, n = self.factory(self.context[0], self.context[1])
47
+ self._gtag = gtag
48
+ return self.__geom__
@@ -1,4 +1,5 @@
1
1
  """
2
+ Iterative forms of operations.
2
3
  """
3
4
 
4
5
  from ctypes import c_char_p, c_size_t
@@ -36,7 +37,7 @@ class BinaryPredicateIterator(object):
36
37
  except TypeError:
37
38
  this_geom = item
38
39
  ob = this_geom
39
- if this_geom._geom is None:
40
+ if not this_geom._geom:
40
41
  raise ValueError, "Null geometry supports no operations"
41
42
  retval = self.fn(geom._geom, this_geom._geom)
42
43
  if retval == 2:
@@ -53,4 +54,3 @@ within = BinaryPredicateIterator(lgeos.GEOSWithin)
53
54
  contains = BinaryPredicateIterator(lgeos.GEOSContains)
54
55
  overlaps = BinaryPredicateIterator(lgeos.GEOSOverlaps)
55
56
  equals = BinaryPredicateIterator(lgeos.GEOSEquals)
56
-
@@ -0,0 +1,29 @@
1
+ from shapely.geos import lgeos
2
+ from shapely.geometry.base import geom_factory, BaseGeometry
3
+ from shapely.geometry import asShape, asLineString
4
+ from ctypes import byref, c_void_p
5
+
6
+ def shapeup(ob):
7
+ if isinstance(ob, BaseGeometry):
8
+ return ob
9
+ else:
10
+ try:
11
+ return asShape(ob)
12
+ except ValueError:
13
+ return asLineString(ob)
14
+
15
+ def polygonize(iterator):
16
+ """Creates polygons from a list of LineString objects.
17
+ """
18
+ lines = [shapeup(ob) for ob in iterator]
19
+ geom_array_type = c_void_p * len(lines)
20
+ geom_array = geom_array_type()
21
+ for i, line in enumerate(lines):
22
+ geom_array[i] = line._geom
23
+ product = lgeos.GEOSPolygonize(byref(geom_array), len(lines))
24
+ collection = geom_factory(product)
25
+ for g in collection.geoms:
26
+ clone = lgeos.GEOSGeom_clone(g._geom)
27
+ g = geom_factory(clone)
28
+ g._owned = False
29
+ yield g
@@ -27,7 +27,7 @@ class BinaryPredicate(object):
27
27
  return self
28
28
 
29
29
  def __call__(self, other):
30
- if self.context._geom is None or other._geom is None:
30
+ if not self.context._geom or not other._geom:
31
31
  raise ValueError, "Null geometry supports no operations"
32
32
  return bool(self.fn(self.context._geom, other._geom))
33
33
 
@@ -49,7 +49,7 @@ class UnaryPredicate(object):
49
49
  self.fn.errcheck = errcheck
50
50
 
51
51
  def __get__(self, obj, objtype=None):
52
- if obj._geom is None:
52
+ if not obj._geom:
53
53
  raise ValueError, "Null geometry supports no operations"
54
54
  return bool(self.fn(obj._geom))
55
55
 
@@ -97,8 +97,8 @@ Now, the inverse
97
97
 
98
98
  >>> la.__array_interface__ == la.context.__array_interface__
99
99
  True
100
- >>> as = asarray(la)
101
- >>> as
100
+ >>> pas = asarray(la)
101
+ >>> pas
102
102
  array([[ 1., 2.],
103
103
  [ 3., 4.]])
104
104
 
@@ -71,8 +71,8 @@ Adapter
71
71
  >>> geoma.__array_interface__ == geoma.context.__array_interface__
72
72
  True
73
73
  >>> from numpy import asarray
74
- >>> as = asarray(geoma)
75
- >>> as
74
+ >>> pas = asarray(geoma)
75
+ >>> pas
76
76
  array([[ 1., 2.],
77
77
  [ 3., 4.]])
78
78
 
@@ -99,8 +99,8 @@ Adapter
99
99
  >>> pa.__array_interface__ == pa.context.__array_interface__
100
100
  True
101
101
  >>> from numpy import asarray
102
- >>> as = asarray(pa)
103
- >>> as
102
+ >>> pas = asarray(pa)
103
+ >>> pas
104
104
  array([ 1., 2.])
105
105
 
106
106
  Adapt a coordinate list to a point
@@ -123,8 +123,8 @@ Adapter
123
123
  Now, the inverse
124
124
 
125
125
  >>> ai = pa.__array_interface__
126
- >>> as = asarray(pa)
127
- >>> as
126
+ >>> pas = asarray(pa)
127
+ >>> pas
128
128
  array([ 1., 4.])
129
129
 
130
130
  Test Non-operability of Null geometry
@@ -139,4 +139,10 @@ Check that we can set coordinates of a null geometry
139
139
  >>> print r_null.length # doctest: +ELLIPSIS
140
140
  3.414...
141
141
 
142
+ Error handling
143
+ --------------
142
144
 
145
+ >>> p = Polygon([[1,2], [2, 3]])
146
+ Traceback (most recent call last):
147
+ ...
148
+ ValueError: A LinearRing must have at least 3 coordinate tuples
@@ -28,13 +28,7 @@ Binary Predicates
28
28
  >>> point.equals(Point(-1.0, -1.0))
29
29
  False
30
30
 
31
- >>> point == Point(0.0, 0.0)
32
- True
33
-
34
- >>> point == Point(-1.0, -1.0)
35
- False
36
-
37
- >>> point != Point(-1.0, -1.0)
31
+ >>> point.equals(Point(0.0, 0.0))
38
32
  True
39
33
 
40
34
  Unary Predicates
@@ -0,0 +1,29 @@
1
+ Polygonizing
2
+ ============
3
+
4
+ >>> from shapely.geometry import LineString, Point
5
+ >>> from shapely.ops import polygonize
6
+ >>> lines = [
7
+ ... LineString(((0, 0), (1, 1))),
8
+ ... LineString(((0, 0), (0, 1))),
9
+ ... LineString(((0, 1), (1, 1))),
10
+ ... LineString(((1, 1), (1, 0))),
11
+ ... LineString(((1, 0), (0, 0))),
12
+ ... LineString(((5, 5), (6, 6))),
13
+ ... Point(0, 0),
14
+ ... ]
15
+ >>> result = polygonize(lines)
16
+ >>> list(result)
17
+ [<shapely.geometry.polygon.Polygon object at ...>, <shapely.geometry.polygon.Polygon object at ...>]
18
+
19
+ >>> lines2 = [
20
+ ... ((0, 0), (1, 1)),
21
+ ... ((0, 0), (0, 1)),
22
+ ... ((0, 1), (1, 1)),
23
+ ... ((1, 1), (1, 0)),
24
+ ... ((1, 0), (0, 0)),
25
+ ... ((5, 5), (6, 6)),
26
+ ... ]
27
+ >>> result2 = polygonize(lines2)
28
+ >>> list(result2)
29
+ [<shapely.geometry.polygon.Polygon object at ...>, <shapely.geometry.polygon.Polygon object at ...>]
Shapely-1.0.3/CHANGES.txt DELETED
@@ -1,10 +0,0 @@
1
- All tickets are children of http://trac.gispython.org/projects/PCL/ticket/
2
-
3
- 1.0.3 (2008-04-09)
4
- ------------------
5
- - Do not release GIL when calling GEOS functions (#158).
6
- - Prevent faults when chaining multiple GEOS operators (#159).
7
-
8
- 1.0.2 (2008-02-26)
9
- ------------------
10
- - Fix loss of dimensionality in polygon rings (#155).
@@ -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
-
@@ -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
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes