from shapely.geometry import Point, LineString, Polygon
= Point(0, 0)
pt pt
Spatial (Shapely)
Shapely is a Python library for creating and manipulating geometric objects such as points, lines, and polygons. It offers an intuitive way to work with these shapes within a Cartesian coordinate system. Widely used in spatial analysis, Shapely also underpins other libraries like GeoPandas, which is designed for handling geospatial data.
In a nutshell, Shapely allows you to:
- Create points, lines, and polygons.
- Analyse spatial relationships such as containment, intersection, and proximity.
- Carry out geometric operations like buffering, union, and intersection.
- Integrate with libraries such as GeoPandas for more advanced geospatial tasks.
For more comprehensive details, please refer to the Shapely API documentation.
In this lesson, we’ll explore the fundamentals of Shapely and its applications in urban contexts. You’ll learn how to model spatial relationships and perform various geometric operations using this library.
This lesson assumes some familiarity with fundamental GIS concepts. We won’t be covering basics such as coordinate reference systems or spatial predicates in detail. However, if you’ve used tools like QGIS, you’ll find concepts such as spatial types (points, linestrings, polygons) and operations (buffering, predicates) quite familiar.
Basic Geometry
Shapely uses its geometry
module to construct basic geometric shapes.
Points are the most fundamental geometric objects in Shapely, serving as the building blocks for more complex shapes.
Linestrings represent sequences of connected points. You can define them using a series of XY coordinate pairs or a list of Point objects.
= LineString([(0, 5), (5, 0), (10, 5)])
line
line
Polygons are closed shapes defined by a sequence of coordinates. Similar to linestrings, you can create them from a list of points or coordinate tuples.
= Polygon([(0, 0), (0, 10), (10, 10), (10, 0)])
poly poly
Shapely geometries come with useful properties that provide common information. For instance, you can easily retrieve a polygon’s area:
poly.area
100.0
Similarly, you can get the length of a linestring:
line.length
14.142135623730951
Other handy properties include centroids, x and y coordinates, and WKT (Well-Known Text) representations:
poly.centroid
pt.x, pt.y
(0.0, 0.0)
line.wkt
'LINESTRING (0 5, 5 0, 10 5)'
Operations and Predicates
Shapely supports a range of typical GIS spatial operations and predicates. For example, you can measure the distance between two spatial objects:
pt.distance(line)
3.5355339059327378
Crucially, Shapely operates using Cartesian coordinates. For accurate distance calculations or predicate operations, ensure your geometries are in a projected coordinate reference system and share the same system. Objects must share the same coordinate system for accurate results.
The Shapely documentation provides comprehensive details on all available operations and predicates. For instance, the geometry.Point
page describes everything related to point geometries.
= pt.buffer(2)
pt_buff
pt_buff
As an example, the documentation shows that the Point
geometry has a buffer
method. This method accepts a distance parameter and returns a polygon representing the buffered area.
Common spatial predicates are also readily available. For example, you can use the within
method to check if a point is located inside a polygon:
pt.within(poly)
False
If a point is on a polygon’s boundary, within
returns False
, but intersects
or touches
return True
.
pt.intersects(poly)
True
pt.touches(poly)
True
Buffers, Unions, and Differencing
Other common geometric operations include buffer
. For instance, let’s create a buffer around a linestring:
= line.buffer(2)
line_buff
line_buff
You can use the union
method to combine two polygons into a single, unified geometry:
= Polygon([(5, 5), (5, 15), (15, 15), (15, 5)])
poly2
= poly.union(poly2)
union_poly
union_poly
Operations like difference
also behave intuitively, as you might expect from GIS software:
= poly.difference(pt_buff)
diff_poly
diff_poly
Some operations offer configurable parameters for finer control. For example, the buffer
method includes cap_style
and join_style
parameters, which allow you to control the appearance of the buffer’s ends and joins around a line.
= line.buffer(2, cap_style=1, join_style=1)
buffer_round
buffer_round
Workflows
Shapely’s spatial operations and predicates closely mirror those found in GIS software like QGIS. This means tasks you might perform in a graphical user interface (UI) can often be replicated in Python, and vice-versa. Python becomes particularly advantageous for complex or lengthy workflows, as scripting enables advanced processing that can be cumbersome or difficult to achieve through a UI.
Let’s consider a simple example: modelling streets and checking if they are within a specified distance threshold of particular land uses.
= LineString([(0, 0), (10, 0)])
street = street.buffer(5, cap_style=1, join_style=1)
street_buffer
street_buffer
= Point(3, 4)
land_use land_use
= land_use.within(street_buffer)
is_within is_within
True
= land_use.distance(street)
distance_to_street distance_to_street
4.0
In real-world scenarios, GeoPandas is frequently used for such workflows. It excels at handling multiple features, managing coordinate reference systems, performing file input/output (I/O), and plotting.
Exercises
- Create two points and calculate the distance between them.
- Create a polygon and check if a point is inside it.
- Create two polygons and check if they intersect.
- Create a LineString with at least three points.
- Create a list of points and a polygon. Check which points are inside the polygon.