基于GeoTools使用JavaFx进行矢量数据可视化实战

目录

前言

一、JavaFx展示原理说明

二、GeoTools的Maven依赖问题

三、引入Geotools相关的资源包

四、创建JavaFx的Canvas实例

五、JavaFx的Scene和Node的绑定

六、总结


前言

        众所周知,JavaFx是Java继Swing之后的又一款用于桌面应用的开发利器。当然,现在已经是Web的时代,很多以前需要用桌面软件来支撑的软件,现在都可以使用Web的工具来完成。Web是一个大的趋势,同时现在在这里谈论JavaFx,也并不是说要深入研究。首先还是要根据市场需求来,作为Java开发人员,有可能在实际工作过程中,我们的需求方想要开发一个简单的工具。尤其是面向GIS这样的工具,首先不想像Arcgis那么大,甚至像SuperMap或者MapGIS这样的桌面端软件都不要,需求也是非常简单的,只是进行空间数据的简单可视化,或者做简单的空间分析。同时要求我们的软件是可以在跨平台的环境下运行的。当然除了Java,跨平台的可选择性还有许多。不是说跨平台只有Java能做。

        本文以全球各个国家的矢量数据的展示为例,重点讲解如何在JavaFx中进行展示,结合GeoTools来进行展示为需求背景。大家知道,geotools自身的组件框架中,gt_swing是实现桌面应用的一个可视化展示层,虽然在JavaFx中可以将Swing的一些控件进行集成,把Swing的按钮或者表格等放在JavaFx中进行渲染。但是很少把底图放在JavaFx中进行渲染的。当然,哪些使用JavaFx中的WebView嵌入了本地浏览器的不算在内。通过本文,会讲解如何将Geotools的地图在JavaFx中进行展示,大家在实际应用建设过程当中有这个需求的,可以看看博文。

一、JavaFx展示原理说明

        本节将对如何使用JavaFx进行空间数据的可视化进行说明,与Swing组件的机制不同。这里将重点讲解这两者是如何结合在一起,最终实现空间数据的可视化的。

        上图是一张JavaFx的组件架构图,最下面的是JavaFx的两个基石,Jvm和Java的相关API,这些其实都是它的底层依赖基础。 然后构建在JVM和JDK API基础之上的是相关的组件和开发工具包。这是对不同实现需求的组件封装。最上层是JavaFx的展示层,通过JavaAPI和Scene进行展示,其中Scene场景是JavaFx中一个很重要的对象。因此本文的重点也是围绕Scene来进行,通过Scene的构建和展示,帮助我们来实现空间数据的可视化展示。在实现可视化的过程中,还有一个很重要的对象,就是Canvas画布,我们在JavaFx当中实现可视化的基础,是中间渲染的桥梁。

二、GeoTools的Maven依赖问题

        关于GeoTools的Maven依赖问题,由于GeoTools工程项目的相关包不是都在Maven的中央仓库中的,因此我们在配置它的Maven依赖来就跟普通的工程是不一样的。关于GeoTools的maven依赖,其它的很多博主也有相应的文章进行介绍。这里就不再进行赘述。需要申明的是,博客编写过程中,我们的JDK使用的1.8的版本,而对应的Geotools我使用的是28.2的版本。现在Geotools的最新版本应该到31了,大家感兴趣可以到Github中查看一下GeoTools的官方仓库的信息传送门。

        应该是31.x的版本是最新的版本。不过为了兼容我们的Jdk的版本,大家用1.8的Jdk,还是可以使用28.x的版本。因此博客提供的案例都是使用28.x版本。

        如果我们的maven仓库引用的是阿里云的maven私服的话,那么在仓库的定义上要设置好,否则可能导致geotools的依赖包不能下下来。来看下项目工程的Pom.xml配置。

<repositories>
<!--从22.x后geotools由OSGeo管理--><repository><id>osgeo</id><name>OSGeo Release Repository</name><url>https://repo.osgeo.org/repository/release/</url><snapshots><enabled>false</enabled></snapshots><releases><enabled>true</enabled></releases></repository><repository><id>osgeo-snapshot</id><name>OSGeo Snapshot Repository</name><url>https://repo.osgeo.org/repository/snapshot/</url><snapshots><enabled>true</enabled></snapshots><releases><enabled>false</enabled></releases></repository><repository><id>GeoSolutions</id><url>http://maven.geo-solutions.it/</url></repository>
</repositories>

三、引入Geotools相关的资源包

        在pom.xml中定义了Geotools的依赖仓库地址后,我们来正式引入Geotools的相关依赖。这里为了简化,只提供其具体的配置代码,具体的每个组件的功能,在后面的博客中会进行逐一介绍。

<dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.11</version><scope>test</scope></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-shapefile</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-swing</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-main</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools.xsd</groupId><artifactId>gt-xsd-sld</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools.xsd</groupId><artifactId>gt-xsd-core</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.geotools</groupId><artifactId>gt-xml</artifactId><version>${geotools.version}</version></dependency><dependency><groupId>org.jfree</groupId><artifactId>fxgraphics2d</artifactId><version>1.3</version></dependency></dependencies>

        经过上面的步骤,我们基本完成了Geotools官方仓库的定义以及相关依赖包的引用申明,在正常有网络的情况下,系统在后台就会自动帮助我们下载依赖的包。接下来我们来进行具体的功能开发即可。

四、创建JavaFx的Canvas实例

        由于在Jdk1.8当中,Javafx还是绑定在一起的,因此我们不需要单独针对JavaFx来进行配置,但是在1.8后面的版本中,jdk就将javaFx和jdk进行了分离,因此要单独进行配置。在引用相应的geotools的资源包之后,我们就可以来创建最重要的Canvas对象,这个Canvas对象是JavaFx的Canvas对象。通过Canvas对象,实现将Map和画布的融合,从而让数据显示处理。因此这里我们定义Canvas对象,并进行地图的初始化等操作。

        首先我们创建一个Node对象,这个Node对象包括Canvas、Map和GraphicsContext。同时我们提供两个方法,第一个是进行地图初始化的方法,第二个是进行地图数据绘制的方法。下面是定义Node类的属性和方法。

package tutorial1;import java.awt.Rectangle;
import java.io.IOException;import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.map.FeatureLayer;
import org.geotools.map.MapContent;
import org.geotools.renderer.lite.StreamingRenderer;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.jfree.fx.FXGraphics2D;import javafx.scene.Node;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;public class MapCanvas {private Canvas canvas;private MapContent map;private GraphicsContext gc;public MapCanvas(int width, int height) {canvas = new Canvas(width, height);gc = canvas.getGraphicsContext2D();initMap();drawMap(gc);}public Node getCanvas() {return canvas;}private void initMap() {}private void drawMap(GraphicsContext gc) {}
}

        Canvas负责进行展示,而Map对象负责提供显示的数据源。在上述的方法中,我们要先创建一个Canvas对象,在进行对象构造时,指定Canvas对象的高和宽,按照这个尺寸要求来创建。下面我们来看一下如何进行地图的初始化,也就是上面的initMap这个方法。

private void initMap() {try {FileDataStore store = FileDataStoreFinder.getDataStore(this.getClass().getClassLoader().getResource("maps/countries.shp"));SimpleFeatureSource featureSource = store.getFeatureSource();map = new MapContent();map.setTitle("Quickstart");Style style = SLD.createSimpleStyle(featureSource.getSchema());FeatureLayer layer = new FeatureLayer(featureSource, style);map.addLayer(layer);map.getViewport().setScreenArea(new Rectangle((int) canvas.getWidth(), (int) canvas.getHeight()));} catch (IOException e) {e.printStackTrace();}
}

        在进行空间矢量数据的展示时,首先要告诉可视化渲染器,具体的文件在什么位置。接下来是使用样式,为了简单起见,这里使用默认样式来进行可视化,创建样式的时候,样式构建器会根据数据的类型来进行分别构建,比如不同的点、线、面,它的默认样式都是不一样的。这里的数据是面,因此会勾画出边界的线信息。代码如下:

Style style = SLD.createSimpleStyle(featureSource.getSchema());

        最后将样式和数据源进行绑定,然后将图层对象设置到map当中。MapContent这个对象就承载着双发的一个展示容器,最后通过返回这个node,将node和JavaFx的scene场景进行融合。再来看一下绘制地图的方法:

private void drawMap(GraphicsContext gc) {StreamingRenderer draw = new StreamingRenderer();draw.setMapContent(map);FXGraphics2D graphics = new FXGraphics2D(gc);graphics.setBackground(java.awt.Color.WHITE);Rectangle rectangle = new Rectangle((int) canvas.getWidth(), (int) canvas.getHeight());draw.paint(graphics, rectangle, map.getViewport().getBounds());
}

        在这里,通过JavaFx的Graphics对象就可以实现地图的绘制。

public Node getCanvas() {return canvas;
}

五、JavaFx的Scene和Node的绑定

        虽然在上面的代码中已经实现了将Node对象进行创建,但是还是没有将Node和JavaFx的容器进行绑定,没有Scene的搭载就像没有舞台的演员,想展示自己的才艺都没有舞台。因此最后我们要将Node对象和Scene进行绑定即可。

package tutorial1;import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.stage.Stage;public class MainTutorial1 extends Application {@Overridepublic void start(Stage primaryStage) {MapCanvas canvas = new MapCanvas(1090, 670);Pane pane = new Pane(canvas.getCanvas());Scene scene = new Scene(pane);primaryStage.setScene(scene);primaryStage.setTitle("JavaFx结合Geotools展示地图");primaryStage.show();}public static void main(String[] args) {launch(args);}
}

        上面的代码非常简单,通过创建的Canvas对象,然后设置一个地图展示的高度和宽度。将创建的对象和JavaFx的Scene进行绑定,最后设置好JavaFx的应用窗口的标题后,调用Show方法实现空间数据的可视化展示,最后运行的可视化效果如下:

        经过以上的步骤,我们就实现了在JavaFx中调用Geotools的相关库实现空间矢量数据的快速预览。 当然,这里只展示了空间可视化的效果。这个程序还是有很多进步的空间,比如需要增加鼠标的拖动和缩放、还要支持样式的定制等操作。时间缘故,下次再深入的来将这些设置,本文到此结束。

六、总结

        以上就是本文的主要内容, 本文以全球各个国家的矢量数据的展示为例,重点讲解如何在JavaFx中进行展示,结合GeoTools来进行展示为需求背景。大家知道,geotools自身的组件框架中,gt_swing是实现桌面应用的一个可视化展示层,虽然在JavaFx中可以将Swing的一些控件进行集成,把Swing的按钮或者表格等放在JavaFx中进行渲染。但是很少把底图放在JavaFx中进行渲染的。当然,哪些使用JavaFx中的WebView嵌入了本地浏览器的不算在内。通过本文,会讲解如何将Geotools的地图在JavaFx中进行展示,大家在实际应用建设过程当中有这个需求的,可以看看博文。

        本文行文仓促,难免有许多不足之处,还恳请各位专家和朋友们在阅读本文时在评论区留下宝贵意见,鄙人不胜感激。GeoTools非常值得学习,在Java进行GIS开发,一定要掌握这个组件库,提高我们的GIS技术开发能力。

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

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

相关文章

9.C基础_指针与数组

数组指针&#xff08;一维数组&#xff09; 数组指针就是" 数组的指针 "&#xff0c;它是一个指向数组首地址的指针变量。 1、数组名的含义 对于一维数组&#xff0c;数组名就是一个指针&#xff0c;指向数组的首地址。 基于如下代码进行分析&#xff1a; int a…

语言模型-神经网络模型(二)

神经网络模型语言模型 神经网络模型神经网络的分类神经网络模型和Ngram对比应用一-话者分离对比优劣 应用二-数字归一化应用三-文本打标 神经网络模型 释义&#xff1a; 与ngram模型相似使用&#xff0c;前n个词预测下一个词&#xff0c;输出在字表上的概率分布&#xff1b;过…

如何设置 Visual Studio Code 的滚轮缩放功能

Visual Studio Code (VSCode) 是一个强大的代码编辑器&#xff0c;提供了许多便捷的功能来提高开发效率。其中之一就是通过滚轮缩放字体大小。以下是详细的设置步骤&#xff1a; 步骤 1&#xff1a;打开设置页面 首先&#xff0c;启动 Visual Studio Code。在左上角点击 “文…

【机器学习基础】线性回归

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈Python机器学习 ⌋ ⌋ ⌋ 机器学习是一门人工智能的分支学科&#xff0c;通过算法和模型让计算机从数据中学习&#xff0c;进行模型训练和优化&#xff0c;做出预测、分类和决策支持。Python成为机器学习的首选语言&#xff0c;…

集成视触觉传感器的机器人操作学习

强化学习是一种仿人学习的方法&#xff0c;其在不断与环境交互试错的过程中进行学习&#xff0c;提高自身的认知。其具有如下的优点&#xff0c;首先是数据依赖性低&#xff0c;强化学习通过与环境的交互来学习&#xff0c;减少了对标记数据的依赖性&#xff0c;可以大量的减少…

Linux 系统框架分析(一)

一、linux内核结构框图 对内核结构框图有个总体的把握&#xff0c;有助于理解为什么驱动要这样写&#xff0c;为什么写的应用程序所用的C库接口能够产生这么多的事情。 框图可以看出来&#xff0c;linux系统&#xff0c;包括五个系统 一、Linux内核结构介绍 Linux 内核是操作…

Spring及相关框架的重要的问题

Java框架 问题一&#xff1a;Spring框架中的单例bean是线程安全的吗&#xff1f; 看下图&#xff0c;不能被修改的成员变量就是无状态的类&#xff0c;无状态的类没有线程安全问题&#xff0c;所以在开发中尽量避免可修改的成员变量。 回答&#xff1a;不是线程安全的&#xf…

Oracle一对多(一主多备)的DG环境如何进行switchover切换?

本文主要分享Oracle一对多(一主多备)的DG环境的switchover切换&#xff0c;如何进行主从切换&#xff0c;切换后怎么恢复正常同步&#xff1f; 1、环境说明 本文的环境为一主两备&#xff0c;数据库版本为11.2.0.4&#xff0c;主要信息如下&#xff1a; 数据库IPdb_unique_n…

Github 2024-08-09 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-08-09统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目6TypeScript项目4Jupyter Notebook项目1Cuda项目1Sentry:开发者优先的错误跟踪和性能监控平台 创建周期:5093 天开发语言:Python,…

android系统中data下的xml乱码无法查看问题剖析及解决方法

背景&#xff1a; Android12高版本以后系统生成的很多data路径下的xml都变成了二进制类型&#xff0c;根本没办法看xml的内容具体如下&#xff1a; 比如想要看当前系统的widget的相关数据 ./system/users/0/appwidgets.xml 以前老版本都是可以直接看的&#xff0c;这些syste…

旅游出行必备商城小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;新闻类型管理&#xff0c;新闻资讯管理&#xff0c;商品类型管理&#xff0c;旅游商品管理&#xff0c;旅游景点&#xff0c;景点分类&#xff0c;系统管理 微信端账号功能包括&am…

GitHub的常用操作

目录 GitHub GitHub加速 克隆GitHub上的项目到本地 克隆GitHub上指定分支的项目 把本地项目上传到GitHub上管理 删除分支里的内容 单个仓库管理多个项目 上传项目到新建的分支 目前正在逐步熟悉GitHub&#xff0c;打算把整理好的代码上传到GitHub上&#xff0c;建立属…

C++ 类与对象

面向对象程序设计基本特点 特点&#xff1a; 抽象&#xff08;数据抽象&#xff0c;行为抽象&#xff09; 数据抽象&#xff1a;int hour,int minute.....,车&#xff1a;长&#xff0c;宽&#xff0c;高.... 功能抽象&#xff1a;showTime(),setTime() .....车&#xff1a;刹车…

使用Cisco进行模拟配置OSPF路由协议

OSPF路由协议 1.实验目的 1&#xff09;理解OSPF 2&#xff09;掌握OSPF的配置方法 3&#xff09;掌握查看OSPF的相关信息 2.实验流程 开始 → 布置拓扑 → 配置IP地址 → 配置OSPF路由并验证PC路由的连通性 → 查看路由器路由信息 → 查看路由协议配置与统计信息 → 查看O…

【从零开始一步步学习VSOA开发】VSOA命令行工具vcx

VSOA命令行工具vcx vcx 介绍 vcx 是一个使用 VSOA RPC 客户端功能执行器&#xff0c;支持 RPC SET/GET 调用。 [rootsylixos:/root]# [rootsylixos:/root]# vcx -help USAGE: vcx [options] url -h : Show help message. -v : Show vcx version. -z …

[MRCTF2020]PYWebsite-1

打开以后查看源码信息 看到flag.php试着打开 提示看到&#xff0c;需要后端审计代码&#xff0c;而且应该要改ip&#xff0c;改成自己本地&#xff0c;burp抓包看一下 改X-Forwarded-For:127.0.0.1 得到flag flag{74242eb7-844f-4638-8aae-9ec37870d585}

通过LLM大模型将「白雪公主的故事」转为图数据存储

&#x1f4a1; 本次将使用LLM大模型将「白雪公主的故事」转为图数据存储于neo4j数据库中&#xff0c;并展示图数据部分的效果 故事内容 很久很久以前&#xff0c;在一个遥远的王国里&#xff0c;有一位美丽的**王后**生下了一个皮肤像雪一样白皙、嘴唇像血一样鲜红的**女儿**…

网页设计模板范例

随着互联网的发展&#xff0c;网页设计变得越来越重要。一个吸引人的网页设计可以吸引更多的用户&#xff0c;提升用户体验&#xff0c;并且使网站内容更加易于浏览和理解。在这篇文章中&#xff0c;我将为大家介绍一个网页设计模板范例。 1. 选择合适的颜色和字体&#xff1a;…

golang for range time.Ticker 和 time.Timer时间通道使用示例 - 每隔指定时间执行一次,执行指定时长后退出执行

golang中的 ticker和timer时间通道除了可以使用for select case语句来执行外&#xff0c; 还可以使用 for range语句来执行ticker或者timer时间通道。 for range time.Ticker 和 time.Timer时间通道使用示例 下面的示例演示了time.Ticker 和 time.Timer的区别和使用演示。 Ti…

JAVA分布式CAP原则

分布式CAP原则主要是使用SpringCloud框架的时候会涉及到该部分知识点 CAP原则指的是在一个分布式系统中&#xff0c;一致性&#xff0c;可用性&#xff0c;分区容错性 实际的项目开发中&#xff0c;这三者往往是不可兼顾的。 AP&#xff1a;牺牲一致性&#xff0c;保证可用性…