成都高端建设网站浙江seo推广
JTS 中的几何关系判断方法
JTS Topology Suite 是 GeoTools 的核心依赖,提供了处理几何对象(如点、线、面)及其空间关系的工具。JTS 的空间关系判断基于 DE-9IM(Dimensionally Extended 9-Intersection Model),通过比较两个几何对象的内部、边界和外部的交集来确定它们的空间关系。以下是 JTS 中常用的空间关系判断方法:
核心方法
- intersects():判断两个几何对象是否相交(至少有一个公共点)。
- contains():判断一个几何对象是否完全包含另一个几何对象(后者所有点都在前者内部)。
- within():判断一个几何对象是否完全位于另一个几何对象内部(与 contains() 互为逆关系)。
- overlaps():判断两个几何对象是否部分重叠(有公共部分,但互不完全包含)。
- touches():判断两个几何对象是否仅在边界接触(无内部交集)。
- disjoint():判断两个几何对象是否完全分离(无任何公共点)。
- covers():判断一个几何对象是否覆盖另一个几何对象(后者所有点在前者内部或边界上,较 contains() 宽松)。
- coveredBy():判断一个几何对象是否被另一个几何对象覆盖(与 covers() 互为逆关系)。
方法特点
- 这些方法返回 boolean 值,表示空间关系是否成立。
- 基于 DE-9IM 模型,支持点、线、面等多种几何类型。
- 性能高效,适合大规模空间分析。
空间关系判断示例
我们将通过 GeoTools 和 JTS 实现以下空间关系判断示例:
- 判断一个点是否在一个多边形(面)内。
- 判断两条线是否相交。
- 判断两个多边形是否接触。
项目设置
-
添加依赖:在 Maven 项目中添加 GeoTools 和 JTS 依赖:
<dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>24.0</version> </dependency> <dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.18.2</version> </dependency> <repository><id>osgeo</id><url>https://repo.osgeo.org/repository/release/</url> </repository>
-
开发环境:Java 11+,IDE(如 IntelliJ 或 Eclipse)。
示例代码
以下代码展示如何使用 JTS 的几何关系判断方法:
import org.locationtech.jts.geom.*;
import org.locationtech.jts.io.WKTReader;public class SpatialRelationshipExample {public static void main(String[] args) throws Exception {// 初始化 WKTReader 用于解析几何WKTReader wktReader = new WKTReader(new GeometryFactory());// 示例 1:判断点是否在多边形内Point point = (Point) wktReader.read("POINT (1 1)");Polygon polygon = (Polygon) wktReader.read("POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))");boolean isPointInPolygon = polygon.contains(point);System.out.println("Point is in Polygon: " + isPointInPolygon); // 应输出 true// 示例 2:判断两条线是否相交LineString line1 = (LineString) wktReader.read("LINESTRING (0 0, 2 2)");LineString line2 = (LineString) wktReader.read("LINESTRING (0 2, 2 0)");boolean doLinesIntersect = line1.intersects(line2);System.out.println("Lines intersect: " + doLinesIntersect); // 应输出 true// 示例 3:判断两个多边形是否接触Polygon polygon1 = (Polygon) wktReader.read("POLYGON ((0 0, 0 2, 2 2, 2 0, 0 0))");Polygon polygon2 = (Polygon) wktReader.read("POLYGON ((2 0, 2 2, 4 2, 4 0, 2 0))");boolean doPolygonsTouch = polygon1.touches(polygon2);System.out.println("Polygons touch: " + doPolygonsTouch); // 应输出 true}
}
代码说明
- WKTReader:用于从 WKT(Well-Known Text)字符串创建几何对象,便于测试。
- GeometryFactory:JTS 的工厂类,用于构造几何对象。
- contains():检查点 (1, 1) 是否在多边形内(结果为 true)。
- intersects():检查两条线是否相交(交叉点为 (1, 1),结果为 true)。
- touches():检查两个多边形是否仅在边界接触(共享边,结果为 true)。
输出结果
运行代码将输出:
Point is in Polygon: true
Lines intersect: true
Polygons touch: true
扩展:使用 GeoTools 的 SimpleFeature
在 GeoTools 中,几何数据通常存储在 SimpleFeature 中。以下示例展示如何从 SimpleFeature 提取几何并进行空间关系判断:
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.locationtech.jts.geom.*;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;public class FeatureSpatialRelationshipExample {public static void main(String[] args) {// 创建 SimpleFeatureTypeSimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder();typeBuilder.setName("Location");typeBuilder.setCRS(DefaultGeographicCRS.WGS84);typeBuilder.add("geometry", Geometry.class);SimpleFeatureType type = typeBuilder.buildFeatureType();// 创建 SimpleFeatureBuilderSimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(type);GeometryFactory geometryFactory = new GeometryFactory();// 创建点要素Point point = geometryFactory.createPoint(new Coordinate(1, 1));featureBuilder.add(point);SimpleFeature pointFeature = featureBuilder.buildFeature("point.1");// 创建多边形要素Polygon polygon = geometryFactory.createPolygon(new Coordinate[] {new Coordinate(0, 0), new Coordinate(0, 2),new Coordinate(2, 2), new Coordinate(2, 0),new Coordinate(0, 0)});featureBuilder.add(polygon);SimpleFeature polygonFeature = featureBuilder.buildFeature("polygon.1");// 提取几何并判断关系Geometry pointGeom = (Geometry) pointFeature.getDefaultGeometry();Geometry polygonGeom = (Geometry) polygonFeature.getDefaultGeometry();boolean isPointInPolygon = polygonGeom.contains(pointGeom);System.out.println("Point Feature is in Polygon Feature: " + isPointInPolygon); // 输出 true}
}
此示例展示了如何结合 GeoTools 的 SimpleFeature 和 JTS 的空间关系判断,适用于从数据存储(如 Shapefile)加载的要素。
应用场景:检查设施是否在特定区域内
空间关系判断在 GIS 应用中有广泛用途。一个典型场景是 检查某个设施(如医院、加油站)是否位于特定区域(如行政区划、洪水风险区)内。以下是具体应用:
场景描述
- 数据:
- 设施数据集:包含设施位置(点几何)和属性(如名称)。
- 区域数据集:包含行政区划或风险区域(多边形几何)。
- 任务:判断哪些设施位于特定区域内。
- 方法:使用 contains() 或 within() 检查设施点是否在区域多边形内。
示例代码:检查设施位置
假设我们有一个 Shapefile 包含设施点(facilities.shp)和一个多边形区域(zone.shp),以下代码实现检查:
import org.geotools.data.DataStore;
import org.geotools.data.DataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FacilityInZoneExample {public static void main(String[] args) throws Exception {// 加载设施数据File facilitiesFile = new File("facilities.shp");Map<String, Object> facilitiesParams = new HashMap<>();facilitiesParams.put("url", facilitiesFile.toURI().toURL());DataStore facilitiesStore = DataStoreFinder.getDataStore(facilitiesParams);SimpleFeatureSource facilitiesSource = facilitiesStore.getFeatureSource(facilitiesStore.getTypeNames()[0]);SimpleFeatureCollection facilities = facilitiesSource.getFeatures();// 加载区域数据(假设只有一个多边形)File zoneFile = new File("zone.shp");Map<String, Object> zoneParams = new HashMap<>();zoneParams.put("url", zoneFile.toURI().toURL());DataStore zoneStore = DataStoreFinder.getDataStore(zoneParams);SimpleFeatureSource zoneSource = zoneStore.getFeatureSource(zoneStore.getTypeNames()[0]);SimpleFeatureCollection zones = zoneSource.getFeatures();SimpleFeature zoneFeature = zones.features().next(); // 取第一个区域Geometry zoneGeometry = (Geometry) zoneFeature.getDefaultGeometry();// 检查设施是否在区域内List<String> facilitiesInZone = new ArrayList<>();try (SimpleFeatureIterator iterator = facilities.features()) {while (iterator.hasNext()) {SimpleFeature facility = iterator.next();Geometry facilityGeometry = (Geometry) facility.getDefaultGeometry();if (zoneGeometry.contains(facilityGeometry)) {String facilityName = (String) facility.getAttribute("name");facilitiesInZone.add(facilityName);}}}// 输出结果System.out.println("Facilities in Zone: " + facilitiesInZone);// 清理资源facilitiesStore.dispose();zoneStore.dispose();}
}
说明
- 数据加载:使用 DataStoreFinder 加载 Shapefile 数据。
- 几何提取:从 SimpleFeature 中获取设施点和区域多边形的几何。
- contains():检查每个设施点是否在区域多边形内。
- 结果输出:记录符合条件的设施名称。
注意 :
JTS 提供了丰富而高效的空间关系判断方法(如 intersects()、contains()),基于 DE-9IM 模型。GeoTools 结合 JTS,支持从 SimpleFeature 提取几何进行空间分析。空间关系判断在设施位置分析等场景中非常实用,易于集成到 GIS 应用中。
实际应用
- 城市规划:检查医院是否在洪水风险区内,辅助选址决策。
- 物流管理:判断仓库是否在配送区域内,优化配送路线。
- 环境监测:检查监测点是否在污染区域内,评估环境风险。
注意事项****坐标系一致性:确保所有几何对象的坐标系(CRS)一致(如 WGS84),否则需进行投影转换。几何有效性:使用 isValid() 检查几何对象,避免因无效几何导致错误。性能优化:对于大规模数据集,考虑使用空间索引(如 R-Tree)加速查询资源管理:及时调用 DataStore.dispose() 释放资源。