当前位置: 首页 > news >正文

8 几何叠加分析

什么是叠加分析?

叠加分析通过对两个或多个地理图层执行几何运算,生成新的图层,用于分析空间关系。也可参考合集中叠加分析内容。常见的叠加操作包括:

  1. 交集(Intersection):提取两个图层重叠的部分。
    • JTS 方法:geometry1.intersection(geometry2)
    • 示例:找出河流穿越的农田区域。
  2. 并集(Union):合并两个图层的几何,保留所有区域。
    • JTS 方法:geometry1.union(geometry2)
    • 示例:合并农田和森林,生成综合土地使用图层。
  3. 差集(Difference):从一个图层中移除与另一个图层重叠的部分。
    • JTS 方法:geometry1.difference(geometry2)
    • 示例:从城市区域移除河流缓冲区。
  4. 对称差(Symmetric Difference):提取两个图层中互不重叠的部分。
    • JTS 方法:geometry1.symDifference(geometry2)
    • 示例:分析保护区与采矿区的非重叠区域。

叠加分析广泛应用于:

  • 土地利用规划:分析不同土地类型的重叠区域。
  • 洪水风险评估:确定洪水淹没区与居民区的交集。
  • 环境管理:评估保护区与开发项目的空间冲突。

GeoTools 借助 JTS(Java Topology Suite) 提供高效的几何运算能力,结合其数据处理功能,成为实现叠加分析的理想工具。


开发环境准备

在开始代码实践之前,需要配置 GeoTools 环境:

添加 Maven 依赖

在 pom.xml 中添加以下依赖:

<repositories><repository><id>osgeo</id><name>OSGeo Repository</name><url>https://repo.osgeo.org/repository/release/</url></repository>
</repositories><dependencies><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>27.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>27.0</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-epsg-hsql</artifactId><version>27.0</version></dependency>
</dependencies>

准备测试数据

使用 Shapefile 格式的地理数据,例如:

  • land_use.shp:包含农田、森林、城市区域的多边形(Polygon),属性包括 land_type(字符串)。
  • rivers.shp:包含河流的线状几何(LineString),属性包括 name(字符串)。
  • 坐标参考系统(CRS):EPSG:4326(WGS84)。

你可以通过 Natural Earth 或其他公开数据集获取测试数据。

开发工具

  • JDK:1.8 或以上
  • IDE:IntelliJ IDEA
  • Maven:3.69

GeoTools 叠加分析代码示例

以下是一个完整的 GeoTools 程序,展示如何实现交集、并集、差集、对称差和缓冲区分析。我们将:

  1. 计算农田与河流的交集。
  2. 合并农田和森林区域。
  3. 从城市区域移除河流缓冲区。
  4. 生成河流的 100 米缓冲区并与土地使用图层交集。
  5. 计算保护区与采矿区的对称差。

完整代码

import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.DefaultFeatureCollection;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Polygon;
import org.geotools.data.shapefile.ShapefileDataStore;import java.io.File;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;public class OverlayAnalysisDemo {public static void main(String[] args) throws Exception {// 加载 ShapefileFile landUseFile = new File("path/to/land_use.shp");File riversFile = new File("path/to/rivers.shp");FileDataStore landUseStore = FileDataStoreFinder.getDataStore(landUseFile);FileDataStore riversStore = FileDataStoreFinder.getDataStore(riversFile);SimpleFeatureSource landUseSource = landUseStore.getFeatureSource();SimpleFeatureSource riversSource store.getFeatureSource();SimpleFeatureCollection landUseFeatures = landUseSource.getFeatures();SimpleFeatureCollection riverFeatures = riversSource.getFeatures();// 确保 CRS 一致CoordinateReferenceSystem landUseCRS = landUseSource.getSchema().getCoordinateReferenceSystem();CoordinateReferenceSystem riverCRS = riversSource.getSchema().getCoordinateReferenceSystem();if (!CRS.equalsIgnoreMetadata(landUseCRS, riverCRS)) {throw new Exception("CRS mismatch between layers!");}// 交集分析:农田与河流SimpleFeatureCollection intersectionResult = performIntersection(landUseFeatures, riverFeatures);saveShapefile(intersectionResult, "intersection_output.shp");// 并集分析:农田与森林SimpleFeatureCollection unionResult = performUnion(landUseFeatures);saveShapefile(unionResult, "union_output.shp");// 差集分析:城市区域移除河流SimpleFeatureCollection differenceResult = performDifference(landUseFeatures, riverFeatures);saveShapefile(differenceResult, "difference_output.shp");// 对称差分析:保护区与采矿区SimpleFeatureCollection symDiffResult = performSymmetricDifference(landUseFeatures, riverFeatures);saveShapefile(symDiffResult, "sym_diff_output.shp");// 缓冲区分析:河流 100 米缓冲区与土地使用SimpleFeatureCollection bufferResult = performBufferAndIntersection(landUseFeatures, riverFeatures, 100.0);saveShapefile(bufferResult, "buffer_intersection_output.shp");// 清理资源landUseStore.dispose();riversStore.dispose();}// 交集分析private static SimpleFeatureCollection performIntersection(SimpleFeatureCollection landUseFeatures, SimpleFeatureCollection riverFeatures) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("IntersectionType", Polygon.class);try (SimpleFeatureIterator landUseIterator = landUseFeatures.features()) {while (landUseIterator.hasNext()) {SimpleFeature landUseFeature = landUseIterator.next();Geometry landUseGeom = (Geometry) landUseFeature.getDefaultGeometry();try (SimpleFeatureIterator riverIterator = riverFeatures.features()) {while (riverIterator.hasNext()) {SimpleFeature riverFeature = riverIterator.next();Geometry riverGeom = (Geometry) riverFeature.getDefaultGeometry();Geometry intersection = landUseGeom.intersection(riverGeom);if (!intersection.isEmpty() && intersection instanceof Polygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", intersection);builder.set("land_type", landUseFeature.getAttribute("land_type"));result.add(builder.buildFeature(null));}}}}}return result;}// 并集分析private static SimpleFeatureCollection performUnion(SimpleFeatureCollection landUseFeatures) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("UnionType", Polygon.class);List<Geometry> geometries = new ArrayList<>();try (SimpleFeatureIterator iterator = landUseFeatures.features()) {while (iterator.hasNext()) {SimpleFeature feature = iterator.next();Geometry geom = (Geometry) feature.getDefaultGeometry();geometries.add(geom);}}Geometry union = geometries.get(0);for (int i = 1; i < geometries.size(); i++) {union = union.union(geometries.get(i));}if (union instanceof Polygon || union instanceof MultiPolygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", union);builder.set("land_type", "Combined");result.add(builder.buildFeature(null));}return result;}// 差集分析private static SimpleFeatureCollection performDifference(SimpleFeatureCollection landUseFeatures, SimpleFeatureCollection riverFeatures) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("DifferenceType", Polygon.class);try (SimpleFeatureIterator landUseIterator = landUseFeatures.features()) {while (landUseIterator.hasNext()) {SimpleFeature landUseFeature = landUseIterator.next();Geometry landUseGeom = (Geometry) landUseFeature.getDefaultGeometry();try (SimpleFeatureIterator riverIterator = riverFeatures.features()) {Geometry combinedRivers = null;while (riverIterator.hasNext()) {SimpleFeature riverFeature = riverIterator.next();Geometry riverGeom = (Geometry) riverFeature.getDefaultGeometry();combinedRivers = combinedRivers == null ? riverGeom : combinedRivers.union(riverGeom);}if (combinedRivers != null) {Geometry difference = landUseGeom.difference(combinedRivers);if (!difference.isEmpty() && difference instanceof Polygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", difference);builder.set("land_type", landUseFeature.getAttribute("land_type"));result.add(builder.buildFeature(null));}}}}}return result;}// 对称差分析private static SimpleFeatureCollection performSymmetricDifference(SimpleFeatureCollection landUseFeatures, SimpleFeatureCollection riverFeatures) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("SymDiffType", Polygon.class);try (SimpleFeatureIterator landUseIterator = landUseFeatures.features()) {while (landUseIterator.hasNext()) {SimpleFeature landUseFeature = landUseIterator.next();Geometry landUseGeom = (Geometry) landUseFeature.getDefaultGeometry();try (SimpleFeatureIterator riverIterator = riverFeatures.features()) {while (riverIterator.hasNext()) {SimpleFeature riverFeature = riverIterator.next();Geometry riverGeom = (Geometry) riverFeature.getDefaultGeometry();Geometry symDiff = landUseGeom.symDifference(riverGeom);if (!symDiff.isEmpty()) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", symDiff);builder.set("type", "NonOverlapping");result.add(builder.buildFeature(null));}}}}}return result;}// 缓冲区分析与交集private static SimpleFeatureCollection performBufferAndIntersection(SimpleFeatureCollection landUseFeatures, SimpleFeatureCollection riverFeatures, double bufferDistance) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("BufferIntersectionType", Polygon.class);List<Geometry> bufferGeoms = new ArrayList<>();try (SimpleFeatureIterator riverIterator = riverFeatures.features()) {while (riverIterator.hasNext()) {SimpleFeature riverFeature = riverIterator.next();Geometry riverGeom = (Geometry) riverFeature.getDefaultGeometry();Geometry buffer = riverGeom.buffer(bufferDistance);bufferGeoms.add(buffer);}}try (SimpleFeatureIterator landUseIterator = landUseFeatures.features()) {while (landUseIterator.hasNext()) {SimpleFeature landUseFeature = landUseIterator.next();Geometry landUseGeom = (Geometry) landUseFeature.getDefaultGeometry();for (Geometry bufferGeom : bufferGeoms) {Geometry intersection = landUseGeom.intersection(bufferGeom);if (!intersection.isEmpty() && intersection instanceof Polygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", intersection);builder.set("land_type", landUseFeature.getAttribute("land_type"));result.add(builder.buildFeature(null));}}}}return result;}// 创建 FeatureTypeprivate static SimpleFeatureType createFeatureType(String typeName, Class<? extends Geometry> geomType) throws Exception {SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();builder.setName(typeName);builder.setCRS(CRS.decode("EPSG:4326"));builder.add("geometry", geomType);builder.add("land_type", String.class);return builder.buildFeatureType();}// 保存到 Shapefileprivate static void saveShapefile(SimpleFeatureCollection featureCollection, String outputPath) throws Exception {File outputFile = new File(outputPath);ShapefileDataStore dataStore = new ShapefileDataStore(outputFile.toURI().toURL());dataStore.setCharset(StandardCharsets.UTF_8);dataStore.createSchema(featureCollection.getSchema());try (SimpleFeatureIterator iterator = featureCollection.features()) {while (iterator.hasNext()) {SimpleFeature feature = iterator.next();dataStore.getFeatureWriterAppend().write(feature);}}dataStore.dispose();}
}

代码说明

  • 数据加载:使用 FileDataStoreFinder 读取 Shapefile,获取 SimpleFeatureCollection。
  • CRS 检查:确保两个图层的 CRS 一致(如 EPSG:4326)。
  • 几何运算
    • 交集:使用 geometry1.intersection(geometry2) 提取农田与河流重叠区域。
    • 并集:通过 geometry1.union(geometry2) 合并农田和森林。
    • 差集:使用 geometry1.difference(geometry2) 从城市区域移除河流。
    • 对称差:通过 geometry1.symDifference(geometry2) 提取非重叠区域。
    • 缓冲区:使用 geometry.buffer(distance) 生成河流缓冲区,再与土地使用图层交集。
  • 结果保存:将结果保存为新的 Shapefile 文件,可用 QGIS 或 ArcGIS 查看。

运行结果

运行后生成以下文件:

  • intersection_output.shp:农田与河流的交集。
  • union_output.shp:农田与森林的合并区域。
  • difference_output.shp:城市区域移除河流后的结果。
  • sym_diff_output.shp:保护区与河流的非重叠区域。
  • buffer_intersection_output.shp:河流 100 米缓冲区与土地使用的交集。

应用场景

叠加分析在实际项目中有广泛应用,以下是两个典型场景的代码实现。

土地利用规划:绿地与道路交集

目标:找出城市绿地被道路穿越的区域,用于规划修复。

private static SimpleFeatureCollection findGreenRoadsIntersection(SimpleFeatureCollection greenAreas, SimpleFeatureCollection roads) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("GreenRoadsIntersection", Polygon.class);try (SimpleFeatureIterator greenIterator = greenAreas.features()) {while (greenIterator.hasNext()) {SimpleFeature greenFeature = greenIterator.next();Geometry greenGeom = (Geometry) greenFeature.getDefaultGeometry();try (SimpleFeatureIterator roadIterator = roads.features()) {while (roadIterator.hasNext()) {SimpleFeature roadFeature = roadIterator.next();Geometry roadGeom = (Geometry) roadFeature.getDefaultGeometry();Geometry intersection = greenGeom.intersection(roadGeom);if (!intersection.isEmpty() && intersection instanceof Polygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", intersection);builder.set("area_name", greenFeature.getAttribute("name"));result.add(builder.buildFeature(null));}}}}}return result;
}

应用:帮助城市规划者识别需要修复的绿地碎片。

洪水风险评估:洪水淹没区与居民区

目标:分析洪水风险区 200 米缓冲区内的居民区,评估受影响的房屋

private static SimpleFeatureCollection floodRiskAnalysis(SimpleFeatureCollection floodZones, SimpleFeatureCollection residentialAreas, double bufferDistance) throws Exception {DefaultFeatureCollection result = new DefaultFeatureCollection();SimpleFeatureType resultType = createFeatureType("FloodRiskType", Polygon.class);List<Geometry> floodBuffers = new ArrayList<>();try (SimpleFeatureIterator floodIterator = floodZones.features()) {while (floodIterator.hasNext()) {SimpleFeature floodFeature = floodIterator.next();Geometry floodGeom = (Geometry) floodFeature.getDefaultGeometry();Geometry buffer = floodGeom.buffer(bufferDistance);floodBuffers.add(buffer);}}try (SimpleFeatureIterator residentialIterator = residentialAreas.features()) {while (residentialIterator.hasNext()) {SimpleFeature residentialFeature = residentialIterator.next();Geometry residentialGeom = (Geometry) residentialFeature.getDefaultGeometry();for (Geometry floodBuffer : floodBuffers) {Geometry intersection = residentialGeom.intersection(floodBuffer);if (!intersection.isEmpty() && intersection instanceof Polygon) {SimpleFeatureBuilder builder = new SimpleFeatureBuilder(resultType);builder.set("geometry", intersection);builder.set("res_type", residentialFeature.getAttribute("type"));result.add(builder.buildFeature(null));}}}}return result;
}

应用:为防洪规划提供数据支持,识别需要搬迁的居民区。


常见问题与优化

  1. 性能优化

    • 问题:大数据量图层运算缓慢。

    • 解决:使用 GeoTools 的 Quadtree 或 STRtree 空间索引,减少几何比较次数。

    • 示例:在处理前构建索引:

      STRtree index = new STRtree();
      try (SimpleFeatureIterator iterator = features.features()) {while (iterator.hasNext()) {SimpleFeature feature = iterator.next();index.insert(((Geometry) feature.getDefaultGeometry()).getEnvelopeInternal(), feature);}
      }
      
  2. 几何有效性

    • 问题:无效几何(如自相交)导致运算失败。
    • 解决:使用 Geometry.isValid() 检查,调用 Geometry.buffer(0) 修复。
  3. CRS 不一致

    • 解决:使用 CRS.transform 将图层投影到统一 CRS。
  4. 空几何处理

    • 解决:检查 Geometry.isEmpty(),跳过无效结果。

GeoTools 结合 JTS 提供了强大的叠加分析功能,支持交集、并集、差集、对称差和缓冲区操作,适用于土地利用规划、洪水风险评估、环境管理等场景。本文通过详细的代码示例和实际应用场景,展示了如何使用 GeoTools 实现这些操作。

http://www.dtcms.com/a/284403.html

相关文章:

  • 系统设计时平衡超时时间与多因素认证(MFA)带来的用户体验下降
  • 量子计算的安全与伦理:当技术革命叩击数字时代的潘多拉魔盒
  • sqli-labs靶场通关笔记:第25-26a关 and、or、空格和注释符多重过滤
  • 4G模块 A7680通过MQTT协议连接到腾讯云
  • AI赋能Baklib,重塑企业知识管理与客户支持方式
  • Curr. Res. Food Sci.|福州大学吕旭聪团队:富硒鼠李糖乳杆菌GG重塑肠-肝轴,显著缓解酒精性肝损伤
  • 网络通信之基础知识
  • deep learning(李宏毅)--(六)--loss
  • day19-四剑客与正则-特殊符号正则-awk
  • [yotroy.cool] 记一次 Git 移除某个不该提交的文件
  • iOS WebView 调试与性能优化 跨平台团队高效协作方法解析
  • PyTorch生成式人工智能(18)——循环神经网络详解与实现
  • 可视化图解算法56:岛屿数量
  • Word 中为什么我的图片一拖就乱跑,怎么精确定位?
  • python使用pymysql库
  • modbus 校验
  • 泛型与类型安全深度解析及响应式API实战
  • Java 集合框架详解:Collection 接口全解析,从基础到实战
  • 7月17日日记
  • 【机器学习】向量数据库选型指南:企业内网部署场景
  • 从零开始:C++ UDP通信实战教程
  • 河南萌新联赛2025第(一)场:河南工业大学(补题)
  • SQLite的可视化界面软件的安装
  • YOLO11 vs LMWP-YOLO:参数量-52.5%,mAP+22.07%,小型无人机的远距离检测
  • 7月17日
  • 深度学习 -- Tensor属性及torch梯度计算
  • 大型语言模型的白日梦循环
  • Ollama使用指南-更改默认安装路径和Model路径(安装到非C盘)
  • 【深度学习】神经网络反向传播算法-part4
  • Java数组补充v2