惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Security Archives - TechRepublic
Security Archives - TechRepublic
爱范儿
爱范儿
Recent Announcements
Recent Announcements
AI
AI
V
Visual Studio Blog
H
Heimdal Security Blog
L
LINUX DO - 最新话题
Attack and Defense Labs
Attack and Defense Labs
宝玉的分享
宝玉的分享
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
W
WeLiveSecurity
人人都是产品经理
人人都是产品经理
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
WordPress大学
WordPress大学
S
Secure Thoughts
S
Security Affairs
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
N
News and Events Feed by Topic
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园 - 聂微东
博客园 - Franky
阮一峰的网络日志
阮一峰的网络日志
Schneier on Security
Schneier on Security
Hugging Face - Blog
Hugging Face - Blog
Apple Machine Learning Research
Apple Machine Learning Research
Forbes - Security
Forbes - Security
The Cloudflare Blog
博客园 - 【当耐特】
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
有赞技术团队
有赞技术团队
博客园 - 司徒正美
博客园_首页
Recent Commits to openclaw:main
Recent Commits to openclaw:main
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
NISL@THU
NISL@THU
C
Cybersecurity and Infrastructure Security Agency CISA
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
P
Proofpoint News Feed
罗磊的独立博客
V
Vulnerabilities – Threatpost
S
Securelist
N
News and Events Feed by Topic
Cloudbric
Cloudbric
P
Proofpoint News Feed
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V2EX - 技术
V2EX - 技术
小众软件
小众软件

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第5章:枚举类型与常量定义 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
第1章:Shapely 概述与入门
我才是银古 · 2026-06-23 · via 博客园 - 我才是银古

第1章:Shapely 概述与入门

Shapely 是 Python 生态中最重要的计算几何库之一。本章将全面介绍 Shapely 的定义、背景、设计理念、在 GIS 生态中的位置,以及如何快速上手使用它。无论你是 GIS 开发者、数据科学家还是空间分析师,Shapely 都是你工具箱中不可或缺的利器。


1.1 什么是 Shapely

1.1.1 Shapely 的定义

Shapely 是一个基于 BSD 开源许可证发布的 Python 包,专门用于在 二维笛卡尔平面上进行几何对象的操作与分析。它提供了创建、操作和分析平面几何体(如点、线、多边形)的能力,是 Python 空间数据处理的核心基础库。

Shapely 的核心能力包括:

  • 几何对象创建:支持点(Point)、线(LineString)、多边形(Polygon)等所有 OGC Simple Features 标准定义的几何类型
  • 空间关系判断:包含、相交、接触、重叠等拓扑关系的判断
  • 几何运算:交集、并集、差集、缓冲区等空间操作
  • 几何属性计算:面积、长度、质心、边界框等属性的获取
  • 几何验证与修复:检查几何体的有效性并进行修复
# Shapely 的基本用法一览
from shapely import Point, Polygon

# 创建一个点
point = Point(1.0, 2.0)
print(f"点: {point}")           # POINT (1 2)
print(f"类型: {point.geom_type}")  # Point

# 创建一个多边形
polygon = Polygon([(0, 0), (4, 0), (4, 4), (0, 4)])
print(f"面积: {polygon.area}")     # 16.0
print(f"周长: {polygon.length}")   # 16.0

# 空间关系判断
print(f"点在多边形内: {polygon.contains(point)}")  # True

1.1.2 核心特征

特征 说明
开源许可 BSD 3-Clause License,允许商业使用
几何维度 二维笛卡尔平面(支持 Z 坐标存储但不参与计算)
底层引擎 基于 GEOS(C/C++ 几何计算引擎)
标准兼容 遵循 OGC Simple Features 规范
Python 版本 支持 Python 3.8+
线程安全 GEOS 操作时释放 GIL,支持多线程

1.2 项目背景与历史

1.2.1 技术渊源

Shapely 的技术基础深植于一条成熟的开源几何计算链条:

┌─────────────────────────────────────────────────────────────┐
│                    几何计算引擎的技术传承                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────────┐                                          │
│   │    JTS      │  Java Topology Suite                     │
│   │  (Java)     │  最早的计算几何库(2002 年)                │
│   └──────┬──────┘                                          │
│          │ C++ 移植                                         │
│          ▼                                                  │
│   ┌─────────────┐                                          │
│   │    GEOS     │  Geometry Engine - Open Source            │
│   │  (C/C++)    │  PostGIS 的几何引擎                       │
│   └──────┬──────┘                                          │
│          │ Python 绑定                                      │
│          ▼                                                  │
│   ┌─────────────┐                                          │
│   │   Shapely   │  Python 几何操作库                        │
│   │  (Python)   │  优雅的 Pythonic API                      │
│   └─────────────┘                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘

JTS(Java Topology Suite):由加拿大 Vivid Solutions 公司于 2002 年开发的 Java 计算几何库,实现了 OGC 的 Simple Features 规范。JTS 是整个开源几何计算生态的源头。

GEOS(Geometry Engine - Open Source):JTS 的 C/C++ 移植版本,由 Refractions Research 开发,是 PostGIS 空间数据库的核心几何引擎。GEOS 继承了 JTS 的所有算法实现,并针对 C/C++ 环境进行了优化。

Shapely:通过 Python 的 ctypes(1.x 版本)或 Cython(2.0 版本)机制调用 GEOS 的 C API,为 Python 开发者提供了简洁、优雅的几何操作接口。

1.2.2 版本发展历程

时间 版本 重要里程碑
2007 1.0 Shapely 首次发布,通过 ctypes 绑定 GEOS
2010 1.2 改进了几何操作性能和稳定性
2014 1.4 支持 GEOS 3.4+,增加了 prepared geometry
2017 1.6 改进了 vectorized operations 的初步支持
2019 1.7 引入了对 NumPy 数组的初步支持
2022 2.0 重大版本更新:不可变几何体、向量化操作、NumPy 深度集成
2023 2.0.1-2.0.6 持续修复和性能改进

1.2.3 Shapely 2.0 的重大变化

Shapely 2.0 是一次破坏性的大版本更新,带来了根本性的架构变化:

1. 不可变几何体(Immutable Geometries)

from shapely import Point

p = Point(1, 2)
# Shapely 2.0 中,几何对象是不可变的
# 不能修改已有几何体,只能创建新的
# p.coords = [(3, 4)]  # 这在 2.0 中会抛出异常

# 正确方式:创建新的几何体
p_new = Point(3, 4)

2. 向量化操作(Vectorized Operations)

import numpy as np
import shapely

# 批量创建点——向量化操作,性能远优于循环
coords = np.array([[0, 0], [1, 1], [2, 2], [3, 3]])
points = shapely.points(coords)
print(points)  # 返回 NumPy 数组,包含 4 个 Point 对象

# 批量计算距离
origin = Point(0, 0)
distances = shapely.distance(points, origin)
print(distances)  # [0.  1.41421356  2.82842712  4.24264069]

3. 可哈希(Hashable)

from shapely import Point

p1 = Point(1, 2)
p2 = Point(3, 4)

# 2.0 中几何对象可用作字典键和集合元素
point_set = {p1, p2}
point_dict = {p1: "A", p2: "B"}
print(point_dict[p1])  # "A"

4. NumPy 深度集成

import numpy as np
import shapely

# NumPy 数组可直接存储几何对象
geom_array = np.array([Point(0, 0), Point(1, 1), Point(2, 2)])

# 所有 shapely 顶级函数都支持数组输入
areas = shapely.area(geom_array)
is_valid = shapely.is_valid(geom_array)

1.3 核心设计理念

1.3.1 专注于几何计算

Shapely 的设计哲学非常明确——只做几何计算,做到极致

  • 不处理坐标参考系统(CRS):Shapely 不知道也不关心你的坐标是 WGS84、UTM 还是其他任何投影。所有计算都在笛卡尔平面上进行。如果需要坐标转换,请使用 pyproj 库。
  • 不关注数据序列化格式:虽然 Shapely 支持 WKT、WKB 和 GeoJSON 格式的输入输出,但它的核心不是数据格式转换。如果需要读写地理数据文件(Shapefile、GeoPackage 等),请使用 FionaGDAL/OGR
  • 不提供可视化功能:Shapely 本身不绑定任何可视化引擎。如果需要绘图,请配合 matplotlib 使用。
# Shapely 专注于几何计算的示例
from shapely import Point, Polygon

# 创建几何体(不需要指定坐标系)
park = Polygon([(0, 0), (100, 0), (100, 80), (0, 80)])
school = Point(50, 40)

# 几何分析
buffer_zone = school.buffer(30)          # 缓冲区分析
overlap = park.intersection(buffer_zone)  # 交集运算
print(f"重叠面积: {overlap.area:.2f}")    # 几何计算结果

1.3.2 Pythonic API 设计

Shapely 提供了非常符合 Python 编程习惯的 API:

from shapely import Point, Polygon, box

# 像使用普通 Python 对象一样使用几何体
p = Point(1, 2)
print(f"x={p.x}, y={p.y}")        # 属性访问
print(f"WKT: {p}")                 # 字符串表示即 WKT
print(f"repr: {repr(p)}")          # POINT (1 2)

# 运算符重载
poly1 = box(0, 0, 2, 2)
poly2 = box(1, 1, 3, 3)

union = poly1 | poly2              # | 运算符 = union
inter = poly1 & poly2              # & 运算符 = intersection
diff = poly1 - poly2               # - 运算符 = difference
sym_diff = poly1 ^ poly2           # ^ 运算符 = symmetric_difference

# in 运算符
print(Point(1, 1) in poly1)       # 等价于 poly1.contains(Point(1, 1))

1.3.3 多线程支持

Shapely 2.0 在执行 GEOS 操作时会释放 Python 的全局解释器锁(GIL),这意味着你可以在多线程环境中高效地使用 Shapely:

import shapely
import numpy as np
from concurrent.futures import ThreadPoolExecutor

# 生成大量几何体
polygons = shapely.box(
    np.random.uniform(0, 100, 1000),
    np.random.uniform(0, 100, 1000),
    np.random.uniform(100, 200, 1000),
    np.random.uniform(100, 200, 1000)
)

# GEOS 操作在多线程中可以并行执行
# 因为 GEOS 计算时释放了 GIL
areas = shapely.area(polygons)       # 向量化操作,内部已并行
buffers = shapely.buffer(polygons, 5.0)

1.4 Shapely 在 GIS 生态中的位置

1.4.1 Python 空间数据处理生态全景

┌─────────────────────────────────────────────────────────────────┐
│                    Python GIS 生态全景                           │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  应用层                                                         │
│  ┌────────────┐  ┌──────────┐  ┌────────────┐  ┌──────────┐   │
│  │ Web GIS    │  │ 数据分析  │  │  科学计算   │  │ 可视化   │   │
│  │ (Flask/    │  │(Jupyter) │  │ (SciPy)    │  │(Folium/  │   │
│  │  Django)   │  │          │  │            │  │ Kepler)  │   │
│  └─────┬──────┘  └────┬─────┘  └─────┬──────┘  └────┬─────┘   │
│        │              │              │              │           │
│        └──────────────┼──────────────┼──────────────┘           │
│                       ▼                                         │
│  数据框架层     ┌──────────────┐                                │
│                │  GeoPandas   │  空间数据框                      │
│                └──────┬───────┘                                 │
│                       │                                         │
│  核心几何层     ┌──────▼───────┐                                │
│                │   Shapely    │  几何计算  ◄── 你在这里           │
│                └──────┬───────┘                                 │
│                       │                                         │
│  I/O 层        ┌──────▼───────┐  ┌──────────┐                  │
│                │    Fiona     │  │  pyproj   │  坐标转换         │
│                └──────┬───────┘  └──────────┘                   │
│                       │                                         │
│  底层引擎       ┌──────▼───────┐  ┌──────────┐                  │
│                │    GEOS      │  │  GDAL     │  空间数据 I/O    │
│                │   (C/C++)    │  │  (C/C++)  │                  │
│                └──────────────┘  └──────────┘                   │
└─────────────────────────────────────────────────────────────────┘

1.4.2 与相关库的关系

Shapely 与 GEOS

Shapely 是 GEOS 的 Python 绑定。GEOS 提供底层的 C/C++ 几何算法实现,Shapely 将其封装为 Pythonic 的接口。Shapely 2.0 使用 Cython 直接绑定 GEOS 的 C API,相比 1.x 的 ctypes 方式性能大幅提升。

import shapely
# 查看 GEOS 版本
print(f"GEOS 版本: {shapely.geos_version}")         # (3, 11, 2)
print(f"Shapely 版本: {shapely.__version__}")        # 2.0.x

Shapely 与 GeoPandas

GeoPandas 是基于 Pandas 和 Shapely 的空间数据框库。GeoPandas 的 geometry 列中的每个元素都是一个 Shapely 几何对象。

import geopandas as gpd
from shapely import Point

# GeoPandas 内部使用 Shapely 几何对象
gdf = gpd.GeoDataFrame({
    'name': ['北京', '上海', '广州'],
    'geometry': [Point(116.4, 39.9), Point(121.5, 31.2), Point(113.3, 23.1)]
})

# 每个元素都是 Shapely 对象
print(type(gdf.geometry[0]))  # <class 'shapely.geometry.point.Point'>

Shapely 与 Fiona

Fiona 负责地理数据文件的读写(Shapefile、GeoPackage 等),读入的几何数据可以直接转换为 Shapely 对象进行分析。

import fiona
from shapely.geometry import shape

# Fiona 读取,Shapely 分析
with fiona.open("buildings.shp") as src:
    for feature in src:
        geom = shape(feature['geometry'])  # 转为 Shapely 对象
        print(f"面积: {geom.area}")

Shapely 与 PostGIS

PostGIS 和 Shapely 共享相同的底层引擎(GEOS),因此它们的几何计算结果是一致的。Shapely 适合在 Python 中进行几何分析,而 PostGIS 适合在数据库中进行大规模空间查询。

1.4.3 关系对比表

定位 与 Shapely 的关系
GEOS C/C++ 几何引擎 Shapely 的底层引擎
JTS Java 几何引擎 GEOS 的 Java 原版,算法同源
PostGIS 空间数据库 与 Shapely 共享 GEOS 引擎
GeoPandas 空间数据框 基于 Shapely 构建
Fiona 地理文件 I/O 与 Shapely 搭配使用
pyproj 坐标转换 补充 Shapely 不具备的 CRS 转换能力
GDAL/OGR 底层空间数据 I/O Fiona 的底层引擎
matplotlib 绑图库 可用于绘制 Shapely 几何体

1.5 适用场景

1.5.1 空间数据预处理

在进行空间分析之前,通常需要对几何数据进行预处理:

from shapely import Polygon, MultiPolygon
from shapely.ops import unary_union
from shapely.validation import make_valid

# 修复无效的几何体
invalid_poly = Polygon([(0, 0), (2, 2), (2, 0), (0, 2)])  # 自交叉
valid_poly = make_valid(invalid_poly)
print(f"修复前有效: {invalid_poly.is_valid}")  # False
print(f"修复后有效: {valid_poly.is_valid}")    # True

# 合并多个几何体
polygons = [
    Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]),
    Polygon([(1, 1), (3, 1), (3, 3), (1, 3)]),
    Polygon([(2, 2), (4, 2), (4, 4), (2, 4)])
]
merged = unary_union(polygons)
print(f"合并后类型: {merged.geom_type}")

1.5.2 几何分析

from shapely import Point, Polygon, LineString

# 点在面内判断(地理围栏)
fence = Polygon([(0, 0), (10, 0), (10, 10), (0, 10)])
location = Point(5, 5)
print(f"在围栏内: {fence.contains(location)}")  # True

# 路径与区域的交集(道路穿过公园的部分)
road = LineString([(0, 5), (15, 5)])
park = Polygon([(2, 2), (8, 2), (8, 8), (2, 8)])
road_in_park = road.intersection(park)
print(f"穿过公园的路段长度: {road_in_park.length}")  # 6.0

1.5.3 Web GIS 后端

from shapely import Point, box
from shapely.geometry import mapping
import json

# GeoJSON 输出(Web API 返回)
polygon = box(0, 0, 10, 10)
geojson = mapping(polygon)
print(json.dumps(geojson, indent=2))
# {
#   "type": "Polygon",
#   "coordinates": [[[0.0, 0.0], [10.0, 0.0], [10.0, 10.0], [0.0, 10.0], [0.0, 0.0]]]
# }

# 空间查询:找到视口范围内的点
viewport = box(100, 30, 120, 40)  # 经度 100-120, 纬度 30-40
cities = [Point(116.4, 39.9), Point(121.5, 31.2), Point(113.3, 23.1)]
visible = [c for c in cities if viewport.contains(c)]
print(f"可见城市数: {len(visible)}")

1.5.4 科学计算

import numpy as np
import shapely

# 批量生成随机多边形并计算面积分布
np.random.seed(42)
n = 10000
x = np.random.uniform(0, 100, n)
y = np.random.uniform(0, 100, n)
points = shapely.points(x, y)
buffers = shapely.buffer(points, np.random.uniform(1, 10, n))
areas = shapely.area(buffers)

print(f"平均面积: {areas.mean():.2f}")
print(f"最大面积: {areas.max():.2f}")
print(f"面积标准差: {areas.std():.2f}")

1.6 快速上手示例

1.6.1 创建基本几何体

from shapely import Point, LineString, Polygon

# 创建点
p1 = Point(0, 0)
p2 = Point(3, 4)
print(f"点 p1: {p1}")               # POINT (0 0)
print(f"点 p2: {p2}")               # POINT (3 4)
print(f"两点距离: {p1.distance(p2)}")  # 5.0

# 创建线
line = LineString([(0, 0), (1, 1), (2, 0), (3, 1)])
print(f"线: {line}")
print(f"线长度: {line.length:.4f}")   # 4.2426

# 创建多边形
poly = Polygon([(0, 0), (4, 0), (4, 3), (0, 3)])
print(f"多边形: {poly}")
print(f"面积: {poly.area}")           # 12.0
print(f"周长: {poly.length}")         # 14.0
print(f"质心: {poly.centroid}")       # POINT (2 1.5)

1.6.2 缓冲区分析

from shapely import Point

# 以点为圆心创建缓冲区(近似圆)
center = Point(0, 0)
circle = center.buffer(10)
print(f"缓冲区面积: {circle.area:.2f}")  # 约 314.16(≈ π * 10²)
print(f"缓冲区顶点数: {len(circle.exterior.coords)}")  # 默认 65 个顶点

# 控制缓冲区精度
circle_low = center.buffer(10, quad_segs=4)   # 低精度
circle_high = center.buffer(10, quad_segs=64)  # 高精度
print(f"低精度面积: {circle_low.area:.2f}")
print(f"高精度面积: {circle_high.area:.2f}")

1.6.3 交集运算

from shapely import Polygon

# 两个重叠的矩形
rect1 = Polygon([(0, 0), (3, 0), (3, 3), (0, 3)])
rect2 = Polygon([(1, 1), (4, 1), (4, 4), (1, 4)])

# 交集
intersection = rect1.intersection(rect2)
print(f"交集面积: {intersection.area}")  # 4.0
print(f"交集形状: {intersection}")
# POLYGON ((1 1, 3 1, 3 3, 1 3, 1 1))

# 并集
union = rect1.union(rect2)
print(f"并集面积: {union.area}")  # 14.0

# 差集
difference = rect1.difference(rect2)
print(f"差集面积: {difference.area}")  # 5.0

# 对称差集
sym_diff = rect1.symmetric_difference(rect2)
print(f"对称差集面积: {sym_diff.area}")  # 10.0

1.6.4 综合示例:简易地理围栏检测

from shapely import Point, Polygon

# 定义围栏区域(模拟校园边界)
campus = Polygon([
    (116.32, 39.98), (116.34, 39.98),
    (116.34, 40.00), (116.32, 40.00)
])

# 模拟 GPS 定位点
locations = [
    ("小明", Point(116.33, 39.99)),   # 校园内
    ("小红", Point(116.35, 39.99)),   # 校园外
    ("小刚", Point(116.34, 39.98)),   # 边界上
]

for name, loc in locations:
    if campus.contains(loc):
        status = "在校园内 ✓"
    elif campus.touches(loc) or campus.boundary.distance(loc) < 0.0001:
        status = "在校园边界 ~"
    else:
        status = "在校园外 ✗"
    print(f"{name}: {status}")

1.7 与其他库的对比

1.7.1 Shapely vs GDAL/OGR

对比维度 Shapely GDAL/OGR
主要功能 几何计算 空间数据读写 + 基本几何操作
编程体验 Pythonic,优雅简洁 C 风格 API,较为繁琐
数据 I/O 不支持文件读写 支持 200+ 种空间数据格式
几何能力 全面的几何分析和操作 基本的几何操作
底层引擎 GEOS GEOS + 自有实现
适用场景 几何分析和处理 数据格式转换和读写

1.7.2 Shapely vs GeoPandas

对比维度 Shapely GeoPandas
抽象层级 单个几何对象 几何对象集合(GeoDataFrame)
数据管理 不管理属性数据 管理几何 + 属性数据
文件 I/O 不支持 支持 Shapefile、GeoJSON 等
依赖关系 独立 依赖 Shapely
适用场景 精细几何操作 批量空间数据分析

1.7.3 Shapely vs PostGIS

对比维度 Shapely PostGIS
运行环境 Python 进程内 PostgreSQL 数据库
数据规模 适合中小规模 适合大规模数据
引擎 GEOS GEOS(相同引擎)
并发支持 多线程 多连接并行
空间索引 STRtree GiST / SP-GiST
适用场景 脚本分析、原型开发 生产环境、大规模查询

1.7.4 互补使用模式

在实际项目中,这些库通常是互补使用的:

# 典型的 Python GIS 工作流
import fiona          # 读取空间数据文件
from shapely.geometry import shape, mapping  # 几何操作
import pyproj         # 坐标转换
import geopandas as gpd  # 空间数据框分析

# 1. 用 Fiona 读取数据
# 2. 用 Shapely 做几何计算
# 3. 用 pyproj 做坐标转换
# 4. 用 GeoPandas 管理数据和批量操作
# 5. 用 matplotlib 可视化结果

1.8 本章小结

本章我们学习了:

  • Shapely 是什么:一个基于 BSD 许可的 Python 几何操作库,专注于二维笛卡尔平面几何计算
  • 技术渊源:JTS → GEOS → Shapely 的技术传承链
  • 设计理念:专注几何计算、Pythonic API、多线程支持
  • 生态位置:与 GEOS、GeoPandas、Fiona、PostGIS 的关系
  • 版本演进:Shapely 2.0 带来了不可变几何体、向量化操作和 NumPy 集成
  • 适用场景:空间预处理、几何分析、Web 后端、科学计算
  • 快速上手:创建点线面、缓冲区、交集运算

下一章我们将详细介绍 Shapely 的安装与环境配置。