简介

概念:
JTS:JTS Topology Suite (JTS)是一个开源的Java软件库,它提供了平面几何的对象模型和基本的几何函数,符合OGC发布的“Simple Features for SQL”(SFSQL)规范。JTS被设计用作基于矢量地理信息软件的核心组件,还可以用作计算几何的通用算法库。

GeoTools:GeoTools 是一个开源 (LGPL) Java 代码库,它为操作地理空间数据提供符合标准的方法,例如实现地理信息系统。GeoTools 库数据结构基于开放地理空间联盟 (OGC) 规范。
官网地址:
https://www.geotools.org/

你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。

数据操作

  1. **shape
public static void readShpFile(String shpPath) {
       File shpFile = new File(shpPath);
       try {
           ShapefileDataStore shapefileDataStore = new ShapefileDataStore(shpFile.toURI().toURL());
           // 设置编码,防止属性的中文字符出现乱码
           shapefileDataStore.setCharset(Charset.forName("UTF-8"));
           // 这个typeNamae不传递,默认是文件名称
           FeatureSource featuresource = shapefileDataStore.getFeatureSource(shapefileDataStore.getTypeNames()[0]);
           // 读取bbox
           ReferencedEnvelope bbox  =featuresource.getBounds();
           // 读取投影
           CoordinateReferenceSystem crs = featuresource.getSchema().getCoordinateReferenceSystem();
           // 特征总数
           int count = featuresource.getCount(Query.ALL);
           // 获取当前数据的geometry类型(点、线、面)
           GeometryType geometryType = featuresource.getSchema().getGeometryDescriptor().getType();
           // 读取要素
           SimpleFeatureCollection simpleFeatureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
           // 获取当前矢量数据有哪些属性字段值
           List<AttributeDescriptor> attributes = simpleFeatureCollection.getSchema().getAttributeDescriptors();
           // 拿到迭代器
           SimpleFeatureIterator simpleFeatureIterator = simpleFeatureCollection.features();
           // 遍历每一个要素
           while(simpleFeatureIterator.hasNext()) {
               SimpleFeature simpleFeature = simpleFeatureIterator.next();
               // java8新特性流api
               attributes.stream().forEach((a) -> {
                   // 依次读取这个shape中每一个属性值,当然这个属性值,可以处理其它业务
                   System.out.println(a.getLocalName() + ":" + simpleFeature.getAttribute(a.getLocalName()));
               });
           }
       } catch (IOException e) {
           e.printStackTrace();
       }
       System.out.println("读取完成!");
   }

2. Geoserver服务数据读取

    public static final String getFeatureApi = "{{url}}/geoserver/wfs?service=wfs&version=2.0.0&outputFormat=application/json&request=GetFeature&typeNames={{workspace}}:{{layerName}}";
        /**
     * 获取SimpleFeatureCollection
     */
    public static SimpleFeatureCollection getFeature(
            String url,
            String username,
            String password,
            String workspace,
            String layerName) {
        try {
            String urlStr = buildUrl(getFeatureApi, url, workspace, layerName);
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
            CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build();
            HttpGet httpGet = new HttpGet(urlStr);
            HttpResponse response = httpClient.execute(httpGet);
            String jsonStr = EntityUtils.toString(response.getEntity());
            ByteArrayInputStream inputStream = new ByteArrayInputStream(jsonStr.getBytes(StandardCharsets.UTF_8));
            return (SimpleFeatureCollection) new FeatureJSON().readFeatureCollection(inputStream);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

3. wkt数据读取

// ex : MultiPolygon ( ((10 10, 10 20, 20 20, 20 15, 10 10)), ((60 60, 70 70, 80 60, 60 60 )) )
WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(wktStr);

4. geojson读取

//{“type”:“Feature”,“crs”:{“type”:“name”,“properties”:{“name”:“EPSG:2380”}},“geometry”:{“type”:“MultiPolygon”,“coordinates”:[[[[646398.9535,3267941.9664],[649558.7196,3267895.3528],[649674.763,3265683.4124],[646387.8773,3265827.4858],[646398.9535,3267941.9664]]]]},“properties”:{“Id”:0}}
public static void readGeoJson(String jsonPath) throws IOException {
       File file = new File(jsonPath);
       FileInputStream fileInputStream = new FileInputStream(file);
       // 这里可能存在问题,如果是超大文件怎么办,一次性读入会不会报内存
       // 解决方案是不是对大文件进行拆分
       GeoJSONReader geoJSONReader = new GeoJSONReader(fileInputStream);
       SimpleFeatureCollection featureCollection = geoJSONReader.getFeatures();
       SimpleFeatureIterator iterator = featureCollection.features();
       List<AttributeDescriptor> attributes = featureCollection.getSchema().getAttributeDescriptors();
       while (iterator.hasNext()) {
           SimpleFeature simpleFeature = iterator.next();
           System.out.println();
           attributes.stream().forEach((a) -> {
               // 依次读取这个shape中每一个属性值,当然这个属性值,可以处理其它业务
               System.out.println(a.getLocalName() + ":" + simpleFeature.getAttribute(a.getLocalName()));
           });
       }
       fileInputStream.close();
       System.out.println("读取JSON完毕!");
   }

5. 遍历要素及属性

SimpleFeatureCollection simpleFeatureCollection = (SimpleFeatureCollection) featuresource.getFeatures();
// 获取当前矢量数据有哪些属性字段值
List<AttributeDescriptor> attributes = simpleFeatureCollection.getSchema().getAttributeDescriptors();
// 拿到迭代器
SimpleFeatureIterator simpleFeatureIterator = simpleFeatureCollection.features();
// 遍历每一个要素
while(simpleFeatureIterator.hasNext()) {
   SimpleFeature simpleFeature = simpleFeatureIterator.next();
   // java8新特性流api
   attributes.stream().forEach((a) -> {
       // 依次读取这个shape中每一个属性值,当然这个属性值,可以处理其它业务
       //Object jzmcValue = feature.getAttribute("jzmc");
       System.out.println(a.getLocalName() + ":" + simpleFeature.getAttribute(a.getLocalName()));
   });
}

6.新增要素(创建图层)

//1.构造TYPE(定义数据的坐标参考、属性字段)
//Class的取值可以是:几何(Point.class,Polygon.class,MultiPolygon.class),属性(String.class,Integer.class, Double.class)
public static SimpleFeatureType createType(Class<?> c, String layerName) {
     SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
     builder.setCRS(DefaultGeographicCRS.WGS84);
     builder.add("FID",String.class);
     // 需要注意的是几何字段的属性名称是固定的
     builder.add("the_geom", c);
     // 设置了图层的名字
     builder.setName(layerName);
     SimpleFeatureType simpleFeatureType = builder.buildFeatureType();
     return simpleFeatureType;
 }
 
 //2.根据TYPE构建单个要素
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(simpleFeatureType);
WKTReader wktReader = new WKTReader();
Geometry geometry = wktReader.read(wktStr);
// 这里的添加顺序和上面TYPE的时候保持一致
featureBuilder.add("1");
featureBuilder.add(geometry);
SimpleFeature feature = featureBuilder.buildFeature(null);

//3.创建FeatureCollection
List<SimpleFeature> features = new ArrayList<>();
 // 只需要将上面步骤的单个要素放入循环中创建更多的要素
 features.add(feature);
 SimpleFeatureCollection collection = new ListFeatureCollection(TYPE, features);
 
 //4. 生成shpfile
File shpFile = new File(shpPath);
ShapefileDataStoreFactory dataStoreFactory = new ShapefileDataStoreFactory();
// 创造shpstore需要的参数
Map<String, Serializable> params = new HashMap<>();
params.put("url", shpFile.toURI().toURL());
params.put("create spatial index", Boolean.TRUE);
ShapefileDataStore newDataStore = (ShapefileDataStore) dataStoreFactory.createNewDataStore(params);
newDataStore.createSchema(simpleFeatureType);
Transaction transaction = new DefaultTransaction("create");
String typeName = newDataStore.getTypeNames()[0];
SimpleFeatureSource featureSource = newDataStore.getFeatureSource(typeName);
SimpleFeatureStore featureStore = (SimpleFeatureStore) featureSource;
SimpleFeatureCollection collection = new ListFeatureCollection(simpleFeatureType, features);
featureStore.setTransaction(transaction);
featureStore.addFeatures(collection);
featureStore.setTransaction(transaction);
transaction.commit();
transaction.close();

7.读取TIFF

public static Coverage readTiff(String tiffPath) throws IOException {
     File f = new File(tiffPath);
     ParameterValue<OverviewPolicy> policy = AbstractGridFormat.OVERVIEW_POLICY.createValue();
     policy.setValue(OverviewPolicy.IGNORE);
     ParameterValue<String> gridsize = AbstractGridFormat.SUGGESTED_TILE_SIZE.createValue();
     ParameterValue<Boolean> useJaiRead = AbstractGridFormat.USE_JAI_IMAGEREAD.createValue();
     useJaiRead.setValue(true);
     GridCoverage2D image = new GeoTiffReader(f).read(new GeneralParameterValue[]{policy, gridsize, useJaiRead});
     return image;
 }

生成TIFF

File file = new File(outTiffPath);
GeoTiffWriter geoTiffWriter = new GeoTiffWriter(file);
final GeoTiffFormat format = new GeoTiffFormat();
final GeoTiffWriteParams wp = new GeoTiffWriteParams();
// 设置写出参数
wp.setCompressionMode(GeoTiffWriteParams.MODE_DEFAULT);
wp.setTilingMode(GeoToolsWriteParams.MODE_DEFAULT);
ParameterValueGroup paramWrite = format.getWriteParameters();
paramWrite.parameter(AbstractGridFormat.GEOTOOLS_WRITE_PARAMS.getName().toString()).setValue(wp);
geoTiffWriter.write((GridCoverage) coverage, paramWrite.values().toArray(new GeneralParameterValue[4]) );
geoTiffWriter.dispose();

空间分析

空间关系(Geometry Relationships):
常见的空间关系(Geometry Relationships)包括:Disjoint、Intersects、Touches、Crosses、Within、Contains、Overlaps、Relates。

空间操作(Geometry Operations):
常见的空间操作(Geometry Operations)包括:Buffer、Intersection、ConvexHull、Intersection、Union、Difference、SymDifference。

裁剪

    /**
     * 裁剪
     *
     **/
    public static  List<String>  newClip(GeoserverAnalysisClipDTO dto) {
        //获取服务数据
        SimpleFeatureCollection collection = GeoServerAnalysisUtils.getFeature(dto.getGeoserverUrl(), dto.getUsername(), dto.getPassword(), dto.getWorkspace(), dto.getLayerName());

        // 要裁剪的几何形状
        Geometry clipGeometry = SpatialAnalysisUtils.convertToJtsGeometry(dto.getPolygon());

        // 创建一个用于存储裁剪后要素的 SimpleFeatureCollection
        //DefaultFeatureCollection clippedCollection = new DefaultFeatureCollection();
        List<Geometry> list = new ArrayList<>();

        // 遍历每个要素
        try (SimpleFeatureIterator iterator = collection.features()) {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                // 获取要素的几何属性
                Geometry featureGeometry = (Geometry) feature.getDefaultGeometry();
                if (featureGeometry.intersects(clipGeometry)) {                    // 判断要素的几何形状与指定几何形状是否有交集
                    Geometry intersection = featureGeometry.intersection(clipGeometry);
                    if (!intersection.isEmpty()) {
                        // 将交集部分保留下来,作为裁剪后的几何形状
                        //clippedCollection.add(SimpleFeatureBuilder.build(feature.getFeatureType(), new Object[]{intersection}, null));
                        list.add(intersection);
                    }
                }
            }
        }

        return geometryToWKT(list);
    }

筛选分析

 // 筛选分析API接口
    public static final String screeningApi = "{{url}}/geoserver/wfs?service=wfs&version=2.0.0&request=GetFeature&outputFormat=application/json&typeNames={{workspace}}:{{layerName}}";

   public static String screening( String geoserverUrl, String username,String password,String workspace,String layerName, Map<String, Object> filter) {
        try {
            String urlStr = buildUrl(screeningApi, geoserverUrl, workspace, layerName);
            String filterStr = buildCQLFilter(filter);
            urlStr = urlStr + "&" + filterStr;
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
            CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build();
            HttpGet httpGet = new HttpGet(urlStr);
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
            return "后台异常";
        }
     }

割裂

    // 割裂API接口
    public static final String splitApi = "{{url}}/geoserver/wfs?service=wfs&version=2.0.0&request=GetFeature&outputFormat=application/json&typeNames={{workspace}}:{{layerName}}&splitField={{splitField}}";
    public static String split(String geoserverUrl, String username,String password,String workspace,String layerName,
            String splitField) {
        try {
            String urlStr = buildUrl(splitApi, geoserverUrl, workspace, layerName, splitField);
            CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
            CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credentialsProvider).build();
            HttpGet httpGet = new HttpGet(urlStr);
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            return EntityUtils.toString(entity);
        } catch (Exception e) {
            e.printStackTrace();
            return "后台异常";
        }
    }

交集

intersection

并集

union

差集

difference

缓冲区

    public static String buffer(GeoserverAnalysiBufferDTO dto){
        BufferFeatureCollection bf = new BufferFeatureCollection();
        SimpleFeatureCollection featureCollection = getFeature(dto.getGeoserverUrl(),dto.getUsername(),dto.getPassword(),dto.getWorkspace(),dto.getLayerName());
        //featureCollection.getSchema().getDescriptor();
        String[] attributeHeaders = getAttributeHeaders(featureCollection);
        // 打印属性字段头
        for (String header : attributeHeaders) {
            System.out.println(header);
        }
        SimpleFeatureCollection simpleFeatureCollection = bf.execute(featureCollection, dto.getDistance(), dto.getAttribute());
        return Shp2GeojsonUtils.shape2Geojson(simpleFeatureCollection);
    }
    
   private static String[] getAttributeHeaders(SimpleFeatureCollection featureCollection) {
        // 获取第一个要素
        SimpleFeatureIterator iterator = featureCollection.features();
        Feature feature = iterator.next();
        iterator.close();

        // 获取属性字段
        List<String> attributeHeaders = new ArrayList<>();
        for (Property property : feature.getProperties()) {
            String attributeName = property.getName().getLocalPart();
            attributeHeaders.add(attributeName);
        }

        // 将属性字段头转换为字符串数组并返回
        return attributeHeaders.toArray(new String[0]);
    }

擦除

    public static String newErase(GeoserverAnalysisEraseDTO dto) {
        SimpleFeatureCollection collection = GeoServerAnalysisUtils.getFeature(dto.getGeoserverUrl(), dto.getUsername(), dto.getPassword(), dto.getWorkspace(), dto.getLayerName());
        Geometry oldGeo = SpatialAnalysisUtils.convertToJtsGeometry(dto.getPolygon());
        Geometry resultGeo = null;

        try (SimpleFeatureIterator iterator = collection.features()) {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                Geometry geometry = (Geometry) feature.getDefaultGeometry();
                if (geometry instanceof org.locationtech.jts.geom.Polygon || geometry instanceof org.locationtech.jts.geom.MultiPolygon) {
                    if (geometry.intersects(oldGeo)) {
                        Geometry difference = geometry.difference(oldGeo);
                        if (resultGeo == null) {
                            resultGeo = difference;
                        } else {
                            resultGeo = resultGeo.union(difference);
                        }

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        WKTWriter writer = new WKTWriter();
        return  writer.write(resultGeo);
    }

点距离

    /**
     * 两点之间距离计算
     * @Date 2024/4/7 15:19
     **/
    public static double getDistance(double x1, double y1, double x2, double y2) {
        // 84坐标系构造GeodeticCalculator
        GeodeticCalculator geodeticCalculator = new GeodeticCalculator(DefaultGeographicCRS.WGS84);
        // 起点经纬度
        geodeticCalculator.setStartingGeographicPoint(x1, y1);
        // 末点经纬度
        geodeticCalculator.setDestinationGeographicPoint(x2, y2);
        // 计算距离,单位:米
        return geodeticCalculator.getOrthodromicDistance();
    }

近邻分析

    public static GeoServerNeighborVO getNeighbor(GeoServerNeighborDTO dto) {

        GeoServerNeighborVO vo = new GeoServerNeighborVO();
        double miniDist = Double.MAX_VALUE;

        SimpleFeatureCollection collection = GeoServerAnalysisUtils.getFeature(dto.getGeoserverUrl(), dto.getUsername(), dto.getPassword(), dto.getWorkspace(), dto.getLayerName());

        if (collection != null) {
            // 遍历 feature 集合
            try (SimpleFeatureIterator iterator = collection.features()) {
                while (iterator.hasNext()) {
                    SimpleFeature feature = iterator.next();
                    Geometry geometry = (Geometry) feature.getDefaultGeometry();

                    String jzmc = null;

                    // 检查几何类型是否为点
                    if (geometry instanceof org.locationtech.jts.geom.Point) {
                        Coordinate coordinate = geometry.getCoordinate();
                        Point point = new Point(coordinate.getX(), coordinate.getY());
                        // 获取点的坐标
                        double x = point.getX();
                        double y = point.getY();
                        //System.out.println("Point coordinates: (" + x + ", " + y + ")");
                        //计算距离
                        double distance = findShort(dto.getPolygon(), point);
                        if (distance != 0) {
                            if (distance < miniDist) {
                                miniDist = distance;

                                Object jzmcValue = feature.getAttribute("jzmc");
                                if (jzmcValue != null) {
                                    jzmc = (String) jzmcValue;
                                }
                                vo.setPoint(point);
                                vo.setName(jzmc);
                            }
                        }
                    } else {
                        System.out.println("This feature is not a point.");
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        vo.setDistance(miniDist * 100);
        System.out.println("近邻分析结果:" + vo.toString());
        return vo;
    }

面邻域

    public static List<String> getSquareNeighbor(GeoServerNeighborDTO dto) {

        SimpleFeatureCollection collection = GeoServerAnalysisUtils.getFeature(dto.getGeoserverUrl(), dto.getUsername(), dto.getPassword(), dto.getWorkspace(), dto.getLayerName());
        Geometry oldGeo = convertToJtsGeometry(dto.getPolygon());

        //GeoServerSquareNeighborVO vo = new GeoServerSquareNeighborVO();
        List<Geometry> list = new ArrayList<>();
        List<String> result = new ArrayList<>();
        if (collection == null) {
            return result ;
        }
        try (SimpleFeatureIterator iterator = collection.features()) {
            while (iterator.hasNext()) {
                SimpleFeature feature = iterator.next();
                Geometry geometry = (Geometry) feature.getDefaultGeometry();
                if (geometry instanceof org.locationtech.jts.geom.Polygon || geometry instanceof org.locationtech.jts.geom.MultiPolygon) {
                    // org.locationtech.jts.geom.MultiPolygon multiPolygon = (org.locationtech.jts.geom.MultiPolygon) geometry;
                    if (geometry.intersects(oldGeo)) {
                        list.add(geometry);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("相交:" +  geometryToWKT(list));

        return geometryToWKT(list);
    }
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐