【GIS系列】通过Java代码高效实现ArcGIS SDE数据库的数据叠加分析

作者:后端小肥肠

🍇 我写过的文章中的相关代码放到了gitee,地址:xfc-fdw-cloud: 公共解决方案

🍊 有疑问可私信或评论区联系我。

🥑  创作不易未经允许严禁转载。

本文涉及GDAL及GeoTools代码实践,基础环境搭建可查看博客:

【GIS系列】GeoTools简介及工具类分享-CSDN博客

Springboot+GDAL3.x在windows上配置开发环境_springboot集成gdal 3.0.1-CSDN博客

目录

1.前言

2. 技术路线

3. sde数据准备

4. 技术方案实现

4.1.  gdal直连读取sde(失败)

4.2   postgis读取sde数据做空间分析叠加(失败)

4.3. 基于geotools进行叠加分析

4. 结语


1.前言

最近,我接了一个要求利用Java从ArcGIS的Spatial Database Engine (SDE) 数据库中读取数据进行空间叠加分析的项目需求。考虑到这个任务的复杂性,以及在网上缺乏具体的实现指导,我决定写下这篇文章,记录我在项目中的实际经验和解决方案,希望能帮助到面临类似挑战的开发者。

2. 技术路线

上述流程图可解释为以下步骤:

1. 获取SDE图层信息

第一步是连接到SDE数据库并查询可用的图层信息。这一信息是执行叠加分析的基础,需要确保连接的稳定性和数据的准确性。

2. 读取并缓存SDE中的数据集

一旦获取了必要的图层信息,下一步是从这些图层中读取数据。

3. 执行空间叠加分析

这是技术实现的核心部分。我们将缓存的SDE数据与输入的WKT数据进行叠加分析。这一步骤涉及复杂的空间算法,可能包括但不限于多边形重叠、交集和并集等操作,本文仅对相交进行实践

4. 获取最终叠加分析结果

叠加分析完成后,我们提取分析结果。这些结果将用于报告、可视化展示或作为决策支持的数据输入。

3. sde数据准备

首先我们应该准备一些sde数据,具体步骤不演示,可查看arcgis帮助文档:教程:PostgreSQL 中地理数据库入门—帮助 | ArcGIS Desktop

数据库中查看数据,可看出空间数据以wkb形式存储:

数据拖到展示区:

本文中将以overlay3为叠加分析输入图形,以阿里节点为源图层进行叠加分析操作,我们先基于arcgis做一下叠加分析查看一下结果:

 大红色部分为叠加分析(相交)结果:

4. 技术方案实现

4.1.  gdal直连读取sde(失败)

GDAL是一个非常流行的地理数据处理库,支持多种地理数据格式。理论上,使用GDAL直连读取SDE数据似乎是一个有效的技术选择。我们的初衷是利用GDAL的强大功能来简化数据访问,并直接进行空间叠加分析,先通过代码获取sde中的空间要素,代码如下:

    @Test
    public void test3() {
        // 注册所有GDAL/OGR驱动
        ogr.RegisterAll();

        // 定义连接字符串,确保将密码替换为实际的密码
        String connection = "PG:host=127.0.0.1 port=5432 dbname='spatial_db_st' user='sde' password='admin'";

        // 打开数据源
        DataSource ds = ogr.Open(connection, 0);
        if (ds == null) {
            System.out.println("无法连接到数据库");
            return;
        }

        System.out.println("成功连接到数据库");
        System.out.println("图层列表:");

        // 循环遍历所有图层并打印图层名称及其几何类型
        for (int i = 0; i < ds.GetLayerCount(); i++) {
            Layer layer = ds.GetLayerByIndex(i);
            if (layer != null) {
                String layerName = layer.GetName();
                if(layerName.equals("阿里节点")||layerName.equals("规划院节点")||layerName.equals("overlay3")){
                    long count = layer.GetFeatureCount();
                    int geomType = layer.GetGeomType(); // 获取几何类型
                    String geomTypeName = ogr.GeometryTypeToName(geomType); // 将几何类型转换为可读名称
                    System.out.println((i + 1) + ": " + layerName + "      要素个数: " + count+"        几何类型:"+geomTypeName);
                }

            }
        }

        // 关闭数据源
        ds.delete();
    }

 上述使用GDAL库的OGR组件来尝试连接到一个基于PostGIS的SDE数据库,并列出其所有图层的名称、要素个数以及几何类型。代码首先注册所有GDAL/OGR驱动,然后使用一个包含数据库连接详细信息的字符串尝试打开数据源。一旦连接成功,它遍历所有图层,并打印每个图层的名称、包含的要素数量和几何类型。最后,代码会关闭数据源以释放资源。

运行结果如下图,我们能看到,gdal打印类型为空:

为空的原因是gdal并没有提供sde相关的支持,我们运行以下命令:

ogrinfo --formats

打印的结果:

Supported Formats:
  PCIDSK -raster,vector- (rw+v): PCIDSK Database File
  PDS4 -raster,vector- (rw+vs): NASA Planetary Data System 4
  VICAR -raster,vector- (rw+v): MIPL VICAR file
  JP2OpenJPEG -raster,vector- (rwv): JPEG-2000 driver based on OpenJPEG library
  PDF -raster,vector- (w+): Geospatial PDF
  MBTiles -raster,vector- (rw+v): MBTiles
  EEDA -vector- (ro): Earth Engine Data API
  OGCAPI -raster,vector- (rov): OGCAPI
  ESRI Shapefile -vector- (rw+v): ESRI Shapefile
  MapInfo File -vector- (rw+v): MapInfo File
  UK .NTF -vector- (rov): UK .NTF
  LVBAG -vector- (rov): Kadaster LV BAG Extract 2.0
  OGR_SDTS -vector- (rov): SDTS
  S57 -vector- (rw+v): IHO S-57 (ENC)
  DGN -vector- (rw+v): Microstation DGN
  OGR_VRT -vector- (rov): VRT - Virtual Datasource
  REC -vector- (ro): EPIInfo .REC
  Memory -vector- (rw+): Memory
  CSV -vector- (rw+v): Comma Separated Value (.csv)
  GML -vector- (rw+v): Geography Markup Language (GML)
  GPX -vector- (rw+v): GPX
  KML -vector- (rw+v): Keyhole Markup Language (KML)
  GeoJSON -vector- (rw+v): GeoJSON
  GeoJSONSeq -vector- (rw+v): GeoJSON Sequence
  ESRIJSON -vector- (rov): ESRIJSON
  TopoJSON -vector- (rov): TopoJSON
  OGR_GMT -vector- (rw+v): GMT ASCII Vectors (.gmt)
  GPKG -raster,vector- (rw+vs): GeoPackage
  SQLite -vector- (rw+v): SQLite / Spatialite
  ODBC -vector- (ro):
  WAsP -vector- (rw+v): WAsP .map format
  PGeo -vector- (ro): ESRI Personal GeoDatabase
  MSSQLSpatial -vector- (rw+): Microsoft SQL Server Spatial Database
  OpenFileGDB -vector- (rov): ESRI FileGDB
  DXF -vector- (rw+v): AutoCAD DXF
  CAD -raster,vector- (rovs): AutoCAD Driver
  FlatGeobuf -vector- (rw+v): FlatGeobuf
  Geoconcept -vector- (rw+v): Geoconcept
  GeoRSS -vector- (rw+v): GeoRSS
  GPSTrackMaker -vector- (rw+v): GPSTrackMaker
  VFK -vector- (ro): Czech Cadastral Exchange Data Format
  PGDUMP -vector- (w+v): PostgreSQL SQL dump
  OSM -vector- (rov): OpenStreetMap XML and PBF
  GPSBabel -vector- (rw+): GPSBabel
  OGR_PDS -vector- (rov): Planetary Data Systems TABLE
  WFS -vector- (rov): OGC WFS (Web Feature Service)
  OAPIF -vector- (ro): OGC API - Features
  Geomedia -vector- (ro): Geomedia .mdb
  EDIGEO -vector- (rov): French EDIGEO exchange format
  SVG -vector- (rov): Scalable Vector Graphics
  CouchDB -vector- (rw+): CouchDB / GeoCouch
  Cloudant -vector- (rw+): Cloudant / CouchDB
  Idrisi -vector- (rov): Idrisi Vector (.vct)
  ARCGEN -vector- (rov): Arc/Info Generate
  XLS -vector- (ro): MS Excel format
  ODS -vector- (rw+v): Open Document/ LibreOffice / OpenOffice Spreadsheet
  XLSX -vector- (rw+v): MS Office Open XML spreadsheet
  Elasticsearch -vector- (rw+): Elastic Search
  Walk -vector- (ro):
  Carto -vector- (rw+): Carto
  AmigoCloud -vector- (rw+): AmigoCloud
  SXF -vector- (rov): Storage and eXchange Format
  Selafin -vector- (rw+v): Selafin
  JML -vector- (rw+v): OpenJUMP JML
  PLSCENES -raster,vector- (ro): Planet Labs Scenes API
  CSW -vector- (ro): OGC CSW (Catalog  Service for the Web)
  VDV -vector- (rw+v): VDV-451/VDV-452/INTREST Data Format
  MVT -vector- (rov): Mapbox Vector Tiles
  NGW -raster,vector- (rw+s): NextGIS Web
  MapML -vector- (rw+v): MapML
  TIGER -vector- (rw+v): U.S. Census TIGER/Line
  AVCBin -vector- (rov): Arc/Info Binary Coverage
  AVCE00 -vector- (rov): Arc/Info E00 (ASCII) Coverage
  HTTP -raster,vector- (ro): HTTP Fetching Wrapper

从打印的结果来看,gdal不提供sde相关技术支持,这个方案宣布作废╮(╯▽╰)╭。

4.2   postgis读取sde数据做空间分析叠加(失败)

在第3章中我们可以看出sde中空间数据是以wkb的方式存储,那么能不能借助postgis的方式实现呢?二话不说先写一个sql来运行看看:


SELECT
  "objectid",
  ST_AsText(ST_Intersection(shape, ST_GeomFromText('POLYGON ((...))'))) AS intersection_geometry
FROM
  "sde"."阿里节点"
WHERE
  ST_Intersects(shape, ST_GeomFromText('POLYGON ((...))'));

 这段SQL查询旨在从名为“阿里节点”的表中检索与指定多边形相交的几何要素对象。首先使用ST_GeomFromText函数将WKT字符串转换为几何对象,然后通过ST_Intersects函数筛选出表中与该多边形空间相交的记录。对于每个找到的相交记录,使用ST_Intersection函数计算实际的交集区域,并将结果几何形状转换为文本格式输出。

运行结果如下:

报错没有ST_GeomFromText这个函数,postgis读取sde数据做空间分析叠加这个方案再次宣告失败。 

4.3. 基于geotools进行叠加分析

引入maven依赖:


        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-main</artifactId>
            <version>28.3</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>28.3</version>
        </dependency>
        <dependency>
            <groupId>org.locationtech.jts</groupId>
            <artifactId>jts-core</artifactId>
            <version>1.18.1</version> <!-- 最新的 JTS 版本 -->
        </dependency>

基于geotools进行叠加分析代码如下:

@Test
    public void test1() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            // 1. 连接到数据库
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            System.out.println("成功连接到数据库");

            // 2. 查询 "阿里节点" 表的几何字段 shape(以 WKT 格式输出)
            String sql = "SELECT objectid, ST_AsText(shape) AS wkt_shape FROM sde.\"阿里节点\" WHERE objectid = ?";

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, 2); // 查询 objectid 为 1 的记录,您可以根据需要更改

            rs = pstmt.executeQuery();

            // 3. 获取查询结果
            if (rs.next()) {
                String wktFromDatabase = rs.getString("wkt_shape");
//                System.out.println("从数据库中获取的 WKT: " + wktFromDatabase);

                // 4. 将数据库中的 WKT 与另一个输入的 WKT 进行叠加分析
                String externalWkt = "POLYGON(( 85.71074699 34.77325272 0.00000000, 84.53150517 32.55857906 0.00000000, 88.93209050 31.20676526 0.00000000, 89.70866438 33.73782088 0.00000000, 85.71074699 34.77325272 0.00000000))";

                WKTReader reader = new WKTReader();

                // 解析数据库中查询到的 WKT 和外部提供的 WKT
                Geometry geomFromDb = reader.read(wktFromDatabase);
                Geometry externalGeom = reader.read(externalWkt);

                // 检查是否相交
                if (geomFromDb.intersects(externalGeom)) {
                    System.out.println("几何体相交!");
                    Geometry intersection = geomFromDb.intersection(externalGeom);
                    System.out.println("相交区域的 WKT 表示: " + intersection.toText());
                } else {
                    System.out.println("几何体不相交。");
                }
            }

        } catch (SQLException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        } finally {
            // 5. 关闭资源
            try {
                if (rs != null) rs.close();
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

 上述代码从数据库中读取特定记录的地理空间数据,并与外部提供的WKT(Well-Known Text)格式的多边形进行空间叠加分析。首先,代码通过JDBC连接到数据库,并使用PreparedStatement执行SQL查询,以获取objectid为2的记录的shape字段。接着,使用JTS(Java Topology Suite)库的WKTReader来解析从数据库中得到的WKT以及外部定义的WKT,然后检查这两个几何体是否相交。如果它们相交,将计算并输出它们的交集区域。

结果打印:

在可视化的工具中验证一下wkt:

 从上图可看出代码运行的结果与我们在arcgis中进行叠加分析的结果是一致的。

5. 结语

在本文中,我们探讨了如何使用Java从ArcGIS的SDE数据库读取数据并进行空间叠加分析。虽然在尝试中遇到了一些挑战,但通过应用GeoTools框架,我们最终成功实现了所需功能。这次经验强调了在GIS开发中灵活选择和应用技术的重要性。

感谢大家的阅读,希望这篇文章能为相关开发者提供帮助。如有疑问或进一步讨论的需求,欢迎留言或私信联系我。让我们继续探索GIS的世界,共同推动技术发展。

  • 32
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端小肥肠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值