| name | geometry-api-java |
| description | Esri Geometry API for Java 是一个自包含的空间几何计算库,提供对二维和三维几何对象的创建、解析、序列化以及空间关系运算能力。 |
| tags | ["java","geometry","esri","spatial","wkt","wkb","geojson","geodesic"] |
项目地址: https://github.com/Esri/geometry-api-java
Maven Central: com.esri.geometry:esri-geometry-api
许可证: Apache License 2.0
概述
Esri Geometry API for Java 是一个自包含的空间几何计算库,提供对二维和三维几何对象的创建、解析、序列化以及空间关系运算能力。它无需任何外部 GIS 依赖,可直接嵌入 Java 应用、Hadoop MapReduce、Hive UDF、Spark 等大数据处理框架中。
快速集成
Maven
<dependency>
<groupId>com.esri.geometry</groupId>
<artifactId>esri-geometry-api</artifactId>
<version>2.2.4</version>
</dependency>
Gradle
implementation 'com.esri.geometry:esri-geometry-api:2.2.4'
环境要求: JDK 1.7+;运行时依赖 jackson-core(JSON 处理)。
维护状态提示: esri-geometry-api 最新版本仍为 2.2.4(2020-09),已多年未更新。若需活跃维护的几何库,新项目建议优先选用 JTS(Java)或 NetTopologySuite(.NET)。
核心类一览
| 类 | 包 | 用途 |
|---|
GeometryEngine | com.esri.core.geometry | 推荐入口——提供几何操作的静态便捷方法 |
OperatorFactoryLocal | com.esri.core.geometry | 算子工厂,适用于高性能批量处理 |
SpatialReference | com.esri.core.geometry | 空间参考 / 坐标系(通过 WKID 或 WKT 创建) |
MapGeometry | com.esri.core.geometry | 将 Geometry 与 SpatialReference 打包在一起 |
Point | com.esri.core.geometry | 点(0 维) |
MultiPoint | com.esri.core.geometry | 多点集合(0 维) |
Polyline | com.esri.core.geometry | 折线 / 路径集合(1 维) |
Polygon | com.esri.core.geometry | 面 / 环集合(2 维) |
Envelope | com.esri.core.geometry | 外接矩形(2 维) |
几何对象创建
import com.esri.core.geometry.*;
Point pt = new Point(116.4, 39.9);
Point pt3d = new Point(116.4, 39.9, 50.0);
Polyline line = new Polyline();
line.startPath(0, 0);
line.lineTo(10, 10);
line.lineTo(20, 0);
Polygon polygon = new Polygon();
polygon.startPath(0, 0);
polygon.lineTo(10, 0);
polygon.lineTo(10, 10);
polygon.lineTo(0, 10);
Envelope env = new Envelope(0, 0, 10, 10);
MultiPoint mp = new MultiPoint();
mp.add(1, 2);
mp.add(3, 4);
空间参考
SpatialReference srWGS84 = SpatialReference.create(4326);
SpatialReference srCustom = SpatialReference.create("GEOGCS[\"GCS_WGS_1984\",...]]");
MapGeometry mapGeom = new MapGeometry(pt, srWGS84);
空间操作(通过 GeometryEngine)
集合运算
SpatialReference sr = SpatialReference.create(4326);
Geometry buffered = GeometryEngine.buffer(point, sr, 100.0);
Geometry inter = GeometryEngine.intersect(polygon1, polygon2, sr);
Geometry united = GeometryEngine.union(new Geometry[]{poly1, poly2, poly3}, sr);
Geometry diff = GeometryEngine.difference(polygon1, polygon2, sr);
Geometry symDiff = GeometryEngine.symmetricDifference(geom1, geom2, sr);
Geometry clipped = GeometryEngine.clip(geometry, envelope, sr);
Geometry[] parts = GeometryEngine.cut(polygon, cuttingLine, sr);
距离与邻近
double dist = GeometryEngine.distance(geom1, geom2, sr);
空间关系判断
boolean eq = GeometryEngine.equals(g1, g2, sr);
boolean wn = GeometryEngine.within(point, polygon, sr);
boolean ct = GeometryEngine.contains(polygon, point, sr);
boolean ix = GeometryEngine.intersects(g1, g2, sr);
boolean dj = GeometryEngine.disjoint(g1, g2, sr);
boolean tc = GeometryEngine.touches(g1, g2, sr);
boolean cr = GeometryEngine.crosses(line, polygon, sr);
boolean ol = GeometryEngine.overlaps(poly1, poly2, sr);
boolean rel = GeometryEngine.relate(g1, g2, sr, "T*F**FFF*");
几何分析
Geometry hull = GeometryEngine.convexHull(geometry);
Geometry simplified = GeometryEngine.simplify(geometry, sr);
Geometry generalized = GeometryEngine.generalize(geometry, maxDeviation, true, sr);
Point centroid = GeometryEngine.getLabelPoint(polygon, sr);
大地测量(椭球面计算)
Geometry geoBuffer = GeometryEngine.geodesicBuffer(geometry, sr, 1000.0);
double geoLen = GeometryEngine.geodesicLength(polyline, sr, null);
double geoArea = GeometryEngine.geodesicArea(polygon, sr, null);
格式转换
JSON(Esri JSON)
MapGeometry mg = GeometryEngine.jsonToGeometry(jsonString);
Geometry geom = mg.getGeometry();
SpatialReference sr = mg.getSpatialReference();
String json = GeometryEngine.geometryToJson(4326, geometry);
GeoJSON
MapGeometry mg = GeometryEngine.geoJsonToGeometry(geoJsonString, 0, Geometry.Type.Unknown);
String geoJson = GeometryEngine.geometryToGeoJson(geometry);
WKT(Well-Known Text)
Geometry geom = GeometryEngine.geometryFromWkt(
"POLYGON((0 0,10 0,10 10,0 10,0 0))",
0,
Geometry.Type.Polygon
);
String wkt = GeometryEngine.geometryToWkt(geometry, 0);
WKB(Well-Known Binary)
Geometry geom = GeometryEngine.geometryFromWkb(byteBuffer, Geometry.Type.Unknown);
ByteBuffer wkb = GeometryEngine.geometryToWkb(geometry, 0);
Esri Shape
Geometry geom = GeometryEngine.geometryFromEsriShape(byteBuffer, Geometry.Type.Polygon);
byte[] shape = GeometryEngine.geometryToEsriShape(geometry);
高级用法:Operator 直接调用
当需要批量处理大量几何对象时,使用 OperatorFactoryLocal 获取算子并配合 GeometryCursor 可获得更好的性能:
OperatorFactoryLocal factory = OperatorFactoryLocal.getInstance();
OperatorBuffer bufferOp = (OperatorBuffer) factory.getOperator(Operator.Type.Buffer);
SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geometryArray);
double[] distances = {100.0};
GeometryCursor resultCursor = bufferOp.execute(inputCursor, sr, distances, false, null);
Geometry result;
while ((result = resultCursor.next()) != null) {
}
几何类型判断
Geometry.Type type = geometry.getType();
switch (type) {
case Point: Point p = (Point) geometry; break;
case Polygon: Polygon pg = (Polygon) geometry; break;
case Polyline: Polyline pl = (Polyline) geometry; break;
case MultiPoint: MultiPoint mp = (MultiPoint) geometry; break;
case Envelope: Envelope ev = (Envelope) geometry; break;
}
boolean isPoint = Geometry.isPoint(type.value());
boolean isLinear = Geometry.isLinear(type.value());
boolean isArea = Geometry.isArea(type.value());
顶点属性(Z / M / ID)
geometry.hasZ();
geometry.hasM();
geometry.hasID();
geometry.addAttribute(VertexDescription.Semantics.Z);
geometry.addAttribute(VertexDescription.Semantics.M);
典型应用场景
| 场景 | 关键方法 |
|---|
| 地理围栏 / 点在面内判断 | GeometryEngine.contains() 或 within() |
| 计算两点距离 | GeometryEngine.distance() 或 geodesicLength() |
| 创建缓冲区(如 POI 周边范围) | GeometryEngine.buffer() 或 geodesicBuffer() |
| 面求交 / 叠加分析 | GeometryEngine.intersect() / union() / difference() |
| 坐标格式互转 | jsonToGeometry() / geometryToGeoJson() / geometryFromWkt() 等 |
| 几何有效性检查与修复 | GeometryEngine.simplify() |
| Hadoop / Spark 空间处理 | 搭配 Operator + GeometryCursor 批量处理 |
常见注意事项
- 坐标系一致:进行空间运算前,确保所有几何对象使用相同的
SpatialReference。
- 简化几何:导入外部数据后,使用
GeometryEngine.simplify() 确保拓扑正确。
- 大地测量 vs 平面:对地理坐标(经纬度)执行面积/长度计算时,优先使用
geodesicArea() / geodesicLength() 以获得椭球面精确结果。
- 性能优化:批量操作建议使用
OperatorFactoryLocal + GeometryCursor,而非逐个调用 GeometryEngine 静态方法。
- 线程安全:
GeometryEngine 的静态方法是线程安全的。
AI 使用建议
推荐工作流
- 创建几何对象:使用
Point、Polyline、Polygon 等构造函数创建几何
- 设置空间参考:通过
SpatialReference.create(wkid) 指定坐标系
- 空间运算:优先使用
GeometryEngine 静态方法(线程安全、API 简洁);批量处理使用 OperatorFactoryLocal + GeometryCursor
- 格式转换:使用
GeometryEngine.geometryToGeoJson() / geometryFromWkt() 等方法进行 WKT、WKB、GeoJSON、Esri JSON 互转
- 大地测量:对地理坐标(经纬度)的面积/长度计算,使用
geodesicArea() / geodesicLength() / geodesicBuffer() 获得椭球面精确结果
关键注意事项
- 坐标系一致:进行空间运算前,确保所有几何对象使用相同的
SpatialReference
- 简化几何:导入外部数据后,使用
GeometryEngine.simplify() 确保拓扑正确
- 大地测量 vs 平面:地理坐标系下距离/面积计算优先使用大地测量方法
- 性能优化:批量操作使用
OperatorFactoryLocal + GeometryCursor,而非逐个调用 GeometryEngine 静态方法
- 线程安全:
GeometryEngine 静态方法是线程安全的;Operator 实例非线程安全
相关技能
参考链接