java调用GDAL及JTS实现生成泰森多边形(Voronoi图)的一种方法

目录

一、关于泰森多边形

1.泰森多边形的特性

2.本文的目的

二、实现思路

1.gdal和jts库的maven坐标 

2.jts生成泰森多边形的关键代码

3.使用GDAL读取源文件信息的关键代码

4.使用GDAL将生成的泰森多边形写入文件

三、实现结果

1.实现的效果

2.完整代码示例


一、关于泰森多边形

泰森多边形,又称Voronoi图,是由一组由连接两邻点直线的垂直平分线组成的连续多边形组成。

泰森多边形示意图

1.泰森多边形的特性

  • 每个泰森多边形内仅含有一个离散点数据;
  • 泰森多边形内的点到相应离散点的距离最近;
  • 位于泰森多边形边上的点到其两边的离散点的距离相等。

2.本文的目的

泰森多边形在地理信息系统(GIS)领域有着广泛的应用,一般可用于点插值,也可以在不直接计算距离的情况进行最邻近分析。目前常见的桌面GIS软件基本都有此功能。本文不讨论泰森多边形的实现算法,仅仅从应用开发的角度出发介绍如何使用已有的java矢量数据读写库、几何处理库来实现泰森多边形的生成。

二、实现思路

GDAL是一种常用的地理空间栅格及矢量数据的读写库其由C/C++编写而成,存在java绑定库,可以被java语言调用。GDAL内置了部分几何处理和空间分析的算法,经作者了解,其暂未内置泰森多边形算法。GDAL在矢量数据的功能方面,支持读写geopackage、shapefile、kml、geojson、gml、xlsx等多种格式的数据。

JTS是一个java语言开发的几何图形处理库,具有较丰富的几何图形处理能力。经了解,JTS内置了泰森多边形算法,即VoronoiDiagramBuilder。基于上述分析,使用java调用GDAL和JTS库实现泰森多边形的生成在技术上是可行的。

1.gdal和jts库的maven坐标 

    <dependency><groupId>org.gdal</groupId><artifactId>gdal</artifactId><version>3.2.0</version></dependency><dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.18.2</version></dependency>

2.jts生成泰森多边形的关键代码

VoronoiDiagramBuilder voronoiBuilder = new VoronoiDiagramBuilder();
voronoiBuilder.setSites(points);
voronoiBuilder.setClipEnvelope(envelope);
Geometry voronoiPolygons = voronoiBuilder.getDiagram(geometryFactory);

其中points为坐标类的Coordinate列表, envelope为泰森多边形的空间范围定义。

points、envelope均需要从源文件中读取,这时可以使用gdal读取有关信息。

3.使用GDAL读取源文件信息的关键代码

Geometry ogrGeo = f.GetGeometryRef();
Coordinate coordinate = new Coordinate(ogrGeo.GetX(), ogrGeo.GetY());

 上面的代码是读取矢量文件坐标点的gdal代码,f为gdal的Feature类。此处的Geometry为gdal的Geometry类,非JTS的Geometry类。下面的代码是读取矢量文件范围的gdal代码。

double[] extent = layer.GetExtent();
Envelope envelope = new Envelope(extent[0],extent[1],extent[2],extent[3]);

4.使用GDAL将生成的泰森多边形写入文件

通过gdal读取矢量文件中调用jts获取泰森多边形需要的参数后,jts生成了Geometry类(org.locationtech.jts.geom.Geometry),逐个读取Geometry的面状图形,将面状图形的坐标点生成wkt文本,利用gdal的根据wkt文本创建几何的功能,将坐标串转换为gdal的几何对象,最后调用gdal写矢量图层的方法将数据生成指定格式的文件即可。以下是转换数据的核心代码。

String wkt = voronoiPolygons.getGeometryN(i).toText();
Geometry geometryOut = Geometry.CreateFromWkt(wkt);

三、实现结果

1.实现的效果

通过本文的示例代码,可以实现最基础的泰森多边形的生成,从而应用于所需要的应用场景中。以下是QGIS中查看代码生成的泰森多边形的实现效果,可以看到,除了生成了多边形外,还继承了点的属性数据,与QGIS自带的泰森多边形功能生成的多边形几何形状一致。详细的示例代码请见下一节。

本文代码生成的泰森多边形在QGIS中的显示效果

2.完整代码示例

package com.hjzx.util;import org.gdal.ogr.*;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.triangulate.VoronoiDiagramBuilder;import java.io.File;
import java.util.*;public class Voronoi {public static void main(String[] args) {String vectorPath = "E:\\随机点.gpkg";String outPath = "E:\\泰森多边形.shp";boolean success = createVoronoiByVector(vectorPath, outPath, "ESRI Shapefile");}/*** 生成泰森多边形* @param vectorPath 矢量数据的绝对路径* @param outPath 要输出的泰森多边形绝对路径* @param outDriverName 要输出的数据格式对应的驱动字符串* @return 是否生成成功*/public static boolean createVoronoiByVector(String vectorPath, String outPath, String outDriverName) {ogr.RegisterAll();DataSource dataSource = ogr.Open(vectorPath);System.out.printf("输入的矢量文件路径:%s\t", vectorPath);if (dataSource == null) {System.out.println("打开数据源失败");return false;}Driver driver = dataSource.GetDriver();if (driver == null) {System.out.println("打开驱动失败");return false;}System.out.printf("打开驱动成功:驱动名称:%s\n", driver.getName());//这里简化了操作,只读取了第1个图层Layer layer = dataSource.GetLayer(0);if (layer == null) {System.out.printf("打开矢量图层失败,文件路径:%s", vectorPath);return false;}if (ogrConstants.wkbPoint != layer.GetGeomType()) {System.out.printf("矢量图层不是点状几何图形,无法生成泰森多边形,文件路径:%s", vectorPath);return false;}//gdal获取矢量图层范围double[] extent = layer.GetExtent();// 创建JTS几何工厂GeometryFactory geometryFactory = new GeometryFactory();// 创建一组点List<Coordinate> points = new ArrayList<>();//gdal读取坐标点并赋值给pointsFeature feature;//使用Map集合存储坐标与要素的对应关系Map<Coordinate, Feature> gdalKeyValue = new HashMap<>();while ((feature = layer.GetNextFeature()) != null) {Geometry ogrGeo = feature.GetGeometryRef();//将gdal矢量要素的点转换到JTS中去Coordinate coordinate = new Coordinate(ogrGeo.GetX(), ogrGeo.GetY());points.add(coordinate);gdalKeyValue.put(coordinate, feature);}System.out.printf("输入矢量数据要素转换为坐标点列表成功,要素数量:%d\n", points.size());Envelope envelope = new Envelope(extent[0], extent[1], extent[2], extent[3]);VoronoiDiagramBuilder voronoiBuilder = new VoronoiDiagramBuilder();voronoiBuilder.setSites(points);voronoiBuilder.setClipEnvelope(envelope);org.locationtech.jts.geom.Geometry voronoiPolygons = voronoiBuilder.getDiagram(geometryFactory);int geometryCount = voronoiPolygons.getNumGeometries();System.out.printf("泰森多边形几何图形创建成功,要素数量:%d\n", geometryCount);System.out.println("开始写入泰森多边形矢量文件!");//获取数据数据源的驱动Driver outDriver = ogr.GetDriverByName(outDriverName);if (outDriver == null) {System.out.printf("打开输出文件的驱动失败,驱动字符串:%s\t", outDriverName);return false;}DataSource outDataSource = outDriver.CreateDataSource(outPath);Vector<String> options = new Vector<>();options.add("ENCODING=UTF-8");/*将文件名作为图层名*/File file = new File(outPath);String name = file.getName();name = name.substring(0, name.lastIndexOf("."));//创建输出矢量图层,沿用源坐标系Layer layerOut = outDataSource.CreateLayer(name, layer.GetSpatialRef(), ogr.wkbMultiPolygon, options);//沿用源文件字段FeatureDefn featureDefn = layer.GetLayerDefn();System.out.printf("输入源文件要素定义数量:%d\n", featureDefn.GetFieldCount());FeatureDefn featureDefnOut = new FeatureDefn();//给输出图层创建字段for (int i = 0; i < featureDefn.GetFieldCount(); i++) {featureDefnOut.AddFieldDefn(featureDefn.GetFieldDefn(i));layerOut.CreateField(featureDefn.GetFieldDefn(i));}for (int i = 0; i < geometryCount; i++) {//取出泰森多边形中的每个面对应的Coordinate对象Coordinate coordinate = (Coordinate) voronoiPolygons.getGeometryN(i).getUserData();String wkt = voronoiPolygons.getGeometryN(i).toText();Geometry geometryOut = Geometry.CreateFromWkt(wkt);//根据Coordinate对象到hashMap中获取矢量要素Feature featureOut = gdalKeyValue.get(coordinate);//改变要素的几何图形featureOut.SetGeometry(geometryOut);//创建要素到要输出的图层layerOut.CreateFeature(featureOut);}//保存数据outDataSource.SyncToDisk();//销毁输出数据源layerOut.delete();outDataSource.delete();//销毁输入数据源layer.delete();dataSource.delete();System.out.printf("创建泰森多边形文件成功,文件路径:%s\n", outPath);return true;}
}

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

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

相关文章

【稳定检索/投稿优惠】2024年智慧金融与财务管理国际会议(SFFM 2024)

2024 International Conference on Smart Finance and Financial Management 2024年智慧金融与财务管理国际会议 【会议信息】 会议简称&#xff1a;SFFM 2024 截稿时间&#xff1a;以官网为准 大会地点&#xff1a;中国广州 会议官网&#xff1a;www.iacsffm.com 会议邮箱&am…

【漏洞复现】海康威视综合安防管理平台 多处 FastJson反序列化RCE漏洞

0x01 产品简介 海康威视综合安防管理平台是一套“集成化”、“智能化”的平台,通过接入视频监控、一卡通、停车场、报警检测等系统的设备。海康威视集成化综合管理软件平台,可以对接入的视频监控点集中管理,实现统一部署、统一配置、统一管理和统一调度。 0x02 漏洞概述 由于…

【安装笔记-20240607-Linux-适合个人用户及初创企业的 SSL 证书服务】

安装笔记-系列文章目录 安装笔记-20240607-Linux-适合个人用户及初创企业的 SSL 证书服务 文章目录 安装笔记-系列文章目录安装笔记-20240607-Linux-适合个人用户及初创企业的 SSL 证书服务 前言一、软件介绍名称&#xff1a;acme.sh主页官方介绍 二、安装步骤测试版本&#x…

React@16.x(21)渲染流程-更新

目录 1&#xff0c;更新的2种场景2&#xff0c;节点更新3&#xff0c;对比 diff 更新3.1&#xff0c;React 的假设3.1.2&#xff0c;key 2.1&#xff0c;找到了对比的目标2.1.1&#xff0c;节点类型一致1&#xff0c;空节点2&#xff0c;DOM节点3&#xff0c;文本节点4&#xf…

Nginx 配置防护 缓慢的 HTTP拒绝服务攻击+点击劫持:X-Frame-Options未配置

一 安全团队检测网站 1 检测到目标主机可能存在缓慢的HTTP拒绝服务攻击 缓慢的HTTP拒绝服务攻击是一种专门针对于Web的应用层拒绝服务攻击&#xff0c;攻击者操纵网络,对目标Web服务器进行海量HTTP请求攻击&#xff0c;直到服务器带宽被打满&#xff0c;造成了拒绝服务。 慢…

Flink SQL实践

环境准备 方式1&#xff1a;基于Standalone Flink集群的SQL Client 启动Flink集群 [hadoopnode2 ~]$ start-cluster.sh [hadoopnode2 ~]$ sql-client.sh ... 省略若干日志输出... Flink SQL> 方式2&#xff1a;基于Yarn Session Flink集群的SQL Client 启动hadoop集群…

使用difflib实现文件差异比较用html显示

1.默认方式&#xff0c;其中加入文本过长&#xff0c;需要换行&#xff0c;因此做 contenthtml_output.replace(</style>,table.diff td {word-wrap: break-word;white-space: pre-wrap;max-width: 100%;}</style>)&#xff0c;添加换行操作 ps&#xff1a;当前te…

内存经验分享

目录 内存统计工具 /proc/meminfo Buddy ​​​​​​​​​​​​​​Slub ​​​​​​​Procrank /proc/pid/smaps ​​​​​​​Dumpsys meminfo 内存评估 内存泄漏 Lmk 水位调整 内存统计工具 /proc/meminfo 可以提供整体内存信息&#xff0c;各字段表示的意思如…

mysql工具----dbForgeStudio2020

dbForgeStudio2020&#xff0c;除了基本的操作外&#xff0c;还具有可调试mysql存储过程的功能&#xff0c;是一个不可夺得的mysql软件工具。 本文的软件将简单介绍软件的安装方式&#xff0c;仅供学习交流&#xff0c;不可做它用。 1.安装软件&#xff0c;安装后&#xff0c…

【Linux操作系统】Linux中进程的五种状态:R、S、D、T、X以及僵尸进程、孤儿进程

操作系统中有许多同时执行的进程&#xff0c;这些进程都可能处于不同的状态代表着不同的含义。 R运行状态(running) 概念&#xff1a;并不意味着进程一定在运行中&#xff0c;它表明进程要么是在运行中要么在运行队列里。 我们运行可执行程序myproc利用指令 ps ajx可以看到进程…

BC9 printf的返回值

BC9 printf的返回值 这里我们先要了解库函数printf printf的返回值&#xff0c;是写入的字符总数 我们第一遍写代码时候可能写成这样: #include<stdio.h> int main() {int retprintf("Hello world!");printf("%d", ret);return 0; }我们发现这样是通…

问题:在本案复议阶段,复议机关()。 #其他#媒体

问题&#xff1a;在本案复议阶段&#xff0c;复议机关&#xff08;&#xff09;。 A&#xff0e;有权责令被申请人纠正违法的征税行为 B&#xff0e;应当对被申请人作出的税务具体行政行为所依据的事实证据、法律程序、法律依据及设定权利义务内容的合法性、适当性进行全面审…

【JMeter接口测试工具】第二节.JMeter基本功能介绍(上)【入门篇】

文章目录 前言一、获取所有学院信息接口执行二、线程组的介绍 2.1 并发和顺序执行 2.2 优先和最后执行线程组 2.3 线程组的设置细节三、HTTP请求的介绍四、查看结果树的配置使用总结 前言 一、获取所有学院信息接口执行 我们先针对一条简单的接口进行执行&#…

【Spring Cloud Alibaba】13.自建存储对象服务与集成(minio版)

文章目录 简介什么是云存储服务&#xff08;OSS&#xff09;为什么选择MiniIOMiniIO相关地址 搭建(docker)安装Docker部署MinIO创建存储桶配置存储桶设置存储桶可以直接在浏览器访问 集成到Spring Cloud Alibaba项目创建子模块引入依赖包项目结构配置文件工具类接口类测试 简介…

别让你的品牌失去声音,品牌策划如何成为你的王牌?

品牌策划可不仅仅是一个简单的概念&#xff0c;它是一门真正的艺术和科学。 它涉及到在确立品牌定位之后&#xff0c;进行一系列精心设计的传播和推广活动&#xff0c;从而塑造和管理品牌&#xff0c;让品牌价值达到最大化。 在这个竞争激烈的市场中&#xff0c;想要让你的品…

【人工智能】第三部分:ChatGPT的应用场景和挑战

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

FactoryTalk View Site Edition的VBA基本应用

第一节 在VBA中标签的读取和写入 本例要达到的目标是通过FactoryTalk View Site Edition&#xff08;以下简称SE&#xff09;的VBA来访问PLC中的下位标签&#xff0c;并实现标签的读写。 1.准备工作 打开SE&#xff0c;选择应用程序类型&#xff08;本例是Site Edition Netwo…

燃烧截稿倒计时,NDSS‘25大会即将召开,你的论文准备好了吗?

燃烧截稿倒计时&#xff01;NDSS25大会即将召开&#xff0c;你的论文准备好了吗&#xff1f; 第32届NDSS25(Network and Distributed System Security Symposium)即网络与分布式系统安全研讨会将于2025年2月23日至28日在加利福尼亚州圣地亚哥举行&#xff01; 作为信息安全领域…

【Python机器学习】将PCA用于cancer数据集并可视化

PCA最常见的应用之一就是将高维数据集可视化。一般对于有两个以上特征的数据&#xff0c;很难绘制散点图&#xff0c;。对于Iris&#xff08;鸢尾花&#xff09;数据集&#xff0c;我们可以创建散点矩阵图&#xff0c;通过展示特征所有可能的两两组合来展示数据的局部图像。 不…

MI-SegNet: 基于互信息的超越领域泛化的超声图像分割

文章目录 MI-SegNet: Mutual Information-Based US Segmentation for Unseen Domain Generalization摘要方法实验结果 MI-SegNet: Mutual Information-Based US Segmentation for Unseen Domain Generalization 摘要 针对医学图像分割在不同领域间泛化能力有限的问题,特别是针…