shapely 1.0__py2.4.egg
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- EGG-INFO/PKG-INFO +173 -0
- EGG-INFO/SOURCES.txt +52 -0
- EGG-INFO/dependency_links.txt +1 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/requires.txt +2 -0
- EGG-INFO/top_level.txt +1 -0
- shapely/__init__.py +1 -0
- shapely/__init__.pyc +0 -0
- shapely/geometry/__init__.py +9 -0
- shapely/geometry/__init__.pyc +0 -0
- shapely/geometry/base.py +415 -0
- shapely/geometry/base.pyc +0 -0
- shapely/geometry/collection.py +24 -0
- shapely/geometry/collection.pyc +0 -0
- shapely/geometry/geo.py +35 -0
- shapely/geometry/geo.pyc +0 -0
- shapely/geometry/linestring.py +234 -0
- shapely/geometry/linestring.pyc +0 -0
- shapely/geometry/multilinestring.py +157 -0
- shapely/geometry/multilinestring.pyc +0 -0
- shapely/geometry/multipoint.py +187 -0
- shapely/geometry/multipoint.pyc +0 -0
- shapely/geometry/multipolygon.py +143 -0
- shapely/geometry/multipolygon.pyc +0 -0
- shapely/geometry/point.py +259 -0
- shapely/geometry/point.pyc +0 -0
- shapely/geometry/polygon.py +429 -0
- shapely/geometry/polygon.pyc +0 -0
- shapely/geos.py +80 -0
- shapely/geos.pyc +0 -0
- shapely/iterops.py +56 -0
- shapely/iterops.pyc +0 -0
- shapely/kml.py +0 -0
- shapely/kml.pyc +0 -0
- shapely/predicates.py +58 -0
- shapely/predicates.pyc +0 -0
- shapely/topology.py +66 -0
- shapely/topology.pyc +0 -0
- shapely/wkb.py +40 -0
- shapely/wkb.pyc +0 -0
- shapely/wkt.py +40 -0
- shapely/wkt.pyc +0 -0
shapely/geometry/geo.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
from point import PointAdapter
|
|
3
|
+
from linestring import LineStringAdapter
|
|
4
|
+
from polygon import PolygonAdapter
|
|
5
|
+
from multipoint import MultiPointAdapter
|
|
6
|
+
from multilinestring import MultiLineStringAdapter
|
|
7
|
+
from multipolygon import MultiPolygonAdapter
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def asShape(context):
|
|
11
|
+
"""Adapts the context to a geometry interface. The coordinates remain
|
|
12
|
+
stored in the context.
|
|
13
|
+
"""
|
|
14
|
+
if hasattr(context, "__geo_interface__"):
|
|
15
|
+
ob = context.__geo_interface__
|
|
16
|
+
else:
|
|
17
|
+
ob = context
|
|
18
|
+
|
|
19
|
+
geom_type = ob.get("type").lower()
|
|
20
|
+
|
|
21
|
+
if geom_type == "point":
|
|
22
|
+
return PointAdapter(ob["coordinates"])
|
|
23
|
+
elif geom_type == "linestring":
|
|
24
|
+
return LineStringAdapter(ob["coordinates"])
|
|
25
|
+
elif geom_type == "polygon":
|
|
26
|
+
return PolygonAdapter(ob["coordinates"][0], ob["coordinates"][1:])
|
|
27
|
+
elif geom_type == "multipoint":
|
|
28
|
+
return MultiPointAdapter(ob["coordinates"])
|
|
29
|
+
elif geom_type == "multilinestring":
|
|
30
|
+
return MultiLineStringAdapter(ob["coordinates"])
|
|
31
|
+
elif geom_type == "multipolygon":
|
|
32
|
+
return MultiPolygonAdapter(ob["coordinates"])
|
|
33
|
+
else:
|
|
34
|
+
raise ValueError, "Unknown geometry type: %s" % geom_type
|
|
35
|
+
|
shapely/geometry/geo.pyc
ADDED
|
Binary file
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Line strings.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from ctypes import byref, c_double, c_int, cast, POINTER, pointer
|
|
6
|
+
from ctypes import ArgumentError
|
|
7
|
+
|
|
8
|
+
from shapely.geos import lgeos
|
|
9
|
+
from shapely.geometry.base import BaseGeometry, exceptNull
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
13
|
+
try:
|
|
14
|
+
# From array protocol
|
|
15
|
+
array = ob.__array_interface__
|
|
16
|
+
assert len(array['shape']) == 2
|
|
17
|
+
m = array['shape'][0]
|
|
18
|
+
n = array['shape'][1]
|
|
19
|
+
assert m >= 2
|
|
20
|
+
assert n == 2 or n == 3
|
|
21
|
+
|
|
22
|
+
# Make pointer to the coordinate array
|
|
23
|
+
try:
|
|
24
|
+
cp = cast(array['data'][0], POINTER(c_double))
|
|
25
|
+
except ArgumentError:
|
|
26
|
+
cp = array['data']
|
|
27
|
+
|
|
28
|
+
# Create a coordinate sequence
|
|
29
|
+
if update_geom is not None:
|
|
30
|
+
cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
|
|
31
|
+
if n != update_ndim:
|
|
32
|
+
raise ValueError, \
|
|
33
|
+
"Wrong coordinate dimensions; this geometry has dimensions: %d" \
|
|
34
|
+
% update_ndim
|
|
35
|
+
else:
|
|
36
|
+
cs = lgeos.GEOSCoordSeq_create(m, n)
|
|
37
|
+
|
|
38
|
+
# add to coordinate sequence
|
|
39
|
+
for i in xrange(m):
|
|
40
|
+
dx = c_double(cp[n*i])
|
|
41
|
+
dy = c_double(cp[n*i+1])
|
|
42
|
+
dz = None
|
|
43
|
+
if n == 3:
|
|
44
|
+
dz = c_double(cp[n*i+2])
|
|
45
|
+
|
|
46
|
+
# Because of a bug in the GEOS C API,
|
|
47
|
+
# always set X before Y
|
|
48
|
+
lgeos.GEOSCoordSeq_setX(cs, i, dx)
|
|
49
|
+
lgeos.GEOSCoordSeq_setY(cs, i, dy)
|
|
50
|
+
if n == 3:
|
|
51
|
+
lgeos.GEOSCoordSeq_setZ(cs, i, dz)
|
|
52
|
+
|
|
53
|
+
except AttributeError:
|
|
54
|
+
# Fall back on list
|
|
55
|
+
m = len(ob)
|
|
56
|
+
n = len(ob[0])
|
|
57
|
+
assert m >= 2
|
|
58
|
+
assert n == 2 or n == 3
|
|
59
|
+
|
|
60
|
+
# Create a coordinate sequence
|
|
61
|
+
if update_geom is not None:
|
|
62
|
+
cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
|
|
63
|
+
if n != update_ndim:
|
|
64
|
+
raise ValueError, \
|
|
65
|
+
"Wrong coordinate dimensions; this geometry has dimensions: %d" \
|
|
66
|
+
% update_ndim
|
|
67
|
+
else:
|
|
68
|
+
cs = lgeos.GEOSCoordSeq_create(m, n)
|
|
69
|
+
|
|
70
|
+
# add to coordinate sequence
|
|
71
|
+
for i in xrange(m):
|
|
72
|
+
coords = ob[i]
|
|
73
|
+
dx = c_double(coords[0])
|
|
74
|
+
dy = c_double(coords[1])
|
|
75
|
+
dz = None
|
|
76
|
+
if n == 3:
|
|
77
|
+
dz = c_double(coords[2])
|
|
78
|
+
|
|
79
|
+
# Because of a bug in the GEOS C API,
|
|
80
|
+
# always set X before Y
|
|
81
|
+
lgeos.GEOSCoordSeq_setX(cs, i, dx)
|
|
82
|
+
lgeos.GEOSCoordSeq_setY(cs, i, dy)
|
|
83
|
+
if n == 3:
|
|
84
|
+
lgeos.GEOSCoordSeq_setZ(cs, i, dz)
|
|
85
|
+
|
|
86
|
+
if update_geom is not None:
|
|
87
|
+
return None
|
|
88
|
+
else:
|
|
89
|
+
return lgeos.GEOSGeom_createLineString(cs), n
|
|
90
|
+
|
|
91
|
+
def update_linestring_from_py(geom, ob):
|
|
92
|
+
geos_linestring_from_py(ob, geom._geom, geom._ndim)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class LineString(BaseGeometry):
|
|
96
|
+
|
|
97
|
+
"""A line string, also known as a polyline.
|
|
98
|
+
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
def __init__(self, coordinates=None):
|
|
102
|
+
"""Initialize.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
|
|
107
|
+
coordinates : sequence or array
|
|
108
|
+
This may be an object that satisfies the numpy array protocol,
|
|
109
|
+
providing an M x 2 or M x 3 (with z) array, or it may be a sequence
|
|
110
|
+
of x, y (,z) coordinate sequences.
|
|
111
|
+
|
|
112
|
+
Example
|
|
113
|
+
-------
|
|
114
|
+
|
|
115
|
+
>>> line = LineString([[0.0, 0.0], [1.0, 2.0]])
|
|
116
|
+
>>> line = LineString(array([[0.0, 0.0], [1.0, 2.0]]))
|
|
117
|
+
|
|
118
|
+
Each result in a line string from (0.0, 0.0) to (1.0, 2.0).
|
|
119
|
+
"""
|
|
120
|
+
BaseGeometry.__init__(self)
|
|
121
|
+
self._init_geom(coordinates)
|
|
122
|
+
|
|
123
|
+
def _init_geom(self, coordinates):
|
|
124
|
+
if coordinates is None:
|
|
125
|
+
# allow creation of null lines, to support unpickling
|
|
126
|
+
pass
|
|
127
|
+
else:
|
|
128
|
+
self._geom, self._ndim = geos_linestring_from_py(coordinates)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def __geo_interface__(self):
|
|
132
|
+
return {
|
|
133
|
+
'type': 'LineString',
|
|
134
|
+
'coordinates': tuple(self.coords)
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
@exceptNull
|
|
139
|
+
def ctypes(self):
|
|
140
|
+
if not self._ctypes_data:
|
|
141
|
+
cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
|
|
142
|
+
cs_len = c_int(0)
|
|
143
|
+
lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len))
|
|
144
|
+
temp = c_double()
|
|
145
|
+
n = self._ndim
|
|
146
|
+
m = cs_len.value
|
|
147
|
+
array_type = c_double * (m * n)
|
|
148
|
+
data = array_type()
|
|
149
|
+
for i in xrange(m):
|
|
150
|
+
lgeos.GEOSCoordSeq_getX(cs, i, byref(temp))
|
|
151
|
+
data[n*i] = temp.value
|
|
152
|
+
lgeos.GEOSCoordSeq_getY(cs, i, byref(temp))
|
|
153
|
+
data[n*i+1] = temp.value
|
|
154
|
+
if n == 3: # TODO: use hasz
|
|
155
|
+
lgeos.GEOSCoordSeq_getZ(cs, i, byref(temp))
|
|
156
|
+
data[n*i+2] = temp.value
|
|
157
|
+
self._ctypes_data = data
|
|
158
|
+
return self._ctypes_data
|
|
159
|
+
|
|
160
|
+
def array_interface(self):
|
|
161
|
+
"""Provide the Numpy array protocol."""
|
|
162
|
+
ai = self.array_interface_base
|
|
163
|
+
ai.update({'shape': (len(self.coords), self._ndim)})
|
|
164
|
+
return ai
|
|
165
|
+
__array_interface__ = property(array_interface)
|
|
166
|
+
|
|
167
|
+
# Coordinate access
|
|
168
|
+
|
|
169
|
+
def set_coords(self, coordinates):
|
|
170
|
+
if self._geom is None:
|
|
171
|
+
self._init_geom(coordinates)
|
|
172
|
+
update_linestring_from_py(self, coordinates)
|
|
173
|
+
|
|
174
|
+
coords = property(BaseGeometry.get_coords, set_coords)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
class LineStringAdapter(LineString):
|
|
178
|
+
|
|
179
|
+
"""Adapts a Python coordinate pair or a numpy array to the line string
|
|
180
|
+
interface.
|
|
181
|
+
"""
|
|
182
|
+
|
|
183
|
+
context = None
|
|
184
|
+
__geom = None
|
|
185
|
+
_owned = False
|
|
186
|
+
|
|
187
|
+
def __init__(self, context):
|
|
188
|
+
self.context = context
|
|
189
|
+
|
|
190
|
+
@property
|
|
191
|
+
def _ndim(self):
|
|
192
|
+
try:
|
|
193
|
+
# From array protocol
|
|
194
|
+
array = self.context.__array_interface__
|
|
195
|
+
n = array['shape'][1]
|
|
196
|
+
assert n == 2 or n == 3
|
|
197
|
+
return n
|
|
198
|
+
except AttributeError:
|
|
199
|
+
# Fall back on list
|
|
200
|
+
return len(self.context[0])
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def _geom(self):
|
|
204
|
+
"""Keeps the GEOS geometry in synch with the context."""
|
|
205
|
+
if self.__geom is not None:
|
|
206
|
+
lgeos.GEOSGeom_destroy(self.__geom)
|
|
207
|
+
self.__geom, n = geos_linestring_from_py(self.context)
|
|
208
|
+
return self.__geom
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def __array_interface__(self):
|
|
212
|
+
"""Provide the Numpy array protocol."""
|
|
213
|
+
try:
|
|
214
|
+
return self.context.__array_interface__
|
|
215
|
+
except AttributeError:
|
|
216
|
+
return self.array_interface()
|
|
217
|
+
|
|
218
|
+
coords = property(BaseGeometry.get_coords)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def asLineString(context):
|
|
222
|
+
"""Factory for PointAdapter instances."""
|
|
223
|
+
return LineStringAdapter(context)
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
# Test runner
|
|
227
|
+
def _test():
|
|
228
|
+
import doctest
|
|
229
|
+
doctest.testmod()
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
_test()
|
|
234
|
+
|
|
Binary file
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Multi-part collection of linestrings.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
|
|
6
|
+
|
|
7
|
+
from shapely.geos import lgeos
|
|
8
|
+
from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
|
|
9
|
+
from shapely.geometry.linestring import LineString, geos_linestring_from_py
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def geos_multilinestring_from_py(ob):
|
|
13
|
+
"""ob must be either a sequence or array of sequences or arrays."""
|
|
14
|
+
try:
|
|
15
|
+
# From array protocol
|
|
16
|
+
array = ob.__array_interface__
|
|
17
|
+
assert len(array['shape']) == 1
|
|
18
|
+
L = array['shape'][0]
|
|
19
|
+
assert L >= 1
|
|
20
|
+
|
|
21
|
+
# Make pointer to the coordinate array
|
|
22
|
+
cp = cast(array['data'][0], POINTER(c_double))
|
|
23
|
+
|
|
24
|
+
# Array of pointers to sub-geometries
|
|
25
|
+
subs = (c_void_p * L)()
|
|
26
|
+
|
|
27
|
+
for l in xrange(L):
|
|
28
|
+
geom, ndims = geos_linestring_from_py(array['data'][l])
|
|
29
|
+
subs[i] = cast(geom, c_void_p)
|
|
30
|
+
N = lgeos.GEOSGeom_getDimensions(subs[0])
|
|
31
|
+
|
|
32
|
+
except AttributeError:
|
|
33
|
+
# Fall back on list
|
|
34
|
+
L = len(ob)
|
|
35
|
+
N = len(ob[0][0])
|
|
36
|
+
assert L >= 1
|
|
37
|
+
assert N == 2 or N == 3
|
|
38
|
+
|
|
39
|
+
# Array of pointers to point geometries
|
|
40
|
+
subs = (c_void_p * L)()
|
|
41
|
+
|
|
42
|
+
# add to coordinate sequence
|
|
43
|
+
for l in xrange(L):
|
|
44
|
+
geom, ndims = geos_linestring_from_py(ob[l])
|
|
45
|
+
subs[l] = cast(geom, c_void_p)
|
|
46
|
+
|
|
47
|
+
return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MultiLineString(BaseGeometry):
|
|
51
|
+
|
|
52
|
+
"""a multiple linestring geometry.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, coordinates=None):
|
|
56
|
+
"""Initialize.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
|
|
61
|
+
coordinates : sequence
|
|
62
|
+
Contains coordinate sequences or objects that provide the numpy
|
|
63
|
+
array protocol, providing an M x 2 or M x 3 (with z) array.
|
|
64
|
+
|
|
65
|
+
Example
|
|
66
|
+
-------
|
|
67
|
+
|
|
68
|
+
>>> geom = MultiLineString( [[[0.0, 0.0], [1.0, 2.0]]] )
|
|
69
|
+
>>> geom = MultiLineString( [ array([[0.0, 0.0], [1.0, 2.0]]) ] )
|
|
70
|
+
|
|
71
|
+
Each result in a collection containing one line string.
|
|
72
|
+
"""
|
|
73
|
+
BaseGeometry.__init__(self)
|
|
74
|
+
|
|
75
|
+
if coordinates is None:
|
|
76
|
+
# allow creation of null lines, to support unpickling
|
|
77
|
+
pass
|
|
78
|
+
else:
|
|
79
|
+
self._geom, self._ndim = geos_multilinestring_from_py(coordinates)
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def __geo_interface__(self):
|
|
83
|
+
return {
|
|
84
|
+
'type': 'MultiLineString',
|
|
85
|
+
'coordinates': tuple(tuple(c for c in g.coords) for g in self.geoms)
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@property
|
|
89
|
+
def ctypes(self):
|
|
90
|
+
raise NotImplementedError, \
|
|
91
|
+
"Multi-part geometries have no ctypes representations"
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def __array_interface__(self):
|
|
95
|
+
"""Provide the Numpy array protocol."""
|
|
96
|
+
raise NotImplementedError, \
|
|
97
|
+
"Multi-part geometries do not themselves provide the array interface"
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def coords(self):
|
|
101
|
+
raise NotImplementedError, \
|
|
102
|
+
"Multi-part geometries do not provide a coordinate sequence"
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
@exceptNull
|
|
106
|
+
def geoms(self):
|
|
107
|
+
return GeometrySequence(self, LineString)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
class MultiLineStringAdapter(MultiLineString):
|
|
111
|
+
|
|
112
|
+
"""Adapts sequences of sequences or numpy arrays to the multilinestring
|
|
113
|
+
interface.
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
context = None
|
|
117
|
+
__geom = None
|
|
118
|
+
_owned = False
|
|
119
|
+
|
|
120
|
+
def __init__(self, context):
|
|
121
|
+
self.context = context
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def _ndim(self):
|
|
125
|
+
try:
|
|
126
|
+
# From array protocol
|
|
127
|
+
array = self.context[0].__array_interface__
|
|
128
|
+
n = array['shape'][1]
|
|
129
|
+
assert n == 2 or n == 3
|
|
130
|
+
return n
|
|
131
|
+
except AttributeError:
|
|
132
|
+
# Fall back on list
|
|
133
|
+
return len(self.context[0][0])
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def _geom(self):
|
|
137
|
+
"""Keeps the GEOS geometry in synch with the context."""
|
|
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
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def asMultiLineString(context):
|
|
145
|
+
"""Factory for MultiLineStringAdapter instances."""
|
|
146
|
+
return MultiLineStringAdapter(context)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
# Test runner
|
|
150
|
+
def _test():
|
|
151
|
+
import doctest
|
|
152
|
+
doctest.testmod()
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
if __name__ == "__main__":
|
|
156
|
+
_test()
|
|
157
|
+
|
|
Binary file
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Multiple points.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from ctypes import byref, c_double, c_int, c_void_p, cast, POINTER, pointer
|
|
6
|
+
|
|
7
|
+
from shapely.geos import lgeos
|
|
8
|
+
from shapely.geometry.base import BaseGeometry, GeometrySequence, exceptNull
|
|
9
|
+
from shapely.geometry.point import Point, geos_point_from_py
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def geos_multipoint_from_py(ob):
|
|
13
|
+
try:
|
|
14
|
+
# From array protocol
|
|
15
|
+
array = ob.__array_interface__
|
|
16
|
+
assert len(array['shape']) == 2
|
|
17
|
+
m = array['shape'][0]
|
|
18
|
+
n = array['shape'][1]
|
|
19
|
+
assert m >= 1
|
|
20
|
+
assert n == 2 or n == 3
|
|
21
|
+
|
|
22
|
+
# Make pointer to the coordinate array
|
|
23
|
+
cp = cast(array['data'][0], POINTER(c_double))
|
|
24
|
+
|
|
25
|
+
# Array of pointers to sub-geometries
|
|
26
|
+
subs = (c_void_p * m)()
|
|
27
|
+
|
|
28
|
+
for i in xrange(m):
|
|
29
|
+
geom, ndims = geos_point_from_py(cp[n*i:n*i+2])
|
|
30
|
+
subs[i] = cast(geom, c_void_p)
|
|
31
|
+
|
|
32
|
+
except AttributeError:
|
|
33
|
+
# Fall back on list
|
|
34
|
+
m = len(ob)
|
|
35
|
+
n = len(ob[0])
|
|
36
|
+
assert n == 2 or n == 3
|
|
37
|
+
|
|
38
|
+
# Array of pointers to point geometries
|
|
39
|
+
subs = (c_void_p * m)()
|
|
40
|
+
|
|
41
|
+
# add to coordinate sequence
|
|
42
|
+
for i in xrange(m):
|
|
43
|
+
coords = ob[i]
|
|
44
|
+
geom, ndims = geos_point_from_py(coords)
|
|
45
|
+
subs[i] = cast(geom, c_void_p)
|
|
46
|
+
|
|
47
|
+
return lgeos.GEOSGeom_createCollection(4, subs, m), n
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class MultiPoint(BaseGeometry):
|
|
51
|
+
|
|
52
|
+
"""A multiple point geometry.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(self, coordinates=None):
|
|
56
|
+
"""Initialize.
|
|
57
|
+
|
|
58
|
+
Parameters
|
|
59
|
+
----------
|
|
60
|
+
|
|
61
|
+
coordinates : sequence or array
|
|
62
|
+
This may be an object that satisfies the numpy array protocol,
|
|
63
|
+
providing an M x 2 or M x 3 (with z) array, or it may be a sequence
|
|
64
|
+
of x, y (,z) coordinate sequences.
|
|
65
|
+
|
|
66
|
+
Example
|
|
67
|
+
-------
|
|
68
|
+
|
|
69
|
+
>>> geom = MultiPoint([[0.0, 0.0], [1.0, 2.0]])
|
|
70
|
+
>>> geom = MultiPoint(array([[0.0, 0.0], [1.0, 2.0]]))
|
|
71
|
+
|
|
72
|
+
Each result in a line string from (0.0, 0.0) to (1.0, 2.0).
|
|
73
|
+
"""
|
|
74
|
+
BaseGeometry.__init__(self)
|
|
75
|
+
|
|
76
|
+
if coordinates is None:
|
|
77
|
+
# allow creation of null lines, to support unpickling
|
|
78
|
+
pass
|
|
79
|
+
else:
|
|
80
|
+
self._geom, self._ndim = geos_multipoint_from_py(coordinates)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
@exceptNull
|
|
85
|
+
def __geo_interface__(self):
|
|
86
|
+
return {
|
|
87
|
+
'type': 'MultiPoint',
|
|
88
|
+
'coordinates': tuple([g.coords[0] for g in self.geoms])
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@property
|
|
92
|
+
@exceptNull
|
|
93
|
+
def ctypes(self):
|
|
94
|
+
if not self._ctypes_data:
|
|
95
|
+
temp = c_double()
|
|
96
|
+
n = self._ndim
|
|
97
|
+
m = len(self.geoms)
|
|
98
|
+
array_type = c_double * (m * n)
|
|
99
|
+
data = array_type()
|
|
100
|
+
for i in xrange(m):
|
|
101
|
+
g = self.geoms[i]._geom
|
|
102
|
+
cs = lgeos.GEOSGeom_getCoordSeq(g)
|
|
103
|
+
lgeos.GEOSCoordSeq_getX(cs, 0, byref(temp))
|
|
104
|
+
data[n*i] = temp.value
|
|
105
|
+
lgeos.GEOSCoordSeq_getY(cs, 0, byref(temp))
|
|
106
|
+
data[n*i+1] = temp.value
|
|
107
|
+
if n == 3: # TODO: use hasz
|
|
108
|
+
lgeos.GEOSCoordSeq_getZ(cs, 0, byref(temp))
|
|
109
|
+
data[n*i+2] = temp.value
|
|
110
|
+
self._ctypes_data = data
|
|
111
|
+
return self._ctypes_data
|
|
112
|
+
|
|
113
|
+
@exceptNull
|
|
114
|
+
def array_interface(self):
|
|
115
|
+
"""Provide the Numpy array protocol."""
|
|
116
|
+
ai = self.array_interface_base
|
|
117
|
+
ai.update({'shape': (len(self.geoms), self._ndim)})
|
|
118
|
+
return ai
|
|
119
|
+
__array_interface__ = property(array_interface)
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def coords(self):
|
|
123
|
+
raise NotImplementedError, \
|
|
124
|
+
"Multipart geometries do not themselves provide coordinate sequences"
|
|
125
|
+
|
|
126
|
+
@property
|
|
127
|
+
@exceptNull
|
|
128
|
+
def geoms(self):
|
|
129
|
+
return GeometrySequence(self, Point)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class MultiPointAdapter(MultiPoint):
|
|
133
|
+
|
|
134
|
+
"""Adapts a Python coordinate pair or a numpy array to the multipoint
|
|
135
|
+
interface.
|
|
136
|
+
"""
|
|
137
|
+
|
|
138
|
+
context = None
|
|
139
|
+
__geom = None
|
|
140
|
+
_owned = False
|
|
141
|
+
|
|
142
|
+
def __init__(self, context):
|
|
143
|
+
self.context = context
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def _ndim(self):
|
|
147
|
+
try:
|
|
148
|
+
# From array protocol
|
|
149
|
+
array = self.context.__array_interface__
|
|
150
|
+
n = array['shape'][1]
|
|
151
|
+
assert n == 2 or n == 3
|
|
152
|
+
return n
|
|
153
|
+
except AttributeError:
|
|
154
|
+
# Fall back on list
|
|
155
|
+
return len(self.context[0])
|
|
156
|
+
|
|
157
|
+
@property
|
|
158
|
+
def _geom(self):
|
|
159
|
+
"""Keeps the GEOS geometry in synch with the context."""
|
|
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
|
|
164
|
+
|
|
165
|
+
@property
|
|
166
|
+
def __array_interface__(self):
|
|
167
|
+
"""Provide the Numpy array protocol."""
|
|
168
|
+
try:
|
|
169
|
+
return self.context.__array_interface__
|
|
170
|
+
except AttributeError:
|
|
171
|
+
return self.array_interface()
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def asMultiPoint(context):
|
|
175
|
+
"""Factory for MultiPointAdapter instances."""
|
|
176
|
+
return MultiPointAdapter(context)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
# Test runner
|
|
180
|
+
def _test():
|
|
181
|
+
import doctest
|
|
182
|
+
doctest.testmod()
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
if __name__ == "__main__":
|
|
186
|
+
_test()
|
|
187
|
+
|
|
Binary file
|