在项目中经常用到多个城市地理数据的合并,但因城市的边界的规则性,就造成了在合并两个城市边界时出现了中间有空洞区域的情况。
以青海与甘肃张掖地理边界进行合并为例(为什么不用甘肃省的,因为省与省的地理边界往往是从同一套地理数据中提取的,存在边界空洞的情况就少一些)。来说明一下我的处理思路。
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();
}
}
效果图,红色框中的为根据关键点保留的空白区域。
文章浏览阅读6.9k次,点赞5次,收藏35次。基于模板匹配的数字识别,将标准的8*16像素的数字0123456789读取,二值化,对每个数字进行等分区域分割,统计每个区域内的黑色像素点的个数,即为特征初值。采用欧式距离的模板匹配法。z//基于模板匹配的数字识别#include#include#include#include #includeusing namespace std; int main()_基于模板匹配的数字电表数字识别
文章浏览阅读7.2k次,点赞11次,收藏74次。Python代码的编写运行方式详解_python安装好后怎么写代码
文章浏览阅读1.2k次。VS Code配置Code runner_vscode无法识别gcc
文章浏览阅读1.5w次,点赞10次,收藏14次。Unity3D中使用mesh collider和box collider的区别踩坑过程记录。设备是HTC的VIVE 和 Unity 5.xCPU: Intel Xeon Silver 4116 * 2GPU: NVIDIA Quadro P6000RAM: 64GB这个问题是在解决项目卡顿问题的同时出现的:最近在用U3D做一个VR项目,需求是要给网格加碰撞体以实现获取手柄射线与..._mesh collider和box collider
文章浏览阅读4.7k次。问题场景问题一:后端项目jar包打包上传运行,终端上正常,终端退出后,项目未能运行。问题二:第二次上传jar包并运行时提示该端口被占用。解决方法问题一:使用nohub命令启动jar包。nohup java -jar 1.0.0.jar &问题二:由于两次使用的同一个端口,先查找到当前端口正在运行的进程的进程号。netstat -lnp|grep 端口号然后用杀掉进程..._centos启动jar包不显示端口占用
文章浏览阅读3.9k次,点赞6次,收藏39次。MySql高级—视图、函数、存储过程、触发器目录 一、视图 11、视图的定义 1 2、视图的作用 1 (1)可以简化查询。 1 (2)可以进行权限控制, 3 3、查询视图 4 4、修改视图 4 5、删除视图 4_触发器 存储过程 函数 视图
文章浏览阅读399次。一,简单介绍KNN算法---就是获取临近点,范围内,哪一种点最多(例如:红点:6,黑点:2,未知点肯定是红点),就是属于最多一方定义样本,拥有四个样本,已知A区两点分别(2,5)和(1,4),B区(8,1)和(9,2),求灰点(4,3)属于哪一区?代码定义实体类/** * 定义数据和数据类型 * @author peng * */ private s..._jf.knn-%; 9 &
文章浏览阅读8.9k次,点赞2次,收藏9次。对于ffmpeg的配置请看我的上篇博客:http://blog.csdn.net/kuaile123/article/details/11367309所用视频为 flv格式的,用的vs2010,电脑为64位,下面的也是64位,别下错了。因为ffmpeg的函数和版本有关系,这里记录下我所用的整合的版本,是昨天下的最新版的,需要请下载http://download.csdn.n_从视频中获取flag
在直接映射缓存中,每个内存地址通过某种映射函数(通常是地址的一部分)映射到一个特定的缓存行。这种结构简单,硬件实现成本较低,但可能会导致较高的缓存冲突(两个内存地址映射到同一缓存行),从而降低缓存效率。在介绍直接映射之前,以停车场停车作为例子,先把结构的特点简单地概括出来,便于读者了解。
持续学习,跟进Objective-C的最新发展和技术。了解Objective-C的基本语法和编程概念。掌握Objective-C的高级特性和常用框架。应用所学知识,完成实际项目。
设R为G的所有生成树的集合,若T为R中边的权值之和最小的生成树,则T称为G的最小生成树(MST)。每次选则一条权值最小的边,使这条边的两头连通(原本已经连通的不选),直到所有结点都连通。,生成树不同,每棵树的权(即树中所有边上的权值之和)也可能不同。1.最小生成树可能有多个,但边的权值之和总是唯一且最小的;每次将代价最小的新顶点纳入生成树,直到所有顶点都纳入为止。数组,找到最小值,将其加入树中,并继续遍历与其相连的边。数组,初始为false,判断结点是否加入树。最低的,且还没加入树的顶点。
文章浏览阅读216次。python 模块 wmi 远程连接 windows 获取配置信息_python windows组策略