| 1 |
================== |
|---|
| 2 |
The Shapely Manual |
|---|
| 3 |
================== |
|---|
| 4 |
|
|---|
| 5 |
:Author: Sean Gillies |
|---|
| 6 |
:address: sgillies@frii.com |
|---|
| 7 |
:revision: 1.0.5 |
|---|
| 8 |
:date: 20 May 2008 |
|---|
| 9 |
:copyright: This work is licensed under a `Creative Commons Attribution 3.0 |
|---|
| 10 |
United States License`__. |
|---|
| 11 |
|
|---|
| 12 |
.. __: http://creativecommons.org/licenses/by/3.0/us/ |
|---|
| 13 |
|
|---|
| 14 |
:abstract: This document describes the Shapely Python package for programming |
|---|
| 15 |
with geospatial geometries. |
|---|
| 16 |
|
|---|
| 17 |
.. sectnum:: |
|---|
| 18 |
|
|---|
| 19 |
.. contents:: |
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 |
Background |
|---|
| 23 |
========== |
|---|
| 24 |
|
|---|
| 25 |
Shapely is a Python package for programming with geospatial geometries. It is |
|---|
| 26 |
based on the GEOS_ library, a port of the `Java Topology Suite`_. Please refer |
|---|
| 27 |
to the JTS overview for definitions and illustrations of the various geometry |
|---|
| 28 |
types, operations, and predicates. See also the Shapely wiki_ and Python |
|---|
| 29 |
Package Index record_. |
|---|
| 30 |
|
|---|
| 31 |
.. _GEOS: http://geos.refractions.net |
|---|
| 32 |
.. _Java Topology Suite: http://www.jump-project.org/project.php?PID=JTS&SID=OVER |
|---|
| 33 |
.. _record: http://pypi.python.org/pypi/Shapely |
|---|
| 34 |
.. _wiki: http://trac.gispython.org/projects/PCL/wiki/Shapely |
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 |
Geometries |
|---|
| 38 |
========== |
|---|
| 39 |
|
|---|
| 40 |
The basic, standard GIS geometry model consists of single points, line strings, |
|---|
| 41 |
and polygons, homogeneous multi-point, multi-line string, and multi-polygon |
|---|
| 42 |
collections, and heterogeneous geometry collections. See the JTS illustration_. |
|---|
| 43 |
|
|---|
| 44 |
.. _illustration: http://www.jump-project.org/project.php?PID=JTS&SID=OVER#spatialdatatypes |
|---|
| 45 |
|
|---|
| 46 |
Shapely 1.0 does not provide circles, arcs, splines or the like. |
|---|
| 47 |
|
|---|
| 48 |
|
|---|
| 49 |
Factories |
|---|
| 50 |
--------- |
|---|
| 51 |
|
|---|
| 52 |
Geometries can be created in the typical Python fashion, using the geometry |
|---|
| 53 |
classes themselves as factories. |
|---|
| 54 |
|
|---|
| 55 |
Pseudo-code blocks in this section will use the following notation. Let **a** |
|---|
| 56 |
be a Cartesian *x*, *y*, and optional *z* coordinate sequence. The coordinates |
|---|
| 57 |
values must be numeric types. Let (**a**\ 1, ..., **a**\ M) and (**b**\ 1, ..., |
|---|
| 58 |
**b**\ N) be ordered sequences of *M* and *N* such coordinate sequences, |
|---|
| 59 |
defining lines or rings. |
|---|
| 60 |
|
|---|
| 61 |
Points |
|---|
| 62 |
++++++ |
|---|
| 63 |
|
|---|
| 64 |
The point factory *Point* takes a coordinate sequence parameter |
|---|
| 65 |
|
|---|
| 66 |
.. code-block:: python |
|---|
| 67 |
|
|---|
| 68 |
>>> from shapely.geometry import Point |
|---|
| 69 |
>>> point = Point(a) |
|---|
| 70 |
|
|---|
| 71 |
The alternate form is to pass individual coordinate parameters |
|---|
| 72 |
|
|---|
| 73 |
.. code-block:: python |
|---|
| 74 |
|
|---|
| 75 |
>>> point = Point(x0, y0 [, z0]) |
|---|
| 76 |
|
|---|
| 77 |
LineStrings |
|---|
| 78 |
+++++++++++ |
|---|
| 79 |
|
|---|
| 80 |
To create a line string, pass in an ordered sequence of coordinate sequences: |
|---|
| 81 |
|
|---|
| 82 |
.. code-block:: python |
|---|
| 83 |
|
|---|
| 84 |
>>> from shapely.geometry import LineString |
|---|
| 85 |
>>> line = LineString((a1, ..., aM)) |
|---|
| 86 |
|
|---|
| 87 |
Polygons |
|---|
| 88 |
++++++++ |
|---|
| 89 |
|
|---|
| 90 |
A polygon with only an exterior boundary and no holes is created by passing the sequence representation of a closed ring |
|---|
| 91 |
|
|---|
| 92 |
.. code-block:: python |
|---|
| 93 |
|
|---|
| 94 |
>>> from shapely.geometry import Polygon |
|---|
| 95 |
>>> polygon = Polygon((a1, ..., aM)) |
|---|
| 96 |
|
|---|
| 97 |
If **a**\ 1 is not exactly equal to **a**\ M, the factory will close the ring. |
|---|
| 98 |
The following (unit square) polygons are therefore topologically equal |
|---|
| 99 |
|
|---|
| 100 |
.. code-block:: python |
|---|
| 101 |
|
|---|
| 102 |
>>> polygon1 = Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))) |
|---|
| 103 |
>>> polygon2 = Polygon(((0, 0), (0, 1), (1, 1), (1, 0))) |
|---|
| 104 |
|
|---|
| 105 |
To create a polygon with interior boundaries pass a sequence of rings to the |
|---|
| 106 |
second parameter (*holes*) |
|---|
| 107 |
|
|---|
| 108 |
.. code-block:: python |
|---|
| 109 |
|
|---|
| 110 |
>>> polygon = Polygon((a1, ..., aM), [(b1, ..., bN), ...]) |
|---|
| 111 |
|
|---|
| 112 |
Rings *must* be non-crossing, ordered coordinate sequences. The order may be |
|---|
| 113 |
clockwise or counter-clockwise. The resulting topology is independent of the |
|---|
| 114 |
order. |
|---|
| 115 |
|
|---|
| 116 |
|
|---|
| 117 |
Multipart Geometry Factories |
|---|
| 118 |
---------------------------- |
|---|
| 119 |
|
|---|
| 120 |
MultiPoints |
|---|
| 121 |
+++++++++++ |
|---|
| 122 |
|
|---|
| 123 |
An *N*\ -point geometry is created by passing an unordered sequence of |
|---|
| 124 |
coordinate sequences [**c**\ 1, ..., **c**\ N] |
|---|
| 125 |
|
|---|
| 126 |
.. code-block:: python |
|---|
| 127 |
|
|---|
| 128 |
>>> from shapely.geometry import MultiPoint |
|---|
| 129 |
>>> points = MultiPoint([c1, ..., cN]) |
|---|
| 130 |
|
|---|
| 131 |
MultiLineStrings |
|---|
| 132 |
++++++++++++++++ |
|---|
| 133 |
|
|---|
| 134 |
A multi-line geometry is created by passing a sequence of representations of |
|---|
| 135 |
lines |
|---|
| 136 |
|
|---|
| 137 |
.. code-block:: python |
|---|
| 138 |
|
|---|
| 139 |
>>> from shapely.geometry import MultiLineString |
|---|
| 140 |
>>> lines = MultiLineString([(a1, ..., aM), (b1, ..., bN), ...]) |
|---|
| 141 |
|
|---|
| 142 |
MultiPolygons |
|---|
| 143 |
+++++++++++++ |
|---|
| 144 |
|
|---|
| 145 |
A multi-polygon geometry is created by passing a sequence of exterior ring and |
|---|
| 146 |
hole list tuples |
|---|
| 147 |
|
|---|
| 148 |
.. code-block:: python |
|---|
| 149 |
|
|---|
| 150 |
>>> from shapely.geometry import MultiPolygon |
|---|
| 151 |
>>> lines = MultiPolygon([((a1, ..., aM), [(b1, ..., bN), ...]), ...]) |
|---|
| 152 |
|
|---|
| 153 |
More explicit notation for the exterior and interior boundaries (or shells and |
|---|
| 154 |
holes) makes usage more clear |
|---|
| 155 |
|
|---|
| 156 |
.. code-block:: python |
|---|
| 157 |
|
|---|
| 158 |
>>> shell = (a1, ..., aM) |
|---|
| 159 |
>>> holes = [(b1, ..., bN), ...] |
|---|
| 160 |
>>> lines = MultiPolygon([(shell, holes), ...]) |
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 |
Null Geometries |
|---|
| 164 |
--------------- |
|---|
| 165 |
|
|---|
| 166 |
Null geometries can be created by calling the factories with no arguments, but |
|---|
| 167 |
almost nothing can be done with a null geometry. |
|---|
| 168 |
|
|---|
| 169 |
.. code-block:: python |
|---|
| 170 |
|
|---|
| 171 |
>>> line_null = LineString() |
|---|
| 172 |
>>> line_null.length |
|---|
| 173 |
Traceback (most recent call last): |
|---|
| 174 |
... |
|---|
| 175 |
ValueError: Null geometry supports no operations |
|---|
| 176 |
|
|---|
| 177 |
The coordinates of a null geometry *can* be set (see Section 3), after which |
|---|
| 178 |
the geometry is no longer null. |
|---|
| 179 |
|
|---|
| 180 |
.. code-block:: python |
|---|
| 181 |
|
|---|
| 182 |
>>> l_null.coords = [(0, 0), (1, 1)] |
|---|
| 183 |
>>> print l_null.length |
|---|
| 184 |
1.414... |
|---|
| 185 |
|
|---|
| 186 |
|
|---|
| 187 |
Constructive Spatial Analysis Methods |
|---|
| 188 |
------------------------------------- |
|---|
| 189 |
|
|---|
| 190 |
There are methods of geometry classes that also serve as factories for new |
|---|
| 191 |
geometries. It is important to note that these are topological and not |
|---|
| 192 |
point-wise operations, and therefore may produce results that are not what one |
|---|
| 193 |
might expect from operations on Python sets. |
|---|
| 194 |
|
|---|
| 195 |
See also the JTS |illustration2|_. |
|---|
| 196 |
|
|---|
| 197 |
.. |illustration2| replace:: illustration |
|---|
| 198 |
.. _illustration2: http://www.jump-project.org/project.php?PID=JTS&SID=OVER#spatialanalysismethods |
|---|
| 199 |
|
|---|
| 200 |
Example Geometries |
|---|
| 201 |
++++++++++++++++++ |
|---|
| 202 |
|
|---|
| 203 |
.. code-block:: python |
|---|
| 204 |
|
|---|
| 205 |
>>> polygon = Polygon(((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0))) |
|---|
| 206 |
>>> point_r = Point(-1.5, 1.2) |
|---|
| 207 |
>>> point_g = Point(-1.0, 1.0) |
|---|
| 208 |
>>> point_b = Point(-0.5, 0.5) |
|---|
| 209 |
>>> line_r = LineString(((-0.5, 0.5), (0.5, 0.5))) |
|---|
| 210 |
>>> line_g = LineString(((1.0, -1.0), (1.8, 0.5))) |
|---|
| 211 |
>>> line_b = LineString(((-1.8, -1.2), (1.8, 0.5))) |
|---|
| 212 |
|
|---|
| 213 |
Buffer |
|---|
| 214 |
++++++ |
|---|
| 215 |
|
|---|
| 216 |
.buffer(width, quadsegs=16) : geometry |
|---|
| 217 |
Returns a buffer region having the given width and with a specified number of |
|---|
| 218 |
segments used to approximate curves. |
|---|
| 219 |
|
|---|
| 220 |
The default result of buffering a point is an N-gon approximation of a circle: |
|---|
| 221 |
|
|---|
| 222 |
.. code-block:: python |
|---|
| 223 |
|
|---|
| 224 |
>>> buffered = point_r.buffer(1.0) |
|---|
| 225 |
>>> buffered |
|---|
| 226 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 227 |
>>> buffered.length |
|---|
| 228 |
6.2806623139097271 |
|---|
| 229 |
>>> buffered.area |
|---|
| 230 |
3.1365484905463727 |
|---|
| 231 |
>>> len(buffered.exterior.coords) |
|---|
| 232 |
66 |
|---|
| 233 |
|
|---|
| 234 |
Boundary |
|---|
| 235 |
++++++++ |
|---|
| 236 |
|
|---|
| 237 |
.boundary : geometry |
|---|
| 238 |
Returns a lower dimension geometry. The boundary of a polygon is a line, the |
|---|
| 239 |
boundary of a line is a collection of points. The boundary of a point is an |
|---|
| 240 |
empty (null) collection. |
|---|
| 241 |
|
|---|
| 242 |
.. code-block:: python |
|---|
| 243 |
|
|---|
| 244 |
>>> polygon.boundary |
|---|
| 245 |
<shapely.geometry.linestring.LineString object at ...> |
|---|
| 246 |
>>> line_b.boundary |
|---|
| 247 |
<shapely.geometry.multipoint.MultiPoint object at ...> |
|---|
| 248 |
>>> point_r.boundary.is_empty |
|---|
| 249 |
True |
|---|
| 250 |
|
|---|
| 251 |
Centroid |
|---|
| 252 |
++++++++ |
|---|
| 253 |
|
|---|
| 254 |
.centroid : geometry |
|---|
| 255 |
Returns the centroid, or geometric center of the polygon. |
|---|
| 256 |
|
|---|
| 257 |
.. code-block:: python |
|---|
| 258 |
|
|---|
| 259 |
>>> centroid_point = polygon.centroid |
|---|
| 260 |
>>> centroid_point.wkt |
|---|
| 261 |
'POINT (-0.0000000000000000 -0.0000000000000000)' |
|---|
| 262 |
|
|---|
| 263 |
Convex Hull |
|---|
| 264 |
+++++++++++ |
|---|
| 265 |
|
|---|
| 266 |
.convex_hull : geometry |
|---|
| 267 |
Imagine an elastic band stretched around the geometry: that's a convex hull, |
|---|
| 268 |
more or less. |
|---|
| 269 |
|
|---|
| 270 |
For example, collect the three points into a multi-point geometry, and get the |
|---|
| 271 |
triangular polygon that is their convex hull: |
|---|
| 272 |
|
|---|
| 273 |
.. code-block:: python |
|---|
| 274 |
|
|---|
| 275 |
>>> multi_point = point_r.union(point_g) |
|---|
| 276 |
>>> multi_point = multi_point.union(point_b) |
|---|
| 277 |
>>> multi_point.convex_hull |
|---|
| 278 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 279 |
|
|---|
| 280 |
Difference |
|---|
| 281 |
++++++++++ |
|---|
| 282 |
|
|---|
| 283 |
.difference(other) : geometry |
|---|
| 284 |
Returns a geometry representing the points making up this geometry that do |
|---|
| 285 |
not make up *other*. Note that A.difference(B) is not necessarily equal to |
|---|
| 286 |
B.difference(A). |
|---|
| 287 |
|
|---|
| 288 |
.. code-block:: python |
|---|
| 289 |
|
|---|
| 290 |
>>> hull = multi_point.convex_hull |
|---|
| 291 |
>>> polygon.difference(hull) |
|---|
| 292 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 293 |
|
|---|
| 294 |
Envelope |
|---|
| 295 |
++++++++ |
|---|
| 296 |
|
|---|
| 297 |
.envelope : geometry |
|---|
| 298 |
Returns the geometry's rectangular polygon envelope. |
|---|
| 299 |
|
|---|
| 300 |
.. code-block:: python |
|---|
| 301 |
|
|---|
| 302 |
>>> polygon.envelope |
|---|
| 303 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 304 |
|
|---|
| 305 |
Intersection |
|---|
| 306 |
++++++++++++ |
|---|
| 307 |
|
|---|
| 308 |
.intersection(other) : geometry |
|---|
| 309 |
Returns the intersection of one geometry and the *other* geometry. |
|---|
| 310 |
|
|---|
| 311 |
.. code-block:: python |
|---|
| 312 |
|
|---|
| 313 |
>>> polygon.intersection(hull) |
|---|
| 314 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 315 |
|
|---|
| 316 |
Symmetric Difference |
|---|
| 317 |
++++++++++++++++++++ |
|---|
| 318 |
|
|---|
| 319 |
.symmetric_difference(other) : geometry |
|---|
| 320 |
Returns a geometry combining the points in this geometry not in *other*, and |
|---|
| 321 |
the points in *other* not in this geometry. |
|---|
| 322 |
|
|---|
| 323 |
.. code-block:: python |
|---|
| 324 |
|
|---|
| 325 |
>>> polygon.symmetric_difference(hull) |
|---|
| 326 |
<shapely.geometry.multipolygon.MultiPolygon object at ...> |
|---|
| 327 |
|
|---|
| 328 |
Union |
|---|
| 329 |
+++++ |
|---|
| 330 |
|
|---|
| 331 |
.union(other) : geometry |
|---|
| 332 |
Returns the union of one geometry and the *other* geometry. |
|---|
| 333 |
|
|---|
| 334 |
Point unions were demonstrated above under convex hull. The union of polygons |
|---|
| 335 |
will be a polygon or a multi-polygon depending on whether they intersect or |
|---|
| 336 |
not: |
|---|
| 337 |
|
|---|
| 338 |
.. code-block:: python |
|---|
| 339 |
|
|---|
| 340 |
>>> hull.union(polygon) |
|---|
| 341 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 |
Other Operations |
|---|
| 345 |
---------------- |
|---|
| 346 |
|
|---|
| 347 |
Polygonization |
|---|
| 348 |
++++++++++++++ |
|---|
| 349 |
|
|---|
| 350 |
shapely.ops.polygonize(lines) : iterator |
|---|
| 351 |
Returns an iterator over polygons constructed from the *lines* iterator. The |
|---|
| 352 |
elements of *lines* may be Shapely geometries, objects that provide the geo |
|---|
| 353 |
interface, or Numpy arrays or Python sequences shaped like LineStrings. |
|---|
| 354 |
|
|---|
| 355 |
.. code-block:: python |
|---|
| 356 |
|
|---|
| 357 |
>>> from shapely.ops import polygonize |
|---|
| 358 |
>>> lines = [ |
|---|
| 359 |
... ((0, 0), (1, 1)), |
|---|
| 360 |
... ((0, 0), (0, 1)), |
|---|
| 361 |
... ((0, 1), (1, 1)), |
|---|
| 362 |
... ((1, 1), (1, 0)), |
|---|
| 363 |
... ((1, 0), (0, 0)) |
|---|
| 364 |
... ] |
|---|
| 365 |
>>> result = polygonize(lines) |
|---|
| 366 |
>>> list(result.geoms) |
|---|
| 367 |
[<shapely.geometry.polygon.Polygon object at ...>, <shapely.geometry.polygon.Polygon object at ...>] |
|---|
| 368 |
|
|---|
| 369 |
|
|---|
| 370 |
Unary Spatial Predicates |
|---|
| 371 |
------------------------ |
|---|
| 372 |
|
|---|
| 373 |
These are implemented as Python attributes. |
|---|
| 374 |
|
|---|
| 375 |
Is Empty |
|---|
| 376 |
++++++++ |
|---|
| 377 |
|
|---|
| 378 |
.is_empty : bool |
|---|
| 379 |
True if the set of points in this geometry is empty, else False. For more |
|---|
| 380 |
details, see |
|---|
| 381 |
http://geos.refractions.net/ro/doxygen_docs/html/classgeos_1_1geom_1_1Geometry.html#a17. |
|---|
| 382 |
|
|---|
| 383 |
Is Valid |
|---|
| 384 |
++++++++ |
|---|
| 385 |
|
|---|
| 386 |
.is_valid : bool |
|---|
| 387 |
True if the geometry is valid (definition depends on sub-class), else False. |
|---|
| 388 |
For more details, see |
|---|
| 389 |
http://geos.refractions.net/ro/doxygen_docs/html/classgeos_1_1geom_1_1Geometry.html#a16. |
|---|
| 390 |
|
|---|
| 391 |
Is Ring |
|---|
| 392 |
+++++++ |
|---|
| 393 |
|
|---|
| 394 |
.is_ring : bool |
|---|
| 395 |
True if the geometry is a closed ring, else False. |
|---|
| 396 |
|
|---|
| 397 |
Has Z |
|---|
| 398 |
+++++ |
|---|
| 399 |
|
|---|
| 400 |
.has_z : bool |
|---|
| 401 |
True if the geometry's coordinate sequence(s) have z values (are |
|---|
| 402 |
3-dimensional) |
|---|
| 403 |
|
|---|
| 404 |
Examples |
|---|
| 405 |
++++++++ |
|---|
| 406 |
|
|---|
| 407 |
.. code-block:: python |
|---|
| 408 |
|
|---|
| 409 |
>>> polygon.is_empty |
|---|
| 410 |
False |
|---|
| 411 |
>>> polygon.is_valid |
|---|
| 412 |
True |
|---|
| 413 |
>>> polygon.is_ring |
|---|
| 414 |
False |
|---|
| 415 |
>>> polygon.boundary.is_ring |
|---|
| 416 |
True |
|---|
| 417 |
>>> polygon.has_z |
|---|
| 418 |
False |
|---|
| 419 |
|
|---|
| 420 |
(Note: that last return value exposes a bug in GEOS 2.2.3.) |
|---|
| 421 |
|
|---|
| 422 |
|
|---|
| 423 |
Binary Spatial Predicates |
|---|
| 424 |
------------------------- |
|---|
| 425 |
|
|---|
| 426 |
All of these methods take a single positional argument, an *other* geometry. It |
|---|
| 427 |
is important to note that these are topological and not point-wise operations, |
|---|
| 428 |
and therefore may produce results that are not what one might expect from |
|---|
| 429 |
operations on Python. |
|---|
| 430 |
|
|---|
| 431 |
Contains |
|---|
| 432 |
++++++++ |
|---|
| 433 |
|
|---|
| 434 |
.contains(other) : bool |
|---|
| 435 |
True if the geometry is spatially within, without touching. Applies to all |
|---|
| 436 |
types of geometries. |
|---|
| 437 |
|
|---|
| 438 |
.. code-block:: python |
|---|
| 439 |
|
|---|
| 440 |
>>> polygon.contains(point_b) |
|---|
| 441 |
True |
|---|
| 442 |
|
|---|
| 443 |
Crosses |
|---|
| 444 |
+++++++ |
|---|
| 445 |
|
|---|
| 446 |
.crosses(other) : bool |
|---|
| 447 |
Only linear geometries (lines, rings, polygon boundaries) may ever cross. No |
|---|
| 448 |
geometry may ever cross a point. |
|---|
| 449 |
|
|---|
| 450 |
.. code-block:: python |
|---|
| 451 |
|
|---|
| 452 |
>>> line_b.crosses(polygon) |
|---|
| 453 |
True |
|---|
| 454 |
|
|---|
| 455 |
Disjoint |
|---|
| 456 |
++++++++ |
|---|
| 457 |
|
|---|
| 458 |
.disjoint(other) : bool |
|---|
| 459 |
True if geometries do not spatially relate in any way, else False. See the |
|---|
| 460 |
complementary *intersects*. |
|---|
| 461 |
|
|---|
| 462 |
.. code-block:: python |
|---|
| 463 |
|
|---|
| 464 |
>>> polygon.disjoint(point_r) |
|---|
| 465 |
True |
|---|
| 466 |
|
|---|
| 467 |
Equals |
|---|
| 468 |
++++++ |
|---|
| 469 |
|
|---|
| 470 |
.equals(other) : bool |
|---|
| 471 |
Two geometries are topologically equal if their interiors intersect and no |
|---|
| 472 |
part of the interior or boundary of one geometry intersects the exterior of |
|---|
| 473 |
the other. Not to be confused with Python's *__equals__*. |
|---|
| 474 |
|
|---|
| 475 |
Intersects |
|---|
| 476 |
++++++++++ |
|---|
| 477 |
|
|---|
| 478 |
.intersects(other) : bool |
|---|
| 479 |
This predicate is the complement of *disjoint*: geometries that do not |
|---|
| 480 |
intersect are disjoint. Intersects is the most inclusive predicate. |
|---|
| 481 |
|
|---|
| 482 |
.. code-block:: python |
|---|
| 483 |
|
|---|
| 484 |
>>> polygon.intersects(point_b) |
|---|
| 485 |
True |
|---|
| 486 |
|
|---|
| 487 |
Touches |
|---|
| 488 |
+++++++ |
|---|
| 489 |
|
|---|
| 490 |
.touches(other) : bool |
|---|
| 491 |
True if geometries *only* touch. The least inclusive predicate. |
|---|
| 492 |
|
|---|
| 493 |
.. code-block:: python |
|---|
| 494 |
|
|---|
| 495 |
>>> polygon.touches(line_g) |
|---|
| 496 |
True |
|---|
| 497 |
>>> polygon.touches(line_b) |
|---|
| 498 |
False |
|---|
| 499 |
|
|---|
| 500 |
Within |
|---|
| 501 |
++++++ |
|---|
| 502 |
|
|---|
| 503 |
.within(other): bool |
|---|
| 504 |
The inverse of *contains*. |
|---|
| 505 |
|
|---|
| 506 |
|
|---|
| 507 |
General Methods |
|---|
| 508 |
--------------- |
|---|
| 509 |
|
|---|
| 510 |
Distance |
|---|
| 511 |
++++++++ |
|---|
| 512 |
|
|---|
| 513 |
.distance(other) : geometry |
|---|
| 514 |
The minimum distance from one geometry to the other. |
|---|
| 515 |
|
|---|
| 516 |
.. code-block:: python |
|---|
| 517 |
|
|---|
| 518 |
>>> Point(0,0).distance(Point(1,1)) |
|---|
| 519 |
1.4142135623730951 |
|---|
| 520 |
|
|---|
| 521 |
|
|---|
| 522 |
Scalar Properties |
|---|
| 523 |
----------------- |
|---|
| 524 |
|
|---|
| 525 |
Area |
|---|
| 526 |
++++ |
|---|
| 527 |
|
|---|
| 528 |
.area : float |
|---|
| 529 |
Area of the geometry, unitless. Non-zero only for surfaces (polygons, |
|---|
| 530 |
multi-polygons). |
|---|
| 531 |
|
|---|
| 532 |
Bounds |
|---|
| 533 |
++++++ |
|---|
| 534 |
|
|---|
| 535 |
.bounds : tuple |
|---|
| 536 |
The geometry's (minx, miny, maxx, maxy) bounding box. |
|---|
| 537 |
|
|---|
| 538 |
Length |
|---|
| 539 |
++++++ |
|---|
| 540 |
|
|---|
| 541 |
.length : float |
|---|
| 542 |
Length of the geometry, unitless. Non-zero only for linear geometries |
|---|
| 543 |
(line strings, rings, polygon boundaries) |
|---|
| 544 |
|
|---|
| 545 |
Examples |
|---|
| 546 |
++++++++ |
|---|
| 547 |
|
|---|
| 548 |
.. code-block:: python |
|---|
| 549 |
|
|---|
| 550 |
>>> polygon.area |
|---|
| 551 |
4.0 |
|---|
| 552 |
>>> polygon.bounds |
|---|
| 553 |
(-1.0, -1.0, 1.0, 1.0) |
|---|
| 554 |
>>> polygon.length |
|---|
| 555 |
8.0 |
|---|
| 556 |
>>> line_r.length |
|---|
| 557 |
1.0 |
|---|
| 558 |
>>> line_b.length |
|---|
| 559 |
3.9812058474788765 |
|---|
| 560 |
|
|---|
| 561 |
|
|---|
| 562 |
Geometry Parts and Coordinates |
|---|
| 563 |
============================== |
|---|
| 564 |
|
|---|
| 565 |
Coordinate Sequences |
|---|
| 566 |
-------------------- |
|---|
| 567 |
|
|---|
| 568 |
The coordinates of points, line strings, and polygon rings can be accessed |
|---|
| 569 |
through the *coords* attribute of a geometry. *Coords* is an iterator over |
|---|
| 570 |
coordinate tuples. |
|---|
| 571 |
|
|---|
| 572 |
.. code-block:: python |
|---|
| 573 |
|
|---|
| 574 |
>>> point_r.coords |
|---|
| 575 |
<shapely.geometry.base.CoordinateSequence object at ...> |
|---|
| 576 |
>>> len(point_r.coords) |
|---|
| 577 |
1 |
|---|
| 578 |
>>> point_r.coords[0] |
|---|
| 579 |
(-1.5, 1.2) |
|---|
| 580 |
>>> list(point_r.coords) |
|---|
| 581 |
[(-1.5, 1.2)] |
|---|
| 582 |
|
|---|
| 583 |
The coordinate sequence can be modifed by assigning a sequence (**a**\ 1, ..., |
|---|
| 584 |
**a**\ M) to the coords attribute. |
|---|
| 585 |
|
|---|
| 586 |
.. code-block:: python |
|---|
| 587 |
|
|---|
| 588 |
>>> point_new = Point(0, 0) |
|---|
| 589 |
>>> point_new.coords = (1, 1) |
|---|
| 590 |
>>> list(point_new.coords) |
|---|
| 591 |
[(1.0, 1.0)] |
|---|
| 592 |
|
|---|
| 593 |
For line strings: |
|---|
| 594 |
|
|---|
| 595 |
.. code-block:: python |
|---|
| 596 |
|
|---|
| 597 |
>>> line_new = LineString([(0,0), (1,1)]) |
|---|
| 598 |
>>> line_new.coords = [(1,1), (2,2)] |
|---|
| 599 |
>>> list(line_new.coords) |
|---|
| 600 |
[(1.0, 1.0), (2.0, 2.0)] |
|---|
| 601 |
|
|---|
| 602 |
|
|---|
| 603 |
Polygon Rings |
|---|
| 604 |
------------- |
|---|
| 605 |
|
|---|
| 606 |
The exterior boundary of a polygon can be accessed through the *exterior* |
|---|
| 607 |
attribute of the geometry object. |
|---|
| 608 |
|
|---|
| 609 |
.. code-block:: python |
|---|
| 610 |
|
|---|
| 611 |
>>> polygon.exterior |
|---|
| 612 |
<shapely.geometry.polygon.LinearRing object at ...> |
|---|
| 613 |
>>> list(polygon.exterior.coords) |
|---|
| 614 |
[(-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0), (-1.0, -1.0)] |
|---|
| 615 |
|
|---|
| 616 |
The interior boundaries (or holes) of a polygon can be accessed through the |
|---|
| 617 |
*interiors* attribute, which is a list of rings. |
|---|
| 618 |
|
|---|
| 619 |
|
|---|
| 620 |
Sub-geometries |
|---|
| 621 |
-------------- |
|---|
| 622 |
|
|---|
| 623 |
The parts of a multi-part geometry can be accessed through the *geoms* |
|---|
| 624 |
attribute of the geometry object, which is an iterator over the sub-geometries: |
|---|
| 625 |
|
|---|
| 626 |
.. code-block:: python |
|---|
| 627 |
|
|---|
| 628 |
>>> multi_point.geoms |
|---|
| 629 |
<shapely.geometry.base.GeometrySequence object at ...> |
|---|
| 630 |
>>> len(multi_point.geoms) |
|---|
| 631 |
3 |
|---|
| 632 |
>>> from pprint import pprint |
|---|
| 633 |
>>> pprint(list(multi_point.geoms)) |
|---|
| 634 |
[<shapely.geometry.point.Point object at ...>, |
|---|
| 635 |
<shapely.geometry.point.Point object at ...>, |
|---|
| 636 |
<shapely.geometry.point.Point object at ...>] |
|---|
| 637 |
|
|---|
| 638 |
The coordinate sequences of these sub-geometries can then be accessed as |
|---|
| 639 |
described above. |
|---|
| 640 |
|
|---|
| 641 |
|
|---|
| 642 |
Point Coordinates |
|---|
| 643 |
----------------- |
|---|
| 644 |
|
|---|
| 645 |
For the sake of convenience the coordinate values of points can be accessed |
|---|
| 646 |
read-only via **x**, **y**, and **z** attributes: |
|---|
| 647 |
|
|---|
| 648 |
.. code-block:: python |
|---|
| 649 |
|
|---|
| 650 |
>>> point = Point(1.0, 1.0) |
|---|
| 651 |
>>> point.x |
|---|
| 652 |
1.0 |
|---|
| 653 |
>>> point.y |
|---|
| 654 |
1.0 |
|---|
| 655 |
|
|---|
| 656 |
|
|---|
| 657 |
Interoperation |
|---|
| 658 |
============== |
|---|
| 659 |
|
|---|
| 660 |
Shapely provides 4 avenues for interoperation with other Python and GIS |
|---|
| 661 |
software. |
|---|
| 662 |
|
|---|
| 663 |
Well-known Formats |
|---|
| 664 |
------------------ |
|---|
| 665 |
|
|---|
| 666 |
Well-known Text (WKT) |
|---|
| 667 |
+++++++++++++++++++++ |
|---|
| 668 |
|
|---|
| 669 |
The WKT representation of any geometry object can be had via the **wkt** |
|---|
| 670 |
attribute: |
|---|
| 671 |
|
|---|
| 672 |
.. code-block:: python |
|---|
| 673 |
|
|---|
| 674 |
>>> point_r.wkt |
|---|
| 675 |
'POINT (-1.5000000000000000 1.2000000000000000)' |
|---|
| 676 |
|
|---|
| 677 |
Hex-encode that string and you have a value that can be conveniently inserted directly into PostGIS |
|---|
| 678 |
|
|---|
| 679 |
.. code-block:: python |
|---|
| 680 |
|
|---|
| 681 |
>>> point_r.wkt.encode('hex') |
|---|
| 682 |
'504f494e5420282d312e3530303030303030303030303030303020312e3230303030303030303030303030303029' |
|---|
| 683 |
|
|---|
| 684 |
New geometries can be created from WKT representations using the |
|---|
| 685 |
*shapely.wkt.loads* factory (inspired by the *pickle* module) |
|---|
| 686 |
|
|---|
| 687 |
.. code-block:: python |
|---|
| 688 |
|
|---|
| 689 |
>>> from shapely.wkt import loads |
|---|
| 690 |
>>> loads('POINT (0 0)') |
|---|
| 691 |
<shapely.geometry.point.Point object at ...> |
|---|
| 692 |
|
|---|
| 693 |
Well-known Binary (WKB) |
|---|
| 694 |
+++++++++++++++++++++++ |
|---|
| 695 |
|
|---|
| 696 |
The WKB representation of any geometry object can be had via the **wkb** |
|---|
| 697 |
attribute. New geometries can be created from WKB data using the |
|---|
| 698 |
*shapely.wkb.loads* factory. Use this format to interoperate with ogr.py: |
|---|
| 699 |
|
|---|
| 700 |
.. code-block:: python |
|---|
| 701 |
|
|---|
| 702 |
>>> import ogr |
|---|
| 703 |
>>> from shapely.wkb import loads |
|---|
| 704 |
>>> source = ogr.Open("/tmp/world_borders.shp") |
|---|
| 705 |
>>> borders = source.GetLayerByName("world_borders") |
|---|
| 706 |
>>> feature = borders.GetNextFeature() |
|---|
| 707 |
>>> loads(feature.GetGeometryRef().ExportToWkb()) |
|---|
| 708 |
<shapely.geometry.polygon.Polygon object at ...> |
|---|
| 709 |
|
|---|
| 710 |
|
|---|
| 711 |
Python Sequences |
|---|
| 712 |
---------------- |
|---|
| 713 |
|
|---|
| 714 |
Python sequence data can be analyzed as Shapely geometries using the |
|---|
| 715 |
*shapely.geometry.as\** adapters while leaving the data in its original |
|---|
| 716 |
storage. A pair of float can be treated as a point with **asPoint**: |
|---|
| 717 |
|
|---|
| 718 |
.. code-block:: python |
|---|
| 719 |
|
|---|
| 720 |
>>> from shapely.geometry import asPoint |
|---|
| 721 |
>>> coords = [3.0, 4.0] |
|---|
| 722 |
>>> pa = asPoint(coords) |
|---|
| 723 |
>>> pa.wkt |
|---|
| 724 |
'POINT (3.0000000000000000 4.0000000000000000)' |
|---|
| 725 |
|
|---|
| 726 |
Move the coordinates and watch the geometry adapter change |
|---|
| 727 |
|
|---|
| 728 |
.. code-block:: python |
|---|
| 729 |
|
|---|
| 730 |
>>> coords[0] = 1.0 |
|---|
| 731 |
>>> pa.wkt |
|---|
| 732 |
'POINT (1.0000000000000000 4.0000000000000000)' |
|---|
| 733 |
|
|---|
| 734 |
The **asLineString** adapter works much the same. The **asPolygon** adapter is |
|---|
| 735 |
used like |
|---|
| 736 |
|
|---|
| 737 |
.. code-block:: python |
|---|
| 738 |
|
|---|
| 739 |
>>> from shapely.geometry import asPolygon |
|---|
| 740 |
>>> coords = [[0.0, 0.0], [0.0, 1.0], [1.0, 1.0], [1.0, 0.0]] |
|---|
| 741 |
>>> hole_coords = [((0.1,0.1), (0.1,0.2), (0.2,0.2), (0.2,0.1))] |
|---|
| 742 |
>>> pa = asPolygon(coords, hole_coords) |
|---|
| 743 |
>>> len(pa.exterior.coords) |
|---|
| 744 |
5 |
|---|
| 745 |
>>> len(pa.interiors) |
|---|
| 746 |
1 |
|---|
| 747 |
>>> len(pa.interiors[0].coords) |
|---|
| 748 |
5 |
|---|
| 749 |
|
|---|
| 750 |
|
|---|
| 751 |
Numpy Array Interface |
|---|
| 752 |
--------------------- |
|---|
| 753 |
|
|---|
| 754 |
Shapely geometries provide the Numpy array interface which means that points, |
|---|
| 755 |
line strings, and polygon rings can be used as Numpy arrays: |
|---|
| 756 |
|
|---|
| 757 |
.. code-block:: python |
|---|
| 758 |
|
|---|
| 759 |
>>> from numpy import array |
|---|
| 760 |
>>> a = array(polygon.exterior) |
|---|
| 761 |
>>> a |
|---|
| 762 |
array([[-1., -1.], |
|---|
| 763 |
[-1., 1.], |
|---|
| 764 |
[ 1., 1.], |
|---|
| 765 |
[ 1., -1.], |
|---|
| 766 |
[-1., -1.]]) |
|---|
| 767 |
|
|---|
| 768 |
The *numpy.asarray* function does not copy coordinate values at the price of |
|---|
| 769 |
slower numpy access to coordinates. |
|---|
| 770 |
|
|---|
| 771 |
The *shapely.geometry.as\** functions can also be used to wrap numpy arrays, |
|---|
| 772 |
which can then be analyzed using Shapely while maintaining their original |
|---|
| 773 |
storage. A 1 x 2 array can be adapted to a point |
|---|
| 774 |
|
|---|
| 775 |
.. code-block:: python |
|---|
| 776 |
|
|---|
| 777 |
>>> a = array([1.0, 2.0]) |
|---|
| 778 |
>>> pa = asPoint(a) |
|---|
| 779 |
>>> pa.wkt |
|---|
| 780 |
'POINT (1.0000000000000000 2.0000000000000000)' |
|---|
| 781 |
|
|---|
| 782 |
and a N x 2 array can be adapted to a line string |
|---|
| 783 |
|
|---|
| 784 |
.. code-block:: python |
|---|
| 785 |
|
|---|
| 786 |
>>> from shapely.geometry import asLineString |
|---|
| 787 |
>>> a = array([[1.0, 2.0], [3.0, 4.0]]) |
|---|
| 788 |
>>> la = asLineString(a) |
|---|
| 789 |
>>> la.wkt |
|---|
| 790 |
'LINESTRING (1.0000000000000000 2.0000000000000000, 3.0000000000000000 4.0000000000000000)' |
|---|
| 791 |
|
|---|
| 792 |
There is no Numpy array representation of a polygon. |
|---|
| 793 |
|
|---|
| 794 |
|
|---|
| 795 |
Python Geo Interface |
|---|
| 796 |
-------------------- |
|---|
| 797 |
|
|---|
| 798 |
Any object that provides the GeoJSON-like `Python geo interface`_ can be |
|---|
| 799 |
adapted and used as a Shapely geometry using the *shapely.geometry.asShape* |
|---|
| 800 |
function. For example, a dictionary: |
|---|
| 801 |
|
|---|
| 802 |
.. code-block:: python |
|---|
| 803 |
|
|---|
| 804 |
>>> from shapely.geometry import asShape |
|---|
| 805 |
>>> d = {"type": "Point", "coordinates": (0.0, 0.0)} |
|---|
| 806 |
>>> shape = asShape(d) |
|---|
| 807 |
>>> shape.geom_type |
|---|
| 808 |
'Point' |
|---|
| 809 |
>>> list(shape.coords) |
|---|
| 810 |
[(0.0, 0.0)] |
|---|
| 811 |
|
|---|
| 812 |
Or a simple placemark-type object: |
|---|
| 813 |
|
|---|
| 814 |
.. code-block:: python |
|---|
| 815 |
|
|---|
| 816 |
>>> class GeoThing(object): |
|---|
| 817 |
... def __init__(self, d): |
|---|
| 818 |
... self.__geo_interface__ = d |
|---|
| 819 |
>>> thing = GeoThing({"type": "Point", "coordinates": (0.0, 0.0)}) |
|---|
| 820 |
>>> shape = asShape(thing) |
|---|
| 821 |
>>> shape.geom_type |
|---|
| 822 |
'Point' |
|---|
| 823 |
>>> list(shape.coords) |
|---|
| 824 |
[(0.0, 0.0)] |
|---|
| 825 |
|
|---|
| 826 |
If you want to copy coordinate data to a new geometry, use the |
|---|
| 827 |
*shapely.geometry.shape* function instead. |
|---|
| 828 |
|
|---|
| 829 |
.. _Python geo interface: http://trac.gispython.org/projects/PCL/wiki/PythonGeoInterface |
|---|
| 830 |
|
|---|
| 831 |
|
|---|
| 832 |
Advanced Features |
|---|
| 833 |
================= |
|---|
| 834 |
|
|---|
| 835 |
Iterative Operations |
|---|
| 836 |
-------------------- |
|---|
| 837 |
|
|---|
| 838 |
Shapely provides functions for efficient operations on large sets of |
|---|
| 839 |
geometries. |
|---|
| 840 |
|
|---|
| 841 |
Contains |
|---|
| 842 |
++++++++ |
|---|
| 843 |
|
|---|
| 844 |
To find the subset of points that are contained within a polygon, use |
|---|
| 845 |
*shapely.iterops.contains*: |
|---|
| 846 |
|
|---|
| 847 |
.. code-block:: python |
|---|
| 848 |
|
|---|
| 849 |
>>> from shapely.geometry import Polygon |
|---|
| 850 |
>>> from shapely.geometry import Point |
|---|
| 851 |
>>> coords = ((0.0, 0.0), (0.0, 1.0), (1.0, 1.0), (1.0, 0.0), (0.0, 0.0)) |
|---|
| 852 |
>>> polygon = Polygon(coords) |
|---|
| 853 |
>>> points = [Point(0.5, 0.5), Point(2.0, 2.0)] |
|---|
| 854 |
>>> from shapely import iterops |
|---|
| 855 |
>>> list(iterops.contains(polygon, points, True)) |
|---|
| 856 |
[<shapely.geometry.point.Point object at ...>] |
|---|
| 857 |
|
|---|
| 858 |
The second parameter to *iterops.contains* can be any kind of iterator, even a |
|---|
| 859 |
generator of objects. If it yields tuples, then the second element of the tuple |
|---|
| 860 |
will be ultimately yielded from *iterops.contains*. |
|---|
| 861 |
|
|---|
| 862 |
.. code-block:: python |
|---|
| 863 |
|
|---|
| 864 |
>>> list(iterops.contains(polygon, iter((p, p.wkt) for p in points))) |
|---|
| 865 |
['POINT (0.5000000000000000 0.5000000000000000)'] |
|---|
| 866 |
|
|---|
| 867 |
|
|---|
| 868 |
Credits |
|---|
| 869 |
======= |
|---|
| 870 |
|
|---|
| 871 |
Shapely is written by Sean Gillies with contributions from Howard Butler, Kai |
|---|
| 872 |
Lautaportti (Hexagon IT), Frédéric Junod (Camptocamp SA), Eric Lemoine |
|---|
| 873 |
(Camptocamp SA) and ctypes tips from Justin Bronn (GeoDjango). |
|---|
| 874 |
|
|---|
| 875 |
|
|---|