shapely 1.0b3__tar.gz → 1.0b4__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 (54) hide show
  1. {Shapely-1.0b3 → Shapely-1.0b4}/PKG-INFO +2 -2
  2. {Shapely-1.0b3 → Shapely-1.0b4}/README.txt +1 -1
  3. {Shapely-1.0b3 → Shapely-1.0b4}/Shapely.egg-info/PKG-INFO +2 -2
  4. {Shapely-1.0b3 → Shapely-1.0b4}/manual/manual.txt +79 -5
  5. {Shapely-1.0b3 → Shapely-1.0b4}/setup.py +1 -1
  6. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/base.py +68 -11
  7. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/linestring.py +13 -7
  8. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/multilinestring.py +8 -6
  9. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/multipoint.py +12 -7
  10. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/multipolygon.py +8 -6
  11. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/point.py +26 -9
  12. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/polygon.py +26 -11
  13. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geos.py +9 -1
  14. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/iterops.py +9 -7
  15. Shapely-1.0b4/shapely/predicates.py +58 -0
  16. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/topology.py +4 -0
  17. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/wkb.py +8 -3
  18. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/wkt.py +9 -2
  19. {Shapely-1.0b3 → Shapely-1.0b4}/tests/LineString.txt +20 -1
  20. {Shapely-1.0b3 → Shapely-1.0b4}/tests/MultiPoint.txt +0 -2
  21. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Point.txt +25 -0
  22. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Polygon.txt +20 -1
  23. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Predicates.txt +1 -1
  24. Shapely-1.0b3/shapely/predicates.py +0 -50
  25. {Shapely-1.0b3 → Shapely-1.0b4}/CHANGES.txt +0 -0
  26. {Shapely-1.0b3 → Shapely-1.0b4}/CREDITS.txt +0 -0
  27. {Shapely-1.0b3 → Shapely-1.0b4}/HISTORY.txt +0 -0
  28. {Shapely-1.0b3 → Shapely-1.0b4}/LICENSE.txt +0 -0
  29. {Shapely-1.0b3 → Shapely-1.0b4}/Shapely.egg-info/SOURCES.txt +0 -0
  30. {Shapely-1.0b3 → Shapely-1.0b4}/Shapely.egg-info/dependency_links.txt +0 -0
  31. {Shapely-1.0b3 → Shapely-1.0b4}/Shapely.egg-info/requires.txt +0 -0
  32. {Shapely-1.0b3 → Shapely-1.0b4}/Shapely.egg-info/top_level.txt +0 -0
  33. {Shapely-1.0b3 → Shapely-1.0b4}/examples/geoms.py +0 -0
  34. {Shapely-1.0b3 → Shapely-1.0b4}/examples/world.py +0 -0
  35. {Shapely-1.0b3 → Shapely-1.0b4}/manual/style.css +0 -0
  36. {Shapely-1.0b3 → Shapely-1.0b4}/setup.cfg +0 -0
  37. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/__init__.py +0 -0
  38. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/__init__.py +0 -0
  39. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/collection.py +0 -0
  40. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/geometry/geo.py +0 -0
  41. {Shapely-1.0b3 → Shapely-1.0b4}/shapely/kml.py +0 -0
  42. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Array.txt +0 -0
  43. {Shapely-1.0b3 → Shapely-1.0b4}/tests/GeoInterface.txt +0 -0
  44. {Shapely-1.0b3 → Shapely-1.0b4}/tests/IterOps.txt +0 -0
  45. {Shapely-1.0b3 → Shapely-1.0b4}/tests/MultiLineString.txt +0 -0
  46. {Shapely-1.0b3 → Shapely-1.0b4}/tests/MultiPolygon.txt +0 -0
  47. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Operations.txt +0 -0
  48. {Shapely-1.0b3 → Shapely-1.0b4}/tests/Persist.txt +0 -0
  49. {Shapely-1.0b3 → Shapely-1.0b4}/tests/__init__.py +0 -0
  50. {Shapely-1.0b3 → Shapely-1.0b4}/tests/binascii_hex.txt +0 -0
  51. {Shapely-1.0b3 → Shapely-1.0b4}/tests/invalid_intersection.txt +0 -0
  52. {Shapely-1.0b3 → Shapely-1.0b4}/tests/rungrind.dist +0 -0
  53. {Shapely-1.0b3 → Shapely-1.0b4}/tests/test_doctests.py +0 -0
  54. {Shapely-1.0b3 → Shapely-1.0b4}/tests/valgrind-python.supp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.0b3
3
+ Version: 1.0b4
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
@@ -23,7 +23,7 @@ Description: Shapely
23
23
  Dependencies
24
24
  ------------
25
25
 
26
- * libgeos_c (2.2.3, also reported to work with 3.0)
26
+ * libgeos_c (2.2.3 or 3.0.0+)
27
27
  * Python ctypes_ (standard in Python 2.5+)
28
28
 
29
29
  .. _ctypes: http://pypi.python.org/pypi/ctypes/
@@ -15,7 +15,7 @@ http://zcologia.com/news/564/shapely-for-python-3-0/.)
15
15
  Dependencies
16
16
  ------------
17
17
 
18
- * libgeos_c (2.2.3, also reported to work with 3.0)
18
+ * libgeos_c (2.2.3 or 3.0.0+)
19
19
  * Python ctypes_ (standard in Python 2.5+)
20
20
 
21
21
  .. _ctypes: http://pypi.python.org/pypi/ctypes/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.0b3
3
+ Version: 1.0b4
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
@@ -23,7 +23,7 @@ Description: Shapely
23
23
  Dependencies
24
24
  ------------
25
25
 
26
- * libgeos_c (2.2.3, also reported to work with 3.0)
26
+ * libgeos_c (2.2.3 or 3.0.0+)
27
27
  * Python ctypes_ (standard in Python 2.5+)
28
28
 
29
29
  .. _ctypes: http://pypi.python.org/pypi/ctypes/
@@ -9,9 +9,9 @@ The Shapely Manual
9
9
  :revision: 1.0
10
10
  :date: 2 January 2008
11
11
 
12
- :copyright: This work is licensed under a `Creative Commons Attribution-Share Alike 3.0 United States License`__.
12
+ :copyright: This work is licensed under a `Creative Commons Attribution 3.0 United States License`__.
13
13
 
14
- .. __: http://creativecommons.org/licenses/by-sa/3.0/us/
14
+ .. __: http://creativecommons.org/licenses/by/3.0/us/
15
15
 
16
16
  :abstract: This document describes the Shapely Python package for programming with geospatial geometries.
17
17
 
@@ -19,6 +19,7 @@ The Shapely Manual
19
19
 
20
20
  .. contents::
21
21
 
22
+
22
23
  Background
23
24
  ==========
24
25
 
@@ -33,6 +34,7 @@ Package Index record_.
33
34
  .. _record: http://pypi.python.org/pypi/Shapely
34
35
  .. _wiki: http://trac.gispython.org/projects/PCL/wiki/Shapely
35
36
 
37
+
36
38
  Geometries
37
39
  ==========
38
40
 
@@ -44,6 +46,7 @@ collections, and heterogeneous geometry collections. See the JTS illustration_.
44
46
 
45
47
  Shapely 1.0 does not provide circles, arcs, splines or the like.
46
48
 
49
+
47
50
  Factories
48
51
  ---------
49
52
 
@@ -111,6 +114,7 @@ Rings *must* be non-crossing, ordered coordinate sequences. The order may be
111
114
  clockwise or counter-clockwise. The resulting topology is independent of the
112
115
  order.
113
116
 
117
+
114
118
  Multipart Geometry Factories
115
119
  ----------------------------
116
120
 
@@ -156,6 +160,31 @@ holes) makes usage more clear
156
160
  >>> holes = [(b1, ..., bN), ...]
157
161
  >>> lines = MultiPolygon([(shell, holes), ...])
158
162
 
163
+
164
+ Null Geometries
165
+ ---------------
166
+
167
+ Null geometries can be created by calling the factories with no arguments, but
168
+ almost nothing can be done with a null geometry.
169
+
170
+ .. code-block:: python
171
+
172
+ >>> line_null = LineString()
173
+ >>> line_null.length
174
+ Traceback (most recent call last):
175
+ ...
176
+ ValueError: Null geometry supports no operations
177
+
178
+ The coordinates of a null geometry *can* be set (see Section 3), after which
179
+ the geometry is no longer null.
180
+
181
+ .. code-block:: python
182
+
183
+ >>> l_null.coords = [(0, 0), (1, 1)]
184
+ >>> print l_null.length
185
+ 1.414...
186
+
187
+
159
188
  Constructive Spatial Analysis Methods
160
189
  -------------------------------------
161
190
 
@@ -232,7 +261,6 @@ Centroid
232
261
  >>> centroid_point.wkt
233
262
  'POINT (-0.0000000000000000 -0.0000000000000000)'
234
263
 
235
-
236
264
  Convex Hull
237
265
  +++++++++++
238
266
 
@@ -264,6 +292,17 @@ Difference
264
292
  >>> polygon.difference(hull)
265
293
  <shapely.geometry.polygon.Polygon object at ...>
266
294
 
295
+ Envelope
296
+ ++++++++
297
+
298
+ .envelope : geometry
299
+ Returns the geometry's rectangular polygon envelope.
300
+
301
+ .. code-block:: python
302
+
303
+ >>> polygon.envelope
304
+ <shapely.geometry.polygon.Polygon object at ...>
305
+
267
306
  Intersection
268
307
  ++++++++++++
269
308
 
@@ -302,6 +341,7 @@ not:
302
341
  >>> hull.union(polygon)
303
342
  <shapely.geometry.polygon.Polygon object at ...>
304
343
 
344
+
305
345
  Unary Spatial Predicates
306
346
  ------------------------
307
347
 
@@ -350,9 +390,10 @@ Examples
350
390
  >>> polygon.boundary.is_ring
351
391
  True
352
392
  >>> polygon.has_z
353
- True
393
+ False
394
+
395
+ (Note: that last return value exposes a bug in GEOS 2.2.3.)
354
396
 
355
- (Note: that last return value exposes a bug in GEOS 2.2.3. Should be False.)
356
397
 
357
398
  Binary Spatial Predicates
358
399
  -------------------------
@@ -437,6 +478,7 @@ Within
437
478
  .within(other): bool
438
479
  The inverse of *contains*.
439
480
 
481
+
440
482
  General Methods
441
483
  ---------------
442
484
 
@@ -462,6 +504,12 @@ Area
462
504
  Area of the geometry, unitless. Non-zero only for surfaces (polygons,
463
505
  multi-polygons).
464
506
 
507
+ Bounds
508
+ ++++++
509
+
510
+ .bounds : tuple
511
+ The geometry's (minx, miny, maxx, maxy) bounding box.
512
+
465
513
  Length
466
514
  ++++++
467
515
 
@@ -476,6 +524,8 @@ Examples
476
524
 
477
525
  >>> polygon.area
478
526
  4.0
527
+ >>> polygon.bounds
528
+ (-1.0, -1.0, 1.0, 1.0)
479
529
  >>> polygon.length
480
530
  8.0
481
531
  >>> line_r.length
@@ -483,6 +533,7 @@ Examples
483
533
  >>> line_b.length
484
534
  3.9812058474788765
485
535
 
536
+
486
537
  Geometry Parts and Coordinates
487
538
  ==============================
488
539
 
@@ -523,6 +574,7 @@ For line strings:
523
574
  >>> list(line_new.coords)
524
575
  [(1.0, 1.0), (2.0, 2.0)]
525
576
 
577
+
526
578
  Polygon Rings
527
579
  -------------
528
580
 
@@ -539,6 +591,7 @@ attribute of the geometry object.
539
591
  The interior boundaries (or holes) of a polygon can be accessed through the
540
592
  *interiors* attribute, which is a list of rings.
541
593
 
594
+
542
595
  Sub-geometries
543
596
  --------------
544
597
 
@@ -560,6 +613,22 @@ attribute of the geometry object, which is an iterator over the sub-geometries:
560
613
  The coordinate sequences of these sub-geometries can then be accessed as
561
614
  described above.
562
615
 
616
+
617
+ Point Coordinates
618
+ -----------------
619
+
620
+ For the sake of convenience the coordinate values of points can be accessed
621
+ read-only via **x**, **y**, and **z** attributes:
622
+
623
+ .. code-block:: python
624
+
625
+ >>> point = Point(1.0, 1.0)
626
+ >>> point.x
627
+ 1.0
628
+ >>> point.y
629
+ 1.0
630
+
631
+
563
632
  Interoperation
564
633
  ==============
565
634
 
@@ -613,6 +682,7 @@ attribute. New geometries can be created from WKB data using the
613
682
  >>> loads(feature.GetGeometryRef().ExportToWkb())
614
683
  <shapely.geometry.polygon.Polygon object at ...>
615
684
 
685
+
616
686
  Python Sequences
617
687
  ----------------
618
688
 
@@ -652,6 +722,7 @@ used like
652
722
  >>> len(pa.interiors[0].coords)
653
723
  5
654
724
 
725
+
655
726
  Numpy Array Interface
656
727
  ---------------------
657
728
 
@@ -695,6 +766,7 @@ and a N x 2 array can be adapted to a line string
695
766
 
696
767
  There is no Numpy array representation of a polygon.
697
768
 
769
+
698
770
  Python Geo Interface
699
771
  --------------------
700
772
 
@@ -728,6 +800,7 @@ Or a simple placemark-type object:
728
800
 
729
801
  .. _Python geo interface: http://trac.gispython.org/projects/PCL/wiki/PythonGeoInterface
730
802
 
803
+
731
804
  Advanced Features
732
805
  =================
733
806
 
@@ -763,6 +836,7 @@ will be ultimately yielded from *iterops.contains*.
763
836
  >>> list(iterops.contains(polygon, iter((p, p.wkt) for p in points)))
764
837
  ['POINT (0.5000000000000000 0.5000000000000000)']
765
838
 
839
+
766
840
  Credits
767
841
  =======
768
842
 
@@ -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.0b3',
14
+ version = '1.0b4',
15
15
  description = 'Geospatial geometries, predicates, and operations',
16
16
  license = 'BSD',
17
17
  keywords = 'geometry topology',
@@ -5,7 +5,7 @@ Base geometry class and utilities.
5
5
  from ctypes import string_at, byref, c_int, c_size_t, c_char_p, c_double
6
6
  import sys
7
7
 
8
- from shapely.geos import lgeos
8
+ from shapely.geos import lgeos, free, allocated_c_char_p
9
9
  from shapely.predicates import BinaryPredicate, UnaryPredicate
10
10
  from shapely.topology import BinaryTopologicalOp, UnaryTopologicalOp
11
11
 
@@ -22,6 +22,8 @@ GEOMETRY_TYPES = [
22
22
  ]
23
23
 
24
24
  def geometry_type_name(g):
25
+ if g is None:
26
+ raise ValueError, "Null geometry has no type"
25
27
  return GEOMETRY_TYPES[lgeos.GEOSGeomTypeId(g)]
26
28
 
27
29
  # Abstract geometry factory for use with topological methods below
@@ -156,23 +158,42 @@ class GeometrySequence(object):
156
158
  max = l
157
159
 
158
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
+
159
180
  class BaseGeometry(object):
160
181
 
161
182
  """Provides GEOS spatial predicates and topological operations.
162
183
  """
163
184
 
164
- _geom = None
185
+ __geom = None # See _geom property below
165
186
  _ctypes_data = None
166
187
  _ndim = None
167
188
  _crs = None
168
189
  _owned = False
169
190
 
170
191
  def __init__(self):
171
- self._geom = lgeos.GEOSGeomFromWKT(c_char_p('GEOMETRYCOLLECTION EMPTY'))
192
+ self.__geom = None
172
193
 
173
194
  def __del__(self):
174
- if self._geom is not None and not self._owned:
175
- lgeos.GEOSGeom_destroy(self._geom)
195
+ if self.__geom is not None and not self._owned:
196
+ lgeos.GEOSGeom_destroy(self.__geom)
176
197
 
177
198
  def __str__(self):
178
199
  return self.to_wkt()
@@ -189,11 +210,20 @@ class BaseGeometry(object):
189
210
  return (self.__class__, (), self.to_wkb())
190
211
 
191
212
  def __setstate__(self, state):
192
- self._geom = lgeos.GEOSGeomFromWKB_buf(
213
+ self.__geom = lgeos.GEOSGeomFromWKB_buf(
193
214
  c_char_p(state),
194
215
  c_size_t(len(state))
195
216
  )
196
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
+
197
227
  # Array and ctypes interfaces
198
228
 
199
229
  @property
@@ -222,6 +252,7 @@ class BaseGeometry(object):
222
252
  """Provide the Numpy array protocol."""
223
253
  raise NotImplementedError
224
254
 
255
+ @exceptNull
225
256
  def get_coords(self):
226
257
  return CoordinateSequence(self)
227
258
 
@@ -243,19 +274,34 @@ class BaseGeometry(object):
243
274
 
244
275
  # Type of geometry and its representations
245
276
 
277
+ @exceptNull
246
278
  def geometryType(self):
247
279
  """Returns a string representing the geometry type, e.g. 'Polygon'."""
248
280
  return geometry_type_name(self._geom)
249
281
 
282
+ @exceptNull
250
283
  def to_wkb(self):
251
284
  """Returns a WKB byte string representation of the geometry."""
285
+ func = lgeos.GEOSGeomToWKB_buf
252
286
  size = c_int()
253
- bytes = lgeos.GEOSGeomToWKB_buf(self._geom, byref(size))
254
- return string_at(bytes, size.value)
255
-
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
256
295
  def to_wkt(self):
257
296
  """Returns a WKT string representation of the geometry."""
258
- return string_at(lgeos.GEOSGeomToWKT(self._geom))
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)
259
305
 
260
306
  geom_type = property(geometryType)
261
307
  wkt = property(to_wkt)
@@ -264,17 +310,20 @@ class BaseGeometry(object):
264
310
  # Basic geometry properties
265
311
 
266
312
  @property
313
+ @exceptNull
267
314
  def area(self):
268
315
  a = c_double()
269
316
  retval = lgeos.GEOSArea(self._geom, byref(a))
270
317
  return a.value
271
318
 
272
319
  @property
320
+ @exceptNull
273
321
  def length(self):
274
322
  len = c_double()
275
323
  retval = lgeos.GEOSLength(self._geom, byref(len))
276
324
  return len.value
277
325
 
326
+ @exceptEitherNull
278
327
  def distance(self, other):
279
328
  d = c_double()
280
329
  retval = lgeos.GEOSDistance(self._geom, other._geom, byref(d))
@@ -295,15 +344,22 @@ class BaseGeometry(object):
295
344
  centroid = UnaryTopologicalOp(lgeos.GEOSGetCentroid, geom_factory)
296
345
 
297
346
  # Buffer has a unique distance argument, so not a descriptor
347
+ @exceptNull
298
348
  def buffer(self, distance, quadsegs=16):
299
349
  return geom_factory(
300
350
  lgeos.GEOSBuffer(self._geom, c_double(distance), c_int(quadsegs))
301
351
  )
302
352
 
303
353
  # Relate has a unique string return value
354
+ @exceptNull
304
355
  def relate(self, other):
305
356
  func = lgeos.GEOSRelate
306
- func.restype = c_char_p
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
307
363
  return lgeos.GEOSRelate(self._geom, other._geom)
308
364
 
309
365
  # Binary predicates
@@ -331,6 +387,7 @@ class BaseGeometry(object):
331
387
  has_z = UnaryPredicate(lgeos.GEOSHasZ)
332
388
 
333
389
  @property
390
+ @exceptNull
334
391
  def bounds(self):
335
392
  env = self.envelope
336
393
  if env.geom_type != 'Polygon':
@@ -6,7 +6,7 @@ from ctypes import byref, c_double, c_int, cast, POINTER, pointer
6
6
  from ctypes import ArgumentError
7
7
 
8
8
  from shapely.geos import lgeos
9
- from shapely.geometry.base import BaseGeometry
9
+ from shapely.geometry.base import BaseGeometry, exceptNull
10
10
 
11
11
 
12
12
  def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
@@ -86,7 +86,7 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
86
86
  if update_geom is not None:
87
87
  return None
88
88
  else:
89
- return (lgeos.GEOSGeom_createLineString(cs), n)
89
+ return lgeos.GEOSGeom_createLineString(cs), n
90
90
 
91
91
  def update_linestring_from_py(geom, ob):
92
92
  geos_linestring_from_py(ob, geom._geom, geom._ndim)
@@ -118,7 +118,9 @@ class LineString(BaseGeometry):
118
118
  Each result in a line string from (0.0, 0.0) to (1.0, 2.0).
119
119
  """
120
120
  BaseGeometry.__init__(self)
121
+ self._init_geom(coordinates)
121
122
 
123
+ def _init_geom(self, coordinates):
122
124
  if coordinates is None:
123
125
  # allow creation of null lines, to support unpickling
124
126
  pass
@@ -133,6 +135,7 @@ class LineString(BaseGeometry):
133
135
  }
134
136
 
135
137
  @property
138
+ @exceptNull
136
139
  def ctypes(self):
137
140
  if not self._ctypes_data:
138
141
  cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
@@ -164,6 +167,8 @@ class LineString(BaseGeometry):
164
167
  # Coordinate access
165
168
 
166
169
  def set_coords(self, coordinates):
170
+ if self._geom is None:
171
+ self._init_geom(coordinates)
167
172
  update_linestring_from_py(self, coordinates)
168
173
 
169
174
  coords = property(BaseGeometry.get_coords, set_coords)
@@ -176,14 +181,12 @@ class LineStringAdapter(LineString):
176
181
  """
177
182
 
178
183
  context = None
184
+ __geom = None
185
+ _owned = False
179
186
 
180
187
  def __init__(self, context):
181
188
  self.context = context
182
189
 
183
- # Override base class __del__
184
- def __del__(self):
185
- pass
186
-
187
190
  @property
188
191
  def _ndim(self):
189
192
  try:
@@ -199,7 +202,10 @@ class LineStringAdapter(LineString):
199
202
  @property
200
203
  def _geom(self):
201
204
  """Keeps the GEOS geometry in synch with the context."""
202
- return geos_linestring_from_py(self.context)[0]
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
203
209
 
204
210
  @property
205
211
  def __array_interface__(self):
@@ -5,7 +5,7 @@ Multi-part collection of linestrings.
5
5
  from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
6
6
 
7
7
  from shapely.geos import lgeos
8
- from shapely.geometry.base import BaseGeometry, GeometrySequence
8
+ from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
9
  from shapely.geometry.linestring import LineString, geos_linestring_from_py
10
10
 
11
11
 
@@ -102,6 +102,7 @@ class MultiLineString(BaseGeometry):
102
102
  "Multi-part geometries do not provide a coordinate sequence"
103
103
 
104
104
  @property
105
+ @exceptNull
105
106
  def geoms(self):
106
107
  return GeometrySequence(self, LineString)
107
108
 
@@ -113,14 +114,12 @@ class MultiLineStringAdapter(MultiLineString):
113
114
  """
114
115
 
115
116
  context = None
117
+ __geom = None
118
+ _owned = False
116
119
 
117
120
  def __init__(self, context):
118
121
  self.context = context
119
122
 
120
- # Override base class __del__
121
- def __del__(self):
122
- pass
123
-
124
123
  @property
125
124
  def _ndim(self):
126
125
  try:
@@ -136,7 +135,10 @@ class MultiLineStringAdapter(MultiLineString):
136
135
  @property
137
136
  def _geom(self):
138
137
  """Keeps the GEOS geometry in synch with the context."""
139
- return geos_multilinestring_from_py(self.context)[0]
138
+ if self.__geom is not None:
139
+ lgeos.GEOSGeom_destroy(self.__geom)
140
+ self.__geom = geos_multilinestring_from_py(self.context)[0]
141
+ return self.__geom
140
142
 
141
143
 
142
144
  def asMultiLineString(context):
@@ -5,7 +5,7 @@ Multiple points.
5
5
  from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
6
6
 
7
7
  from shapely.geos import lgeos
8
- from shapely.geometry.base import BaseGeometry, GeometrySequence
8
+ from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
9
9
  from shapely.geometry.point import Point, geos_point_from_py
10
10
 
11
11
 
@@ -44,7 +44,7 @@ def geos_multipoint_from_py(ob):
44
44
  geom, ndims = geos_point_from_py(coords)
45
45
  subs[i] = cast(geom, c_void_p)
46
46
 
47
- return (lgeos.GEOSGeom_createCollection(4, subs, m), n)
47
+ return lgeos.GEOSGeom_createCollection(4, subs, m), n
48
48
 
49
49
 
50
50
  class MultiPoint(BaseGeometry):
@@ -81,6 +81,7 @@ class MultiPoint(BaseGeometry):
81
81
 
82
82
 
83
83
  @property
84
+ @exceptNull
84
85
  def __geo_interface__(self):
85
86
  return {
86
87
  'type': 'MultiPoint',
@@ -88,6 +89,7 @@ class MultiPoint(BaseGeometry):
88
89
  }
89
90
 
90
91
  @property
92
+ @exceptNull
91
93
  def ctypes(self):
92
94
  if not self._ctypes_data:
93
95
  temp = c_double()
@@ -108,6 +110,7 @@ class MultiPoint(BaseGeometry):
108
110
  self._ctypes_data = data
109
111
  return self._ctypes_data
110
112
 
113
+ @exceptNull
111
114
  def array_interface(self):
112
115
  """Provide the Numpy array protocol."""
113
116
  ai = self.array_interface_base
@@ -121,6 +124,7 @@ class MultiPoint(BaseGeometry):
121
124
  "Multipart geometries do not themselves provide coordinate sequences"
122
125
 
123
126
  @property
127
+ @exceptNull
124
128
  def geoms(self):
125
129
  return GeometrySequence(self, Point)
126
130
 
@@ -132,14 +136,12 @@ class MultiPointAdapter(MultiPoint):
132
136
  """
133
137
 
134
138
  context = None
139
+ __geom = None
140
+ _owned = False
135
141
 
136
142
  def __init__(self, context):
137
143
  self.context = context
138
144
 
139
- # Override base class __del__
140
- def __del__(self):
141
- pass
142
-
143
145
  @property
144
146
  def _ndim(self):
145
147
  try:
@@ -155,7 +157,10 @@ class MultiPointAdapter(MultiPoint):
155
157
  @property
156
158
  def _geom(self):
157
159
  """Keeps the GEOS geometry in synch with the context."""
158
- return geos_multipoint_from_py(self.context)[0]
160
+ if self.__geom is not None:
161
+ lgeos.GEOSGeom_destroy(self.__geom)
162
+ self.__geom, n = geos_multipoint_from_py(self.context)
163
+ return self.__geom
159
164
 
160
165
  @property
161
166
  def __array_interface__(self):