shapely 1.2.8__py2.7-win-amd64.egg
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- DLLs/geos.dll +0 -0
- DLLs/geos_c.dll +0 -0
- EGG-INFO/PKG-INFO +173 -0
- EGG-INFO/not-zip-safe +1 -0
- EGG-INFO/scripts/dissolve.py +53 -0
- EGG-INFO/scripts/intersect.py +81 -0
- shapely/__init__.py +1 -0
- shapely/__init__.pyc +0 -0
- shapely/coords.py +167 -0
- shapely/coords.pyc +0 -0
- shapely/ctypes_declarations.py +279 -0
- shapely/ctypes_declarations.pyc +0 -0
- shapely/ftools.py +78 -0
- shapely/ftools.pyc +0 -0
- shapely/geometry/__init__.py +20 -0
- shapely/geometry/__init__.pyc +0 -0
- shapely/geometry/base.py +595 -0
- shapely/geometry/base.pyc +0 -0
- shapely/geometry/collection.py +43 -0
- shapely/geometry/collection.pyc +0 -0
- shapely/geometry/geo.py +68 -0
- shapely/geometry/geo.pyc +0 -0
- shapely/geometry/linestring.py +259 -0
- shapely/geometry/linestring.pyc +0 -0
- shapely/geometry/multilinestring.py +133 -0
- shapely/geometry/multilinestring.pyc +0 -0
- shapely/geometry/multipoint.py +180 -0
- shapely/geometry/multipoint.pyc +0 -0
- shapely/geometry/multipolygon.py +154 -0
- shapely/geometry/multipolygon.pyc +0 -0
- shapely/geometry/point.py +241 -0
- shapely/geometry/point.pyc +0 -0
- shapely/geometry/polygon.py +449 -0
- shapely/geometry/polygon.pyc +0 -0
- shapely/geometry/proxy.py +54 -0
- shapely/geometry/proxy.pyc +0 -0
- shapely/geos.py +373 -0
- shapely/geos.pyc +0 -0
- shapely/impl.py +119 -0
- shapely/impl.pyc +0 -0
- shapely/iterops.py +53 -0
- shapely/iterops.pyc +0 -0
- shapely/linref.py +26 -0
- shapely/linref.pyc +0 -0
- shapely/ops.py +87 -0
- shapely/ops.pyc +0 -0
- shapely/predicates.py +24 -0
- shapely/predicates.pyc +0 -0
- shapely/prepared.py +58 -0
- shapely/prepared.pyc +0 -0
- shapely/topology.py +62 -0
- shapely/topology.pyc +0 -0
- shapely/validation.py +7 -0
- shapely/validation.pyc +0 -0
- shapely/wkb.py +39 -0
- shapely/wkb.pyc +0 -0
- shapely/wkt.py +34 -0
- shapely/wkt.pyc +0 -0
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""Line strings and related utilities
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from ctypes import c_double, cast, POINTER
|
|
5
|
+
from ctypes import ArgumentError
|
|
6
|
+
|
|
7
|
+
from shapely.geos import lgeos, TopologicalError
|
|
8
|
+
from shapely.geometry.base import BaseGeometry, geom_factory
|
|
9
|
+
from shapely.geometry.proxy import CachingGeometryProxy
|
|
10
|
+
|
|
11
|
+
__all__ = ['LineString', 'asLineString']
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class LineString(BaseGeometry):
|
|
15
|
+
"""
|
|
16
|
+
A one-dimensional figure comprising one or more line segments
|
|
17
|
+
|
|
18
|
+
A LineString has non-zero length and zero area. It may approximate a curve
|
|
19
|
+
and need not be straight. Unlike a LinearRing, a LineString is not closed.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, coordinates=None):
|
|
23
|
+
"""
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
coordinates : sequence
|
|
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.
|
|
30
|
+
|
|
31
|
+
Example
|
|
32
|
+
-------
|
|
33
|
+
Create a line with two segments
|
|
34
|
+
|
|
35
|
+
>>> a = LineString([[0, 0], [1, 0], [1, 1]])
|
|
36
|
+
>>> a.length
|
|
37
|
+
2.0
|
|
38
|
+
"""
|
|
39
|
+
BaseGeometry.__init__(self)
|
|
40
|
+
if coordinates is not None:
|
|
41
|
+
self._set_coords(coordinates)
|
|
42
|
+
|
|
43
|
+
@property
|
|
44
|
+
def __geo_interface__(self):
|
|
45
|
+
return {
|
|
46
|
+
'type': 'LineString',
|
|
47
|
+
'coordinates': tuple(self.coords)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@property
|
|
51
|
+
def ctypes(self):
|
|
52
|
+
if not self._ctypes_data:
|
|
53
|
+
self._ctypes_data = self.coords.ctypes
|
|
54
|
+
return self._ctypes_data
|
|
55
|
+
|
|
56
|
+
def array_interface(self):
|
|
57
|
+
"""Provide the Numpy array protocol."""
|
|
58
|
+
return self.coords.array_interface()
|
|
59
|
+
|
|
60
|
+
__array_interface__ = property(array_interface)
|
|
61
|
+
|
|
62
|
+
# Coordinate access
|
|
63
|
+
def _set_coords(self, coordinates):
|
|
64
|
+
self.empty()
|
|
65
|
+
self._geom, self._ndim = geos_linestring_from_py(coordinates)
|
|
66
|
+
|
|
67
|
+
coords = property(BaseGeometry._get_coords, _set_coords)
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def xy(self):
|
|
71
|
+
"""Separate arrays of X and Y coordinate values
|
|
72
|
+
|
|
73
|
+
Example:
|
|
74
|
+
|
|
75
|
+
>>> x, y = LineString(((0, 0), (1, 1))).xy
|
|
76
|
+
>>> list(x)
|
|
77
|
+
[0.0, 1.0]
|
|
78
|
+
>>> list(y)
|
|
79
|
+
[0.0, 1.0]
|
|
80
|
+
"""
|
|
81
|
+
return self.coords.xy
|
|
82
|
+
|
|
83
|
+
def parallel_offset(
|
|
84
|
+
self, distance, side,
|
|
85
|
+
resolution=16, join_style=1, mitre_limit=1.0):
|
|
86
|
+
|
|
87
|
+
"""Returns a LineString or MultiLineString geometry at a distance from
|
|
88
|
+
the object on its right or its left side.
|
|
89
|
+
|
|
90
|
+
Distance must be a positive float value. The side parameter may be
|
|
91
|
+
'left' or 'right'. The resolution of the buffer around each vertex of
|
|
92
|
+
the object increases by increasing the resolution keyword parameter or
|
|
93
|
+
third positional parameter.
|
|
94
|
+
|
|
95
|
+
The join style is for outside corners between line segments. Accepted
|
|
96
|
+
values are 1 => ROUND, 2 => MITRE, 3 => BEVEL.
|
|
97
|
+
|
|
98
|
+
The mitre ratio limit is used for very sharp corners. It is the ratio
|
|
99
|
+
of the distance from the corner to the end of the mitred offset corner.
|
|
100
|
+
When two line segments meet at a sharp angle, a miter join will extend
|
|
101
|
+
far beyond the original geometry. To prevent unreasonable geometry, the
|
|
102
|
+
mitre limit allows controlling the maximum length of the join corner.
|
|
103
|
+
Corners with a ratio which exceed the limit will be beveled."""
|
|
104
|
+
|
|
105
|
+
try:
|
|
106
|
+
return geom_factory(self.impl['parallel_offset'](
|
|
107
|
+
self, distance, resolution, join_style, mitre_limit,
|
|
108
|
+
bool(side=='left')))
|
|
109
|
+
except WindowsError:
|
|
110
|
+
raise TopologicalError()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
class LineStringAdapter(CachingGeometryProxy, LineString):
|
|
114
|
+
|
|
115
|
+
def __init__(self, context):
|
|
116
|
+
self.context = context
|
|
117
|
+
self.factory = geos_linestring_from_py
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def _ndim(self):
|
|
121
|
+
try:
|
|
122
|
+
# From array protocol
|
|
123
|
+
array = self.context.__array_interface__
|
|
124
|
+
n = array['shape'][1]
|
|
125
|
+
assert n == 2 or n == 3
|
|
126
|
+
return n
|
|
127
|
+
except AttributeError:
|
|
128
|
+
# Fall back on list
|
|
129
|
+
return len(self.context[0])
|
|
130
|
+
|
|
131
|
+
@property
|
|
132
|
+
def __array_interface__(self):
|
|
133
|
+
"""Provide the Numpy array protocol."""
|
|
134
|
+
try:
|
|
135
|
+
return self.context.__array_interface__
|
|
136
|
+
except AttributeError:
|
|
137
|
+
return self.array_interface()
|
|
138
|
+
|
|
139
|
+
_get_coords = BaseGeometry._get_coords
|
|
140
|
+
|
|
141
|
+
def _set_coords(self, ob):
|
|
142
|
+
raise NotImplementedError(
|
|
143
|
+
"Adapters can not modify their coordinate sources")
|
|
144
|
+
|
|
145
|
+
coords = property(_get_coords)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def asLineString(context):
|
|
149
|
+
"""Adapt an object the LineString interface"""
|
|
150
|
+
return LineStringAdapter(context)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
|
|
154
|
+
try:
|
|
155
|
+
# From array protocol
|
|
156
|
+
array = ob.__array_interface__
|
|
157
|
+
assert len(array['shape']) == 2
|
|
158
|
+
m = array['shape'][0]
|
|
159
|
+
if m < 2:
|
|
160
|
+
raise ValueError(
|
|
161
|
+
"LineStrings must have at least 2 coordinate tuples")
|
|
162
|
+
try:
|
|
163
|
+
n = array['shape'][1]
|
|
164
|
+
except IndexError:
|
|
165
|
+
raise ValueError(
|
|
166
|
+
"Input %s is the wrong shape for a LineString" % str(ob))
|
|
167
|
+
assert n == 2 or n == 3
|
|
168
|
+
|
|
169
|
+
# Make pointer to the coordinate array
|
|
170
|
+
try:
|
|
171
|
+
cp = cast(array['data'][0], POINTER(c_double))
|
|
172
|
+
except ArgumentError:
|
|
173
|
+
cp = array['data']
|
|
174
|
+
|
|
175
|
+
# Create a coordinate sequence
|
|
176
|
+
if update_geom is not None:
|
|
177
|
+
cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
|
|
178
|
+
if n != update_ndim:
|
|
179
|
+
raise ValueError(
|
|
180
|
+
"Wrong coordinate dimensions; this geometry has dimensions: %d" \
|
|
181
|
+
% update_ndim)
|
|
182
|
+
else:
|
|
183
|
+
cs = lgeos.GEOSCoordSeq_create(m, n)
|
|
184
|
+
|
|
185
|
+
# add to coordinate sequence
|
|
186
|
+
for i in xrange(m):
|
|
187
|
+
dx = c_double(cp[n*i])
|
|
188
|
+
dy = c_double(cp[n*i+1])
|
|
189
|
+
dz = None
|
|
190
|
+
if n == 3:
|
|
191
|
+
try:
|
|
192
|
+
dz = c_double(cp[n*i+2])
|
|
193
|
+
except IndexError:
|
|
194
|
+
raise ValueError("Inconsistent coordinate dimensionality")
|
|
195
|
+
|
|
196
|
+
# Because of a bug in the GEOS C API,
|
|
197
|
+
# always set X before Y
|
|
198
|
+
lgeos.GEOSCoordSeq_setX(cs, i, dx)
|
|
199
|
+
lgeos.GEOSCoordSeq_setY(cs, i, dy)
|
|
200
|
+
if n == 3:
|
|
201
|
+
lgeos.GEOSCoordSeq_setZ(cs, i, dz)
|
|
202
|
+
|
|
203
|
+
except AttributeError:
|
|
204
|
+
# Fall back on list
|
|
205
|
+
m = len(ob)
|
|
206
|
+
if m < 2:
|
|
207
|
+
raise ValueError(
|
|
208
|
+
"LineStrings must have at least 2 coordinate tuples")
|
|
209
|
+
try:
|
|
210
|
+
n = len(ob[0])
|
|
211
|
+
except TypeError:
|
|
212
|
+
raise ValueError(
|
|
213
|
+
"Input %s is the wrong shape for a LineString" % str(ob))
|
|
214
|
+
assert n == 2 or n == 3
|
|
215
|
+
|
|
216
|
+
# Create a coordinate sequence
|
|
217
|
+
if update_geom is not None:
|
|
218
|
+
cs = lgeos.GEOSGeom_getCoordSeq(update_geom)
|
|
219
|
+
if n != update_ndim:
|
|
220
|
+
raise ValueError(
|
|
221
|
+
"Wrong coordinate dimensions; this geometry has dimensions: %d" \
|
|
222
|
+
% update_ndim)
|
|
223
|
+
else:
|
|
224
|
+
cs = lgeos.GEOSCoordSeq_create(m, n)
|
|
225
|
+
|
|
226
|
+
# add to coordinate sequence
|
|
227
|
+
for i in xrange(m):
|
|
228
|
+
coords = ob[i]
|
|
229
|
+
dx = c_double(coords[0])
|
|
230
|
+
dy = c_double(coords[1])
|
|
231
|
+
dz = None
|
|
232
|
+
if n == 3:
|
|
233
|
+
try:
|
|
234
|
+
dz = c_double(coords[2])
|
|
235
|
+
except IndexError:
|
|
236
|
+
raise ValueError("Inconsistent coordinate dimensionality")
|
|
237
|
+
|
|
238
|
+
# Because of a bug in the GEOS C API,
|
|
239
|
+
# always set X before Y
|
|
240
|
+
lgeos.GEOSCoordSeq_setX(cs, i, dx)
|
|
241
|
+
lgeos.GEOSCoordSeq_setY(cs, i, dy)
|
|
242
|
+
if n == 3:
|
|
243
|
+
lgeos.GEOSCoordSeq_setZ(cs, i, dz)
|
|
244
|
+
|
|
245
|
+
if update_geom is not None:
|
|
246
|
+
return None
|
|
247
|
+
else:
|
|
248
|
+
return lgeos.GEOSGeom_createLineString(cs), n
|
|
249
|
+
|
|
250
|
+
def update_linestring_from_py(geom, ob):
|
|
251
|
+
geos_linestring_from_py(ob, geom._geom, geom._ndim)
|
|
252
|
+
|
|
253
|
+
# Test runner
|
|
254
|
+
def _test():
|
|
255
|
+
import doctest
|
|
256
|
+
doctest.testmod()
|
|
257
|
+
|
|
258
|
+
if __name__ == "__main__":
|
|
259
|
+
_test()
|
|
Binary file
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""Collections of linestrings and related utilities
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from ctypes import c_double, c_void_p, cast, POINTER
|
|
5
|
+
|
|
6
|
+
from shapely.geos import lgeos
|
|
7
|
+
from shapely.geometry.base import BaseMultipartGeometry
|
|
8
|
+
from shapely.geometry.linestring import LineString, geos_linestring_from_py
|
|
9
|
+
from shapely.geometry.proxy import CachingGeometryProxy
|
|
10
|
+
|
|
11
|
+
__all__ = ['MultiLineString', 'asMultiLineString']
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MultiLineString(BaseMultipartGeometry):
|
|
15
|
+
"""
|
|
16
|
+
A collection of one or more line strings
|
|
17
|
+
|
|
18
|
+
A MultiLineString has non-zero length and zero area.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
geoms : sequence
|
|
23
|
+
A sequence of LineStrings
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, lines=None):
|
|
27
|
+
"""
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
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.
|
|
34
|
+
|
|
35
|
+
Example
|
|
36
|
+
-------
|
|
37
|
+
Construct a collection containing one line string.
|
|
38
|
+
|
|
39
|
+
>>> lines = MultiLineString( [[[0.0, 0.0], [1.0, 2.0]]] )
|
|
40
|
+
"""
|
|
41
|
+
super(MultiLineString, self).__init__()
|
|
42
|
+
|
|
43
|
+
if lines is None:
|
|
44
|
+
# allow creation of null lines, to support unpickling
|
|
45
|
+
pass
|
|
46
|
+
else:
|
|
47
|
+
self._geom, self._ndim = geos_multilinestring_from_py(lines)
|
|
48
|
+
|
|
49
|
+
def shape_factory(self, *args):
|
|
50
|
+
return LineString(*args)
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def __geo_interface__(self):
|
|
54
|
+
return {
|
|
55
|
+
'type': 'MultiLineString',
|
|
56
|
+
'coordinates': tuple(tuple(c for c in g.coords) for g in self.geoms)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class MultiLineStringAdapter(CachingGeometryProxy, MultiLineString):
|
|
61
|
+
|
|
62
|
+
context = None
|
|
63
|
+
_owned = False
|
|
64
|
+
|
|
65
|
+
def __init__(self, context):
|
|
66
|
+
self.context = context
|
|
67
|
+
self.factory = geos_multilinestring_from_py
|
|
68
|
+
|
|
69
|
+
@property
|
|
70
|
+
def _ndim(self):
|
|
71
|
+
try:
|
|
72
|
+
# From array protocol
|
|
73
|
+
array = self.context[0].__array_interface__
|
|
74
|
+
n = array['shape'][1]
|
|
75
|
+
assert n == 2 or n == 3
|
|
76
|
+
return n
|
|
77
|
+
except AttributeError:
|
|
78
|
+
# Fall back on list
|
|
79
|
+
return len(self.context[0][0])
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def asMultiLineString(context):
|
|
83
|
+
"""Adapts a sequence of objects to the MultiLineString interface"""
|
|
84
|
+
return MultiLineStringAdapter(context)
|
|
85
|
+
|
|
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
|
+
|
|
127
|
+
# Test runner
|
|
128
|
+
def _test():
|
|
129
|
+
import doctest
|
|
130
|
+
doctest.testmod()
|
|
131
|
+
|
|
132
|
+
if __name__ == "__main__":
|
|
133
|
+
_test()
|
|
Binary file
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"""Collections of points and related utilities
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from ctypes import byref, c_double, c_void_p, cast, POINTER
|
|
5
|
+
from ctypes import ArgumentError
|
|
6
|
+
|
|
7
|
+
from shapely.geos import lgeos
|
|
8
|
+
from shapely.geometry.base import BaseMultipartGeometry, exceptNull
|
|
9
|
+
from shapely.geometry.point import Point, geos_point_from_py
|
|
10
|
+
from shapely.geometry.proxy import CachingGeometryProxy
|
|
11
|
+
|
|
12
|
+
__all__ = ['MultiPoint', 'asMultiPoint']
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class MultiPoint(BaseMultipartGeometry):
|
|
16
|
+
|
|
17
|
+
"""A collection of one or more points
|
|
18
|
+
|
|
19
|
+
A MultiPoint has zero area and zero length.
|
|
20
|
+
|
|
21
|
+
Attributes
|
|
22
|
+
----------
|
|
23
|
+
geoms : sequence
|
|
24
|
+
A sequence of Points
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, points=None):
|
|
28
|
+
"""
|
|
29
|
+
Parameters
|
|
30
|
+
----------
|
|
31
|
+
points : sequence
|
|
32
|
+
A sequence of (x, y [,z]) numeric coordinate pairs or triples or a
|
|
33
|
+
sequence of objects that implement the numpy array interface,
|
|
34
|
+
including instaces of Point.
|
|
35
|
+
|
|
36
|
+
Example
|
|
37
|
+
-------
|
|
38
|
+
Construct a 2 point collection
|
|
39
|
+
|
|
40
|
+
>>> ob = MultiPoint([[0.0, 0.0], [1.0, 2.0]])
|
|
41
|
+
>>> len(ob.geoms)
|
|
42
|
+
2
|
|
43
|
+
>>> type(ob.geoms[0]) == Point
|
|
44
|
+
True
|
|
45
|
+
"""
|
|
46
|
+
super(MultiPoint, self).__init__()
|
|
47
|
+
|
|
48
|
+
if points is None:
|
|
49
|
+
# allow creation of empty multipoints, to support unpickling
|
|
50
|
+
pass
|
|
51
|
+
else:
|
|
52
|
+
self._geom, self._ndim = geos_multipoint_from_py(points)
|
|
53
|
+
|
|
54
|
+
def shape_factory(self, *args):
|
|
55
|
+
return Point(*args)
|
|
56
|
+
|
|
57
|
+
@property
|
|
58
|
+
def __geo_interface__(self):
|
|
59
|
+
return {
|
|
60
|
+
'type': 'MultiPoint',
|
|
61
|
+
'coordinates': tuple([g.coords[0] for g in self.geoms])
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@property
|
|
65
|
+
@exceptNull
|
|
66
|
+
def ctypes(self):
|
|
67
|
+
if not self._ctypes_data:
|
|
68
|
+
temp = c_double()
|
|
69
|
+
n = self._ndim
|
|
70
|
+
m = len(self.geoms)
|
|
71
|
+
array_type = c_double * (m * n)
|
|
72
|
+
data = array_type()
|
|
73
|
+
for i in xrange(m):
|
|
74
|
+
g = self.geoms[i]._geom
|
|
75
|
+
cs = lgeos.GEOSGeom_getCoordSeq(g)
|
|
76
|
+
lgeos.GEOSCoordSeq_getX(cs, 0, byref(temp))
|
|
77
|
+
data[n*i] = temp.value
|
|
78
|
+
lgeos.GEOSCoordSeq_getY(cs, 0, byref(temp))
|
|
79
|
+
data[n*i+1] = temp.value
|
|
80
|
+
if n == 3: # TODO: use hasz
|
|
81
|
+
lgeos.GEOSCoordSeq_getZ(cs, 0, byref(temp))
|
|
82
|
+
data[n*i+2] = temp.value
|
|
83
|
+
self._ctypes_data = data
|
|
84
|
+
return self._ctypes_data
|
|
85
|
+
|
|
86
|
+
@exceptNull
|
|
87
|
+
def array_interface(self):
|
|
88
|
+
"""Provide the Numpy array protocol."""
|
|
89
|
+
ai = self.array_interface_base
|
|
90
|
+
ai.update({'shape': (len(self.geoms), self._ndim)})
|
|
91
|
+
return ai
|
|
92
|
+
__array_interface__ = property(array_interface)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
class MultiPointAdapter(CachingGeometryProxy, MultiPoint):
|
|
96
|
+
|
|
97
|
+
context = None
|
|
98
|
+
_owned = False
|
|
99
|
+
|
|
100
|
+
def __init__(self, context):
|
|
101
|
+
self.context = context
|
|
102
|
+
self.factory = geos_multipoint_from_py
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def _ndim(self):
|
|
106
|
+
try:
|
|
107
|
+
# From array protocol
|
|
108
|
+
array = self.context.__array_interface__
|
|
109
|
+
n = array['shape'][1]
|
|
110
|
+
assert n == 2 or n == 3
|
|
111
|
+
return n
|
|
112
|
+
except AttributeError:
|
|
113
|
+
# Fall back on list
|
|
114
|
+
return len(self.context[0])
|
|
115
|
+
|
|
116
|
+
@property
|
|
117
|
+
def __array_interface__(self):
|
|
118
|
+
"""Provide the Numpy array protocol."""
|
|
119
|
+
try:
|
|
120
|
+
return self.context.__array_interface__
|
|
121
|
+
except AttributeError:
|
|
122
|
+
return self.array_interface()
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def asMultiPoint(context):
|
|
126
|
+
"""Adapt a sequence of objects to the MultiPoint interface"""
|
|
127
|
+
return MultiPointAdapter(context)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def geos_multipoint_from_py(ob):
|
|
131
|
+
try:
|
|
132
|
+
# From array protocol
|
|
133
|
+
array = ob.__array_interface__
|
|
134
|
+
assert len(array['shape']) == 2
|
|
135
|
+
m = array['shape'][0]
|
|
136
|
+
n = array['shape'][1]
|
|
137
|
+
assert m >= 1
|
|
138
|
+
assert n == 2 or n == 3
|
|
139
|
+
|
|
140
|
+
# Make pointer to the coordinate array
|
|
141
|
+
try:
|
|
142
|
+
cp = cast(array['data'][0], POINTER(c_double))
|
|
143
|
+
except ArgumentError:
|
|
144
|
+
cp = array['data']
|
|
145
|
+
|
|
146
|
+
# Array of pointers to sub-geometries
|
|
147
|
+
subs = (c_void_p * m)()
|
|
148
|
+
|
|
149
|
+
for i in xrange(m):
|
|
150
|
+
geom, ndims = geos_point_from_py(cp[n*i:n*i+2])
|
|
151
|
+
subs[i] = cast(geom, c_void_p)
|
|
152
|
+
|
|
153
|
+
except AttributeError:
|
|
154
|
+
# Fall back on list
|
|
155
|
+
m = len(ob)
|
|
156
|
+
try:
|
|
157
|
+
n = len(ob[0])
|
|
158
|
+
except TypeError:
|
|
159
|
+
n = ob[0]._ndim
|
|
160
|
+
assert n == 2 or n == 3
|
|
161
|
+
|
|
162
|
+
# Array of pointers to point geometries
|
|
163
|
+
subs = (c_void_p * m)()
|
|
164
|
+
|
|
165
|
+
# add to coordinate sequence
|
|
166
|
+
for i in xrange(m):
|
|
167
|
+
coords = ob[i]
|
|
168
|
+
geom, ndims = geos_point_from_py(coords)
|
|
169
|
+
subs[i] = cast(geom, c_void_p)
|
|
170
|
+
|
|
171
|
+
return lgeos.GEOSGeom_createCollection(4, subs, m), n
|
|
172
|
+
|
|
173
|
+
# Test runner
|
|
174
|
+
def _test():
|
|
175
|
+
import doctest
|
|
176
|
+
doctest.testmod()
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
if __name__ == "__main__":
|
|
180
|
+
_test()
|
|
Binary file
|