shapely 1.2.18__tar.gz → 1.2.19__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 (98) hide show
  1. {Shapely-1.2.18 → Shapely-1.2.19}/CHANGES.txt +4 -0
  2. {Shapely-1.2.18/Shapely.egg-info → Shapely-1.2.19}/PKG-INFO +5 -1
  3. {Shapely-1.2.18 → Shapely-1.2.19/Shapely.egg-info}/PKG-INFO +5 -1
  4. {Shapely-1.2.18 → Shapely-1.2.19}/Shapely.egg-info/SOURCES.txt +1 -0
  5. Shapely-1.2.19/VERSION.txt +1 -0
  6. {Shapely-1.2.18 → Shapely-1.2.19}/docs/manual.txt +41 -5
  7. Shapely-1.2.19/shapely/__init__.py +1 -0
  8. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/ctypes_declarations.py +8 -3
  9. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/__init__.py +3 -3
  10. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/base.py +44 -2
  11. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/linestring.py +20 -19
  12. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/polygon.py +5 -3
  13. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geos.py +8 -2
  14. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/impl.py +8 -5
  15. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/speedups/_speedups.c +134 -114
  16. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/__init__.py +2 -1
  17. Shapely-1.2.19/shapely/tests/test_styles.py +17 -0
  18. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_unary_union.py +13 -4
  19. Shapely-1.2.18/VERSION.txt +0 -1
  20. Shapely-1.2.18/shapely/__init__.py +0 -1
  21. {Shapely-1.2.18 → Shapely-1.2.19}/CREDITS.txt +0 -0
  22. {Shapely-1.2.18 → Shapely-1.2.19}/LICENSE.txt +0 -0
  23. {Shapely-1.2.18 → Shapely-1.2.19}/README.rst +0 -0
  24. {Shapely-1.2.18 → Shapely-1.2.19}/Shapely.egg-info/dependency_links.txt +0 -0
  25. {Shapely-1.2.18 → Shapely-1.2.19}/Shapely.egg-info/top_level.txt +0 -0
  26. {Shapely-1.2.18 → Shapely-1.2.19}/setup.cfg +0 -0
  27. {Shapely-1.2.18 → Shapely-1.2.19}/setup.py +0 -0
  28. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/affinity.py +0 -0
  29. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/algorithms/__init__.py +0 -0
  30. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/algorithms/cga.py +0 -0
  31. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/coords.py +0 -0
  32. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/examples/__init__.py +0 -0
  33. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/examples/dissolve.py +0 -0
  34. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/examples/geoms.py +0 -0
  35. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/examples/intersect.py +0 -0
  36. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/examples/world.py +0 -0
  37. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/ftools.py +0 -0
  38. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/collection.py +0 -0
  39. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/geo.py +0 -0
  40. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/multilinestring.py +0 -0
  41. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/multipoint.py +0 -0
  42. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/multipolygon.py +0 -0
  43. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/point.py +0 -0
  44. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/geometry/proxy.py +0 -0
  45. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/iterops.py +0 -0
  46. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/linref.py +0 -0
  47. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/ops.py +0 -0
  48. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/predicates.py +0 -0
  49. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/prepared.py +0 -0
  50. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/speedups/__init__.py +0 -0
  51. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Array.txt +0 -0
  52. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/GeoInterface.txt +0 -0
  53. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/IterOps.txt +0 -0
  54. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/LineString.txt +0 -0
  55. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/MultiLineString.txt +0 -0
  56. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/MultiPoint.txt +0 -0
  57. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/MultiPolygon.txt +0 -0
  58. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Operations.txt +0 -0
  59. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Operators.txt +0 -0
  60. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Persist.txt +0 -0
  61. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Point.txt +0 -0
  62. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Polygon.txt +0 -0
  63. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/Predicates.txt +0 -0
  64. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/attribute-chains.txt +0 -0
  65. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/binascii_hex.txt +0 -0
  66. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/cascaded_union.txt +0 -0
  67. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/dimensions.txt +0 -0
  68. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/invalid_intersection.txt +0 -0
  69. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/linemerge.txt +0 -0
  70. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/polygonize.txt +0 -0
  71. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_affinity.py +0 -0
  72. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_box.py +0 -0
  73. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_cga.py +0 -0
  74. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_collection.py +0 -0
  75. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_delegated.py +0 -0
  76. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_dlls.py +0 -0
  77. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_doctests.py +0 -0
  78. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_emptiness.py +0 -0
  79. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_equality.py +0 -0
  80. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_geomseq.py +0 -0
  81. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_getitem.py +0 -0
  82. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_linear_referencing.py +0 -0
  83. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_mapping.py +0 -0
  84. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_ndarrays.py +0 -0
  85. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_pickle.py +0 -0
  86. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_prepared.py +0 -0
  87. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_products_z.py +0 -0
  88. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_singularity.py +0 -0
  89. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_speedups.py +0 -0
  90. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_transform.py +0 -0
  91. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_validation.py +0 -0
  92. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/test_xy.py +0 -0
  93. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/threading_test.py +0 -0
  94. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/tests/wkt_locale.txt +0 -0
  95. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/topology.py +0 -0
  96. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/validation.py +0 -0
  97. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/wkb.py +0 -0
  98. {Shapely-1.2.18 → Shapely-1.2.19}/shapely/wkt.py +0 -0
@@ -1,6 +1,10 @@
1
1
  Changes
2
2
  =======
3
3
 
4
+ 1.2.19 (2013-12-30)
5
+ -------------------
6
+ - Add buffering style options (#55).
7
+
4
8
  1.2.18 (2013-07-23)
5
9
  --------------------
6
10
  - Add shapely.ops.transform.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: Shapely
3
- Version: 1.2.18
3
+ Version: 1.2.19
4
4
  Summary: Geometric objects, predicates, and operations
5
5
  Home-page: https://github.com/Toblerity/Shapely
6
6
  Author: Sean Gillies
@@ -190,6 +190,10 @@ Description: =======
190
190
  Changes
191
191
  =======
192
192
 
193
+ 1.2.19 (2013-12-30)
194
+ -------------------
195
+ - Add buffering style options (#55).
196
+
193
197
  1.2.18 (2013-07-23)
194
198
  --------------------
195
199
  - Add shapely.ops.transform.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 1.1
2
2
  Name: Shapely
3
- Version: 1.2.18
3
+ Version: 1.2.19
4
4
  Summary: Geometric objects, predicates, and operations
5
5
  Home-page: https://github.com/Toblerity/Shapely
6
6
  Author: Sean Gillies
@@ -190,6 +190,10 @@ Description: =======
190
190
  Changes
191
191
  =======
192
192
 
193
+ 1.2.19 (2013-12-30)
194
+ -------------------
195
+ - Add buffering style options (#55).
196
+
193
197
  1.2.18 (2013-07-23)
194
198
  --------------------
195
199
  - Add shapely.ops.transform.
@@ -86,6 +86,7 @@ shapely/tests/test_prepared.py
86
86
  shapely/tests/test_products_z.py
87
87
  shapely/tests/test_singularity.py
88
88
  shapely/tests/test_speedups.py
89
+ shapely/tests/test_styles.py
89
90
  shapely/tests/test_transform.py
90
91
  shapely/tests/test_unary_union.py
91
92
  shapely/tests/test_validation.py
@@ -0,0 +1 @@
1
+ 1.2.19
@@ -1389,11 +1389,47 @@ Constructive Methods
1389
1389
  Shapely geometric object have several methods that yield new objects not
1390
1390
  derived from set-theoretic analysis.
1391
1391
 
1392
- .. method:: object.buffer(distance, resolution=16)
1392
+ .. method:: object.buffer(distance, resolution=16, cap_style=1, join_style=1, mitre_limit=1.0)
1393
1393
 
1394
1394
  Returns an approximate representation of all points within a given `distance`
1395
1395
  of the this geometric object.
1396
1396
 
1397
+ The styles of caps are specified by integer values: 1 (round), 2 (flat),
1398
+ 3 (square). These values are also enumerated by the object
1399
+ :class:`shapely.geometry.CAP_STYLE` (see below).
1400
+
1401
+ The styles of joins between offset segments are specified by integer values:
1402
+ 1 (round), 2 (mitre), and 3 (bevel). These values are also enumerated by the
1403
+ object :class:`shapely.geometry.JOIN_STYLE` (see below).
1404
+
1405
+ .. data:: shapely.geometry.CAP_STYLE
1406
+
1407
+ ========= =====
1408
+ Attribute Value
1409
+ ========= =====
1410
+ round 1
1411
+ flat 2
1412
+ square 3
1413
+ ========= =====
1414
+
1415
+ .. data:: shapely.geometry.JOIN_STYLE
1416
+
1417
+ ========= =====
1418
+ Attribute Value
1419
+ ========= =====
1420
+ round 1
1421
+ mitre 2
1422
+ bevel 3
1423
+ ========= =====
1424
+
1425
+ .. sourcecode:: pycon
1426
+
1427
+ >>> from shapely.geometry import CAP_STYLE, JOIN_STYLE
1428
+ >>> CAP_STYLE.flat
1429
+ 2
1430
+ >>> JOIN_STYLE.bevel
1431
+ 3
1432
+
1397
1433
  A positive distance has an effect of dilation; a negative distance, erosion.
1398
1434
  The optional `resolution` argument determines the number of segments used to
1399
1435
  approximate a quarter circle around a point.
@@ -1494,8 +1530,9 @@ Figure 10. Convex hull (blue) of 2 points (left) and of 6 points (right).
1494
1530
  'right'. The resolution of the offset around each vertex of the object is
1495
1531
  parameterized as in the buffer method.
1496
1532
 
1497
- The styles of joins between offset segments are: 1 (round, the default),
1498
- 2 (mitre or miter), and 3 (bevel).
1533
+ The join style is for outside corners between line segments. Accepted integer
1534
+ values are 1 (round), 2 (mitre), and 3 (bevel). See also
1535
+ :data:`shapely.geometry.JOIN_STYLE`.
1499
1536
 
1500
1537
  Severely mitered corners can be controlled by the mitre_limit parameter
1501
1538
  (spelled in British English, en-gb). The ratio of the distance from the
@@ -1504,8 +1541,7 @@ Figure 10. Convex hull (blue) of 2 points (left) and of 6 points (right).
1504
1541
 
1505
1542
  .. note::
1506
1543
 
1507
- This method is only available for `LinearRing`, `LineString`, and
1508
- `MultiLineString` objects.
1544
+ This method is only available for `LinearRing` and `LineString` objects.
1509
1545
 
1510
1546
  .. plot:: code/parallel_offset.py
1511
1547
 
@@ -0,0 +1 @@
1
+ __version__ = "1.2.19"
@@ -100,6 +100,11 @@ def prototype(lgeos, geosVersion):
100
100
  lgeos.GEOSBuffer.restype = ctypes.c_void_p
101
101
  lgeos.GEOSBuffer.argtypes = [ctypes.c_void_p, ctypes.c_double, ctypes.c_int]
102
102
 
103
+ lgeos.GEOSBufferWithStyle.restype = ctypes.c_void_p
104
+ lgeos.GEOSBufferWithStyle.argtypes = [ctypes.c_void_p, ctypes.c_double,
105
+ ctypes.c_int, ctypes.c_int,
106
+ ctypes.c_int, ctypes.c_double]
107
+
103
108
  lgeos.GEOSSimplify.restype = ctypes.c_void_p
104
109
  lgeos.GEOSSimplify.argtypes = [ctypes.c_void_p, ctypes.c_double]
105
110
 
@@ -271,15 +276,15 @@ def prototype(lgeos, geosVersion):
271
276
  lgeos.GEOSProject.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
272
277
 
273
278
  lgeos.GEOSProjectNormalized.restype = ctypes.c_double
274
- lgeos.GEOSProjectNormalized.argtypes = [ctypes.c_void_p,
279
+ lgeos.GEOSProjectNormalized.argtypes = [ctypes.c_void_p,
275
280
  ctypes.c_void_p]
276
281
 
277
282
  lgeos.GEOSInterpolate.restype = ctypes.c_void_p
278
- lgeos.GEOSInterpolate.argtypes = [ctypes.c_void_p,
283
+ lgeos.GEOSInterpolate.argtypes = [ctypes.c_void_p,
279
284
  ctypes.c_double]
280
285
 
281
286
  lgeos.GEOSInterpolateNormalized.restype = ctypes.c_void_p
282
- lgeos.GEOSInterpolateNormalized.argtypes = [ctypes.c_void_p,
287
+ lgeos.GEOSInterpolateNormalized.argtypes = [ctypes.c_void_p,
283
288
  ctypes.c_double]
284
289
 
285
290
  # TODO: Find out what version of geos_c came with geos 3.3.0
@@ -1,6 +1,7 @@
1
1
  """Geometry classes and factories
2
2
  """
3
3
 
4
+ from base import CAP_STYLE, JOIN_STYLE
4
5
  from geo import box, shape, asShape, mapping
5
6
  from point import Point, asPoint
6
7
  from linestring import LineString, asLineString
@@ -14,7 +15,6 @@ __all__ = [
14
15
  'box', 'shape', 'asShape', 'Point', 'asPoint', 'LineString', 'asLineString',
15
16
  'Polygon', 'asPolygon', 'MultiPoint', 'asMultiPoint',
16
17
  'MultiLineString', 'asMultiLineString', 'MultiPolygon', 'asMultiPolygon',
17
- 'GeometryCollection', 'mapping', 'LinearRing', 'asLinearRing'
18
+ 'GeometryCollection', 'mapping', 'LinearRing', 'asLinearRing',
19
+ 'CAP_STYLE', 'JOIN_STYLE'
18
20
  ]
19
-
20
-
@@ -85,6 +85,16 @@ def exceptNull(func):
85
85
  return func(*args, **kwargs)
86
86
  return wrapper
87
87
 
88
+ class CAP_STYLE(object):
89
+ round = 1
90
+ flat = 2
91
+ square = 3
92
+
93
+ class JOIN_STYLE(object):
94
+ round = 1
95
+ mitre = 2
96
+ bevel = 3
97
+
88
98
  EMPTY = deserialize_wkb('010700000000000000'.decode('hex'))
89
99
 
90
100
  class BaseGeometry(object):
@@ -323,7 +333,9 @@ class BaseGeometry(object):
323
333
  """A figure that envelopes the geometry"""
324
334
  return geom_factory(self.impl['envelope'](self))
325
335
 
326
- def buffer(self, distance, resolution=16, quadsegs=None):
336
+ def buffer(self, distance, resolution=16, quadsegs=None,
337
+ cap_style=CAP_STYLE.round, join_style=JOIN_STYLE.round,
338
+ mitre_limit=0):
327
339
  """Returns a geometry with an envelope at a distance from the object's
328
340
  envelope
329
341
 
@@ -333,6 +345,20 @@ class BaseGeometry(object):
333
345
  or second positional parameter. Note: the use of a `quadsegs` parameter
334
346
  is deprecated and will be gone from the next major release.
335
347
 
348
+ The styles of caps are: CAP_STYLE.round (1), CAP_STYLE.flat (2), and
349
+ CAP_STYLE.square (3).
350
+
351
+ The styles of joins between offset segments are: JOIN_STYLE.round (1),
352
+ JOIN_STYLE.mitre (2), and JOIN_STYLE.bevel (3).
353
+
354
+ The mitre limit ratio is used for very sharp corners. The mitre ratio
355
+ is the ratio of the distance from the corner to the end of the mitred
356
+ offset corner. When two line segments meet at a sharp angle, a miter
357
+ join will extend the original geometry. To prevent unreasonable
358
+ geometry, the mitre limit allows controlling the maximum length of the
359
+ join corner. Corners with a ratio which exceed the limit will be
360
+ beveled.
361
+
336
362
  Example:
337
363
 
338
364
  >>> from shapely.wkt import loads
@@ -343,7 +369,12 @@ class BaseGeometry(object):
343
369
  3.1415138011443009
344
370
  >>> g.buffer(1.0, 3).area # triangle approximation
345
371
  3.0
372
+ >>> list(g.buffer(1.0, cap_style='square').exterior.coords)
373
+ [(1.0, 1.0), (1.0, -1.0), (-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0)]
374
+ >>> g.buffer(1.0, cap_style='square').area
375
+ 4.0
346
376
  """
377
+
347
378
  if quadsegs is not None:
348
379
  warnings.warn(
349
380
  "The `quadsegs` argument is deprecated. Use `resolution`.",
@@ -351,7 +382,18 @@ class BaseGeometry(object):
351
382
  res = quadsegs
352
383
  else:
353
384
  res = resolution
354
- return geom_factory(self.impl['buffer'](self, distance, res))
385
+
386
+ if cap_style == CAP_STYLE.round and join_style == JOIN_STYLE.round:
387
+ return geom_factory(self.impl['buffer'](self, distance, res))
388
+
389
+ if 'buffer_with_style' not in self.impl:
390
+ raise NotImplementedError("Styled buffering not available for "
391
+ "GEOS versions < 3.2.")
392
+
393
+ return geom_factory(self.impl['buffer_with_style'](self, distance, res,
394
+ cap_style,
395
+ join_style,
396
+ mitre_limit))
355
397
 
356
398
  @delegated
357
399
  def simplify(self, tolerance, preserve_topology=True):
@@ -6,7 +6,7 @@ from ctypes import ArgumentError
6
6
 
7
7
  from shapely.coords import required
8
8
  from shapely.geos import lgeos, TopologicalError
9
- from shapely.geometry.base import BaseGeometry, geom_factory
9
+ from shapely.geometry.base import BaseGeometry, geom_factory, JOIN_STYLE
10
10
  from shapely.geometry.proxy import CachingGeometryProxy
11
11
 
12
12
  __all__ = ['LineString', 'asLineString']
@@ -15,7 +15,7 @@ __all__ = ['LineString', 'asLineString']
15
15
  class LineString(BaseGeometry):
16
16
  """
17
17
  A one-dimensional figure comprising one or more line segments
18
-
18
+
19
19
  A LineString has non-zero length and zero area. It may approximate a curve
20
20
  and need not be straight. Unlike a LinearRing, a LineString is not closed.
21
21
  """
@@ -57,7 +57,7 @@ class LineString(BaseGeometry):
57
57
  def array_interface(self):
58
58
  """Provide the Numpy array protocol."""
59
59
  return self.coords.array_interface()
60
-
60
+
61
61
  __array_interface__ = property(array_interface)
62
62
 
63
63
  # Coordinate access
@@ -70,9 +70,9 @@ class LineString(BaseGeometry):
70
70
  @property
71
71
  def xy(self):
72
72
  """Separate arrays of X and Y coordinate values
73
-
73
+
74
74
  Example:
75
-
75
+
76
76
  >>> x, y = LineString(((0, 0), (1, 1))).xy
77
77
  >>> list(x)
78
78
  [0.0, 1.0]
@@ -80,22 +80,23 @@ class LineString(BaseGeometry):
80
80
  [0.0, 1.0]
81
81
  """
82
82
  return self.coords.xy
83
-
83
+
84
84
  def parallel_offset(
85
- self, distance, side,
86
- resolution=16, join_style=1, mitre_limit=1.0):
87
-
85
+ self, distance, side,
86
+ resolution=16, join_style=JOIN_STYLE.round, mitre_limit=1.0):
87
+
88
88
  """Returns a LineString or MultiLineString geometry at a distance from
89
89
  the object on its right or its left side.
90
-
90
+
91
91
  Distance must be a positive float value. The side parameter may be
92
92
  'left' or 'right'. The resolution of the buffer around each vertex of
93
93
  the object increases by increasing the resolution keyword parameter or
94
94
  third positional parameter.
95
-
95
+
96
96
  The join style is for outside corners between line segments. Accepted
97
- values are 1 => ROUND, 2 => MITRE, 3 => BEVEL.
98
-
97
+ values are JOIN_STYLE.round (1), JOIN_STYLE.mitre (2), and
98
+ JOIN_STYLE.bevel (3).
99
+
99
100
  The mitre ratio limit is used for very sharp corners. It is the ratio
100
101
  of the distance from the corner to the end of the mitred offset corner.
101
102
  When two line segments meet at a sharp angle, a miter join will extend
@@ -105,11 +106,11 @@ class LineString(BaseGeometry):
105
106
 
106
107
  try:
107
108
  return geom_factory(self.impl['parallel_offset'](
108
- self, distance, resolution, join_style, mitre_limit,
109
+ self, distance, resolution, join_style, mitre_limit,
109
110
  bool(side=='left')))
110
111
  except WindowsError:
111
112
  raise TopologicalError()
112
-
113
+
113
114
 
114
115
  class LineStringAdapter(CachingGeometryProxy, LineString):
115
116
 
@@ -198,7 +199,7 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
198
199
  except IndexError:
199
200
  raise ValueError("Inconsistent coordinate dimensionality")
200
201
 
201
- # Because of a bug in the GEOS C API,
202
+ # Because of a bug in the GEOS C API,
202
203
  # always set X before Y
203
204
  lgeos.GEOSCoordSeq_setX(cs, i, dx)
204
205
  lgeos.GEOSCoordSeq_setY(cs, i, dy)
@@ -227,11 +228,11 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
227
228
  % update_ndim)
228
229
  else:
229
230
  cs = lgeos.GEOSCoordSeq_create(m, n)
230
-
231
+
231
232
  # add to coordinate sequence
232
233
  for i in xrange(m):
233
234
  coords = ob[i]
234
- # Because of a bug in the GEOS C API,
235
+ # Because of a bug in the GEOS C API,
235
236
  # always set X before Y
236
237
  lgeos.GEOSCoordSeq_setX(cs, i, coords[0])
237
238
  lgeos.GEOSCoordSeq_setY(cs, i, coords[1])
@@ -240,7 +241,7 @@ def geos_linestring_from_py(ob, update_geom=None, update_ndim=0):
240
241
  lgeos.GEOSCoordSeq_setZ(cs, i, coords[2])
241
242
  except IndexError:
242
243
  raise ValueError("Inconsistent coordinate dimensionality")
243
-
244
+
244
245
  if update_geom is not None:
245
246
  return None
246
247
  else:
@@ -430,7 +430,7 @@ def update_linearring_from_py(geom, ob):
430
430
  def geos_polygon_from_py(shell, holes=None):
431
431
  if shell is not None:
432
432
  geos_shell, ndim = geos_linearring_from_py(shell)
433
- if holes:
433
+ if holes is not None and len(holes) > 0:
434
434
  ob = holes
435
435
  L = len(ob)
436
436
  exemplar = ob[0]
@@ -438,8 +438,10 @@ def geos_polygon_from_py(shell, holes=None):
438
438
  N = len(exemplar[0])
439
439
  except TypeError:
440
440
  N = exemplar._ndim
441
- assert L >= 1
442
- assert N == 2 or N == 3
441
+ if not L >= 1:
442
+ raise ValueError("number of holes must be non zero")
443
+ if not N in (2, 3):
444
+ raise ValueError("insufficiant coordinate dimension")
443
445
 
444
446
  # Array of pointers to ring geometries
445
447
  geos_holes = (c_void_p * L)()
@@ -50,12 +50,16 @@ if sys.platform.startswith('linux'):
50
50
  free.restype = None
51
51
 
52
52
  elif sys.platform == 'darwin':
53
- alt_paths = [
53
+ if hasattr(sys, 'frozen'):
54
+ # .app file from py2app
55
+ alt_paths = [os.path.join(os.environ['RESOURCEPATH'], '..', 'Frameworks', 'libgeos_c.dylib')]
56
+ else:
57
+ alt_paths = [
54
58
  # The Framework build from Kyng Chaos:
55
59
  "/Library/Frameworks/GEOS.framework/Versions/Current/GEOS",
56
60
  # macports
57
61
  '/opt/local/lib/libgeos_c.dylib',
58
- ]
62
+ ]
59
63
  _lgeos = load_dll('geos_c', fallbacks=alt_paths)
60
64
  free = load_dll('c').free
61
65
  free.argtypes = [c_void_p]
@@ -350,6 +354,8 @@ class LGEOS16(LGEOS15):
350
354
  def __init__(self, dll):
351
355
  super(LGEOS16, self).__init__(dll)
352
356
 
357
+ self.methods['buffer_with_style'] = self.GEOSBufferWithStyle
358
+
353
359
 
354
360
  class LGEOS16LR(LGEOS16):
355
361
  """Proxy for the reentrant GEOS_C DLL/SO API version 1.6 with linear
@@ -4,7 +4,7 @@ This is layer number 2 from the list below.
4
4
 
5
5
  1) geometric objects: the Python OO API.
6
6
  2) implementation map: an abstraction that permits different backends.
7
- 3) backend: callable objects that take Shapely geometric objects as arguments
7
+ 3) backend: callable objects that take Shapely geometric objects as arguments
8
8
  and, with GEOS as a backend, translate them to C data structures.
9
9
  4) GEOS library: algorithms implemented in C++.
10
10
 
@@ -22,7 +22,7 @@ from shapely.topology import BinaryRealProperty, BinaryTopologicalOp
22
22
  from shapely.topology import UnaryRealProperty, UnaryTopologicalOp
23
23
 
24
24
  def delegated(func):
25
- """A delegated method raises AttributeError in the absence of backend
25
+ """A delegated method raises AttributeError in the absence of backend
26
26
  support."""
27
27
  @wraps(func)
28
28
  def wrapper(*args, **kwargs):
@@ -42,6 +42,8 @@ class BaseImpl(object):
42
42
  self.map.update(values)
43
43
  def __getitem__(self, key):
44
44
  return self.map[key]
45
+ def __contains__(self, key):
46
+ return key in self.map
45
47
 
46
48
  class GEOSImpl(BaseImpl):
47
49
  def __repr__(self):
@@ -82,23 +84,24 @@ IMPL14 = {
82
84
  'touches': (BinaryPredicate, 'touches'),
83
85
  'within': (BinaryPredicate, 'within'),
84
86
  'equals_exact': (BinaryPredicate, 'equals_exact'),
85
-
87
+
86
88
  # First pure Python implementation
87
89
  'is_ccw': (cga.is_ccw_impl, 'is_ccw'),
88
90
  }
89
91
 
90
92
  IMPL15 = {
91
93
  'simplify': (UnaryTopologicalOp, 'simplify'),
92
- 'topology_preserve_simplify':
94
+ 'topology_preserve_simplify':
93
95
  (UnaryTopologicalOp, 'topology_preserve_simplify'),
94
96
  'prepared_intersects': (BinaryPredicate, 'prepared_intersects'),
95
97
  'prepared_contains': (BinaryPredicate, 'prepared_contains'),
96
- 'prepared_contains_properly':
98
+ 'prepared_contains_properly':
97
99
  (BinaryPredicate, 'prepared_contains_properly'),
98
100
  'prepared_covers': (BinaryPredicate, 'prepared_covers'),
99
101
  }
100
102
 
101
103
  IMPL16 = {
104
+ 'buffer_with_style': (UnaryTopologicalOp, 'buffer_with_style'),
102
105
  }
103
106
 
104
107
  IMPL16LR = {