04-空间关系分析
空间关系分析
概述
空间关系分析是GIS的核心功能之一。通过判断几何对象之间的空间关系,可以实现空间查询、叠加分析、选址分析等常见GIS功能。
基本空间关系
相交(Intersects)
两个几何对象有任意公共部分(点、线或面)时,称为相交:
/**
* 判断几何是否相交
*/
public static boolean intersects(Geometry a, Geometry b) {
return a.intersects(b);
}
应用场景:
- 空间查询:找出与指定区域相交的所有要素
- 碰撞检测:判断两个对象是否发生空间重叠
- 路线规划:判断路线是否经过某个区域
相离(Disjoint)
两个几何对象没有任何公共点时,称为相离:
/**
* 判断几何是否相离
* 一个公共点都没有
*/
public static boolean disjoint(Geometry a, Geometry b) {
return a.disjoint(b);
}
说明:disjoint与intersects互为反义关系,即:
disjoint(a, b) == !intersects(a, b)
接触(Touches)
两个几何对象有公共点但没有公共内部区域时,称为接触:
/**
* 判断几何是否接触
* 有公共点但没有公共区域
*/
public static boolean touches(Geometry a, Geometry b) {
return a.touches(b);
}
典型情况:
- 两个相邻的地块共享边界
- 道路与地块的边界相接
- 点落在线或面的边界上
交叉(Crosses)
两个几何对象的内部有公共部分,但既不相等也不包含,称为交叉:
/**
* 判断几何是否交叉
* 有公共区域但不是包含关系
*/
public static boolean crosses(Geometry a, Geometry b) {
return a.crosses(b);
}
典型情况:
- 道路穿过区域(线与面交叉)
- 两条道路相交(线与线交叉)
包含(Contains)与被包含(Within)
包含关系描述一个几何完全位于另一个几何内部:
/**
* 判断几何A是否包含几何B
*/
public static boolean contains(Geometry a, Geometry b) {
return a.contains(b);
}
/**
* 判断几何A是否在几何B内部
*/
public static boolean within(Geometry a, Geometry b) {
return a.within(b);
}
关系说明:
contains(a, b) == within(b, a)
应用场景:
- 判断点是否在某个区域内
- 判断某个地块是否完全位于行政区划内
- 空间过滤:只保留完全落入指定范围的要素
重叠(Overlaps)
两个同维度的几何对象有公共区域,但又不完全相同,称为重叠:
/**
* 判断几何是否重叠
* 有公共区域且包含关系不成立
*/
public static boolean overlaps(Geometry a, Geometry b) {
return a.overlaps(b);
}
说明:重叠只发生在同维度几何之间(面与面、线与线)。
距离计算
最短距离
计算两个几何对象之间的最短距离:
/**
* 计算几何之间的距离
* 不论点线面都是几何间最短距离
*/
public static double distance(Geometry a, Geometry b) {
return a.distance(b);
}
注意:返回值的单位与坐标系单位一致。地理坐标系返回的是度,投影坐标系返回的是米。
距离判断
快速判断两个几何是否在指定距离内:
/**
* 判断几何间最短距离是否小于给定距离
*/
public static boolean isWithinDistance(Geometry a, Geometry b, double distance) {
return a.isWithinDistance(b, distance);
}
应用场景:
- 近邻搜索:查找指定距离内的设施
- 缓冲区分析:判断要素是否在某要素的影响范围内
- 预警系统:判断两个移动目标是否过于接近
DE-9IM模型
DE-9IM(Dimensionally Extended 9-Intersection Model)是空间关系的标准描述模型,提供了更精确的空间关系判断。
关系矩阵
Interior Boundary Exterior
Interior II IB IE
Boundary BI BB BE
Exterior EI EB EE
每个位置的值表示两个几何对应部分的交集维度:
T:有交集(任意维度)F:无交集0:交集为点1:交集为线2:交集为面*:任意(不关心)
获取关系矩阵
/**
* 获取几何关系矩阵
*/
public static String relate(Geometry a, Geometry b) {
return a.relate(b).toString();
}
模式匹配
使用模式字符串判断特定空间关系:
/**
* 判断几何是否符合给定关系
* @param pattern 关系模式,如"T*T***FF*"
*/
public static boolean relatePattern(Geometry a, Geometry b, String pattern) {
return a.relate(b, pattern);
}
常用模式:
| 关系 | 模式 |
|---|---|
| 内部相交 | T******** |
| 边界相交 | *T******* |
| A完全包含B | T*****FF* |
| 相邻(共享边界) | FF*FT**** |
几何相等判断
精确相等
判断两个几何是否结构完全相同:
/**
* 判断几何是否对象结构相等
* 必须有相同的节点和相同的节点顺序
*/
public static boolean equalsExact(Geometry a, Geometry b) {
return a.equalsExact(b);
}
/**
* 带容差的结构相等判断
*/
public static boolean equalsExactTolerance(Geometry a, Geometry b, double tolerance) {
return a.equalsExact(b, tolerance);
}
规范化相等
判断两个几何在规范化后是否相同:
/**
* 判断几何是否对象结构相等(不判断节点顺序)
*/
public static boolean equalsNorm(Geometry a, Geometry b) {
return a.equalsNorm(b);
}
拓扑相等
判断两个几何是否表示相同的点集:
/**
* 判断几何是否拓扑相等
*/
public static boolean equalsTopo(Geometry a, Geometry b) {
return a.equalsTopo(b);
}
区别说明:
equalsExact:节点顺序、数量都必须完全相同equalsNorm:规范化后比较,忽略节点顺序equalsTopo:只比较几何表示的空间是否相同
ESRI几何引擎
除了JTS,还可以使用ESRI几何引擎进行空间关系分析,其API基于WKT字符串:
空间关系判断
/**
* 几何是否相交
*/
public static boolean intersects(String awkt, String bwkt, Integer wkid) {
Geometry a = EsriUtil.createGeometryByWkt(awkt);
Geometry b = EsriUtil.createGeometryByWkt(bwkt);
SpatialReference sr = SpatialReference.create(wkid);
return OperatorIntersects.local().execute(a, b, sr, null);
}
/**
* 判断几何是否相离
*/
public static boolean disjoint(String awkt, String bwkt, Integer wkid) {
Geometry a = EsriUtil.createGeometryByWkt(awkt);
Geometry b = EsriUtil.createGeometryByWkt(bwkt);
SpatialReference sr = SpatialReference.create(wkid);
return OperatorDisjoint.local().execute(a, b, sr, null);
}
/**
* 判断几何是否接触
*/
public static boolean touches(String awkt, String bwkt, Integer wkid) {
Geometry a = EsriUtil.createGeometryByWkt(awkt);
Geometry b = EsriUtil.createGeometryByWkt(bwkt);
SpatialReference sr = SpatialReference.create(wkid);
return OperatorTouches.local().execute(a, b, sr, null);
}
/**
* 判断几何是否包含
*/
public static boolean contains(String awkt, String bwkt, Integer wkid) {
Geometry a = EsriUtil.createGeometryByWkt(awkt);
Geometry b = EsriUtil.createGeometryByWkt(bwkt);
SpatialReference sr = SpatialReference.create(wkid);
return OperatorContains.local().execute(a, b, sr, null);
}
选择建议:
- JTS:内存中的几何对象操作,性能更好
- ESRI:基于WKT字符串操作,接口更简洁
实践案例
案例1:空间查询
查找与指定区域相交的所有要素:
/**
* 空间查询:找出与指定区域相交的要素
*/
public List<WktFeature> spatialQuery(WktLayer layer, String queryWkt) {
List<WktFeature> result = new ArrayList<>();
Geometry queryGeom = GeometryConverter.wkt2Geometry(queryWkt);
for (WktFeature feature : layer.getFeatures()) {
Geometry featureGeom = GeometryConverter.wkt2Geometry(feature.getWkt());
if (featureGeom.intersects(queryGeom)) {
result.add(feature);
}
}
return result;
}
案例2:点在面内判断
判断一个点是否位于某个多边形内部:
/**
* 判断点是否在面内
*/
public boolean isPointInPolygon(double x, double y, String polygonWkt) {
GeometryFactory factory = new GeometryFactory();
Point point = factory.createPoint(new Coordinate(x, y));
Geometry polygon = GeometryConverter.wkt2Geometry(polygonWkt);
// 使用contains判断(严格在内部)
// 或使用intersects判断(含边界上的点)
return polygon.contains(point);
}
案例3:相邻要素查找
查找与指定要素相邻(共享边界)的所有要素:
/**
* 查找相邻要素
*/
public List<WktFeature> findAdjacentFeatures(WktLayer layer, WktFeature target) {
List<WktFeature> result = new ArrayList<>();
Geometry targetGeom = GeometryConverter.wkt2Geometry(target.getWkt());
for (WktFeature feature : layer.getFeatures()) {
if (feature.getWfId().equals(target.getWfId())) {
continue; // 跳过自己
}
Geometry featureGeom = GeometryConverter.wkt2Geometry(feature.getWkt());
// 相邻:接触但不重叠
if (featureGeom.touches(targetGeom)) {
result.add(feature);
}
}
return result;
}
案例4:缓冲区范围查询
查找指定位置周边一定距离内的设施:
/**
* 缓冲区范围查询
* @param centerWkt 中心点WKT
* @param distance 查询距离(米)
* @param layer 要素图层
*/
public List<WktFeature> bufferQuery(String centerWkt, double distance, WktLayer layer) {
List<WktFeature> result = new ArrayList<>();
// 转换到投影坐标系计算缓冲区
int projWkid = CrsUtil.getProjectedWkid(CrsUtil.getDh(centerWkt));
String projWkt = CrsUtil.transform(centerWkt, 4490, projWkid);
// 创建缓冲区
Geometry center = GeometryConverter.wkt2Geometry(projWkt);
Geometry buffer = center.buffer(distance);
// 将缓冲区转回地理坐标系进行查询
buffer = CrsUtil.transform(buffer, projWkid, layer.getWkid());
// 查询相交要素
for (WktFeature feature : layer.getFeatures()) {
Geometry featureGeom = GeometryConverter.wkt2Geometry(feature.getWkt());
if (featureGeom.intersects(buffer)) {
result.add(feature);
}
}
return result;
}
案例5:空间关系矩阵分析
使用DE-9IM进行精确的空间关系分析:
/**
* 分析两个地块的空间关系
*/
public String analyzeRelation(String wkt1, String wkt2) {
Geometry geom1 = GeometryConverter.wkt2Geometry(wkt1);
Geometry geom2 = GeometryConverter.wkt2Geometry(wkt2);
// 获取关系矩阵
String matrix = relate(geom1, geom2);
// 解析关系类型
if (geom1.equals(geom2)) {
return "相等";
} else if (geom1.contains(geom2)) {
return "A包含B";
} else if (geom1.within(geom2)) {
return "A在B内";
} else if (geom1.overlaps(geom2)) {
return "部分重叠";
} else if (geom1.touches(geom2)) {
return "相邻(共享边界)";
} else if (geom1.crosses(geom2)) {
return "穿越";
} else if (geom1.intersects(geom2)) {
return "相交";
} else {
return "相离";
}
}
性能优化
空间索引
对于大数据量的空间查询,使用空间索引可以显著提升性能:
// 构建R树索引
STRtree index = new STRtree();
for (WktFeature feature : layer.getFeatures()) {
Geometry geom = GeometryConverter.wkt2Geometry(feature.getWkt());
index.insert(geom.getEnvelopeInternal(), feature);
}
index.build();
// 使用索引查询
Geometry queryGeom = GeometryConverter.wkt2Geometry(queryWkt);
List<?> candidates = index.query(queryGeom.getEnvelopeInternal());
// 对候选要素进行精确判断
for (Object obj : candidates) {
WktFeature feature = (WktFeature) obj;
Geometry featureGeom = GeometryConverter.wkt2Geometry(feature.getWkt());
if (featureGeom.intersects(queryGeom)) {
// 真正相交的要素
}
}
外包矩形预筛选
在进行精确空间关系判断前,先用外包矩形快速过滤:
// 先判断外包矩形是否相交
if (!geomA.getEnvelopeInternal().intersects(geomB.getEnvelopeInternal())) {
return false; // 外包矩形不相交,几何必定不相交
}
// 再进行精确判断
return geomA.intersects(geomB);
小结
本章介绍了空间关系分析的核心内容:
- 基本空间关系:相交、相离、接触、交叉、包含、重叠
- 距离计算:最短距离计算和距离判断
- DE-9IM模型:精确的空间关系描述和模式匹配
- 几何相等:精确相等、规范化相等、拓扑相等
- 性能优化:空间索引和外包矩形预筛选
下一章将介绍空间计算操作,学习如何进行缓冲区分析、叠加分析等操作。

浙公网安备 33010602011771号