当前位置:   article > 正文

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

基于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配置。

  1. <repositories>
  2. <!--从22.x后geotools由OSGeo管理-->
  3. <repository>
  4. <id>osgeo</id>
  5. <name>OSGeo Release Repository</name>
  6. <url>https://repo.osgeo.org/repository/release/</url>
  7. <snapshots><enabled>false</enabled></snapshots>
  8. <releases><enabled>true</enabled></releases>
  9. </repository>
  10. <repository>
  11. <id>osgeo-snapshot</id>
  12. <name>OSGeo Snapshot Repository</name>
  13. <url>https://repo.osgeo.org/repository/snapshot/</url>
  14. <snapshots><enabled>true</enabled></snapshots>
  15. <releases><enabled>false</enabled></releases>
  16. </repository>
  17. <repository>
  18. <id>GeoSolutions</id>
  19. <url>http://maven.geo-solutions.it/</url>
  20. </repository>
  21. </repositories>

三、引入Geotools相关的资源包

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

  1. <dependencies>
  2. <dependency>
  3. <groupId>junit</groupId>
  4. <artifactId>junit</artifactId>
  5. <version>4.11</version>
  6. <scope>test</scope>
  7. </dependency>
  8. <dependency>
  9. <groupId>org.geotools</groupId>
  10. <artifactId>gt-shapefile</artifactId>
  11. <version>${geotools.version}</version>
  12. </dependency>
  13. <dependency>
  14. <groupId>org.geotools</groupId>
  15. <artifactId>gt-swing</artifactId>
  16. <version>${geotools.version}</version>
  17. </dependency>
  18. <dependency>
  19. <groupId>org.geotools</groupId>
  20. <artifactId>gt-main</artifactId>
  21. <version>${geotools.version}</version>
  22. </dependency>
  23. <dependency>
  24. <groupId>org.geotools.xsd</groupId>
  25. <artifactId>gt-xsd-sld</artifactId>
  26. <version>${geotools.version}</version>
  27. </dependency>
  28. <dependency>
  29. <groupId>org.geotools.xsd</groupId>
  30. <artifactId>gt-xsd-core</artifactId>
  31. <version>${geotools.version}</version>
  32. </dependency>
  33. <dependency>
  34. <groupId>org.geotools</groupId>
  35. <artifactId>gt-xml</artifactId>
  36. <version>${geotools.version}</version>
  37. </dependency>
  38. <dependency>
  39. <groupId>org.jfree</groupId>
  40. <artifactId>fxgraphics2d</artifactId>
  41. <version>1.3</version>
  42. </dependency>
  43. </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类的属性和方法。

  1. package tutorial1;
  2. import java.awt.Rectangle;
  3. import java.io.IOException;
  4. import org.geotools.data.FileDataStore;
  5. import org.geotools.data.FileDataStoreFinder;
  6. import org.geotools.data.simple.SimpleFeatureSource;
  7. import org.geotools.map.FeatureLayer;
  8. import org.geotools.map.MapContent;
  9. import org.geotools.renderer.lite.StreamingRenderer;
  10. import org.geotools.styling.SLD;
  11. import org.geotools.styling.Style;
  12. import org.jfree.fx.FXGraphics2D;
  13. import javafx.scene.Node;
  14. import javafx.scene.canvas.Canvas;
  15. import javafx.scene.canvas.GraphicsContext;
  16. public class MapCanvas {
  17. private Canvas canvas;
  18. private MapContent map;
  19. private GraphicsContext gc;
  20. public MapCanvas(int width, int height) {
  21. canvas = new Canvas(width, height);
  22. gc = canvas.getGraphicsContext2D();
  23. initMap();
  24. drawMap(gc);
  25. }
  26. public Node getCanvas() {
  27. return canvas;
  28. }
  29. private void initMap() {
  30. }
  31. private void drawMap(GraphicsContext gc) {
  32. }
  33. }

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

  1. private void initMap() {
  2. try {
  3. FileDataStore store = FileDataStoreFinder
  4. .getDataStore(this.getClass().getClassLoader().getResource("maps/countries.shp"));
  5. SimpleFeatureSource featureSource = store.getFeatureSource();
  6. map = new MapContent();
  7. map.setTitle("Quickstart");
  8. Style style = SLD.createSimpleStyle(featureSource.getSchema());
  9. FeatureLayer layer = new FeatureLayer(featureSource, style);
  10. map.addLayer(layer);
  11. map.getViewport().setScreenArea(new Rectangle((int) canvas.getWidth(), (int) canvas.getHeight()));
  12. } catch (IOException e) {
  13. e.printStackTrace();
  14. }
  15. }

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

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

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

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

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

  1. public Node getCanvas() {
  2. return canvas;
  3. }

五、JavaFx的Scene和Node的绑定

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

  1. package tutorial1;
  2. import javafx.application.Application;
  3. import javafx.scene.Scene;
  4. import javafx.scene.layout.Pane;
  5. import javafx.stage.Stage;
  6. public class MainTutorial1 extends Application {
  7. @Override
  8. public void start(Stage primaryStage) {
  9. MapCanvas canvas = new MapCanvas(1090, 670);
  10. Pane pane = new Pane(canvas.getCanvas());
  11. Scene scene = new Scene(pane);
  12. primaryStage.setScene(scene);
  13. primaryStage.setTitle("JavaFx结合Geotools展示地图");
  14. primaryStage.show();
  15. }
  16. public static void main(String[] args) {
  17. launch(args);
  18. }
  19. }

        上面的代码非常简单,通过创建的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技术开发能力。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/秋刀鱼在做梦/article/detail/975519
推荐阅读
相关标签
  

闽ICP备14008679号