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

news2024/11/13 13:20:09

作者:后端小肥肠

🍇 我写过的文章中的相关代码放到了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的世界,共同推动技术发展。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2115851.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机毕业设计选题推荐-宠物店管理系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

机器学习(9.2-9.8)pytorch学习(二)

文章目录 摘要Abstract 1 torch 和 torchvision1.1 查看CIFAR10数据集内容1.2 Dataloader的使用 2 神经网络的构建2.1 神经网络的基本骨架2.2 卷积层原理2.2.1 卷积基本原理2.2.2 padding 2.3 构建一个卷积神经网络2.4 池化层2.5 非线性激活2.5.1 RELU的使用2.5.2 Sigmoid的使用…

【开源免费】基于SpringBoot+Vue.J大学生租房平台(JAVA毕业设计)

本文项目编号 T 019 &#xff0c;文末自助获取源码 \color{red}{T019&#xff0c;文末自助获取源码} T019&#xff0c;文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

java基础概念21-权限修饰符、代码块

一、权限修饰符 1-1、作用 权限修饰符&#xff0c;是用来控制一个成员能够被访问的范围的。 可以修饰&#xff1a;成员变量&#xff0c;方法&#xff0c;构造方法&#xff0c;内部类。 1-2、权限修饰符的分类 二、代码块 局部代码块构造代码块静态代码块 2-1、局部代码块 …

【C++ Primer Plus习题】12.5

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream> #include <cstdlib> #in…

Linux-【组管理、权限管理、定时任务调度】

目录 前言 Linux组基本介绍 文件/目录 所有者 查看文件 所有者 修改文件所有者 文件/目录 所在组 修改文件/目录 所在组 其它组 改变用户所在组 权限的基本介绍 rwx权限 rwx作用到文件 rwx作用到目录 修改权限 第一种方式&#xff1a;、-、变更权限 第二种方式…

Java进阶13讲__第11讲

配置文件 日志 1. Properties属性文件 1.1 特点、作用 都只能是键值对键不能重复文件后缀一般是.properties结尾的 1.2 读取 package cn.hdc.oop10.properties;import java.io.FileNotFoundException; import java.io.FileReader; import java.util.Properties; import j…

「iOS」折叠cell

iOS学习 前言简单的折叠cell效果原理 稍作修改总结 前言 在暑期仿写中&#xff0c;3G share项目里我们简单的使用了折叠cell。现在写一篇博客来总结该方法。 简单的折叠cell 效果 先看效果&#xff1a; 原理 将cell的高度设置为一个单元格的高度。创建一个按钮&#xff0…

【C++】作用域指针、智能指针、共享指针、弱指针

十、智能指针、共享指针 从上篇文章 【C】如何用C创建对象&#xff0c;理解作用域、堆栈、内存分配-CSDN博客 中我们知道&#xff0c;你的对象是创建在栈上还是在堆上&#xff0c;最大的区别就是对象的作用域不一样。所以在C中&#xff0c;一旦程序进入另外一个作用域&#xf…

【xinference】(19):在L40设备上通过Xinference框架,快速部署CogVideoX-5b模型,可以生成6秒视频,速度比409D快一点

1&#xff0c;关于Xinference Xorbits Inference (Xinference) 是一个开源平台&#xff0c;用于简化各种 AI 模型的运行和集成。借助 Xinference&#xff0c;您可以使用任何开源 LLM、嵌入模型和多模态模型在云端或本地环境中运行推理&#xff0c;并创建强大的 AI 应用。 htt…

鸿蒙开发笔记_电商严选01_登录页面(静态页面)

由于上班较忙,抽空闲暇时间,快速更新中。。。 效果图 登录页面(静态页面) import CommonConstants from ./CommonConstants;/*** 登录页面*/ // 输入文本框,的自定义样式扩展 // @Extend装饰器表示继承、扩展的意思。这里代表:自定义样式扩展 @Extend(TextInput) functio…

Qt使用小技巧之按钮动态变化

前言 最近写小demo中无意发现的&#xff0c;是想实现当鼠标悬停到按钮上面的时候&#xff0c;按钮实现动态变化&#xff0c;让人知道鼠标经过了按钮&#xff0c;效果如下 hoverDynamicPushButton 正文 首先是将按钮的边框给去掉&#xff0c;然后设置下它的悬停伪状态就行了 格…

linux日常使用命令总结

一、文件复制 在 Linux 中&#xff0c;复制文件是一个常见的操作&#xff0c;通常使用 cp 命令来完成。cp 命令提供了丰富的选项来满足不同的需求。下面是使用 cp 命令复制文件的一些基本用法和示例。 基本用法 cp 命令的基本语法如下&#xff1a; cp [选项] 源文件 目标文…

京东获得JD商品详情 API 返回值说明||京东商品详情数据采集API接口详解

item_get-获得JD商品详情 公共参数 名称类型必须描述keyString是调用key&#xff08;必须以GET方式拼接在URL中&#xff09;secretString是调用密钥api_nameString是API接口名称&#xff08;包括在请求地址中&#xff09;[item_search,item_get,item_search_shop等]cacheStri…

了解分布式事务与本地事物基本概念

一、本地事物 1、事物的基本性质 数据库事物的几个特性&#xff1a;原子性、一致性、隔离性、持久性&#xff0c;简称ACID&#xff1b; 原子性&#xff1a;一系列的操作整体不可拆分&#xff0c;要么全成功&#xff0c;要么同时失败。 一致性&#xff1a;数据在事物的前后&am…

SpringMVC上

SpringMVC介绍 MVC模型 MVC全称Model View Controller&#xff0c;是一种设计创建Web应用程序的模式。这三个单词分别代表Web应用程序的三个部分&#xff1a; Model&#xff08;模型&#xff09;&#xff1a;指数据模型。用于存储数据以及处理用户请求的业务逻辑。在Web应用…

Typora教程

1 TyporaChina https://typorachina.com/guide/

【C语言必学知识点七】坚决不允许你还不知道C/C++程序如何对内存进行分区!!!

动态内存管理——详细解读C/C程序中的内存分区 导读一、C/C程序中的内存分区二、常见的动态内存的错误2.1 内存开辟失败后对空指针进行解引用2.2 对已开辟好的空间进行越界访问2.3 free不是有动态函数开辟的空间2.4 free动态内存开辟空间的一部分2.4.1 free函数的底层逻辑 2.5 …

【HarmonyOS】- 内存优化

文章目录 知识回顾前言源码分析1. onMemoryLevel2. 使用LRUCache优化ArkTS内存原理介绍3. 使用生命周期管理优化ArkTS内存4. 使用purgeable优化C++内存拓展知识1. Purgeable Memory总结知识回顾 前言 当应用程序占用过多内存时,系统可能会频繁进行内存回收和重新分配,导致应…

Excel文档的读取【2】

读取了工作簿对象后&#xff0c;下一步就是读取指定的工作表。每个工作簿中&#xff0c;都包含一个或多个工作表。每个工作表&#xff0c;都有一个名称。阿珍收到的Excel文件&#xff0c;由两个工作表组成&#xff0c;分别为“销售商品”和“销售订单数据”。 使用print输出…