shapely

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Shapely - Planar Geometry

Shapely - 平面几何

Shapely is the engine behind GeoPandas and many other GIS tools. It focuses on the geometry itself: calculating intersections, unions, distances, and checking spatial relationships (like "is this point inside this polygon?").
Shapely是GeoPandas及众多GIS工具的核心引擎,它专注于几何对象本身:计算交集、并集、距离,以及判断空间关系(例如“该点是否在多边形内部?”)。

When to Use

适用场景

  • Precise manipulation of 2D geometric shapes.
  • Performing set-theoretic operations (Intersection, Union, Difference).
  • Checking spatial predicates (Contains, Within, Intersects, Touches).
  • Cleaning and validating "dirty" geometry (fixing self-intersections).
  • Calculating geometric properties (Area, Length, Centroid, Bounds).
  • Generating buffers or simplifying complex lines.
  • Linear referencing (finding points along a line).
  • 精确操作2D几何形状
  • 执行集合论运算(交集、并集、差集)
  • 判断空间谓词(包含、在内部、相交、接触)
  • 清理和验证“无效”几何对象(修复自相交问题)
  • 计算几何属性(面积、长度、质心、边界范围)
  • 生成缓冲区或简化复杂线条
  • 线性参考(查找线条上的点位)

Reference Documentation

参考文档

Official docs: https://shapely.readthedocs.io/
GEOS (Engine): https://libgeos.org/
Search patterns:
shapely.geometry
,
shapely.ops.unary_union
,
shapely.validation.make_valid
官方文档https://shapely.readthedocs.io/
GEOS(核心引擎)https://libgeos.org/
常用搜索关键词
shapely.geometry
,
shapely.ops.unary_union
,
shapely.validation.make_valid

Core Principles

核心原则

Geometric Objects

几何对象

Objects are immutable. Once created, you don't change them; you perform an operation that returns a new object.
  • Points: 0-dimensional.
  • LineStrings: 1-dimensional curves.
  • Polygons: 2-dimensional surfaces with optional holes.
对象是不可变的。一旦创建,就不能修改它们;需通过执行操作返回新对象。
  • Points:0维对象
  • LineStrings:1维曲线
  • Polygons:带可选孔洞的2维面

Cartesian Geometry

笛卡尔几何

Shapely operates in a Cartesian plane. It does not know about Earth's curvature, latitudes, or longitudes. Distance is sqrt(dx² + dy²).
Shapely在笛卡尔平面中运行,不考虑地球曲率、纬度或经度。距离计算采用sqrt(dx² + dy²)公式。

Vectorization (Shapely 2.0+)

向量化(Shapely 2.0+)

Modern Shapely supports vectorized operations on NumPy arrays of geometry objects, making it significantly faster than older versions.
新版Shapely支持对几何对象的NumPy数组执行向量化操作,相比旧版本性能大幅提升。

Quick Reference

快速参考

Installation

安装

bash
pip install shapely numpy
bash
pip install shapely numpy

Standard Imports

标准导入

python
import numpy as np
from shapely import Point, LineString, Polygon, MultiPoint, MultiPolygon
from shapely import ops, wkt, wkb
import shapely
python
import numpy as np
from shapely import Point, LineString, Polygon, MultiPoint, MultiPolygon
from shapely import ops, wkt, wkb
import shapely

Basic Pattern - Creation and Analysis

基础模式 - 创建与分析

python
from shapely.geometry import Point, Polygon
python
from shapely.geometry import Point, Polygon

1. Create objects

1. Create objects

p = Point(0, 0) poly = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])
p = Point(0, 0) poly = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)])

2. Check relationships

2. Check relationships

is_inside = p.within(poly) # True is_on_border = p.touches(poly) # False (interior counts as within)
is_inside = p.within(poly) # True is_on_border = p.touches(poly) # False (interior counts as within)

3. Calculate

3. Calculate

print(f"Area: {poly.area}") print(f"Distance: {p.distance(Point(10, 10))}")
undefined
print(f"Area: {poly.area}") print(f"Distance: {p.distance(Point(10, 10))}")
undefined

Critical Rules

关键规则

✅ DO

✅ 建议做法

  • Check Validity - Use
    .is_valid
    before complex operations. Invalid geometry (like a self-intersecting polygon) will cause errors.
  • Use unary_union - When merging many polygons,
    ops.unary_union([list])
    is orders of magnitude faster than a loop of
    p1.union(p2)
    .
  • Prefer Vectorized Functions - Use
    shapely.intersects(array_a, array_b)
    instead of loops for performance.
  • Use prepare() - If you are checking many points against the same polygon, use
    shapely.prepare(poly)
    to speed up subsequent queries.
  • Simplify for Analysis - Use
    .simplify(tolerance)
    for complex boundaries to improve performance if high precision isn't required.
  • 检查有效性 - 在执行复杂操作前使用
    .is_valid
    检查。无效几何对象(如自相交多边形)会导致错误。
  • 使用unary_union - 合并多个多边形时,
    ops.unary_union([list])
    比循环执行
    p1.union(p2)
    快几个数量级。
  • 优先使用向量化函数 - 为提升性能,使用
    shapely.intersects(array_a, array_b)
    替代循环。
  • 使用prepare() - 如果要针对同一个多边形检查大量点,使用
    shapely.prepare(poly)
    加速后续查询。
  • 简化几何对象以优化分析 - 如果不需要高精度,使用
    .simplify(tolerance)
    简化复杂边界以提升性能。

❌ DON'T

❌ 避免做法

  • Mix Cartesian and Spherical - Don't calculate distance on Lat/Lon points; the result will be in meaningless "degrees".
  • Assume Polygon Orientation - While Shapely handles it, remember that exterior rings should ideally be counter-clockwise and holes clockwise.
  • Use for 3D Math - Shapely supports Z-coordinates for storage, but most operations (like area, intersection) ignore Z and project onto the XY plane.
  • Loop over large collections - Use NumPy-style vectorization provided in Shapely 2.0+.
  • 混合笛卡尔与球面坐标 - 不要对经纬度点计算距离,结果会是无意义的“度数”单位。
  • 假设多边形方向 - 虽然Shapely会处理,但请记住,外部环理想情况下应为逆时针方向,孔洞应为顺时针方向。
  • 用于3D运算 - Shapely支持存储Z坐标,但大多数运算(如面积、交集)会忽略Z坐标,投影到XY平面执行。
  • 循环处理大型集合 - 使用Shapely 2.0+提供的NumPy风格向量化操作。

Anti-Patterns (NEVER)

反模式(绝对避免)

python
from shapely.geometry import Point, Polygon
from shapely.ops import unary_union
python
from shapely.geometry import Point, Polygon
from shapely.ops import unary_union

❌ BAD: Merging geometries in a loop (O(n²) complexity)

❌ BAD: Merging geometries in a loop (O(n²) complexity)

result = geometries[0] for g in geometries[1:]: result = result.union(g)
result = geometries[0] for g in geometries[1:]: result = result.union(g)

✅ GOOD: Use unary_union (O(n log n) complexity)

✅ GOOD: Use unary_union (O(n log n) complexity)

result = unary_union(geometries)
result = unary_union(geometries)

❌ BAD: Checking many points without preparing

❌ BAD: Checking many points without preparing

for p in many_points: if complex_poly.contains(p): # Slow for complex shapes pass
for p in many_points: if complex_poly.contains(p): # Slow for complex shapes pass

✅ GOOD: Prepare the geometry (Builds a spatial index)

✅ GOOD: Prepare the geometry (Builds a spatial index)

from shapely import prepare prepare(complex_poly) for p in many_points: if complex_poly.contains(p): # Much faster pass
undefined
from shapely import prepare prepare(complex_poly) for p in many_points: if complex_poly.contains(p): # Much faster pass
undefined

Geometry Types and Creation

几何类型与创建

Standard Primitives

标准基本类型

python
undefined
python
undefined

Point (x, y, z)

Point (x, y, z)

pt = Point(1.0, 2.0)
pt = Point(1.0, 2.0)

LineString (Ordered sequence of points)

LineString (Ordered sequence of points)

line = LineString([(0, 0), (1, 1), (2, 0)])
line = LineString([(0, 0), (1, 1), (2, 0)])

Polygon (Shell, [Holes])

Polygon (Shell, [Holes])

shell = [(0, 0), (10, 0), (10, 10), (0, 10)] hole = [(2, 2), (2, 4), (4, 4), (4, 2)] poly = Polygon(shell, [hole])
shell = [(0, 0), (10, 0), (10, 10), (0, 10)] hole = [(2, 2), (2, 4), (4, 4), (4, 2)] poly = Polygon(shell, [hole])

Multi-Geometries (Collections)

Multi-Geometries (Collections)

points = MultiPoint([(0,0), (1,1)])
undefined
points = MultiPoint([(0,0), (1,1)])
undefined

Spatial Predicates (Relationships)

空间谓词(关系判断)

Checking how objects relate

判断对象间的关系

python
a = Point(1, 1).buffer(1.5) # A circle
b = Polygon([(0,0), (2,0), (2,2), (0,2)]) # A square

print(a.intersects(b))  # Shared space?
print(a.contains(b))    # B entirely inside A?
print(a.disjoint(b))    # No shared space?
print(a.overlaps(b))    # Same dimension, shared space, but not within?
print(a.touches(b))     # Only boundaries share space?
print(a.crosses(b))     # Line crossing a polygon?
python
a = Point(1, 1).buffer(1.5) # A circle
b = Polygon([(0,0), (2,0), (2,2), (0,2)]) # A square

print(a.intersects(b))  # Shared space?
print(a.contains(b))    # B entirely inside A?
print(a.disjoint(b))    # No shared space?
print(a.overlaps(b))    # Same dimension, shared space, but not within?
print(a.touches(b))     # Only boundaries share space?
print(a.crosses(b))     # Line crossing a polygon?

Set-Theoretic Operations

集合论运算

Creating new geometries from old ones

基于已有几何对象创建新对象

python
poly1 = Point(0, 0).buffer(1)
poly2 = Point(1, 0).buffer(1)
python
poly1 = Point(0, 0).buffer(1)
poly2 = Point(1, 0).buffer(1)

Intersection (Shared area)

Intersection (Shared area)

inter = poly1.intersection(poly2)
inter = poly1.intersection(poly2)

Union (Combined area)

Union (Combined area)

union = poly1.union(poly2)
union = poly1.union(poly2)

Difference (Area in poly1 NOT in poly2)

Difference (Area in poly1 NOT in poly2)

diff = poly1.difference(poly2)
diff = poly1.difference(poly2)

Symmetric Difference (Area in either but NOT both)

Symmetric Difference (Area in either but NOT both)

sdiff = poly1.symmetric_difference(poly2)
undefined
sdiff = poly1.symmetric_difference(poly2)
undefined

Constructive Methods

构造方法

Buffering, Splicing, and Simplifying

缓冲区、拼接与简化

python
undefined
python
undefined

Buffer: Expand/shrink geometry

Buffer: Expand/shrink geometry

cap_style: 1=Round, 2=Flat, 3=Square

cap_style: 1=Round, 2=Flat, 3=Square

line_thick = line.buffer(0.5, cap_style=2)
line_thick = line.buffer(0.5, cap_style=2)

Centroid: Geometric center

Centroid: Geometric center

center = poly.centroid
center = poly.centroid

Representative Point: Guaranteed to be INSIDE the geometry

Representative Point: Guaranteed to be INSIDE the geometry

Useful for label placement in U-shaped polygons

Useful for label placement in U-shaped polygons

label_pt = poly.representative_point()
label_pt = poly.representative_point()

Simplify: Reduce number of vertices

Simplify: Reduce number of vertices

simple_line = complex_line.simplify(tolerance=0.1, preserve_topology=True)
simple_line = complex_line.simplify(tolerance=0.1, preserve_topology=True)

Convex Hull: Smallest convex box containing all points

Convex Hull: Smallest convex box containing all points

hull = MultiPoint(points).convex_hull
undefined
hull = MultiPoint(points).convex_hull
undefined

Linear Referencing

线性参考

Working with positions along a LineString

处理LineString上的点位

python
line = LineString([(0, 0), (0, 10), (10, 10)])
python
line = LineString([(0, 0), (0, 10), (10, 10)])

Find distance along line to the point nearest to (5, 5)

Find distance along line to the point nearest to (5, 5)

dist = line.project(Point(5, 5)) # returns 5.0 (it's at (0, 5))
dist = line.project(Point(5, 5)) # returns 5.0 (it's at (0, 5))

Find the actual point at a specific distance along the line

Find the actual point at a specific distance along the line

pt = line.interpolate(15.0) # returns Point(5, 10)
undefined
pt = line.interpolate(15.0) # returns Point(5, 10)
undefined

I/O: WKT, WKB, and NumPy

输入输出:WKT、WKB与NumPy

Serialization and Data Exchange

序列化与数据交换

python
undefined
python
undefined

WKT (Well-Known Text) - Human readable

WKT (Well-Known Text) - Human readable

text = "POINT (10 20)" p = wkt.loads(text) print(p.wkt)
text = "POINT (10 20)" p = wkt.loads(text) print(p.wkt)

WKB (Well-Known Binary) - Fast and compact

WKB (Well-Known Binary) - Fast and compact

binary = wkb.dumps(p) p_new = wkb.loads(binary)
binary = wkb.dumps(p) p_new = wkb.loads(binary)

NumPy Integration (Shapely 2.0)

NumPy Integration (Shapely 2.0)

points_array = np.array([Point(0,0), Point(1,1), Point(2,2)]) areas = shapely.area(points_array) # Returns array of zeros dist_matrix = shapely.distance(points_array[:, np.newaxis], points_array)
undefined
points_array = np.array([Point(0,0), Point(1,1), Point(2,2)]) areas = shapely.area(points_array) # Returns array of zeros dist_matrix = shapely.distance(points_array[:, np.newaxis], points_array)
undefined

Practical Workflows

实用工作流

1. Cleaning Invalid Geometries

1. 修复无效几何对象

python
from shapely.validation import make_valid

def safe_area(geom):
    """Calculates area even for invalid/self-intersecting polygons."""
    if not geom.is_valid:
        geom = make_valid(geom)
    
    # After make_valid, a Polygon might become a MultiPolygon or GeometryCollection
    return geom.area
python
from shapely.validation import make_valid

def safe_area(geom):
    """Calculates area even for invalid/self-intersecting polygons."""
    if not geom.is_valid:
        geom = make_valid(geom)
    
    # After make_valid, a Polygon might become a MultiPolygon or GeometryCollection
    return geom.area

2. Point-in-Polygon Search (Optimized)

2. 优化版点-in-多边形查询

python
from shapely import prepare

def find_points_in_poly(points, poly):
    """Efficiently filters points inside a complex polygon."""
    prepare(poly) # Builds internal STRtree or spatial index
    
    # Using vectorized intersection (much faster)
    mask = shapely.contains(poly, points)
    return points[mask]
python
from shapely import prepare

def find_points_in_poly(points, poly):
    """Efficiently filters points inside a complex polygon."""
    prepare(poly) # Builds internal STRtree or spatial index
    
    # Using vectorized intersection (much faster)
    mask = shapely.contains(poly, points)
    return points[mask]

3. Splitting a Polygon by a Line

3. 用线条分割多边形

python
from shapely.ops import split

def divide_land(polygon, line):
    """Splits a polygon into multiple parts using a LineString."""
    result = split(polygon, line)
    # Returns a GeometryCollection of the resulting parts
    return list(result.geoms)
python
from shapely.ops import split

def divide_land(polygon, line):
    """Splits a polygon into multiple parts using a LineString."""
    result = split(polygon, line)
    # Returns a GeometryCollection of the resulting parts
    return list(result.geoms)

Performance Optimization

性能优化

STRtree for Nearest Neighbors

用STRtree查找最近邻

If you have thousands of geometries and need to find which ones are near a point, use STRtree.
python
from shapely import STRtree

tree = STRtree(geometries)
如果有数千个几何对象,需要查找某个点附近的对象,可使用STRtree。
python
from shapely import STRtree

tree = STRtree(geometries)

Find indices of geometries whose bounding boxes intersect the point's buffer

Find indices of geometries whose bounding boxes intersect the point's buffer

indices = tree.query(Point(0,0).buffer(10))
indices = tree.query(Point(0,0).buffer(10))

Find the single nearest geometry index

Find the single nearest geometry index

nearest_idx = tree.nearest(Point(0,0))
undefined
nearest_idx = tree.nearest(Point(0,0))
undefined

Common Pitfalls and Solutions

常见陷阱与解决方案

The "Sliver Polygon" problem

“细长三角多边形”问题

Calculations like intersection can sometimes produce tiny, almost invisible polygons due to floating-point errors.
python
undefined
交集等运算有时会因浮点误差产生极小的、几乎不可见的多边形。
python
undefined

✅ Solution: Filter by area

✅ Solution: Filter by area

intersection = p1.intersection(p2) if intersection.area < 1e-9: intersection = None
undefined
intersection = p1.intersection(p2) if intersection.area < 1e-9: intersection = None
undefined

Latitude/Longitude Confusion

经纬度顺序混淆

Points are (x, y). In GIS, this usually means (Longitude, Latitude).
python
undefined
点的格式是(x, y),在GIS中通常对应(经度,纬度)。
python
undefined

❌ Error: Point(Latitude, Longitude)

❌ Error: Point(Latitude, Longitude)

This will plot your maps sideways!

This will plot your maps sideways!

✅ Solution: Always use (Lon, Lat) to match (X, Y)

✅ Solution: Always use (Lon, Lat) to match (X, Y)

nyc = Point(-74.006, 40.7128)
undefined
nyc = Point(-74.006, 40.7128)
undefined

GeometryCollections

GeometryCollections

Operations like split or intersection can return GeometryCollection. This is a container for mixed types.
python
undefined
分割或交集等操作可能返回GeometryCollection,这是一个混合类型的容器。
python
undefined

❌ Problem: Calling .area on a collection with Lines and Polygons

❌ Problem: Calling .area on a collection with Lines and Polygons

✅ Solution: Filter for the type you want

✅ Solution: Filter for the type you want

polys = [g for g in collection.geoms if g.geom_type == 'Polygon']
undefined
polys = [g for g in collection.geoms if g.geom_type == 'Polygon']
undefined

Best Practices

最佳实践

  1. Always validate geometry with
    .is_valid
    before complex operations
  2. Use
    unary_union
    instead of looping over unions
  3. Prepare geometries with
    prepare()
    when checking many points against the same shape
  4. Use vectorized operations in Shapely 2.0+ for performance
  5. Remember Shapely is Cartesian - don't use lat/lon directly for distance calculations
  6. Filter sliver polygons by area threshold after geometric operations
  7. Use STRtree for spatial indexing when working with many geometries
  8. Simplify complex geometries when high precision isn't required
  9. Handle GeometryCollections properly - filter by geometry type when needed
  10. Use representative_point() for guaranteed interior points in complex polygons
Shapely is a specialized, sharp tool. It doesn't care about your coordinate system or your file format — it only cares about the pure, mathematical relationship between shapes. Mastering it is the key to building advanced spatial algorithms.
  1. 执行复杂操作前,始终用
    .is_valid
    验证几何对象
  2. 使用
    unary_union
    替代循环执行并集操作
  3. 当针对同一形状检查大量点时,用
    prepare()
    预处理几何对象
  4. 为提升性能,使用Shapely 2.0+的向量化操作
  5. 记住Shapely基于笛卡尔坐标系 - 不要直接对经纬度计算距离
  6. 几何运算后,通过面积阈值过滤细长三角多边形
  7. 处理大量几何对象时,用STRtree做空间索引
  8. 不需要高精度时,简化复杂几何对象
  9. 正确处理GeometryCollection - 需要时按几何类型过滤
  10. 对复杂多边形,使用representative_point()获取确保在内部的点位
Shapely是一款专业且强大的工具,它不关心你的坐标系或文件格式——只专注于形状之间纯粹的数学关系。掌握它是构建高级空间算法的关键。