概述java
本文讲述如何在geotools中生成泰森多边形,并shp输出。git
泰森多边形github
一、定义web
泰森多边形又叫冯洛诺伊图(Voronoi diagram),得名于Georgy Voronoi,是由一组由链接两邻点直线的垂直平分线组成的连续多边形组成。
算法
二、创建步骤dom
创建泰森多边形算法的关键是对离散数据点合理地连成三角网,即构建Delaunay三角网。创建泰森多边形的步骤为:
1)离散点自动构建三角网,即构建Delaunay三角网。对离散点和造成的三角形编号,记录每一个三角形是由哪三个离散点构成的。
2)找出与每一个离散点相邻的全部三角形的编号,并记录下来。这只要在已构建的三角网中找出具备一个相同顶点的全部三角形便可。
3)对与每一个离散点相邻的三角形按顺时针或逆时针方向排序,以便下一步链接生成泰森多边形。设离散点为o。找出以o为顶点的一个三角形,设为A;取三角形A除o之外的另外一顶点,设为a,则另外一个顶点也可找出,即为f;则下一个三角形必然是以of为边的,即为三角形F;三角形F的另外一顶点为e,则下一三角形是以oe为边的;如此重复进行,直到回到oa边。
4)计算每一个三角形的外接圆圆心,并记录之。
5)根据每一个离散点的相邻三角形,链接这些相邻三角形的外接圆圆心,即获得泰森多边形。对于三角网边缘的泰森多边形,可做垂直平分线与图廓相交,与图廓一块儿构成泰森多边形。
ssh
三、特征ide
1)每一个泰森多边形内仅含有一个离散点数据;
2)泰森多边形内的点到相应离散点的距离最近;
3)位于泰森多边形边上的点到其两边的离散点的距离相等。
测试
geotools中的生成ui
一、建立测试点
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)); }
二、生成泰森多边形
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"); } }
参考文献:
一、百度百科
---------------------------------------------------------------------------------------------------------------
技术博客
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)