在项目中经常用到多个城市地理数据的合并,但因城市的边界的规则性,就造成了在合并两个城市边界时出现了中间有空洞区域的情况。
以青海与甘肃张掖地理边界进行合并为例(为什么不用甘肃省的,因为省与省的地理边界往往是从同一套地理数据中提取的,存在边界空洞的情况就少一些)。来说明一下我的处理思路。
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();
}
}
效果图,红色框中的为根据关键点保留的空白区域。
在多媒体通信领域,MRCP(Media Resource Control Protocol)协议被广泛用于控制语音识别和合成等媒体资源。UniMRCP是一个开源的MRCP实现,提供了客户端和服务端的库。UmcFramework是一个基于UniMRCP客户端库的示例应用程序框架,它帮助开发者快速集成和测试MRCP客户端功能。本文将详细介绍如何使用UmcFramework和unimrcpclient.xml配置文件连接到多个SIP设置,以及如何用C代码进行示例说明。
文章浏览阅读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)
文章浏览阅读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
文章浏览阅读2.8k次,点赞3次,收藏7次。在MATLAB中,ones函数用于创建一个指定大小的由1组成的矩阵或数组。_matlab中ones函数
文章浏览阅读3.9w次,点赞2次,收藏9次。 在使用电脑办公过程中,安装应用程序时难免遇到无法安装或者无法正常启动的问题,这对我们使用电脑带来了诸多不便。那遇到应用程序无法正常启动的问题要如何解决呢?相信大家肯定都是十分疑问的,每次都是只能忍痛重新安装软件。今天,小编就和大家探讨下应用程序无法正常启动的解决方法,帮助大家排忧解难。0xc000007b电脑图解1 第一种方案:SFC检查系统完整性来尝试修复丢失文件 1、打开电脑搜索输入cmd.exe,选择以管理员身份运行,跳出提示框时选择继续。0xc000007b电脑图解2_photoshop应用程序无法正常启动0xc000007b。请单击“确认”关闭应用程序。
文章浏览阅读396次。1、概念 REDO LOG是Oracle为确保已经提交的事务不会丢失而建立的一个机制。实际上REDO LOG的存在是为两种场景准备的:实例恢复(INSTANCE RECOVERY);介质恢复(MEDIA RECOVERY)。 实例恢复的目的是在数据库发生故障时,确保BUFFER CACHE中的数据不会丢失,不会造成数据库的..._oracle 实例恢复和介质恢复
文章浏览阅读486次。HDU1715:大菲波数求第i个斐波那契数问题(与HDU1316类似,但更简单):总结:数组开多大?题目中让求的最大的是第1000个斐波那契数是多少,由于f[0]不用,所以数组开到1001。import java.util.Scanner;import java.math.BigInteger;public class Main { public static void main..._返回第i个斐波那契数
文章浏览阅读418次。概述说明CAS内置了密码找回和密码修改的功能; 密码找回功能是,系统会吧密码重置的连接通过邮件或短信方式发送给用户,用户点击链接后就可以重置密码,cas还支持预留密码重置的问题,只有回答对了,才可以重置密码;系统可配置密码重置后,是否自动登录; 密码修改功能是,用户登录后输入新密码即可完成密码修改。安装步骤`1. 首先,搭建好cas sso server您需要按..._修改cas默认用户密码
文章浏览阅读141次。之前几章演示的熔断,降级 都是 RestTemplate + Ribbon 和RestTemplate + Hystrix ,但是在实际开发并不是这样,实际开发中都是 Feign 远程接口调用。Feign + Hystrix 演示: eruka(略)order 服务工程: pom.xml<?xml version="1.0" encoding="U..._this is order 服务工程
文章浏览阅读3.4k次,点赞35次,收藏43次。学习率是影响目标检测精度和速度的重要因素之一。合适的学习率调度策略可以加速模型的收敛和提高模型的精度。在YOLOv7算法中,可以使用基于余弦函数的学习率调度策略(Cosine Annealing Learning Rate Schedule)来调整学习率。
文章浏览阅读4k次,点赞4次,收藏9次。 linux中进程退出函数:exit()和_exit()的区别(1)_exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。(2)调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr ...). exit函数是在_exit..._linux结束进程可以用哪些函数,它们之间有何区别?
文章浏览阅读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