shapely 1.0b1__py2.4.egg → 1.0b3__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 CHANGED
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.0
2
2
  Name: Shapely
3
- Version: 1.0b1
3
+ Version: 1.0b3
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 after small modifications.)
26
+ * libgeos_c (2.2.3, also reported to work with 3.0)
27
27
  * Python ctypes_ (standard in Python 2.5+)
28
28
 
29
29
  .. _ctypes: http://pypi.python.org/pypi/ctypes/
@@ -124,7 +124,7 @@ Description: Shapely
124
124
  For current information about this project, see the wiki_.
125
125
 
126
126
  .. _wiki: http://trac.gispython.org/projects/PCL/wiki/Shapely
127
- .. _manual: http://trac.gispython.org/projects/PCL/wiki/ShapelyManual
127
+ .. _manual: http://gispython.org/shapely/manual.html
128
128
 
129
129
  If you have questions, please consider joining our community list:
130
130
 
EGG-INFO/SOURCES.txt CHANGED
@@ -11,6 +11,8 @@ Shapely.egg-info/requires.txt
11
11
  Shapely.egg-info/top_level.txt
12
12
  examples/geoms.py
13
13
  examples/world.py
14
+ manual/manual.txt
15
+ manual/style.css
14
16
  shapely/__init__.py
15
17
  shapely/geos.py
16
18
  shapely/iterops.py
@@ -0,0 +1,9 @@
1
+ from geo import asShape
2
+ from point import Point, asPoint
3
+ from linestring import LineString, asLineString
4
+ from polygon import Polygon, asPolygon
5
+ from multipoint import MultiPoint, asMultiPoint
6
+ from multilinestring import MultiLineString, asMultiLineString
7
+ from multipolygon import MultiPolygon, asMultiPolygon
8
+ from collection import GeometryCollection
9
+
Binary file
@@ -0,0 +1,358 @@
1
+ """
2
+ Base geometry class and utilities.
3
+ """
4
+
5
+ from ctypes import string_at, byref, c_int, c_size_t, c_char_p, c_double
6
+ import sys
7
+
8
+ from shapely.geos import lgeos
9
+ from shapely.predicates import BinaryPredicate, UnaryPredicate
10
+ from shapely.topology import BinaryTopologicalOp, UnaryTopologicalOp
11
+
12
+
13
+ GEOMETRY_TYPES = [
14
+ 'Point',
15
+ 'LineString',
16
+ 'LinearRing',
17
+ 'Polygon',
18
+ 'MultiPoint',
19
+ 'MultiLineString',
20
+ 'MultiPolygon',
21
+ 'GeometryCollection'
22
+ ]
23
+
24
+ def geometry_type_name(g):
25
+ return GEOMETRY_TYPES[lgeos.GEOSGeomTypeId(g)]
26
+
27
+ # Abstract geometry factory for use with topological methods below
28
+
29
+ def geom_factory(g):
30
+ if not g:
31
+ raise ValueError, "No Shapely geometry can be created from this null value"
32
+ ob = BaseGeometry()
33
+ geom_type = geometry_type_name(g)
34
+ # TODO: check cost of dynamic import by profiling
35
+ mod = __import__(
36
+ 'shapely.geometry',
37
+ globals(),
38
+ locals(),
39
+ [geom_type],
40
+ )
41
+ ob.__class__ = getattr(mod, geom_type)
42
+ ob._geom = g
43
+ ob._ndim = 2 # callers should be all from 2D worlds
44
+ return ob
45
+
46
+
47
+ class CoordinateSequence(object):
48
+
49
+ _cseq = None
50
+ _ndim = None
51
+ _length = 0
52
+ index = 0
53
+
54
+ def __init__(self, geom):
55
+ self._cseq = lgeos.GEOSGeom_getCoordSeq(geom._geom)
56
+ self._ndim = geom._ndim
57
+
58
+ def __iter__(self):
59
+ self.index = 0
60
+ self._length = self.__len__()
61
+ return self
62
+
63
+ def next(self):
64
+ dx = c_double()
65
+ dy = c_double()
66
+ dz = c_double()
67
+ i = self.index
68
+ if i < self._length:
69
+ lgeos.GEOSCoordSeq_getX(self._cseq, i, byref(dx))
70
+ lgeos.GEOSCoordSeq_getY(self._cseq, i, byref(dy))
71
+ if self._ndim == 3: # TODO: use hasz
72
+ lgeos.GEOSCoordSeq_getZ(self._cseq, i, byref(dz))
73
+ self.index += 1
74
+ return (dx.value, dy.value, dz.value)
75
+ else:
76
+ self.index += 1
77
+ return (dx.value, dy.value)
78
+ else:
79
+ raise StopIteration
80
+
81
+ def __len__(self):
82
+ cs_len = c_int(0)
83
+ lgeos.GEOSCoordSeq_getSize(self._cseq, byref(cs_len))
84
+ return cs_len.value
85
+
86
+ def __getitem__(self, i):
87
+ M = self.__len__()
88
+ if i + M < 0 or i >= M:
89
+ raise IndexError, "index out of range"
90
+ if i < 0:
91
+ ii = M + i
92
+ else:
93
+ ii = i
94
+ dx = c_double()
95
+ dy = c_double()
96
+ dz = c_double()
97
+ lgeos.GEOSCoordSeq_getX(self._cseq, ii, byref(dx))
98
+ lgeos.GEOSCoordSeq_getY(self._cseq, ii, byref(dy))
99
+ if self._ndim == 3: # TODO: use hasz
100
+ lgeos.GEOSCoordSeq_getZ(self._cseq, ii, byref(dz))
101
+ return (dx.value, dy.value, dz.value)
102
+ else:
103
+ return (dx.value, dy.value)
104
+
105
+
106
+ class GeometrySequence(object):
107
+
108
+ _factory = None
109
+ _geom = None
110
+ _ndim = None
111
+ _index = 0
112
+ _length = 0
113
+
114
+ def __init__(self, geom, type):
115
+ self._factory = type
116
+ self._geom = geom._geom
117
+ self._ndim = geom._ndim
118
+
119
+ def __iter__(self):
120
+ self._index = 0
121
+ self._length = self.__len__()
122
+ return self
123
+
124
+ def next(self):
125
+ if self._index < self.__len__():
126
+ g = self._factory()
127
+ g._owned = True
128
+ g._geom = lgeos.GEOSGetGeometryN(self._geom, self._index)
129
+ self._index += 1
130
+ return g
131
+ else:
132
+ raise StopIteration
133
+
134
+ def __len__(self):
135
+ return lgeos.GEOSGetNumGeometries(self._geom)
136
+
137
+ def __getitem__(self, i):
138
+ M = self.__len__()
139
+ if i + M < 0 or i >= M:
140
+ raise IndexError, "index out of range"
141
+ if i < 0:
142
+ ii = M + i
143
+ else:
144
+ ii = i
145
+ g = self._factory()
146
+ g._owned = True
147
+ g._geom = lgeos.GEOSGetGeometryN(self._geom, ii)
148
+ return g
149
+
150
+ @property
151
+ def _longest(self):
152
+ max = 0
153
+ for g in iter(self):
154
+ l = len(g.coords)
155
+ if l > max:
156
+ max = l
157
+
158
+
159
+ class BaseGeometry(object):
160
+
161
+ """Provides GEOS spatial predicates and topological operations.
162
+ """
163
+
164
+ _geom = None
165
+ _ctypes_data = None
166
+ _ndim = None
167
+ _crs = None
168
+ _owned = False
169
+
170
+ def __init__(self):
171
+ self._geom = lgeos.GEOSGeomFromWKT(c_char_p('GEOMETRYCOLLECTION EMPTY'))
172
+
173
+ def __del__(self):
174
+ if self._geom is not None and not self._owned:
175
+ lgeos.GEOSGeom_destroy(self._geom)
176
+
177
+ def __str__(self):
178
+ return self.to_wkt()
179
+
180
+ def __eq__(self, other):
181
+ return self.equals(other)
182
+
183
+ def __ne__(self, other):
184
+ return not self.equals(other)
185
+
186
+ # To support pickling
187
+
188
+ def __reduce__(self):
189
+ return (self.__class__, (), self.to_wkb())
190
+
191
+ def __setstate__(self, state):
192
+ self._geom = lgeos.GEOSGeomFromWKB_buf(
193
+ c_char_p(state),
194
+ c_size_t(len(state))
195
+ )
196
+
197
+ # Array and ctypes interfaces
198
+
199
+ @property
200
+ def ctypes(self):
201
+ """Return a ctypes representation.
202
+
203
+ To be overridden by extension classes."""
204
+ raise NotImplementedError
205
+
206
+ @property
207
+ def array_interface_base(self):
208
+ if sys.byteorder == 'little':
209
+ typestr = '<f8'
210
+ elif sys.byteorder == 'big':
211
+ typestr = '>f8'
212
+ else:
213
+ raise ValueError, "Unsupported byteorder: neither little nor big-endian"
214
+ return {
215
+ 'version': 3,
216
+ 'typestr': typestr,
217
+ 'data': self.ctypes,
218
+ }
219
+
220
+ @property
221
+ def __array_interface__(self):
222
+ """Provide the Numpy array protocol."""
223
+ raise NotImplementedError
224
+
225
+ def get_coords(self):
226
+ return CoordinateSequence(self)
227
+
228
+ def set_coords(self, ob):
229
+ raise NotImplementedError, \
230
+ "set_coords must be provided by derived classes"
231
+
232
+ coords = property(get_coords, set_coords)
233
+
234
+ # Python feature protocol
235
+
236
+ @property
237
+ def __geo_interface__(self):
238
+ raise NotImplementedError
239
+
240
+ @property
241
+ def type(self):
242
+ return self.geometryType()
243
+
244
+ # Type of geometry and its representations
245
+
246
+ def geometryType(self):
247
+ """Returns a string representing the geometry type, e.g. 'Polygon'."""
248
+ return geometry_type_name(self._geom)
249
+
250
+ def to_wkb(self):
251
+ """Returns a WKB byte string representation of the geometry."""
252
+ size = c_int()
253
+ bytes = lgeos.GEOSGeomToWKB_buf(self._geom, byref(size))
254
+ return string_at(bytes, size.value)
255
+
256
+ def to_wkt(self):
257
+ """Returns a WKT string representation of the geometry."""
258
+ return string_at(lgeos.GEOSGeomToWKT(self._geom))
259
+
260
+ geom_type = property(geometryType)
261
+ wkt = property(to_wkt)
262
+ wkb = property(to_wkb)
263
+
264
+ # Basic geometry properties
265
+
266
+ @property
267
+ def area(self):
268
+ a = c_double()
269
+ retval = lgeos.GEOSArea(self._geom, byref(a))
270
+ return a.value
271
+
272
+ @property
273
+ def length(self):
274
+ len = c_double()
275
+ retval = lgeos.GEOSLength(self._geom, byref(len))
276
+ return len.value
277
+
278
+ def distance(self, other):
279
+ d = c_double()
280
+ retval = lgeos.GEOSDistance(self._geom, other._geom, byref(d))
281
+ return d.value
282
+
283
+ # Topology operations
284
+ #
285
+ # These use descriptors to reduce the amount of boilerplate.
286
+
287
+ envelope = UnaryTopologicalOp(lgeos.GEOSEnvelope, geom_factory)
288
+ intersection = BinaryTopologicalOp(lgeos.GEOSIntersection, geom_factory)
289
+ convex_hull = UnaryTopologicalOp(lgeos.GEOSConvexHull, geom_factory)
290
+ difference = BinaryTopologicalOp(lgeos.GEOSDifference, geom_factory)
291
+ symmetric_difference = BinaryTopologicalOp(lgeos.GEOSSymDifference,
292
+ geom_factory)
293
+ boundary = UnaryTopologicalOp(lgeos.GEOSBoundary, geom_factory)
294
+ union = BinaryTopologicalOp(lgeos.GEOSUnion, geom_factory)
295
+ centroid = UnaryTopologicalOp(lgeos.GEOSGetCentroid, geom_factory)
296
+
297
+ # Buffer has a unique distance argument, so not a descriptor
298
+ def buffer(self, distance, quadsegs=16):
299
+ return geom_factory(
300
+ lgeos.GEOSBuffer(self._geom, c_double(distance), c_int(quadsegs))
301
+ )
302
+
303
+ # Relate has a unique string return value
304
+ def relate(self, other):
305
+ func = lgeos.GEOSRelate
306
+ func.restype = c_char_p
307
+ return lgeos.GEOSRelate(self._geom, other._geom)
308
+
309
+ # Binary predicates
310
+ #
311
+ # These use descriptors to reduce the amount of boilerplate.
312
+
313
+ # TODO: Relate Pattern?
314
+ disjoint = BinaryPredicate(lgeos.GEOSDisjoint)
315
+ touches = BinaryPredicate(lgeos.GEOSTouches)
316
+ intersects = BinaryPredicate(lgeos.GEOSIntersects)
317
+ crosses = BinaryPredicate(lgeos.GEOSCrosses)
318
+ within = BinaryPredicate(lgeos.GEOSWithin)
319
+ contains = BinaryPredicate(lgeos.GEOSContains)
320
+ overlaps = BinaryPredicate(lgeos.GEOSOverlaps)
321
+ equals = BinaryPredicate(lgeos.GEOSEquals)
322
+
323
+ # Unary predicates
324
+ #
325
+ # These use descriptors to reduce the amount of boilerplate.
326
+
327
+ is_empty = UnaryPredicate(lgeos.GEOSisEmpty)
328
+ is_valid = UnaryPredicate(lgeos.GEOSisValid)
329
+ is_simple = UnaryPredicate(lgeos.GEOSisSimple)
330
+ is_ring = UnaryPredicate(lgeos.GEOSisRing)
331
+ has_z = UnaryPredicate(lgeos.GEOSHasZ)
332
+
333
+ @property
334
+ def bounds(self):
335
+ env = self.envelope
336
+ if env.geom_type != 'Polygon':
337
+ raise ValueError, env.wkt
338
+ cs = lgeos.GEOSGeom_getCoordSeq(env.exterior._geom)
339
+ cs_len = c_int(0)
340
+ lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len))
341
+
342
+ minx = 1.e+20
343
+ maxx = -1e+20
344
+ miny = 1.e+20
345
+ maxy = -1e+20
346
+ temp = c_double()
347
+ for i in xrange(cs_len.value):
348
+ lgeos.GEOSCoordSeq_getX(cs, i, byref(temp))
349
+ x = temp.value
350
+ if x < minx: minx = x
351
+ if x > maxx: maxx = x
352
+ lgeos.GEOSCoordSeq_getY(cs, i, byref(temp))
353
+ y = temp.value
354
+ if y < miny: miny = y
355
+ if y > maxy: maxy = y
356
+
357
+ return (minx, miny, maxx, maxy)
358
+
Binary file
@@ -0,0 +1,24 @@
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
+
Binary file
@@ -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
+
Binary file
@@ -0,0 +1,228 @@
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
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
+
122
+ if coordinates is None:
123
+ # allow creation of null lines, to support unpickling
124
+ pass
125
+ else:
126
+ self._geom, self._ndim = geos_linestring_from_py(coordinates)
127
+
128
+ @property
129
+ def __geo_interface__(self):
130
+ return {
131
+ 'type': 'LineString',
132
+ 'coordinates': tuple(self.coords)
133
+ }
134
+
135
+ @property
136
+ def ctypes(self):
137
+ if not self._ctypes_data:
138
+ cs = lgeos.GEOSGeom_getCoordSeq(self._geom)
139
+ cs_len = c_int(0)
140
+ lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len))
141
+ temp = c_double()
142
+ n = self._ndim
143
+ m = cs_len.value
144
+ array_type = c_double * (m * n)
145
+ data = array_type()
146
+ for i in xrange(m):
147
+ lgeos.GEOSCoordSeq_getX(cs, i, byref(temp))
148
+ data[n*i] = temp.value
149
+ lgeos.GEOSCoordSeq_getY(cs, i, byref(temp))
150
+ data[n*i+1] = temp.value
151
+ if n == 3: # TODO: use hasz
152
+ lgeos.GEOSCoordSeq_getZ(cs, i, byref(temp))
153
+ data[n*i+2] = temp.value
154
+ self._ctypes_data = data
155
+ return self._ctypes_data
156
+
157
+ def array_interface(self):
158
+ """Provide the Numpy array protocol."""
159
+ ai = self.array_interface_base
160
+ ai.update({'shape': (len(self.coords), self._ndim)})
161
+ return ai
162
+ __array_interface__ = property(array_interface)
163
+
164
+ # Coordinate access
165
+
166
+ def set_coords(self, coordinates):
167
+ update_linestring_from_py(self, coordinates)
168
+
169
+ coords = property(BaseGeometry.get_coords, set_coords)
170
+
171
+
172
+ class LineStringAdapter(LineString):
173
+
174
+ """Adapts a Python coordinate pair or a numpy array to the line string
175
+ interface.
176
+ """
177
+
178
+ context = None
179
+
180
+ def __init__(self, context):
181
+ self.context = context
182
+
183
+ # Override base class __del__
184
+ def __del__(self):
185
+ pass
186
+
187
+ @property
188
+ def _ndim(self):
189
+ try:
190
+ # From array protocol
191
+ array = self.context.__array_interface__
192
+ n = array['shape'][1]
193
+ assert n == 2 or n == 3
194
+ return n
195
+ except AttributeError:
196
+ # Fall back on list
197
+ return len(self.context[0])
198
+
199
+ @property
200
+ def _geom(self):
201
+ """Keeps the GEOS geometry in synch with the context."""
202
+ return geos_linestring_from_py(self.context)[0]
203
+
204
+ @property
205
+ def __array_interface__(self):
206
+ """Provide the Numpy array protocol."""
207
+ try:
208
+ return self.context.__array_interface__
209
+ except AttributeError:
210
+ return self.array_interface()
211
+
212
+ coords = property(BaseGeometry.get_coords)
213
+
214
+
215
+ def asLineString(context):
216
+ """Factory for PointAdapter instances."""
217
+ return LineStringAdapter(context)
218
+
219
+
220
+ # Test runner
221
+ def _test():
222
+ import doctest
223
+ doctest.testmod()
224
+
225
+
226
+ if __name__ == "__main__":
227
+ _test()
228
+
Binary file