GeoTools使用--多面合并的空洞处理_java geotools临近的面合并-程序员宅基地

技术标签: java  geotools  

在项目中经常用到多个城市地理数据的合并,但因城市的边界的规则性,就造成了在合并两个城市边界时出现了中间有空洞区域的情况。
以青海与甘肃张掖地理边界进行合并为例(为什么不用甘肃省的,因为省与省的地理边界往往是从同一套地理数据中提取的,存在边界空洞的情况就少一些)。来说明一下我的处理思路。

1.边界数据来源:阿里的地图选择器。datav.aliyun.com/tools/atlas。
2.在使用Geotools的Polygon.union进行合并后会出现边界有许多线段,从地图上放大看,其实是小块的空白区域。[如图1]
以青海与甘肃张掖地理信息合并为例3.查看了Geotools的文档,有一个GeometryFilter的介绍(它的一些实现类有LineStringExtracter,PolygonExtracter)。可以对需要的几何图形进行过来筛选。
4.参考PolygonExtracter写了一个根据空洞图形内的标识坐标,来筛选哪些空洞图形可以保留,哪些空洞图形可以去掉。
主要是在filter方法,先获取面的外边界,生成一个全面图形。然后遍历原始面的内线InteriorRing,判断哪些标记点在内线图形上,就在全面图形中symDifference掉需要留空的区域。

import java.util.*;
import com.vividsolutions.jts.geom.*;
/**
 * 对面进行处理,去掉内部的空洞面。只保留inPointst满足条件的内部空洞面。
 */
public class MyPolygonExtracter implements GeometryFilter {
    

  private List inPoints;
  private List<Geometry> geometries;

  /**
   * @param inPoints 需要保留区域的标识 。说明:如果给定的inpoints中的其中一个坐标在孔洞平面的内部,就保留这个孔洞
   * @param list
   */
  private MyPolygonExtracter(List<Point> inPoints, List<Geometry> list) {
    
    this.inPoints=inPoints;
    this.geometries=list;
  }

  /**
   * @param geom 多平面合并后的面图形
   * @param inPoints 需要保留区域的标识 。说明:如果给定的inpoints中的其中一个坐标在孔洞平面的内部,就保留这个孔洞
   * @return
   */
  public static Geometry getPolygons(Geometry geom, List<Point> inPoints) {
    
    List<Geometry> list=new ArrayList<>();
    if (geom instanceof Polygon) {
    
      geom.apply(new MyPolygonExtracter(inPoints,list));
    } else if (geom instanceof MultiPolygon) {
    
      geom.apply(new MyPolygonExtracter(inPoints,list));
    }
    return list.get(0);
  }

  @Override
  public void filter(Geometry g) {
    
    if(g instanceof Polygon){
    
      Polygon polygon=(Polygon)g;
      //使用面的外边界生成一个大面
      Geometry tempExterPoly =g.getFactory().createPolygon(polygon.getExteriorRing().getCoordinates());
      if(geometries.size()==0){
    
        geometries.add(tempExterPoly);
      }else {
    
        geometries.set(0,geometries.get(0).union(tempExterPoly));
      }
      //得到面内空洞区域的数量
      int line=polygon.getNumInteriorRing();
      for(int i=0;i<line;i++){
    
        //获取空洞区域线边界
        LineString linearRingIn=((Polygon) g).getInteriorRingN(i);
        //生成空洞面
        Polygon temP=g.getFactory().createPolygon(linearRingIn.getCoordinates());
        //判断
        if(pointInPolygon(temP)){
    
          //symDifference 从外边界面中去掉空洞面
          geometries.set(0,geometries.get(0).symDifference(temP));
        }
      }
    }else if(g instanceof  MultiPolygon){
    
      int geoNums= ((MultiPolygon)g).getNumGeometries();
      for(int i=0;i<geoNums;i++){
    
        filter(g.getGeometryN(i));
      }
    }
  }

  /**
   * 判断 inPoints的坐标是否在空洞面内部
   * @param polygon
   * @return
   */
  private boolean pointInPolygon(Polygon polygon) {
    
    for (int i = 0; inPoints!=null &&i <inPoints.size() ; i++) {
    
      if( polygon.contains((Point)inPoints.get(i))){
    
        return true;
      }
    }
    return false;
  }
}

4.调用方法进行测试和测试效果


import cn.hutool.core.io.FileUtil;
import com.fw121.web.util.MyPolygonExtracter;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.Point;
import org.geotools.geojson.geom.GeometryJSON;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

public class PolygonUnionTest {
    

    GeometryJSON geometryJSON;

    @Before
    public  void before(){
    
        geometryJSON=new GeometryJSON();
    }

    @Test
    public void uninTest() throws IOException {
    
        String qinghai= FileUtil.readUtf8String("C:\\Users\\DELL\\Desktop\\qinghai.json");
        String zhangye= FileUtil.readUtf8String("C:\\Users\\DELL\\Desktop\\zhangye.json");
        Geometry qinghaiGeo=geometryJSON.read(qinghai);
        Geometry zhangyeGeo=geometryJSON.read(zhangye);
        Geometry unionPolygon=qinghaiGeo.union(zhangyeGeo);
        System.out.println(toGeoJsonStr(unionPolygon));

        //需要保留空洞的标识坐标点
        List<Point> inPoint=new ArrayList<>();
        Coordinate coords  = new Coordinate(100.5733966, 38.247051);
        inPoint.add(unionPolygon.getFactory().createPoint(coords));

        Geometry geometry = MyPolygonExtracter.getPolygons(unionPolygon,inPoint);
        System.out.println(toGeoJsonStr(geometry));
    }

    public  String toGeoJsonStr(Geometry geometry) throws IOException {
    
        StringWriter w = new StringWriter();
        geometryJSON.write(geometry,w);
        return w.toString();
    }
}

效果图,红色框中的为根据关键点保留的空白区域。
在这里插入图片描述

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/aofavx/article/details/105092116

智能推荐

使用UmcFramework和unimrcpclient.xml连接多个SIP设置的配置指南及C代码示例

在多媒体通信领域,MRCP(Media Resource Control Protocol)协议被广泛用于控制语音识别和合成等媒体资源。UniMRCP是一个开源的MRCP实现,提供了客户端和服务端的库。UmcFramework是一个基于UniMRCP客户端库的示例应用程序框架,它帮助开发者快速集成和测试MRCP客户端功能。本文将详细介绍如何使用UmcFramework和unimrcpclient.xml配置文件连接到多个SIP设置,以及如何用C代码进行示例说明。

java.net.ProtocolException: Server redirected too many times (20)-程序员宅基地

文章浏览阅读3k次。报错:java.net.ProtocolException: Server redirected too many times (20)1.没有检查到cookie,一直循环重定向。解决:CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));URL url = new URL(url); ..._java.net.protocolexception: server redirected too many times (20)

springboot启动报错 Failed to scan *****/derbyLocale_ja_JP.jar from classloader hierarchy_failed to scan from classloader hierarchy-程序员宅基地

文章浏览阅读4.1k次。问题这是部分报错信息2019-07-11 14:03:34.283 WARN [restartedMain][DirectJDKLog.java:175] - Failed to scan [file:/D:/repo/org/apache/derby/derby/10.14.2.0/derbyLocale_ja_JP.jar] from classloader hierarchyjava...._failed to scan from classloader hierarchy

MATLAB-ones函数_matlab中ones函数-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏7次。在MATLAB中,ones函数用于创建一个指定大小的由1组成的矩阵或数组。_matlab中ones函数

解决PS等软件出现应用程序无法正常启动(0xc000007b)_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。-程序员宅基地

文章浏览阅读3.9w次,点赞2次,收藏9次。  在使用电脑办公过程中,安装应用程序时难免遇到无法安装或者无法正常启动的问题,这对我们使用电脑带来了诸多不便。那遇到应用程序无法正常启动的问题要如何解决呢?相信大家肯定都是十分疑问的,每次都是只能忍痛重新安装软件。今天,小编就和大家探讨下应用程序无法正常启动的解决方法,帮助大家排忧解难。0xc000007b电脑图解1  第一种方案:SFC检查系统完整性来尝试修复丢失文件  1、打开电脑搜索输入cmd.exe,选择以管理员身份运行,跳出提示框时选择继续。0xc000007b电脑图解2_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。

oracle介质恢复和实例恢复的异同-程序员宅基地

文章浏览阅读396次。1、概念 REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:实例恢复(INSTANCE RECOVERY);介质恢复(MEDIA RECOVERY)。 实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的..._oracle 实例恢复和介质恢复

随便推点

HDU1715--第i个斐波那契数 大菲波数_返回第i个斐波那契数-程序员宅基地

文章浏览阅读486次。HDU1715:大菲波数求第i个斐波那契数问题(与HDU1316类似,但更简单):总结:数组开多大?题目中让求的最大的是第1000个斐波那契数是多少,由于f[0]不用,所以数组开到1001。import java.util.Scanner;import java.math.BigInteger;public class Main { public static void main..._返回第i个斐波那契数

轻松搭建CAS 5.x系列(5)-增加密码找回和密码修改功能-程序员宅基地

文章浏览阅读418次。概述说明CAS内置了密码找回和密码修改的功能; 密码找回功能是,系统会吧密码重置的连接通过邮件或短信方式发送给用户,用户点击链接后就可以重置密码,cas还支持预留密码重置的问题,只有回答对了,才可以重置密码;系统可配置密码重置后,是否自动登录; 密码修改功能是,用户登录后输入新密码即可完成密码修改。安装步骤`1. 首先,搭建好cas sso server您需要按..._修改cas默认用户密码

springcloud(七) feign + Hystrix 整合 、-程序员宅基地

文章浏览阅读141次。之前几章演示的熔断,降级 都是 RestTemplate + Ribbon 和RestTemplate + Hystrix ,但是在实际开发并不是这样,实际开发中都是 Feign 远程接口调用。Feign + Hystrix 演示:  eruka(略)order 服务工程:  pom.xml<?xml version="1.0" encoding="U..._this is order 服务工程

YOLOv7如何提高目标检测的速度和精度,基于优化算法提高目标检测速度-程序员宅基地

文章浏览阅读3.4k次,点赞35次,收藏43次。学习率是影响目标检测精度和速度的重要因素之一。合适的学习率调度策略可以加速模型的收敛和提高模型的精度。在YOLOv7算法中,可以使用基于余弦函数的学习率调度策略(Cosine Annealing Learning Rate Schedule)来调整学习率。

linux中进程退出函数:exit()和_exit()的区别_linux结束进程可以用哪些函数,它们之间有何区别?-程序员宅基地

文章浏览阅读4k次,点赞4次,收藏9次。 linux中进程退出函数:exit()和_exit()的区别(1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。(2)调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr ...). exit函数是在_exit..._linux结束进程可以用哪些函数,它们之间有何区别?

sqlserver55555_sqlserver把小数点后面多余的0去掉-程序员宅基地

文章浏览阅读134次。select 5000/10000.0 --想变成0.5select 5500/10000.0 --想变成0.55select 5550/10000.0 --想变成0.555select 5555/10000.0 --想变成0.5555其结果分别为:0.5000000 0.5500000 0.5550000 0.5555000一、如果想去掉数字5后面多余的0 ,需要转化一下:selec..._sql server 去小数 0

推荐文章

热门文章

相关标签