随笔 - 227  文章 - 0  评论 - 13  阅读 - 19万 
  2017年7月23日

概述

本文讲述如何在geotools中生成泰森多边形,并shp输出。


泰森多边形

1、定义

泰森多边形又叫冯洛诺伊图(Voronoi diagram),得名于Georgy Voronoi,是由一组由连接两邻点直线的垂直平分线组成的连续多边形组成。


2、建立步骤

建立泰森多边形算法的关键是对离散数据点合理地连成三角网,即构建Delaunay三角网。建立泰森多边形的步骤为:
1)离散点自动构建三角网,即构建Delaunay三角网。对离散点和形成的三角形编号,记录每个三角形是由哪三个离散点构成的。
2)找出与每个离散点相邻的所有三角形的编号,并记录下来。这只要在已构建的三角网中找出具有一个相同顶点的所有三角形即可。
3)对与每个离散点相邻的三角形按顺时针或逆时针方向排序,以便下一步连接生成泰森多边形。设离散点为o。找出以o为顶点的一个三角形,设为A;取三角形A除o以外的另一顶点,设为a,则另一个顶点也可找出,即为f;则下一个三角形必然是以of为边的,即为三角形F;三角形F的另一顶点为e,则下一三角形是以oe为边的;如此重复进行,直到回到oa边。
4)计算每个三角形的外接圆圆心,并记录之。
5)根据每个离散点的相邻三角形,连接这些相邻三角形的外接圆圆心,即得到泰森多边形。对于三角网边缘的泰森多边形,可作垂直平分线与图廓相交,与图廓一起构成泰森多边形。


3、特征

1)每个泰森多边形内仅含有一个离散点数据;
2)泰森多边形内的点到相应离散点的距离最近;
3)位于泰森多边形边上的点到其两边的离散点的距离相等。


geotools中的生成

1、创建测试点


	    int xmin = 0, xmax=180;
        int ymin = 0, ymax=90;
        Random random = new Random();
        List<Geometry> geomsPoints = new ArrayList<Geometry>();
	    for(int i=0;i<100;i++){
	    	int x = random.nextInt(xmax)%(xmax-xmin+1) + xmin,
	            y = random.nextInt(ymax)%(ymax-ymin+1) + ymin;
	        Coordinate coord = new Coordinate(x,y,i);
	        coords.add(coord);
	        clipEnvelpoe.expandToInclude(coord);
	        geomsPoints.add(new GeometryFactory().createPoint(coord));
	    }

2、生成泰森多边形


	    voronoiDiagramBuilder.setSites(coords);
	    voronoiDiagramBuilder.setClipEnvelope(clipEnvelpoe);
	    Geometry geom = voronoiDiagramBuilder.getDiagram(JTSFactoryFinder.getGeometryFactory());
	    List<Geometry> geoms = new ArrayList<Geometry>();
	    for(int i=0;i<geom.getNumGeometries();i++){
	        geoms.add(geom.getGeometryN(i));
	    }

完整代码如下:

package com.lzugis.geotools;

import java.io.File;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

import org.geotools.data.FeatureWriter;
import org.geotools.data.Transaction;
import org.geotools.data.shapefile.ShapefileDataStore;
import org.geotools.data.shapefile.ShapefileDataStoreFactory;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.triangulate.VoronoiDiagramBuilder;

public class TsdbxTest {
	static TsdbxTest tsdbx = new TsdbxTest();
	public void voronoiTest(){
	    VoronoiDiagramBuilder voronoiDiagramBuilder = new VoronoiDiagramBuilder();
	    List<Coordinate> coords = new ArrayList<Coordinate>();
	    Envelope clipEnvelpoe = new Envelope();
	    int xmin = 0, xmax=180;
        int ymin = 0, ymax=90;
        Random random = new Random();
        List<Geometry> geomsPoints = new ArrayList<Geometry>();
	    for(int i=0;i<100;i++){
	    	int x = random.nextInt(xmax)%(xmax-xmin+1) + xmin,
	            y = random.nextInt(ymax)%(ymax-ymin+1) + ymin;
	        Coordinate coord = new Coordinate(x,y,i);
	        coords.add(coord);
	        clipEnvelpoe.expandToInclude(coord);
	        geomsPoints.add(new GeometryFactory().createPoint(coord));
	    }
	    String pointpath = "d:/data/tsdbxpt.shp";
	    tsdbx.writeShape(pointpath,"Point", geomsPoints);

	    voronoiDiagramBuilder.setSites(coords);
	    voronoiDiagramBuilder.setClipEnvelope(clipEnvelpoe);
	    Geometry geom = voronoiDiagramBuilder.getDiagram(JTSFactoryFinder.getGeometryFactory());
	    List<Geometry> geoms = new ArrayList<Geometry>();
	    for(int i=0;i<geom.getNumGeometries();i++){
	        geoms.add(geom.getGeometryN(i));
	    }
	    
	    String polygonpath = "d:/data/tsdbx.shp";
	    tsdbx.writeShape(polygonpath,"Polygon", geoms);
	}
	/**
	 * 
	 * @param filepath
	 * @param geoType
	 * @param geoms
	 */
	public void writeShape(String filepath, String geoType, List<Geometry> geoms) {
		try {
			//创建shape文件对象
			File file = new File(filepath);
			Map<String, Serializable> params = new HashMap<String, Serializable>();
			params.put( ShapefileDataStoreFactory.URLP.key, file.toURI().toURL() );
			ShapefileDataStore ds = (ShapefileDataStore) new ShapefileDataStoreFactory().createNewDataStore(params);
			//定义图形信息和属性信息
			SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder();
			tb.setCRS(DefaultGeographicCRS.WGS84);
			tb.setName("shapefile");
			if(geoType=="Point"){
				tb.add("the_geom", Point.class);
			}
			else{
				tb.add("the_geom", Polygon.class);
			}
			
			ds.createSchema(tb.buildFeatureType());
			//设置编码
            Charset charset = Charset.forName("GBK");
            ds.setCharset(charset);
			//设置Writer
			FeatureWriter<SimpleFeatureType, SimpleFeature> writer = ds.getFeatureWriter(ds.getTypeNames()[0], Transaction.AUTO_COMMIT);
			for(int i=0,len=geoms.size();i<len;i++){
				//写下一条
				SimpleFeature feature = writer.next();
				Geometry geom = geoms.get(i);
				feature.setAttribute("the_geom", geom);
			}
			writer.write();
			writer.close();
			ds.dispose();
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args){
		long start = System.currentTimeMillis();
		tsdbx.voronoiTest();
		System.out.println("共耗时"+(System.currentTimeMillis() - start)+"ms");
	}
}


参考文献:

1、百度百科

2、geotools user guide


---------------------------------------------------------------------------------------------------------------

技术博客

CSDN:http://blog.csdn.NET/gisshixisheng

博客园:http://www.cnblogs.com/lzugis/

在线教程

http://edu.csdn.Net/course/detail/799

Github

https://github.com/lzugis/

联系方式

q       q:1004740957

e-mail:niujp08@qq.com

公众号:lzugis15

Q Q 群:452117357(webgis)

             337469080(Android)

posted @ 2017-07-23 09:17 LZU-GIS 阅读(5771) 评论(2) 推荐(0) 编辑
  2017年7月9日
摘要: 截止发文时间,博主“LZUGIS”CSDN博客文章总访问量突破50W,值此特殊的时刻,特发此文,以表纪念与督促。博客详情博客专栏公众号常言道:不积跬步,无以至千里;不积小流,无以成江河。博主LZUGIS用自己的努力证明了这句话。从2004年年底创建博客开始,博主不忘初心、勤于耕耘,用自己的方式在为G... 阅读全文
posted @ 2017-07-09 21:10 LZU-GIS 阅读(256) 评论(0) 推荐(1) 编辑
  2017年7月5日
摘要: 概述:本文说说geotools中坐标转换的那点事情,以WGS84和web墨卡托相互转换为例。效果:转换前转换后单个Geometry转换实现代码:package com.lzugis.geotools;import java.io.File;import java.io.Serializable;im... 阅读全文
posted @ 2017-07-05 08:45 LZU-GIS 阅读(4859) 评论(0) 推荐(0) 编辑
  2017年7月2日
摘要: 概述:在本文中,讲述如何在geotools中实现shp和geojson数据的相互转换。效果:实现代码:package com.lzugis.geotools;import java.io.File;import java.io.Reader;import java.io.Serializable;i... 阅读全文
posted @ 2017-07-02 08:20 LZU-GIS 阅读(10318) 评论(0) 推荐(0) 编辑
  2017年6月30日
摘要: 概述:本文讲述如何在geotools中实现shp数据的缓冲区分析并保存到shp文件中。效果:实现代码:package com.lzugis.geotools;import java.io.File;import java.io.Serializable;import java.nio.charset... 阅读全文
posted @ 2017-06-30 07:28 LZU-GIS 阅读(2092) 评论(1) 推荐(0) 编辑
  2017年6月28日
摘要: 概述:本文讲解通过Geotools实现用shp和sld导出图片。实现:生成后的图片实现代码:package com.lzugis.geotools;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Rectangl... 阅读全文
posted @ 2017-06-28 10:43 LZU-GIS 阅读(3540) 评论(0) 推荐(0) 编辑
  2017年6月24日
摘要: 概述:本文讲述如何在OL3中加载Geojson并动态修改图层样式。效果:地图展示样式修改面板实现代码: Ol3 wms 显示标注 填充颜色: 黑色 蓝色 红色 自定义 填充透明度: ... 阅读全文
posted @ 2017-06-24 21:47 LZU-GIS 阅读(541) 评论(0) 推荐(0) 编辑
摘要: 经过一个多月的准备,“GIS讲堂”正式改名为“牛讲堂”,并对形象也做了相应的修改与更新,让我们一起记住“牛讲堂”,它在后面的时间里会给大家带来更多的福利与惊喜。“图释高校”项目实战课程详细内容如下:实现过程标记: 优先级 1 1、需求调研 2、数据收集 3、框架设计 4、编码实现 5、测试部署 6、... 阅读全文
posted @ 2017-06-24 15:28 LZU-GIS 阅读(281) 评论(0) 推荐(0) 编辑
  2017年6月22日
摘要: 概述本文讲述OL3结合echart,实现echart中的炫酷特效。效果echart3echart2说明:1、echart3中特效没出来,找了半天原因,还未搞定,感兴趣的可以一起看看。思路1、通过OL3种屏幕坐标和地理坐标的相互转换,实现echatt在地图中的展示;2、通过监控view的propert... 阅读全文
posted @ 2017-06-22 06:58 LZU-GIS 阅读(1258) 评论(0) 推荐(0) 编辑
  2017年6月18日
摘要: 概述:本文实现唐宋诗人分布数据的获取与webgis的展示。效果:获取的数据概览放大后详细信息实现:1、数据获取本文的数据是从搜韵获取而来的,地址为http://sou-yun.com/poetlife.html,为方便大家使用,将数据保存到了百度云盘,下载信息为:链接:http://pan.baid... 阅读全文
posted @ 2017-06-18 08:34 LZU-GIS 阅读(667) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示