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自带的泰森多边形功能生成的多边形几何形状一致。详细的示例代码请见下一节。
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;}
}
相关文章:
java调用GDAL及JTS实现生成泰森多边形(Voronoi图)的一种方法
目录 一、关于泰森多边形 1.泰森多边形的特性 2.本文的目的 二、实现思路 1.gdal和jts库的maven坐标 2.jts生成泰森多边形的关键代码 3.使用GDAL读取源文件信息的关键代码 4.使用GDAL将生成的泰森多边形写入文件 三、实现结果 1.实现的效果 2.完整代码示例 一、关于…...
Type-C音频转接器方案
在数字化时代,音频设备作为我们生活中不可或缺的一部分,其连接方式的便捷性和高效性显得尤为重要。Type-C音频转接器,作为一种新型的音频连接解决方案,正逐渐走进我们的生活,以其独特的优势改变着我们的音频体验。 一、…...
linux 服务器上离线安装 node nvm
因为是离线环境 如果你是可以访问外网的 下面内容仅供参考 也可以继续按步骤来 node 安装路径 Node.js — Download Node.js nvm 安装路径 Tags nvm-sh/nvm GitHub 后来发现 nvm安装后 nvm use 版本号 报错 让我去nvm install 版本 我是内网环境 install不了 下面 你要 把安…...
Web前端三大主流框架:React、Angular和Vue的比较与选择
Web前端三大主流框架:React、Angular和Vue的比较与选择 Web前端技术的快速发展为开发者提供了丰富的工具和框架,其中React、Angular和Vue是当前最受欢迎的三大框架。这三个框架各有特点,适用于不同的项目需求和开发团队。本文将对React、Ang…...
C# MemoryCache 缓存应用
摘要 缓存是一种非常常见的性能优化技术,在开发过程中经常会用到。.NET提供了内置的内存缓存类 MemoryCache,它可以很方便地存储数据并在后续的请求中快速读取,从而提高应用程序的响应速度。 正文 通过使用 Microsoft.Extensions.Caching.Me…...
【学习笔记】Linux前置准备
视频学习资料 基础: 黑马0基础(前面四章即可,包含软件基础安装配置) 进阶: 黑马程序员-Linux系统编程 黑马程序员-Linux网络编程 我也还没看,看了眼目录感觉把八股里面很多场景都讲到了,感觉有…...
各种空气能热泵安装图
空气能热泵安装图 循环式空气能热泵安装图 直热循环式空气能热泵安装图 泳池空气能热泵安装图 循环式水源热泵热安装系统原理图 直热循环式水源热泵安装系统图 空气水源热泵安装图...
软件杯 题目:基于深度学习的中文对话问答机器人
文章目录 0 简介1 项目架构2 项目的主要过程2.1 数据清洗、预处理2.2 分桶2.3 训练 3 项目的整体结构4 重要的API4.1 LSTM cells部分:4.2 损失函数:4.3 搭建seq2seq框架:4.4 测试部分:4.5 评价NLP测试效果:4.6 梯度截断…...
UI学习笔记(一)
UI学习 一:UIView基础frame属性隐藏视图对象:UIView的层级关系 二:UIWindow对象三:UIViewController基础UIViewController使用 四:定时器与视图移动五:UISwitch控件六:滑动条和进度条七…...
【C语言训练题库】扫雷->简单小游戏!
🔥博客主页🔥:【 坊钰_CSDN博客 】 欢迎各位点赞👍评论✍收藏⭐ 目录 1. 题目 2. 解析 3. 代码 4. 小结 1. 题目 小sun上课的时候非常喜欢玩扫雷。他现小sun有一个初始的雷矩阵,他希望你帮他生成一个扫雷矩阵。 扫雷…...
WMS仓储管理系统高效驱动制造企业物料管理
在现代制造业的快速发展中,仓储管理作为供应链的核心环节,其效率直接影响到企业的生产力和市场竞争力。随着科技的进步,实施WMS仓储管理系统逐渐成为推动仓储管理向智能化转型的关键力量。本文将深入探讨WMS仓储管理系统如何以创新的方式驱动…...
python使用appium打开程序后,为什么没有操作后程序就自动退出了
当使用Appium打开应用程序并在没有执行任何操作后它自动退出,这可能是由于几个不同的原因。以下是一些可能的原因和相应的解决方案: 应用程序的默认行为: 有些应用程序在启动后如果没有用户交互,可能会因为超时或其他逻辑而自动关…...
MacBook M系列芯片安装php8.2
适用于M1\M2\M3等系列的MacBook,记录下安装过程 安装brew 打开终端,执行如下命令: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装zsh(非必须) …...
OlSoul系统调校程序v2024.06.05
软件介绍 OlSoul是一款能够适配用于Win各个系统的系统调校软件,OlSoul内置有众多调校功能可以直接使用,如有启用无线网络功能、启用打印机功能、系统快速休眠与休眠开关、快捷方式小箭头去除功能等,具体的调校功能多达几十项,可自…...
图像特征提取 python
1. 边缘检测 (Edge Detection) 1.1 Sobel 算子 Sobel 算子是一种边缘检测算子,通过计算图像梯度来检测边缘。 import cv2 import numpy as np# 读取图像 image cv2.imread(image.jpg, 0)# 应用 Sobel 算子 sobel_x cv2.Sobel(image, cv2.CV_64F, 1, 0, ksize5)…...
width: 100%和 width: 100vw这两种写法有什么区别
width: 100%; 和 width: 100vw; 是两种不同的 CSS 写法,它们在实际应用中会有不同的效果。以下是这两种写法的主要区别: width: 100%; 定义:将元素的宽度设置为其包含块(通常是父元素)宽度的 100%。效果:元…...
如何在另一台电脑上使用相同的Python环境和依赖包
如果您想在另一台电脑上使用相同的Python环境和依赖包,有几种方法可以实现: 使用requirements.txt: 在您当前的虚拟环境中,您可以使用pip freeze > requirements.txt命令生成一个包含所有已安装包及其版本的文件。然后&#x…...
Vue3 响应式 API:工具函数(一)
isRef() isRef 是一个简单的工具函数,它接受一个参数并返回一个布尔值,指示该参数是否是一个由 ref 创建的响应式引用。 在某些情况下,你可能需要编写一些通用逻辑或函数,这些逻辑或函数需要处理不同类型的响应式数据(…...
开发常用软件
开发相关 代码编译 Visual Studio 2019 Visual Studio 2022 代码测试工具 LINQPad Premium 5 LINQPad 7 打包工具 Advanced Installer 反编译工具 ILSpy dnSpy spy 数据库相关 SQLite Expert Professional 5 DLL扫描工具 depends 界面设计 SvgToXaml Materi…...
conntrack如何限制您的k8s网关
1.1 conntrack 介绍 对于那些不熟悉的人来说,conntrack简单来说是Linux内核的一个子系统,它跟踪所有进入、出去或通过系统的网络连接,允许它监控和管理每个连接的状态,这对于诸如NAT(网络地址转换)、防火墙和保持会话连续性等任务至关重要。它作为Netfilter的一部分运行,…...
Kook Zimage真实幻想Turbo快速调试:找到属于你的幻想风格黄金参数组合
Kook Zimage真实幻想Turbo快速调试:找到属于你的幻想风格黄金参数组合 1. 认识Kook Zimage真实幻想Turbo Kook Zimage真实幻想Turbo是一款专为个人GPU设计的轻量化幻想风格图像生成系统。它基于Z-Image-Turbo极速文生图底座,通过独特的权重融合技术&am…...
终极指南:facenet-pytorch API参考手册与完整函数方法详解
终极指南:facenet-pytorch API参考手册与完整函数方法详解 【免费下载链接】facenet-pytorch Pretrained Pytorch face detection (MTCNN) and facial recognition (InceptionResnet) models 项目地址: https://gitcode.com/gh_mirrors/fa/facenet-pytorch f…...
从Blender到虚幻引擎:除了FBX,试试GLTF格式导入的完整流程与优势对比
从Blender到虚幻引擎:GLTF格式导入的完整流程与优势解析 在三维内容创作领域,Blender与虚幻引擎的组合已经成为许多专业团队的标准工具链。当我们需要将精心制作的模型从Blender迁移到虚幻引擎时,传统的FBX格式虽然广为人知,但GLT…...
AOP 代理对象的诞生时刻:Bean 生命周期中的“夺舍”瞬间
各位大佬,欢迎来到 Spring 容器最神秘、最惊心动魄的现场!很多人以为 AOP 是“天生”的, Bean 一出生就带着光环。大错特错!不过是前人在负重前行:Spring 先造出一个“纯净的肉身”(原始对象)&a…...
嵌入式系统调试常见问题与解决方案
嵌入式系统调试中的典型问题分析与解决策略1. 常见调试问题案例分析1.1 程序文件版本错误在嵌入式开发过程中,一个常见的低级错误是使用了错误的程序文件版本。某工程师在调试时发现单片机完全不执行程序,即使是最基本的GPIO控制也无法实现。经过以下排查…...
如何用Python零依赖快速获取百度搜索结果?python-baidusearch深度解析
如何用Python零依赖快速获取百度搜索结果?python-baidusearch深度解析 【免费下载链接】python-baidusearch 自己手写的百度搜索接口的封装,pip安装,支持命令行执行。Baidu Search unofficial API for Python with no external dependencies …...
AI辅助开发:用提示词让快马AI自动生成技术职级成长路径分析应用
AI辅助开发:用提示词让快马AI自动生成技术职级成长路径分析应用 最近在研究技术职级体系时,发现很多开发者对阿里P10这类高级职位的成长路径特别感兴趣。但手动整理这些信息费时费力,于是尝试用AI辅助开发的方式快速生成一个可视化分析工具。…...
脉冲雷达系统仿真:从理论建模到Matlab代码实现
1. 脉冲雷达系统仿真入门指南 第一次接触雷达系统仿真时,我和大多数初学者一样,面对满屏的数学公式和专业术语完全摸不着头脑。直到把实验室那台老式示波器玩坏了三次之后,我才真正理解脉冲雷达仿真的核心逻辑——它本质上就是在计算机里搭建…...
feishu2md:飞书文档批量下载与Markdown转换解决方案
feishu2md:飞书文档批量下载与Markdown转换解决方案 【免费下载链接】feishu2md 一键命令下载飞书文档为 Markdown 项目地址: https://gitcode.com/gh_mirrors/fe/feishu2md 在团队协作和知识管理场景中,飞书文档已成为许多组织的核心工具。然而&…...
