【GIS系列】GeoTools简介及工具类分享

news2024/10/5 20:23:11

本文将对GeoTools相关概念进行介绍,同时会给大家分享我工作中用到的工具类及使用方法。

作者:后端小肥肠

目录

1.前言

2. GeoTools简介

3. Geotools使用示例

3.1. 开发环境搭建

3.1.1. 所需版本和工具

3.1.2. pom依赖​​​​​​​

4. 工具类介绍

4.1. 读取shp工具类

4.1.1 准备数据

4.1.2. 部分方法

4.1.3. 完整工具类代码

4.2. 坐标转换工具类

4.2.1. 准备数据

4.2.2. 完整工具类代码

5. 结语

6. 参考链接 


1.前言

GeoTools是一个功能强大的开源GIS工具库,为地理空间数据处理和分析提供了丰富的功能和便利的接口。无论您是GIS专业人士还是对地理空间数据感兴趣的开发人员,掌握GeoTools都是必不可少的。本文将从基本概念入手,介绍GeoTools的功能和使用方法,并重点分享一些实用的工具类和技巧,希望能为您在GIS应用开发中提供帮助和启发。

2. GeoTools简介

GeoTools是一个开源的Java库,用于处理和分析地理空间数据。它提供了一系列用于读取、写入、处理和可视化地理空间数据的工具和API。以下是与GeoTools相关的一些重要概念:

  1. 地理空间数据(Geospatial Data): GeoTools主要用于处理地理空间数据,这包括地图、地形、卫星影像、矢量数据等地理信息。这些数据通常具有地理坐标信息和地理属性信息。

  2. 地理坐标系统(Geographic Coordinate System,GCS): 地理坐标系统是用于在地球上定位点的一种方法。GeoTools支持多种地理坐标系统,包括经纬度坐标系统等。

  3. 投影坐标系统(Projected Coordinate System,PCS): 投影坐标系统是将地球表面的地理坐标投影到平面上的一种方法。GeoTools提供了许多常用的投影方法和投影坐标系统的支持。

  4. 数据格式(Data Formats): GeoTools支持多种地理空间数据格式,如Shapefile、GeoJSON、KML、GML等,可以方便地读取和写入这些数据格式。

  5. 空间分析(Spatial Analysis): GeoTools提供了丰富的空间分析功能,包括缓冲区分析、空间查询、空间叠加分析等,可以帮助用户进行地理空间数据的处理和分析。

总的来说,GeoTools是一个功能丰富的GIS工具库,提供了丰富的功能和工具,可以帮助用户处理和分析各种地理空间数据,并构建地理空间应用。

3. Geotools使用示例

3.1. 开发环境搭建

3.1.1. 所需版本和工具
依赖版本
Spring Boot2.6.14
GeoTools4.4.18
java1.8以上
ArcGis10.8

我这里用的不是GeoTools的最新版本,需要最新版本的同学可登录GeoTools的官网(GeoTools The Open Source Java GIS Toolkit — GeoTools)查看最新版本和其使用规则。

如上图所示,最新版本的GeoTools跟java11适配。

3.1.2. pom依赖
         <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-shapefile</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-geojson</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.geotools</groupId>
            <artifactId>gt-swing</artifactId>
            <version>${geotools.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

4. 工具类介绍

4.1. 读取shp工具类

4.1.1 准备数据

打开ArcGis绘制面数据,我这里绘制了4490坐标系的几个面要素。

4.1.2. 部分方法

1. 读取shp中的空间要素信息(wkt)

public static List<String> getWktFromShp(String shpPath) {
        List<String> shpList = new ArrayList<>();
        SimpleFeatureCollection simpleFeatureCollection = null;
        try {
            //获取文件
            File file = new File(shpPath);
            // 读取到数据存储中
            FileDataStore dataStore = FileDataStoreFinder.getDataStore(file);
            // 获取特征资源
            SimpleFeatureSource simpleFeatureSource = dataStore.getFeatureSource();
            // 要素集合
            simpleFeatureCollection = simpleFeatureSource.getFeatures();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取要素迭代器
        SimpleFeatureIterator featureIterator = simpleFeatureCollection.features();
        while (featureIterator.hasNext()) {
            // 要素对象
            SimpleFeature feature = featureIterator.next();
            Object geometryText = feature.getDefaultGeometry();
            log.info(geometryText.toString());
            shpList.add(geometryText.toString());

        }
        featureIterator.close();
        return shpList;
    }

2. 运行结果

3. 读取shp文件并将其转换为Geojson

    /**
     * 构造Geojson结构体
     * @param featuresJson
     * @return
     */
    public static JSONObject buildGeoJson(JSONArray featuresJson) {
        JSONObject Geojson = new JSONObject();
        Geojson.put("type", "FeatureCollection");
        Geojson.put("features", featuresJson);
        return Geojson;
    }
 /**
     * 构造Geojson的features部分 单个
     *
     * @param geoObject
     * @param properties
     * @return
     */
    public static JSONObject buildFeature(Map geoObject, Map properties) {
        JSONObject featureObject = new JSONObject();
        Map featureMap = new HashMap();
        featureMap.put("type", "Feature");
        featureMap.putAll(geoObject);
        featureMap.put("properties", properties);
        featureObject.putAll(featureMap);
        return featureObject;
    }
 /**
     * 获取空间信息并构造为Map
     * @param wkt
     * @return
     */
    public static Map getGeoMap(String wkt) {
        Map<String, Object> geoMap = new HashMap<>();
        String json = null;
        try {
            WKTReader reader = new WKTReader();
            Geometry geometry = reader.read(wkt);
            StringWriter writer = new StringWriter();
            GeometryJSON g = new GeometryJSON();
            g.write(geometry, writer);
            geoMap.put("geometry", writer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return geoMap;
    }

 /**
     * 基于shp构造geojson并返回
     *
     * @param shpPath
     * @return
     */
    public static JSONObject buildGeojsonFromShp(String shpPath) {
        JSONArray featureArray = new JSONArray();
//        List<String>shpList=new ArrayList<>();
        SimpleFeatureCollection simpleFeatureCollection = null;
        try {
//            要素合集
            //获取文件
            File file = new File(shpPath);
            // 读取到数据存储中
            ShapefileDataStore dataStore = (ShapefileDataStore) FileDataStoreFinder.getDataStore(file);
            dataStore.setCharset(Charset.forName("GBK"));
            // 获取特征资源
            SimpleFeatureSource simpleFeatureSource = dataStore.getFeatureSource();
            // 要素集合
            simpleFeatureCollection = simpleFeatureSource.getFeatures();
        } catch (IOException e) {
            e.printStackTrace();
        }
        SimpleFeatureIterator featureIterator = simpleFeatureCollection.features();
//            // 要素数量
        int featureSize = simpleFeatureCollection.size();
//            log.info("要素数量"+featureSize);
        //创建properties  Map
        while (featureIterator.hasNext()) {
            // 要素对象
            SimpleFeature feature = featureIterator.next();
            Collection<Property> propertyCollection = (Collection<Property>) feature.getValue();
            //填充属性map
            Map<String, Object> properMap = new HashMap<>();
            for (Property property : propertyCollection) {
                if (property.getName().toString().equals("the_geom")) {
                    continue;
                }
                properMap.put(property.getName().toString(), property.getValue());
            }
            //获取geo信息
            Object geometryText = feature.getDefaultGeometry();
            Map geoMap = getGeoMap(geometryText.toString());
            JSONObject featureObject = buildFeature(geoMap, properMap);
            featureArray.add(featureObject);
        }
        featureIterator.close();
        JSONObject GeoJson = buildGeoJson(featureArray);

        return GeoJson;
    }

4. 运行结果

4.1.3. 完整工具类代码
import lombok.extern.slf4j.Slf4j;
import org.geotools.data.FileDataStore;
import org.geotools.data.FileDataStoreFinder;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.geojson.geom.GeometryJSON;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.io.WKTWriter;
import org.opengis.feature.Property;
import org.opengis.feature.simple.SimpleFeature;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.Charset;
import java.util.*;

/**
 * @version 1.0
 * @description: gis工具类
 * @author: chenss
 * @date 2024-03-14 16:19
 */
@Slf4j
public class GisUtil {
    public static void main(String[] args) {
        JSONObject Geojson=buildGeojsonFromShp("D:\\arcgisdata\\mesh4490.shp");
        log.info(Geojson.toJSONString());
//        List<String> wkts = getWktFromShp("D:\\arcgisdata\\mesh4490.shp");
//        for (String wkt : wkts) {
//            log.info(wkt);
//        }
    }

    /**
     * 构造Geojson结构体
     * @param featuresJson
     * @return
     */
    public static JSONObject buildGeoJson(JSONArray featuresJson) {
        JSONObject Geojson = new JSONObject();
        Geojson.put("type", "FeatureCollection");
        Geojson.put("features", featuresJson);
        return Geojson;
    }

    /**
     * 构造Geojson的features部分 单个
     *
     * @param geoObject
     * @param properties
     * @return
     */
    public static JSONObject buildFeature(Map geoObject, Map properties) {
        JSONObject featureObject = new JSONObject();
        Map featureMap = new HashMap();
        featureMap.put("type", "Feature");
        featureMap.putAll(geoObject);
        featureMap.put("properties", properties);
        featureObject.putAll(featureMap);
        return featureObject;
    }

    /**
     * 获取空间信息并构造为Map
     * @param wkt
     * @return
     */
    public static Map getGeoMap(String wkt) {
        Map<String, Object> geoMap = new HashMap<>();
        String json = null;
        try {
            WKTReader reader = new WKTReader();
            Geometry geometry = reader.read(wkt);
            StringWriter writer = new StringWriter();
            GeometryJSON g = new GeometryJSON();
            g.write(geometry, writer);
            geoMap.put("geometry", writer);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return geoMap;
    }

    /**
     * 只读取geo信息 wkt
     *
     * @param shpPath
     * @return
     */
    public static List<String> getWktFromShp(String shpPath) {
        List<String> shpList = new ArrayList<>();
        SimpleFeatureCollection simpleFeatureCollection = null;
        try {
            //获取文件
            File file = new File(shpPath);
            // 读取到数据存储中
            FileDataStore dataStore = FileDataStoreFinder.getDataStore(file);
            // 获取特征资源
            SimpleFeatureSource simpleFeatureSource = dataStore.getFeatureSource();
            // 要素集合
            simpleFeatureCollection = simpleFeatureSource.getFeatures();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 获取要素迭代器
        SimpleFeatureIterator featureIterator = simpleFeatureCollection.features();
        while (featureIterator.hasNext()) {
            // 要素对象
            SimpleFeature feature = featureIterator.next();
            Object geometryText = feature.getDefaultGeometry();
            log.info(geometryText.toString());
            shpList.add(geometryText.toString());

        }
        featureIterator.close();
        return shpList;
    }

    /**
     * 基于shp构造geojson并返回
     *
     * @param shpPath
     * @return
     */
    public static JSONObject buildGeojsonFromShp(String shpPath) {
        JSONArray featureArray = new JSONArray();
//        List<String>shpList=new ArrayList<>();
        SimpleFeatureCollection simpleFeatureCollection = null;
        try {
//            要素合集
            //获取文件
            File file = new File(shpPath);
            // 读取到数据存储中
            ShapefileDataStore dataStore = (ShapefileDataStore) FileDataStoreFinder.getDataStore(file);
            dataStore.setCharset(Charset.forName("GBK"));
            // 获取特征资源
            SimpleFeatureSource simpleFeatureSource = dataStore.getFeatureSource();
            // 要素集合
            simpleFeatureCollection = simpleFeatureSource.getFeatures();
        } catch (IOException e) {
            e.printStackTrace();
        }
        SimpleFeatureIterator featureIterator = simpleFeatureCollection.features();
//            // 要素数量
        int featureSize = simpleFeatureCollection.size();
//            log.info("要素数量"+featureSize);
        //创建properties  Map
        while (featureIterator.hasNext()) {
            // 要素对象
            SimpleFeature feature = featureIterator.next();
            Collection<Property> propertyCollection = (Collection<Property>) feature.getValue();
            //填充属性map
            Map<String, Object> properMap = new HashMap<>();
            for (Property property : propertyCollection) {
                if (property.getName().toString().equals("the_geom")) {
                    continue;
                }
                properMap.put(property.getName().toString(), property.getValue());
            }
            //获取geo信息
            Object geometryText = feature.getDefaultGeometry();
            Map geoMap = getGeoMap(geometryText.toString());
            JSONObject featureObject = buildFeature(geoMap, properMap);
            featureArray.add(featureObject);
        }
        featureIterator.close();
        JSONObject GeoJson = buildGeoJson(featureArray);

        return GeoJson;
    }

    /**
     * 根据给定的wkt面求出中心点,并以wkt形式返回
     */
    public static String calculateCenter(String wktPolygon) throws ParseException {
        // 创建 WKT 解析器和写入器
        WKTReader reader = new WKTReader(new GeometryFactory());
        WKTWriter writer = new WKTWriter();

        // 解析面的几何对象
        Geometry geometry = reader.read(wktPolygon);

        // 计算面的中心点
        Point center = geometry.getCentroid();

        // 将中心点转换为 WKT 格式
        String wktCenter = writer.write(center);

        return wktCenter;
    }


}

4.2. 坐标转换工具类

我这个坐标转换工具只应用于同椭球(本文示例为2000坐标系-EPSG:4490)坐标投影转换。已云南的投影带为33-35,对应的EPSG为4521、4522、4523。

4.2.1. 准备数据

1. 准备4490、4521、4522、4523的shp

2. 获取.prj中坐标描述信息

3. 将坐标描述信息存放到常量Map中

static final  Map<String,String> projMap=new HashMap();
static {
    projMap.put("4522","PROJCS["CGCS2000_3_Degree_GK_Zone_34",GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",DATUM["D_China_2000",SPHEROID["CGCS2000",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",34500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",102.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]");
    projMap.put("4490","GEOGCS["China Geodetic Coordinate System 2000",\n" +
            "    DATUM["China_2000",\n" +
            "        SPHEROID["CGCS2000",6378137,298.257222101,\n" +
            "            AUTHORITY["EPSG","1024"]],\n" +
            "        AUTHORITY["EPSG","1043"]],\n" +
            "    PRIMEM["Greenwich",0,\n" +
            "        AUTHORITY["EPSG","8901"]],\n" +
            "    UNIT["degree",0.0174532925199433,\n" +
            "        AUTHORITY["EPSG","9122"]],\n" +
            "    AUTHORITY["EPSG","4490"]]");
    projMap.put("4521","PROJCS["CGCS2000_3_Degree_GK_Zone_33",GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",DATUM["D_China_2000",SPHEROID["CGCS2000",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",33500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",99.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]");
    projMap.put("4523","PROJCS["CGCS2000_3_Degree_GK_Zone_35",GEOGCS["GCS_China_Geodetic_Coordinate_System_2000",DATUM["D_China_2000",SPHEROID["CGCS2000",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Gauss_Kruger"],PARAMETER["False_Easting",35500000.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",105.0],PARAMETER["Scale_Factor",1.0],PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]");
}
4.2.2. 完整工具类代码
import lombok.extern.slf4j.Slf4j;
import org.geotools.data.FeatureWriter;
import org.geotools.data.FileDataStoreFactorySpi;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.data.simple.SimpleFeatureIterator;
import org.geotools.data.simple.SimpleFeatureSource;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.CRS;
import org.locationtech.jts.geom.Geometry;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import java.io.File;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@Slf4j
public class ProjTransUtil {
    static final  Map<String,String> projMap=new HashMap();
    static {
        projMap.put("4522","PROJCS[\"CGCS2000_3_Degree_GK_Zone_34\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",34500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",102.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]");
        projMap.put("4490","GEOGCS[\"China Geodetic Coordinate System 2000\",\n" +
                "    DATUM[\"China_2000\",\n" +
                "        SPHEROID[\"CGCS2000\",6378137,298.257222101,\n" +
                "            AUTHORITY[\"EPSG\",\"1024\"]],\n" +
                "        AUTHORITY[\"EPSG\",\"1043\"]],\n" +
                "    PRIMEM[\"Greenwich\",0,\n" +
                "        AUTHORITY[\"EPSG\",\"8901\"]],\n" +
                "    UNIT[\"degree\",0.0174532925199433,\n" +
                "        AUTHORITY[\"EPSG\",\"9122\"]],\n" +
                "    AUTHORITY[\"EPSG\",\"4490\"]]");
        projMap.put("4521","PROJCS[\"CGCS2000_3_Degree_GK_Zone_33\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",33500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",99.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]");
        projMap.put("4523","PROJCS[\"CGCS2000_3_Degree_GK_Zone_35\",GEOGCS[\"GCS_China_Geodetic_Coordinate_System_2000\",DATUM[\"D_China_2000\",SPHEROID[\"CGCS2000\",6378137.0,298.257222101]],PRIMEM[\"Greenwich\",0.0],UNIT[\"Degree\",0.0174532925199433]],PROJECTION[\"Gauss_Kruger\"],PARAMETER[\"False_Easting\",35500000.0],PARAMETER[\"False_Northing\",0.0],PARAMETER[\"Central_Meridian\",105.0],PARAMETER[\"Scale_Factor\",1.0],PARAMETER[\"Latitude_Of_Origin\",0.0],UNIT[\"Meter\",1.0]]");
    }

    /**
     * 根据传入wkt获取数据坐标系
     * @param wkt
     * @return
     */
    public static String getProj(String wkt){
        String resEpsg="";
        int lonLatStart=-1;
        //根据wkt字符串判断平面坐标位于哪一度带
        try {
            for (int i = 0; i < wkt.length(); i++) {
                if(Integer.valueOf(wkt.charAt(i))>=48&&Integer.valueOf(wkt.charAt(i))<58){
                    lonLatStart=i;
                    break;
                }
            }
            int lonLatEnd=wkt.indexOf(",");
            String projLonLat=wkt.substring(lonLatStart,lonLatEnd);
            String[]lonlat=projLonLat.split(" ");
            String projLon=lonlat[0];
            if(projLon.substring(0,2).equals("33")){
                resEpsg="4521";
            }else if(projLon.substring(0,2).equals("34")){
                resEpsg="4522";
            }else if(projLon.substring(0,2).equals("35")){
                resEpsg="4523";
            }
            else
                return "4490";
        } catch (Exception e) {
            log.info(wkt+"出错");
            log.error(e.getMessage(),e);
        }
        return resEpsg;

    }

    /**
     * 坐标转换
     * @param geom
     * @param sourceEpsg
     * @return
     */
    public static Geometry lonlat2WebMactor(Geometry geom,String sourceEpsg){
        try{
            //这里是以OGC WKT形式定义的是World Mercator投影,网页地图一般使用该投影
            CoordinateReferenceSystem crsSource=CRS.parseWKT(projMap.get(sourceEpsg));
            CoordinateReferenceSystem crsTarget = CRS.parseWKT(projMap.get("4490"));
            // 投影转换
//            MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, crsTarget);
            MathTransform transform = CRS.findMathTransform(crsSource, crsTarget);
            return JTS.transform(geom, transform);
        }
        catch (Exception e) {
            // TODO Auto-generated catch block
            log.error(e.getMessage(),e);
            return null;
        }
    }

    /**
     *给定inputshp转换为targetEpsg坐标系,并输出到outputShp位置
     * @param inputShp
     * @param outputShp
     * @param targetEpsg
     * @return
     */
    public static Map projectShape(String inputShp, String outputShp,String targetEpsg){
        Map map = new HashMap();
        try {
            //源shape文件
            ShapefileDataStore shapeDS = (ShapefileDataStore) new ShapefileDataStoreFactory().createDataStore(new File(inputShp).toURI().toURL());
            //创建目标shape文件对象
            Map<String, Serializable> params = new HashMap<String, Serializable>();
            FileDataStoreFactorySpi factory = new ShapefileDataStoreFactory();
            File file=FileUtil.createFileByPath(outputShp);
//            if(!file.exists()){
                params.put(ShapefileDataStoreFactory.URLP.key,file.toURI().toURL());
                ShapefileDataStore ds = (ShapefileDataStore) factory.createNewDataStore(params);
//            Charset charset = Charset.forName("UTF-8");
//            ds.setCharset(charset);
                // 设置属性
                SimpleFeatureSource fs = shapeDS.getFeatureSource(shapeDS.getTypeNames()[0]);
                //下面这行还有其他写法,根据源shape文件的simpleFeatureType可以不用retype,而直接用fs.getSchema设置
//            CoordinateReferenceSystem crs = CRS.parseWKT(strWKTMercator);
                CoordinateReferenceSystem crs = CRS.parseWKT(projMap.get("4490"));
                ds.createSchema(SimpleFeatureTypeBuilder.retype(fs.getSchema(), crs));

                //设置writer
                FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);

                //写记录
                SimpleFeatureIterator it = fs.getFeatures().features();
                try {
                    while (it.hasNext()) {
                        SimpleFeature f = it.next();
                        SimpleFeature fNew = writer.next();
                        fNew.setAttributes(f.getAttributes());
                        Geometry geom = lonlat2WebMactor((Geometry)f.getAttribute("the_geom"),targetEpsg);
                        fNew.setAttribute("the_geom", geom);
                    }
                }
                finally {
                    it.close();
                }
                writer.write();
                writer.close();
                ds.dispose();
                shapeDS.dispose();
//            }
            map.put("status", "success");
            map.put("message", outputShp);
        }
        catch (Exception e) {
            log.error(e.getMessage(),e);
            map.put("status", "failure");
            map.put("message", e.getMessage());
        }
        return map;
    }

//    public static void main(String[] args) {
//        String input="D:\\jsonshp\\test.shp";
//        String output="D:\\jsonshp\\test4490.shp";
//        projectShape(input,output);
//    }

}

5. 结语

本文对GeoTools的基本概念进行了简介,之后介绍了Geotools的工具类及其具体用法。下一篇文章将讲解Postgis+Geotools+MybatisPlus实现数据的读取,写入及前端展示。对Gis开发领域感兴趣的同学可动动你们发财的小手点点关注~

6. 参考链接 

常见2000坐标系对应的EPSG代号 - 知乎

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

为什么不用 index 做 key 引出的 Diff 算法

文章目录 问题分析 问题 大家耳熟能详的最常见的问题就是 为什么不用 index 做 key &#xff0c;在刚开始学习的时候&#xff0c;只是知道在 v-for 做循环遍历的时候需要加上唯一标识 key&#xff0c;但好像都是这么写的 v-for"(item,index) in dictList" :key"…

IT系统可观测性

什么是可观测性 可观测性&#xff08;Observability&#xff09;是指能够从系统的外部输出推断出系统内部状态的能力。在IT和云计算领域&#xff0c;它涉及使用软件工具和实践来收集、关联和分析分布式应用程序以及运行这些应用程序的硬件和网络产生的性能数据流。这样做可以更…

数据分析-Pandas序列时间移动窗口化操作

数据分析-Pandas序列时间移动窗口化操作 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表…

【考研数学】全年保姆级规划+资料选择

直接跟考研课学即可 跟宋浩学第一遍说是基础&#xff0c;但宋浩的课程毕竟针对的是大学期末考试&#xff0c;基础知识方面讲的可能没有考研课程全面&#xff0c;毕竟大学课程的授课时间和考核要求不同于考研。 备考之前对自己做一个评估&#xff0c;每一个要准备的科目和其中…

代码随想录 动态规划-0-1背包问题

目录 标准0-1背包问题 二维dp数组01背包 一维dp数组01背包&#xff08;滚动数组&#xff09; 416.分割等和子集 1049.最后一块石头的重量|| 494.目标和 474.一和零 背包问题的分类 标准0-1背包问题 46. 携带研究材料&#xff08;第六期模拟笔试&#xff09; 时间限制…

超越传统的极限:解密B树与B+树的数据结构之美!

超越传统的极限&#xff1a;解密B树与B树的数据结构之美&#xff01; B树和B树是在计算机科学中常用的平衡查找树数据结构&#xff0c;它们在处理大规模数据和磁盘存储方面具有重要的优势。本文将深入介绍B树和B树的基本概念、特点以及它们在数据库和文件系统中的应用&#xff…

【德语常识】分类单词

【德语常识】分类单词 一&#xff0c;Colors二&#xff0c;Countries & Languages三&#xff0c; 一&#xff0c;Colors 二&#xff0c;Countries & Languages 三&#xff0c;

JNDI注入原理及利用IDEA漏洞复现

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java、PHP】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收…

VMware虚拟机Centos7硬盘扩容详细图文教程

这里写自定义目录标题 设置扩容空间容量10G为列子开机后输入df -h 查看磁盘空间运行fdisk -l&#xff0c;查看硬盘信息运行fdisk /dev/sda输入m&#xff0c;查看n为add new partition&#xff0c;输入n输入p &#xff0c;p之后的东西都选择为默认再输入t&#xff0c;分区号根据…

洛谷-P1449 后缀表达式

目录 何为后缀表达式&#xff1f; 模拟过程 AC代码 采用STL的stack 题目链接&#xff1a;P1449 后缀表达式 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 何为后缀表达式&#xff1f; 那后缀表达式是怎么算的呢 那显然就需要引用最开始说的栈了 因为后缀表表达式本来就是栈…

HTML5+CSS3+JS小实例:全屏范围滑块

实例:全屏范围滑块 技术栈:HTML+CSS+JS 效果: 源码: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale…

零延迟轻量级网站指纹防御

文章信息 论文题目&#xff1a;Zero-delay Lightweight Defenses against Website Fingerprinting 期刊&#xff08;会议&#xff09;&#xff1a; 29th USENIX Security Symposium 时间&#xff1a;2020 级别&#xff1a;CCF A 文章链接&#xff1a;https://www.usenix.org/s…

PHP反序列化---字符串逃逸(增加/减少)

一、PHP反序列化逃逸--增加&#xff1a; 首先分析源码&#xff1a; <?php highlight_file(__FILE__); error_reporting(0); class A{public $v1 ls;public $v2 123;public function __construct($arga,$argc){$this->v1 $arga;$this->v2 $argc;} } $a $_GET[v…

一文了解如何做全基因集GSEA富集分析

原文链接:一文完成全基因集GSEA富集分析 本期内容 写在前面 我们前面分享过一文掌握单基因GSEA富集分析的教程,主要使用单基因的角度进行GSEA富集分析。 我们社群的同学咨询,全基因集的GSEA如何分析呢??其实,原理都是大同小异的,那么今天我们就简单的整理一下吧。 若…

PyTorch学习笔记之激活函数篇(二)

文章目录 2、Tanh函数2.1 公式2.2 对应的图像2.3 对应生成图像代码2.4 优点与不足2.5 torch.tanh()函数 2、Tanh函数 2.1 公式 Tanh函数的公式&#xff1a; f ( x ) e x − e − x e x e − x f(x)\frac{e^x-e^{-x}}{e^xe^{-x}} f(x)exe−xex−e−x​ Tanh函数的导函数&am…

Java实现定时发送邮件(基于Springboot工程)

1、功能概述&#xff1f; 1、在企业中有很多需要定时提醒的任务&#xff1a;如每天下午四点钟给第二天的值班人员发送值班消息&#xff1f;如提前一天给参与第二天会议的人员发送参会消息等。 2、这种定时提醒有很多方式如短信提醒、站内提醒等邮件提醒是其中较为方便且廉价的…

旅行社旅游线路预定管理系统asp.net

旅行社旅游线路预定管理系统 首页 国内游 境外游 旅游景点 新闻资讯 酒店信息―留言板 后台管理 后台管理导航菜单系统管理修改密码留言管理注册会员管理基础数据设置国别设置有份设地区设置 旅行社管理友情链接管理添加友情链接友情链接管理新闻资讯管理添加新闻资讯新闻资讯管…

10|代理(中):AgentExecutor究竟是怎样驱动模型和工具完成任务的?

LangChain 中的“代理”和“链”的差异究竟是什么&#xff1f;在链中&#xff0c;一系列操作被硬编码&#xff08;在代码中&#xff09;。在代理中&#xff0c;语言模型被用作推理引 擎来确定要采取哪些操作以及按什么顺序执行这些操作。 Agent 的关键组件 代理&#xff08…

静态综合实验

一&#xff0c;1.搭建拓扑结构并启动。 2.根据题意得该图需要14个网段&#xff0c;根据192.168.1.0/24划分子网段&#xff0c;如下&#xff1a; 划分完如图所示&#xff1a; 二、配置IP地址 R1路由器&#xff1a; 1.进入系统视图并改名. 2.接口配置IP地址&#xff1a…

Linux系统中安装Docker

用Linux既可以用虚拟机操作&#xff0c;也可以自己弄一个云服务器进行操作&#xff0c;两者没啥区别。 操作之前需要将用户等级升级到root级别&#xff0c;防止有些操作因为权限限制而不能操作。 安装docker非常简单&#xff0c;只需要一直按照下列命令顺序进行操作即可。 安装…