shapely 1.2b4__tar.gz → 1.2b5__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 (66) hide show
  1. {Shapely-1.2b4 → Shapely-1.2b5}/CHANGES.txt +12 -0
  2. {Shapely-1.2b4 → Shapely-1.2b5}/PKG-INFO +1 -1
  3. {Shapely-1.2b4 → Shapely-1.2b5}/Shapely.egg-info/PKG-INFO +1 -1
  4. {Shapely-1.2b4 → Shapely-1.2b5}/setup.py +1 -1
  5. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/base.py +15 -6
  6. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/linestring.py +108 -120
  7. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/multilinestring.py +54 -60
  8. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/multipoint.py +57 -57
  9. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/multipolygon.py +48 -43
  10. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/point.py +81 -76
  11. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/polygon.py +178 -180
  12. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/LineString.txt +10 -6
  13. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/MultiLineString.txt +18 -1
  14. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/MultiPoint.txt +17 -1
  15. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/MultiPolygon.txt +17 -1
  16. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Point.txt +10 -10
  17. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Polygon.txt +3 -7
  18. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/test_geomseq.py +2 -5
  19. {Shapely-1.2b4 → Shapely-1.2b5}/CREDITS.txt +0 -0
  20. {Shapely-1.2b4 → Shapely-1.2b5}/LICENSE.txt +0 -0
  21. {Shapely-1.2b4 → Shapely-1.2b5}/MANIFEST.in +0 -0
  22. {Shapely-1.2b4 → Shapely-1.2b5}/README.txt +0 -0
  23. {Shapely-1.2b4 → Shapely-1.2b5}/Shapely.egg-info/SOURCES.txt +0 -0
  24. {Shapely-1.2b4 → Shapely-1.2b5}/Shapely.egg-info/dependency_links.txt +0 -0
  25. {Shapely-1.2b4 → Shapely-1.2b5}/Shapely.egg-info/top_level.txt +0 -0
  26. {Shapely-1.2b4 → Shapely-1.2b5}/examples/dissolve.py +0 -0
  27. {Shapely-1.2b4 → Shapely-1.2b5}/examples/intersect.py +0 -0
  28. {Shapely-1.2b4 → Shapely-1.2b5}/setup.cfg +0 -0
  29. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/__init__.py +0 -0
  30. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/coords.py +0 -0
  31. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/ctypes_declarations.py +0 -0
  32. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/__init__.py +0 -0
  33. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/collection.py +0 -0
  34. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/geo.py +0 -0
  35. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geometry/proxy.py +0 -0
  36. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geoms.py +0 -0
  37. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/geos.py +0 -0
  38. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/impl.py +0 -0
  39. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/iterops.py +0 -0
  40. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/linref.py +0 -0
  41. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/ops.py +0 -0
  42. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/predicates.py +0 -0
  43. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/prepared.py +0 -0
  44. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Array.txt +0 -0
  45. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/GeoInterface.txt +0 -0
  46. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/IterOps.txt +0 -0
  47. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Operations.txt +0 -0
  48. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Persist.txt +0 -0
  49. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/Predicates.txt +0 -0
  50. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/__init__.py +0 -0
  51. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/attribute-chains.txt +0 -0
  52. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/binascii_hex.txt +0 -0
  53. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/dimensions.txt +0 -0
  54. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/invalid_intersection.txt +0 -0
  55. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/linear-referencing.txt +0 -0
  56. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/linemerge.txt +0 -0
  57. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/polygonize.txt +0 -0
  58. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/test_doctests.py +0 -0
  59. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/test_equality.py +0 -0
  60. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/test_prepared.py +0 -0
  61. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/test_xy.py +0 -0
  62. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/threading_test.py +0 -0
  63. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/tests/wkt_locale.txt +0 -0
  64. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/topology.py +0 -0
  65. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/wkb.py +0 -0
  66. {Shapely-1.2b4 → Shapely-1.2b5}/shapely/wkt.py +0 -0
@@ -1,5 +1,17 @@
1
1
  All tickets are children of http://trac.gispython.org/lab/ticket.
2
2
 
3
+ 1.2b5 (2010-04-09)
4
+ ------------------
5
+ - Objects can be constructed from others of the same type, thereby making
6
+ copies. Collections can be constructed from sequences of objects, also making
7
+ copies.
8
+ - Collections are now iterators over their component objects.
9
+ - New code for manual figures, using the descartes package.
10
+
11
+ 1.2b4 (2010-03-19)
12
+ ------------------
13
+ - Adds support for the "sunos5" platform.
14
+
3
15
  1.2b3 (2010-02-28)
4
16
  ------------------
5
17
  - Only provide simplification implementations for GEOS C API >= 1.5.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.2b4
3
+ Version: 1.2b5
4
4
  Summary: Planar geometries, predicates, and operations
5
5
  Home-page: http://trac.gispython.org/lab/wiki/Shapely
6
6
  Author: Sean Gillies
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.2b4
3
+ Version: 1.2b5
4
4
  Summary: Planar geometries, predicates, and operations
5
5
  Home-page: http://trac.gispython.org/lab/wiki/Shapely
6
6
  Author: Sean Gillies
@@ -16,7 +16,7 @@ readme_text = file('README.txt', 'rb').read()
16
16
  setup_args = dict(
17
17
  metadata_version = '1.2',
18
18
  name = 'Shapely',
19
- version = '1.2b4',
19
+ version = '1.2b5',
20
20
  requires_python = '>=2.5,<3',
21
21
  requires_external = 'libgeos_c (>=3.1)',
22
22
  description = 'Planar geometries, predicates, and operations',
@@ -48,8 +48,8 @@ def exceptNull(func):
48
48
  """Decorator which helps avoid GEOS operations on null pointers."""
49
49
  @wraps(func)
50
50
  def wrapper(*args, **kwargs):
51
- if not args[0]._geom:
52
- raise ValueError("Null geometry supports no operations")
51
+ if not args[0]._geom or args[0].is_empty:
52
+ raise ValueError("Null/empty geometry supports no operations")
53
53
  return func(*args, **kwargs)
54
54
  return wrapper
55
55
 
@@ -84,12 +84,12 @@ class BaseGeometry(object):
84
84
  _ndim = None
85
85
  _crs = None
86
86
  _owned = False
87
-
87
+
88
88
  # Backend config
89
89
  impl = DefaultImplementation
90
90
 
91
91
  def __init__(self):
92
- self.__geom__ = None
92
+ self.__geom__ = wkb.deserialize('010700000000000000'.decode('hex'))
93
93
 
94
94
  def __del__(self):
95
95
  if self.__geom__ is not None and not self._owned:
@@ -227,8 +227,11 @@ class BaseGeometry(object):
227
227
  @property
228
228
  def bounds(self):
229
229
  """Returns minimum bounding region (minx, miny, maxx, maxy)"""
230
- return self.impl['bounds'](self)
231
-
230
+ if self.is_empty:
231
+ return ()
232
+ else:
233
+ return self.impl['bounds'](self)
234
+
232
235
  @property
233
236
  def centroid(self):
234
237
  """Returns the geometric center of the polygon"""
@@ -451,6 +454,12 @@ class BaseMultipartGeometry(BaseGeometry):
451
454
  def geoms(self):
452
455
  return GeometrySequence(self, self.shape_factory)
453
456
 
457
+ def __iter__(self):
458
+ if not self.is_empty:
459
+ return iter(self.geoms)
460
+ else:
461
+ return iter([])
462
+
454
463
 
455
464
  class GeometrySequence(object):
456
465
  """
@@ -11,107 +11,6 @@ from shapely.geometry.proxy import CachingGeometryProxy
11
11
  __all__ = ['LineString', 'asLineString']
12
12
 
13
13
 
14
- def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
15
- try:
16
- # From array protocol
17
- array = ob.__array_interface__
18
- assert len(array['shape']) == 2
19
- m = array['shape'][0]
20
- if m < 2:
21
- raise ValueError(
22
- "LineStrings must have at least 2 coordinate tuples")
23
- try:
24
- n = array['shape'][1]
25
- except IndexError:
26
- raise ValueError(
27
- "Input %s is the wrong shape for a LineString" % str(ob))
28
- assert n == 2 or n == 3
29
-
30
- # Make pointer to the coordinate array
31
- try:
32
- cp = cast(array['data'][0], POINTER(c_double))
33
- except ArgumentError:
34
- cp = array['data']
35
-
36
- # Create a coordinate sequence
37
- if update_geom is not None:
38
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
39
- if n != update_ndim:
40
- raise ValueError(
41
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
42
- % update_ndim)
43
- else:
44
- cs = lgeos.GEOSCoordSeq_create(m, n)
45
-
46
- # add to coordinate sequence
47
- for i in xrange(m):
48
- dx = c_double(cp[n*i])
49
- dy = c_double(cp[n*i+1])
50
- dz = None
51
- if n == 3:
52
- try:
53
- dz = c_double(cp[n*i+2])
54
- except IndexError:
55
- raise ValueError("Inconsistent coordinate dimensionality")
56
-
57
- # Because of a bug in the GEOS C API,
58
- # always set X before Y
59
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
60
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
61
- if n == 3:
62
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
63
-
64
- except AttributeError:
65
- # Fall back on list
66
- m = len(ob)
67
- if m < 2:
68
- raise ValueError(
69
- "LineStrings must have at least 2 coordinate tuples")
70
- try:
71
- n = len(ob[0])
72
- except TypeError:
73
- raise ValueError(
74
- "Input %s is the wrong shape for a LineString" % str(ob))
75
- assert n == 2 or n == 3
76
-
77
- # Create a coordinate sequence
78
- if update_geom is not None:
79
- cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
80
- if n != update_ndim:
81
- raise ValueError(
82
- "Wrong coordinate dimensions; this geometry has dimensions: %d" \
83
- % update_ndim)
84
- else:
85
- cs = lgeos.GEOSCoordSeq_create(m, n)
86
-
87
- # add to coordinate sequence
88
- for i in xrange(m):
89
- coords = ob[i]
90
- dx = c_double(coords[0])
91
- dy = c_double(coords[1])
92
- dz = None
93
- if n == 3:
94
- try:
95
- dz = c_double(coords[2])
96
- except IndexError:
97
- raise ValueError("Inconsistent coordinate dimensionality")
98
-
99
- # Because of a bug in the GEOS C API,
100
- # always set X before Y
101
- lgeos.GEOSCoordSeq_setX(cs, i, dx)
102
- lgeos.GEOSCoordSeq_setY(cs, i, dy)
103
- if n == 3:
104
- lgeos.GEOSCoordSeq_setZ(cs, i, dz)
105
-
106
- if update_geom is not None:
107
- return None
108
- else:
109
- return lgeos.GEOSGeom_createLineString(cs), n
110
-
111
- def update_linestring_from_py(geom, ob):
112
- geos_linestring_from_py(ob, geom._geom, geom._ndim)
113
-
114
-
115
14
  class LineString(BaseGeometry):
116
15
  """
117
16
  A one-dimensional figure comprising one or more line segments
@@ -121,29 +20,21 @@ class LineString(BaseGeometry):
121
20
  """
122
21
 
123
22
  def __init__(self, coordinates=None):
124
- """Initialize a linestring instance
125
-
23
+ """
126
24
  Parameters
127
25
  ----------
128
-
129
26
  coordinates : sequence
130
- A sequence of (x, y [,z]) numeric coordinate pairs or triples
27
+ A sequence of (x, y [,z]) numeric coordinate pairs or triples or
28
+ an object that provides the numpy array interface, including another
29
+ instance of LineString.
131
30
 
132
31
  Example
133
32
  -------
134
-
135
33
  Create a line with two segments
136
34
 
137
35
  >>> a = LineString([[0, 0], [1, 0], [1, 1]])
138
36
  >>> a.length
139
37
  2.0
140
-
141
- Copy it by exploiting API symmetry
142
-
143
- >>> b = LineString(a.coords)
144
- >>> b.equals(a)
145
- True
146
-
147
38
  """
148
39
  BaseGeometry.__init__(self)
149
40
  self._init_geom(coordinates)
@@ -177,6 +68,9 @@ class LineString(BaseGeometry):
177
68
  # Coordinate access
178
69
 
179
70
  def _set_coords(self, coordinates):
71
+ if self.is_empty:
72
+ lgeos.GEOSGeom_destroy(self.__geom__)
73
+ self.__geom__ = None
180
74
  if self._geom is None:
181
75
  self._init_geom(coordinates)
182
76
  update_linestring_from_py(self, coordinates)
@@ -194,17 +88,12 @@ class LineString(BaseGeometry):
194
88
  [0.0, 1.0]
195
89
  >>> list(y)
196
90
  [0.0, 1.0]
197
-
198
91
  """
199
92
  return self.coords.xy
200
93
 
201
94
 
202
95
  class LineStringAdapter(CachingGeometryProxy, LineString):
203
96
 
204
- """Adapts Python coordinate pairs or a numpy array to the line string
205
- interface
206
- """
207
-
208
97
  context = None
209
98
  _owned = False
210
99
 
@@ -242,15 +131,114 @@ class LineStringAdapter(CachingGeometryProxy, LineString):
242
131
 
243
132
 
244
133
  def asLineString(context):
245
- """Factory for PointAdapter instances."""
134
+ """Adapt an object the LineString interface"""
246
135
  return LineStringAdapter(context)
247
136
 
137
+
138
+ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
139
+ try:
140
+ # From array protocol
141
+ array = ob.__array_interface__
142
+ assert len(array['shape']) == 2
143
+ m = array['shape'][0]
144
+ if m < 2:
145
+ raise ValueError(
146
+ "LineStrings must have at least 2 coordinate tuples")
147
+ try:
148
+ n = array['shape'][1]
149
+ except IndexError:
150
+ raise ValueError(
151
+ "Input %s is the wrong shape for a LineString" % str(ob))
152
+ assert n == 2 or n == 3
153
+
154
+ # Make pointer to the coordinate array
155
+ try:
156
+ cp = cast(array['data'][0], POINTER(c_double))
157
+ except ArgumentError:
158
+ cp = array['data']
159
+
160
+ # Create a coordinate sequence
161
+ if update_geom is not None:
162
+ cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
163
+ if n != update_ndim:
164
+ raise ValueError(
165
+ "Wrong coordinate dimensions; this geometry has dimensions: %d" \
166
+ % update_ndim)
167
+ else:
168
+ cs = lgeos.GEOSCoordSeq_create(m, n)
169
+
170
+ # add to coordinate sequence
171
+ for i in xrange(m):
172
+ dx = c_double(cp[n*i])
173
+ dy = c_double(cp[n*i+1])
174
+ dz = None
175
+ if n == 3:
176
+ try:
177
+ dz = c_double(cp[n*i+2])
178
+ except IndexError:
179
+ raise ValueError("Inconsistent coordinate dimensionality")
180
+
181
+ # Because of a bug in the GEOS C API,
182
+ # always set X before Y
183
+ lgeos.GEOSCoordSeq_setX(cs, i, dx)
184
+ lgeos.GEOSCoordSeq_setY(cs, i, dy)
185
+ if n == 3:
186
+ lgeos.GEOSCoordSeq_setZ(cs, i, dz)
187
+
188
+ except AttributeError:
189
+ # Fall back on list
190
+ m = len(ob)
191
+ if m < 2:
192
+ raise ValueError(
193
+ "LineStrings must have at least 2 coordinate tuples")
194
+ try:
195
+ n = len(ob[0])
196
+ except TypeError:
197
+ raise ValueError(
198
+ "Input %s is the wrong shape for a LineString" % str(ob))
199
+ assert n == 2 or n == 3
200
+
201
+ # Create a coordinate sequence
202
+ if update_geom is not None:
203
+ cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
204
+ if n != update_ndim:
205
+ raise ValueError(
206
+ "Wrong coordinate dimensions; this geometry has dimensions: %d" \
207
+ % update_ndim)
208
+ else:
209
+ cs = lgeos.GEOSCoordSeq_create(m, n)
210
+
211
+ # add to coordinate sequence
212
+ for i in xrange(m):
213
+ coords = ob[i]
214
+ dx = c_double(coords[0])
215
+ dy = c_double(coords[1])
216
+ dz = None
217
+ if n == 3:
218
+ try:
219
+ dz = c_double(coords[2])
220
+ except IndexError:
221
+ raise ValueError("Inconsistent coordinate dimensionality")
222
+
223
+ # Because of a bug in the GEOS C API,
224
+ # always set X before Y
225
+ lgeos.GEOSCoordSeq_setX(cs, i, dx)
226
+ lgeos.GEOSCoordSeq_setY(cs, i, dy)
227
+ if n == 3:
228
+ lgeos.GEOSCoordSeq_setZ(cs, i, dz)
248
229
 
230
+ if update_geom is not None:
231
+ return None
232
+ else:
233
+ return lgeos.GEOSGeom_createLineString(cs), n
234
+
235
+ def update_linestring_from_py(geom, ob):
236
+ geos_linestring_from_py(ob, geom._geom, geom._ndim)
237
+
249
238
  # Test runner
250
239
  def _test():
251
240
  import doctest
252
241
  doctest.testmod()
253
242
 
254
-
255
243
  if __name__ == "__main__":
256
244
  _test()
@@ -1,4 +1,4 @@
1
- """Multi-part collections of linestrings and related utilities
1
+ """Collections of linestrings and related utilities
2
2
  """
3
3
 
4
4
  from ctypes import c_double, c_void_p, cast, POINTER
@@ -11,47 +11,9 @@ from shapely.geometry.proxy import CachingGeometryProxy
11
11
  __all__ = ['MultiLineString', 'asMultiLineString']
12
12
 
13
13
 
14
- def geos_multilinestring_from_py(ob):
15
- """ob must be either a sequence or array of sequences or arrays."""
16
- try:
17
- # From array protocol
18
- array = ob.__array_interface__
19
- assert len(array['shape']) == 1
20
- L = array['shape'][0]
21
- assert L >= 1
22
-
23
- # Make pointer to the coordinate array
24
- cp = cast(array['data'][0], POINTER(c_double))
25
-
26
- # Array of pointers to sub-geometries
27
- subs = (c_void_p * L)()
28
-
29
- for l in xrange(L):
30
- geom, ndims = geos_linestring_from_py(array['data'][l])
31
- subs[i] = cast(geom, c_void_p)
32
- N = lgeos.GEOSGeom_getDimensions(subs[0])
33
-
34
- except AttributeError:
35
- # Fall back on list
36
- L = len(ob)
37
- N = len(ob[0][0])
38
- assert L >= 1
39
- assert N == 2 or N == 3
40
-
41
- # Array of pointers to point geometries
42
- subs = (c_void_p * L)()
43
-
44
- # add to coordinate sequence
45
- for l in xrange(L):
46
- geom, ndims = geos_linestring_from_py(ob[l])
47
- subs[l] = cast(geom, c_void_p)
48
-
49
- return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
50
-
51
-
52
14
  class MultiLineString(BaseMultipartGeometry):
53
-
54
- """A one-dimensional figure comprising one or more line strings
15
+ """
16
+ A collection of one or more line strings
55
17
 
56
18
  A MultiLineString has non-zero length and zero area.
57
19
 
@@ -61,31 +23,28 @@ class MultiLineString(BaseMultipartGeometry):
61
23
  A sequence of LineStrings
62
24
  """
63
25
 
64
- def __init__(self, coordinates=None):
65
- """Initialize.
66
-
26
+ def __init__(self, lines=None):
27
+ """
67
28
  Parameters
68
29
  ----------
69
-
70
- coordinates : sequence
71
- Contains coordinate sequences or objects that provide the numpy
72
- array protocol, providing an M x 2 or M x 3 (with z) array.
30
+ lines : sequence
31
+ A sequence of line-like coordinate sequences or objects that
32
+ provide the numpy array interface, including instances of
33
+ LineString.
73
34
 
74
35
  Example
75
36
  -------
37
+ Construct a collection containing one line string.
76
38
 
77
- >>> geom = MultiLineString( [[[0.0, 0.0], [1.0, 2.0]]] )
78
- >>> geom = MultiLineString( [ array([[0.0, 0.0], [1.0, 2.0]]) ] )
79
-
80
- Each result in a collection containing one line string.
39
+ >>> lines = MultiLineString( [[[0.0, 0.0], [1.0, 2.0]]] )
81
40
  """
82
41
  super(MultiLineString, self).__init__()
83
42
 
84
- if coordinates is None:
43
+ if lines is None:
85
44
  # allow creation of null lines, to support unpickling
86
45
  pass
87
46
  else:
88
- self._geom, self._ndim = geos_multilinestring_from_py(coordinates)
47
+ self._geom, self._ndim = geos_multilinestring_from_py(lines)
89
48
 
90
49
  def shape_factory(self, *args):
91
50
  return LineString(*args)
@@ -99,10 +58,6 @@ class MultiLineString(BaseMultipartGeometry):
99
58
 
100
59
 
101
60
  class MultiLineStringAdapter(CachingGeometryProxy, MultiLineString):
102
-
103
- """Adapts sequences of sequences or numpy arrays to the multilinestring
104
- interface.
105
- """
106
61
 
107
62
  context = None
108
63
  _owned = False
@@ -125,15 +80,54 @@ class MultiLineStringAdapter(CachingGeometryProxy, MultiLineString):
125
80
 
126
81
 
127
82
  def asMultiLineString(context):
128
- """Factory for MultiLineStringAdapter instances."""
83
+ """Adapts a sequence of objects to the MultiLineString interface"""
129
84
  return MultiLineStringAdapter(context)
130
85
 
131
86
 
87
+ def geos_multilinestring_from_py(ob):
88
+ # ob must be either a sequence or array of sequences or arrays
89
+ try:
90
+ # From array protocol
91
+ array = ob.__array_interface__
92
+ assert len(array['shape']) == 1
93
+ L = array['shape'][0]
94
+ assert L >= 1
95
+
96
+ # Make pointer to the coordinate array
97
+ cp = cast(array['data'][0], POINTER(c_double))
98
+
99
+ # Array of pointers to sub-geometries
100
+ subs = (c_void_p * L)()
101
+
102
+ for l in xrange(L):
103
+ geom, ndims = geos_linestring_from_py(array['data'][l])
104
+ subs[i] = cast(geom, c_void_p)
105
+ N = lgeos.GEOSGeom_getDimensions(subs[0])
106
+ except (NotImplementedError, AttributeError):
107
+ obs = getattr(ob, 'geoms', ob)
108
+ L = len(obs)
109
+ exemplar = obs[0]
110
+ try:
111
+ N = len(exemplar[0])
112
+ except TypeError:
113
+ N = exemplar._ndim
114
+ assert L >= 1
115
+ assert N == 2 or N == 3
116
+
117
+ # Array of pointers to point geometries
118
+ subs = (c_void_p * L)()
119
+
120
+ # add to coordinate sequence
121
+ for l in xrange(L):
122
+ geom, ndims = geos_linestring_from_py(obs[l])
123
+ subs[l] = cast(geom, c_void_p)
124
+
125
+ return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
126
+
132
127
  # Test runner
133
128
  def _test():
134
129
  import doctest
135
130
  doctest.testmod()
136
131
 
137
-
138
132
  if __name__ == "__main__":
139
133
  _test()