当前位置: 首页 > 工具软件 > ContentTools > 使用案例 >

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

江天宇
2023-12-01

1. 前言

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

2. 数据准备

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

3. pom文件

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

<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">
    <modelVersion>4.0.0</modelVersion>
    <groupId>cn.surpass</groupId>
    <artifactId>geotools</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <url>http://maven.apache.org</url>
    <!--定义的常量-->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <geotools.version>19.1</geotools.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</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>
    </dependencies>
    <repositories>
      <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>
    </repositories>
    <build>
        <plugins>
            <plugin>
                <inherited>true</inherited>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

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

4. 展示代码

package cn.curpass.geotools.quickstart;

import java.io.File;
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.Layer;
import org.geotools.map.MapContent;
import org.geotools.styling.SLD;
import org.geotools.styling.Style;
import org.geotools.swing.JMapFrame;
import org.geotools.swing.data.JFileDataStoreChooser;


public class Quickstart {

    public static void main(String[] args) throws Exception {
        // 选择一个shp文件
        File file = JFileDataStoreChooser.showOpenFile("shp", null);
        if (file == null) {
            return;
        }

        //加载shp图层数据源
        FileDataStore store = FileDataStoreFinder.getDataStore(file);
        SimpleFeatureSource featureSource = store.getFeatureSource();

        // 创建一个地图容器
        MapContent map = new MapContent();
        map.setTitle("Quickstart");

        //创建一个简单的样式,并将样式和shp数据源加载到一个图层上
        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Layer layer = new FeatureLayer(featureSource, style);
        
        //在地图容器添加图层
        map.addLayer(layer);

        // 展示地图
        JMapFrame.showMap(map);
    }
}

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

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

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

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

shp文件
要 素 数 据 源
图层
MapContent
地图展示
SLD 样式文件

5. 效果展示

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

6. 程序改进

6.1 自动识别shp文件

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

private static File findShpFile(File file){
    if(file.getName().toLowerCase().endsWith(".shp")){
        return file;
    }
    String path = file.getAbsolutePath();
    String shpPath = path.substring(0,path.lastIndexOf(".")) + ".shp";
    File shpFile = new File(shpPath);
    if(!shpFile.exists()){
        throw new RuntimeException("当前文件夹不存在以shp结尾的文件");
    }
    return shpFile;
}

6.2 配置多种数据源

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

File file = JFileDataStoreChooser.showOpenFile("shp", null);

Map<String, Object> params = new HashMap<>();
params.put("url", file.toURI().toURL());
params.put("create spatial index", false);
params.put("memory mapped buffer", false);
params.put("charset", "ISO-8859-1");

DataStore store = DataStoreFinder.getDataStore(params);
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引入

要增加如下的依赖

<dependency>
    <groupId>org.geotools.jdbc</groupId>
    <artifactId>gt-jdbc-postgis</artifactId>
    <version>${geotools.version}</version>
</dependency>
6.2.1.2 post连接工具类
/**
     * 通过PostGis获取FeatureSource
     * @param host ip地址
     * @param port 端口号
     * @param database 需要连接的数据库
     * @param userName 用户名
     * @param password 密码
     * @param tableName 需要连接的表名
     * @return
     */
    public static SimpleFeatureSource connAndGetFeatureSource(
        		String host, String port, String database, 
        		String userName,String password, String tableName) {
        Map<String, Object> params = new HashMap<String, Object>(8);
        //需要连接何种数据库,postgis
        params.put(PostgisNGDataStoreFactory.DBTYPE.key, "postgis");
        //ip地址
        params.put(PostgisNGDataStoreFactory.HOST.key, host);
        //端口号
        params.put(PostgisNGDataStoreFactory.PORT.key, new Integer(port));
        //需要连接的数据库
        params.put(PostgisNGDataStoreFactory.DATABASE.key, database);
        //架构
        params.put(PostgisNGDataStoreFactory.SCHEMA.key, "public");
        //需要连接数据库的名称
        params.put(PostgisNGDataStoreFactory.USER.key, userName);
        //数据库的密码
        params.put(PostgisNGDataStoreFactory.PASSWD.key, password);
        try {
            //获取存储空间
            DataStore pgDataStore = DataStoreFinder.getDataStore(params);
            //根据表名获取source
            return pgDataStore.getFeatureSource(tableName);
        } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }
6.2.1.3 测试类
public class QuickStart {

    public static void main(String[] args) throws IOException {

        SimpleFeatureSource featureSource = getFeatureSourceByPostGis();

        MapContent map = new MapContent();
        map.setTitle("Quickstart");

        Style style = SLD.createSimpleStyle(featureSource.getSchema());
        Layer layer = new FeatureLayer(featureSource, style);
        map.addLayer(layer);
        JMapFrame.showMap(map);
    }

    private static SimpleFeatureSource getFeatureSourceByPostGis() {
            String ip = "192.168.10.201";
            String port = "5432";
            String database = "nyc";
            String userName = "postgres";
            String password = "postgres";
        String tableName = "nyc_neighborhoods";
        return PostGisUtil.connAndGetFeatureSource(
            ip, port, database, userName, password, tableName);
    }
}
 类似资料: