2019-JTS-Design-Principles
JTS 设计原则
原文:JTS Design Principles
作者:Martin Davis
日期:2019年2月
概述
JTS(Java Topology Suite)作为一个成熟的空间几何库,其成功很大程度上归功于其设计原则。本文探讨了指导 JTS 开发的核心设计理念,这些原则使 JTS 成为可靠、易用且一致的空间操作库。
核心原则:几何统一性
"无意外"原则
JTS 的首要设计原则是几何统一性(Geometric Uniformity),也被称为"无意外"原则(No Surprises)。
核心理念:
在可能的情况下,空间操作应该泛化到适用于所有几何类型,确保一致性和可预测性。
为什么重要?
- 减少边界情况:不同几何类型使用相同的操作逻辑
- 简化学习:用户只需学习一套 API
- 可预测行为:相同操作在不同几何类型上有一致的表现
- 减少 bug:代码复用减少了出错的可能
设计原则详解
原则1:操作的通用性
JTS 的操作设计为尽可能通用:
// 缓冲区操作适用于所有几何类型
Geometry point = factory.createPoint(new Coordinate(0, 0));
Geometry line = factory.createLineString(...);
Geometry polygon = factory.createPolygon(...);
// 相同的方法,不同的几何类型
Geometry pointBuffer = point.buffer(10); // 圆形
Geometry lineBuffer = line.buffer(10); // 腊肠形
Geometry polygonBuffer = polygon.buffer(10); // 扩展的多边形
原则2:一致的语义
相同操作在所有几何类型上有一致的语义:
// 交集操作的一致性
Geometry a = ...; // 可以是点、线或多边形
Geometry b = ...; // 可以是点、线或多边形
// 无论 a 和 b 是什么类型,intersection() 都返回合理的结果
Geometry result = a.intersection(b);
// 结果类型可能是:
// - Point(如果只在一点相交)
// - LineString(如果沿线相交)
// - Polygon(如果区域重叠)
// - GeometryCollection(如果有多种类型的相交)
原则3:避免类型特定的方法
JTS 避免为不同几何类型创建不同的方法:
// 不好的设计(JTS 不这样做)
// pointIntersectsPolygon(Point p, Polygon poly)
// lineIntersectsPolygon(Line l, Polygon poly)
// polygonIntersectsPolygon(Polygon p1, Polygon p2)
// JTS 的设计
// 一个方法适用于所有情况
boolean result = geomA.intersects(geomB);
原则4:明确的行为
对于可能有歧义的操作,JTS 选择最明确、最一致的行为:
// 空几何的处理
Geometry empty = factory.createGeometryCollection(new Geometry[0]);
Geometry other = ...;
// 空几何与任何几何的并集是那个几何
Geometry union = empty.union(other); // 返回 other 的副本
// 空几何与任何几何的交集是空
Geometry intersection = empty.intersection(other); // 返回空几何
实际应用
统一的谓词接口
// 所有空间谓词都适用于所有几何类型
public void checkSpatialRelations(Geometry a, Geometry b) {
// 这些方法对所有几何类型都有效
boolean touches = a.touches(b);
boolean intersects = a.intersects(b);
boolean within = a.within(b);
boolean contains = a.contains(b);
boolean crosses = a.crosses(b);
boolean overlaps = a.overlaps(b);
boolean equals = a.equals(b);
boolean disjoint = a.disjoint(b);
}
统一的构造操作
// 构造操作也是通用的
public void constructiveOperations(Geometry a, Geometry b) {
// 这些操作对所有几何类型组合都有效
Geometry union = a.union(b);
Geometry intersection = a.intersection(b);
Geometry difference = a.difference(b);
Geometry symDifference = a.symDifference(b);
// 缓冲区
Geometry buffer = a.buffer(10);
// 凸包
Geometry convexHull = a.convexHull();
}
与 OGC 标准的关系
JTS 的设计原则与 OGC(开放地理空间联盟)Simple Features 规范高度一致:
| OGC 概念 | JTS 实现 |
|---|---|
| 几何类型层次 | Geometry 抽象基类 |
| 空间关系 | DE-9IM 模型 |
| 空间操作 | 标准化方法 |
// JTS 完全实现 OGC Simple Features
// 几何类型层次
// Geometry
// ├── Point
// ├── LineString
// │ └── LinearRing
// ├── Polygon
// └── GeometryCollection
// ├── MultiPoint
// ├── MultiLineString
// └── MultiPolygon
对用户的意义
简化的 API 学习
// 用户只需学习一套通用的方法
// 不需要记住每种几何类型的特殊方法
Geometry geom = ...; // 可以是任何几何类型
// 总是可用的标准方法
geom.getGeometryType();
geom.isEmpty();
geom.isValid();
geom.getArea();
geom.getLength();
geom.buffer(distance);
geom.convexHull();
geom.intersection(other);
// ... 等等
更健壮的代码
// 代码可以处理任意几何类型
public void processGeometry(Geometry geom) {
// 无需检查几何类型
// 所有操作都适用
if (geom.intersects(targetArea)) {
Geometry clipped = geom.intersection(targetArea);
processResult(clipped);
}
}
更好的错误处理
// JTS 对边界情况有一致的处理
public Geometry safeIntersection(Geometry a, Geometry b) {
// 即使输入为空或类型不同,也能正常工作
return a.intersection(b);
// 不需要特殊处理:
// - 空几何
// - 不同维度的几何
// - 混合类型的集合
}
设计原则的演进
JTS 的设计原则随时间演进,但核心理念保持不变:
| 版本 | 改进 |
|---|---|
| 早期 | 建立基本的几何统一性 |
| 中期 | 增强边界情况处理 |
| 现代 | OverlayNG、RelateNG 等更鲁棒的实现 |
对其他库的影响
JTS 的设计原则影响了许多其他空间库:
- GEOS:C++ 移植版本,保持相同原则
- Shapely:Python 库,基于 GEOS
- NetTopologySuite:.NET 移植版本
- PostGIS:通过 GEOS 间接应用这些原则
总结
JTS 的设计原则——几何统一性和"无意外"——是其成功的关键因素。这些原则使 JTS 成为一个易于学习、使用可靠、行为可预测的空间几何库。无论您使用的是 JTS、GEOS、Shapely 还是 NetTopologySuite,这些设计原则都使空间编程更加简单和一致。

浙公网安备 33010602011771号