GeoTools入门(二)-- 快速入门

今天药忘吃喽~ 2022-10-10 14:55 552阅读 0赞

1. 前言

本系列文章主要参考GeoTools官网的13个示例GeoTools Tutorials,做一简化阐述以及扩展。在第一节Quickstart中,我们主要讲述一下Maven Quickstart这个示例讲解,其他的实例大家可以参照官网做进一步学习。另外,为了降低学习成本,本系列课程的摒弃了QGIS、UDig等可视化工具,而是通过本篇文章提到的JMapFrame框架展示处理结果。

2. 数据准备

本实例主要用到的数据为官网提供的实例数据1:50m Cultural Vectors。

3. pom文件

本示例采用自行编译的19.1的版本。大家可以根据实际情况决定使用的版本。pom文件内容如下:

  1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  2. <modelVersion>4.0.0</modelVersion>
  3. <groupId>cn.surpass</groupId>
  4. <artifactId>geotools</artifactId>
  5. <version>0.0.1-SNAPSHOT</version>
  6. <url>http://maven.apache.org</url>
  7. <!--定义的常量-->
  8. <properties>
  9. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  10. <geotools.version>19.1</geotools.version>
  11. </properties>
  12. <dependencies>
  13. <dependency>
  14. <groupId>junit</groupId>
  15. <artifactId>junit</artifactId>
  16. <version>4.13.1</version>
  17. <scope>test</scope>
  18. </dependency>
  19. <dependency>
  20. <groupId>org.geotools</groupId>
  21. <artifactId>gt-shapefile</artifactId>
  22. <version>${geotools.version}</version>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.geotools</groupId>
  26. <artifactId>gt-swing</artifactId>
  27. <version>${geotools.version}</version>
  28. </dependency>
  29. </dependencies>
  30. <repositories>
  31. <repository>
  32. <id>osgeo</id>
  33. <name>OSGeo Release Repository</name>
  34. <url>https://repo.osgeo.org/repository/release/</url>
  35. <snapshots><enabled>false</enabled></snapshots>
  36. <releases><enabled>true</enabled></releases>
  37. </repository>
  38. <repository>
  39. <id>osgeo-snapshot</id>
  40. <name>OSGeo Snapshot Repository</name>
  41. <url>https://repo.osgeo.org/repository/snapshot/</url>
  42. <snapshots><enabled>true</enabled></snapshots>
  43. <releases><enabled>false</enabled></releases>
  44. </repository>
  45. </repositories>
  46. <build>
  47. <plugins>
  48. <plugin>
  49. <inherited>true</inherited>
  50. <groupId>org.apache.maven.plugins</groupId>
  51. <artifactId>maven-compiler-plugin</artifactId>
  52. <configuration>
  53. <source>1.8</source>
  54. <target>1.8</target>
  55. </configuration>
  56. </plugin>
  57. </plugins>
  58. </build>
  59. </project>

需要指出的一点是: 我们正常的maven仓库(比如alimavenrepo2)并没有提供关于GeoTools的jar包,所以,这里需要指定GeoTools相关依赖包的中心仓库。当然,我这里是自行编译的版本,所以这里可以没有repositories的相关配置。

4. 展示代码

  1. package cn.curpass.geotools.quickstart;
  2. import java.io.File;
  3. import org.geotools.data.FileDataStore;
  4. import org.geotools.data.FileDataStoreFinder;
  5. import org.geotools.data.simple.SimpleFeatureSource;
  6. import org.geotools.map.FeatureLayer;
  7. import org.geotools.map.Layer;
  8. import org.geotools.map.MapContent;
  9. import org.geotools.styling.SLD;
  10. import org.geotools.styling.Style;
  11. import org.geotools.swing.JMapFrame;
  12. import org.geotools.swing.data.JFileDataStoreChooser;
  13. public class Quickstart {
  14. public static void main(String[] args) throws Exception {
  15. // 选择一个shp文件
  16. File file = JFileDataStoreChooser.showOpenFile("shp", null);
  17. if (file == null) {
  18. return;
  19. }
  20. //加载shp图层数据源
  21. FileDataStore store = FileDataStoreFinder.getDataStore(file);
  22. SimpleFeatureSource featureSource = store.getFeatureSource();
  23. // 创建一个地图容器
  24. MapContent map = new MapContent();
  25. map.setTitle("Quickstart");
  26. //创建一个简单的样式,并将样式和shp数据源加载到一个图层上
  27. Style style = SLD.createSimpleStyle(featureSource.getSchema());
  28. Layer layer = new FeatureLayer(featureSource, style);
  29. //在地图容器添加图层
  30. map.addLayer(layer);
  31. // 展示地图
  32. JMapFrame.showMap(map);
  33. }
  34. }

这段代码读起来并不困难,需要注意一点是,我们所说的矢量图层主要记录的是图形的坐标信息,如果要做图形化渲染,还需要一个SLD的样式文件。在这个文件里,主要记录了一些样式信息。比如:

  • 对于点状要素,主要记录点的显示符号、大小等,也可以记录在地图上显示点属性的文本信息;
  • 对于线状要素,主要记录线型、线宽、线的颜色或者文字标注信息。
  • 对于面状要素,主要记录面的轮廓线的信息(线型、线宽、颜色等),填充的样式或者颜色信息以及文字标注的信息。

另外可以针对shp要素的属性信息有区别化的渲染要素信息。比如,对于一个面状的中国地图,可以通过省份的字段针对不用省份显示不同的颜色。

虽然这段代码简单,我还是想画一个图,方便大家记忆:

shp文件

要 素 数 据 源

图层

MapContent

地图展示

SLD 样式文件

5. 效果展示

此时,我们运行程序,选择对应的shp文件(这里需要注意的是我们需要选择以shp为后缀名的shp文件)。通过GeoTools提供的界面按钮我们可以对显示图形做放大、缩小、平移等操作。

6. 程序改进

6.1 自动识别shp文件

通过上诉程序我们知道,必须选择以“shp”为后缀名的文件,否则会报空指针异常。所以我们做的一个优化是通过选择一个文件后,我们会自动查找相同路径、相同文件名字并且以“shp”结尾的文件。

  1. private static File findShpFile(File file){
  2. if(file.getName().toLowerCase().endsWith(".shp")){
  3. return file;
  4. }
  5. String path = file.getAbsolutePath();
  6. String shpPath = path.substring(0,path.lastIndexOf(".")) + ".shp";
  7. File shpFile = new File(shpPath);
  8. if(!shpFile.exists()){
  9. throw new RuntimeException("当前文件夹不存在以shp结尾的文件");
  10. }
  11. return shpFile;
  12. }

6.2 配置多种数据源

在实际的开发过程中,通过选择本地shp文件创建FileDataStore的情况还是不多的,更多的情况是连接到数据库(比如postGis)或者 Web 功能服务器(Geoserver)。此时我们需要另外一种方式创建FileDataStore,即DataStoreFinder,代码如下:

  1. File file = JFileDataStoreChooser.showOpenFile("shp", null);
  2. Map<String, Object> params = new HashMap<>();
  3. params.put("url", file.toURI().toURL());
  4. params.put("create spatial index", false);
  5. params.put("memory mapped buffer", false);
  6. params.put("charset", "ISO-8859-1");
  7. DataStore store = DataStoreFinder.getDataStore(params);
  8. SimpleFeatureSource featureSource = store.getFeatureSource(store.getTypeNames()[0]);

通过上面的代码我们发现,通过传递一个Map,而这个Map有一个key为url,就是配置多种数据源的。到这里,有可能有人有疑问了,这只有一个URL,如果连接数据库涉及到的用户名或者密码怎么办?如果是Web 功能服务器需要传递一些认证信息怎么办?这里就体现了这里设计思想的强大之处,通过一个Map,传递不同的参数。也为后面的多数据源提供了强大的扩展性。下面我们主要以PostGis为例,说明一下GeoTools怎么配置数据库的数据源。

6.2.1 配置postGis数据源

上面的实例只是简单的说明了配置其他的数据源,需要配置postgis数据源还是有点复杂。

6.2.1.1 pom引入

要增加如下的依赖

  1. <dependency>
  2. <groupId>org.geotools.jdbc</groupId>
  3. <artifactId>gt-jdbc-postgis</artifactId>
  4. <version>${geotools.version}</version>
  5. </dependency>
6.2.1.2 post连接工具类
  1. /** * 通过PostGis获取FeatureSource * @param host ip地址 * @param port 端口号 * @param database 需要连接的数据库 * @param userName 用户名 * @param password 密码 * @param tableName 需要连接的表名 * @return */
  2. public static SimpleFeatureSource connAndGetFeatureSource(
  3. String host, String port, String database,
  4. String userName,String password, String tableName) {
  5. Map<String, Object> params = new HashMap<String, Object>(8);
  6. //需要连接何种数据库,postgis
  7. params.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
  8. //ip地址
  9. params.put(PostgisNGDataStoreFactory.HOST.key, host);
  10. //端口号
  11. params.put(PostgisNGDataStoreFactory.PORT.key, new Integer(port));
  12. //需要连接的数据库
  13. params.put(PostgisNGDataStoreFactory.DATABASE.key, database);
  14. //架构
  15. params.put(PostgisNGDataStoreFactory.SCHEMA.key, "public");
  16. //需要连接数据库的名称
  17. params.put(PostgisNGDataStoreFactory.USER.key, userName);
  18. //数据库的密码
  19. params.put(PostgisNGDataStoreFactory.PASSWD.key, password);
  20. try {
  21. //获取存储空间
  22. DataStore pgDataStore = DataStoreFinder.getDataStore(params);
  23. //根据表名获取source
  24. return pgDataStore.getFeatureSource(tableName);
  25. } catch (IOException e) {
  26. throw new RuntimeException(e.getMessage(), e);
  27. }
  28. }
6.2.1.3 测试类
  1. public class QuickStart {
  2. public static void main(String[] args) throws IOException {
  3. SimpleFeatureSource featureSource = getFeatureSourceByPostGis();
  4. MapContent map = new MapContent();
  5. map.setTitle("Quickstart");
  6. Style style = SLD.createSimpleStyle(featureSource.getSchema());
  7. Layer layer = new FeatureLayer(featureSource, style);
  8. map.addLayer(layer);
  9. JMapFrame.showMap(map);
  10. }
  11. private static SimpleFeatureSource getFeatureSourceByPostGis() {
  12. String ip = "192.168.10.201";
  13. String port = "5432";
  14. String database = "nyc";
  15. String userName = "postgres";
  16. String password = "postgres";
  17. String tableName = "nyc_neighborhoods";
  18. return PostGisUtil.connAndGetFeatureSource(
  19. ip, port, database, userName, password, tableName);
  20. }
  21. }

发表评论

表情:
评论列表 (有 0 条评论,552人围观)

还没有评论,来说两句吧...

相关阅读