资讯专栏INFORMATION COLUMN

基于K-means 切割多边形 JAVA实现

haobowd / 894人阅读

摘要:基于切割多边形实现思路初稿详见多边形等分依赖实现实现过程结果类泰森多边形平分多边形结果原始平面随机点集合分组后组中心集合构造泰森多边形聚合类聚合聚合总量数据集合簇族数量中

基于K-means 切割多边形 JAVA实现

思路初稿详见多边形等分

依赖

geotools

ekmeans

 
    
    
      org.locationtech.jts
      jts-core
      1.16.0
    
    
      junit
      junit
      4.12
      test
    

    
      org.geotools
      gt-shapefile
      ${geotools.version}
    

    
    
      org.geotools
      gt-main
      ${geotools.version}
    

    
      org.geotools
      gt-swing
      ${geotools.version}
    
    
      org.geotools
      gt-geojson
      ${geotools.version}
    
    
      org.geotools
      gt-geometry
      ${geotools.version}
    
    
    
      com.vividsolutions
      jts
      1.13
    


    
      org.geotools
      gt-geojson
      ${geotools.version}
    

   
      ca.pjer
      ekmeans
      2.0.0
      compile
    
实现过程

结果类 KmeanPolygonResult

package com.huifer.planar.asEt.entity;

import java.util.ArrayList;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;

/**
 * 

Title : KmeanPolygonResult

*

Description : Kmean+泰森多边形平分多边形结果

* * @author huifer * @date 2019-01-16 */ @Data @NoArgsConstructor @AllArgsConstructor public class KmeanPolygonResult { /** * 原始平面 */ private Polygon polygon; /** * 随机点集合 */ private ArrayList pointList; /** * 分组后组id */ private int[] assignments; /** * 中心集合 */ private double[][] centroids; /** * xlist */ private ArrayList xlist; /** * ylist */ private ArrayList ylist; /** * 构造泰森多边形 */ private List voronoi; }

k-means 聚合类

package com.huifer.planar.asEt.utils;

import ca.pjer.ekmeans.EKmeans;
import lombok.Data;

/**
 * 

Title : Kmeans

*

Description : Kmeans 聚合

* * @author huifer * @date 2019-01-15 */ @Data public class Kmeans { /*** * 聚合总量 */ private int n; /*** * 数据集合 */ private double[][] points; /** * 簇族数量 */ private int k; /** * 中心集合 */ private double[][] centroids; /** * 分组后组id */ private int[] assignments; public Kmeans(double[][] points, int k) { this.n = points.length; this.points = points; this.k = k; this.centroids = new double[k][2]; init(); } /** * 求得分组数据 */ public void init() { EKmeans eKmeans = new EKmeans(centroids, points); eKmeans.setIteration(128); eKmeans.setEqual(true); eKmeans.setDistanceFunction(EKmeans.EUCLIDEAN_DISTANCE_FUNCTION); eKmeans.run(); int[] assignments = eKmeans.getAssignments(); this.assignments = assignments; double[][] centroids = eKmeans.getCentroids(); this.centroids = centroids; } }

泰森多边形构造

package com.huifer.planar.asEt.algo.impl;

import com.huifer.planar.asEt.algo.VoronoiInterface;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.triangulate.VoronoiDiagramBuilder;
import org.locationtech.jts.triangulate.quadedge.QuadEdgeSubdivision;

/**
 * 

Title : VoronoiInterfaceImpl

*

Description : 泰森多边形 & 德劳内三角形

* * @author huifer * @date 2019-01-16 */ public class VoronoiInterfaceImpl implements VoronoiInterface { @Override public List voronoi(double[][] doubles) { return voronoi(doublesToCoordinate(doubles)); } @Override public Collection delaunay(double[][] doubles) { return delaunay(doublesToCoordinate(doubles)); } @Override public List voronoi(ArrayList points) { List voronoi = voronoi(pointToCoordinate(points)); return voronoi; } @Override public Collection delaunay(ArrayList points) { Collection delaunay = delaunay(pointToCoordinate(points)); return delaunay; } private List doublesToCoordinate(double[][] doubles) { List coords = new ArrayList(); for (int i = 0; i < doubles.length; i++) { Coordinate coord = new Coordinate(doubles[i][0], doubles[i][1], i); coords.add(coord); } return coords; } private List pointToCoordinate(ArrayList points) { List coords = new ArrayList(); for (int i = 0; i < points.size(); i++) { Coordinate coord = new Coordinate(points.get(i).getX(), points.get(i).getY(), i); coords.add(coord); } return coords; } private VoronoiDiagramBuilder getVoronoiDiagramBuilder(List coords) { VoronoiDiagramBuilder voronoiDiagramBuilder = new VoronoiDiagramBuilder(); Envelope clipEnvelpoe = new Envelope(); voronoiDiagramBuilder.setSites(coords); voronoiDiagramBuilder.setClipEnvelope(clipEnvelpoe); return voronoiDiagramBuilder; } @Override public List voronoi(List coords) { VoronoiDiagramBuilder voronoiDiagramBuilder = getVoronoiDiagramBuilder( coords); Geometry geom = voronoiDiagramBuilder .getDiagram(JTSFactoryFinder.getGeometryFactory()); List voronoi = new ArrayList<>(); int numGeometries = geom.getNumGeometries(); for (int i = 0; i < numGeometries; i++) { Geometry geometryN = geom.getGeometryN(i); voronoi.add(geometryN); } return voronoi; } @Override public Collection delaunay(List coords) { VoronoiDiagramBuilder voronoiDiagramBuilder = getVoronoiDiagramBuilder(coords); QuadEdgeSubdivision subdivision = voronoiDiagramBuilder.getSubdivision(); Collection delaunay = subdivision.getEdges(); return delaunay; } }

Kmeans 切割面类

package com.huifer.planar.asEt.algo.impl;

import com.huifer.planar.asEt.algo.KmeanPolygonSplitInterface;
import com.huifer.planar.asEt.algo.VoronoiInterface;
import com.huifer.planar.asEt.entity.KmeanPolygonResult;
import com.huifer.planar.asEt.utils.Kmeans;
import com.huifer.planar.asEt.utils.shptools.overlay.Operation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.io.ParseException;

/**
 * 

Title : KmeanPolygonSplitCore

*

Description : Kmean split polygon core

* * @author huifer * @date 2019-01-16 */ public class KmeanPolygonSplitCore implements KmeanPolygonSplitInterface { private static double random(double max, double min) { double d = (Math.random() * (max - min) + min); return d; } @Override public KmeanPolygonResult splitPolygon(String wkt, int setp, int k) throws ParseException { Operation op = new Operation(); KmeanPolygonResult result = new KmeanPolygonResult(); Polygon polygon = op.createPolygonByWKT(wkt); Coordinate[] coordinates = polygon.getCoordinates(); ArrayList xList = new ArrayList<>(); ArrayList yList = new ArrayList<>(); Arrays.stream(coordinates).forEach( s -> { xList.add(s.x); yList.add(s.y); } ); // xy 最大最小值 Double xMax = xList.stream().reduce(Double::max).get(); Double xMin = xList.stream().reduce(Double::min).get(); Double yMax = yList.stream().reduce(Double::max).get(); Double yMin = yList.stream().reduce(Double::min).get(); // 当前点数量 int pointCount = 0; ArrayList pointArrayList = new ArrayList<>(); for (int i = 0; i < Integer.MAX_VALUE; i++) { // 最大最小值随机 if (pointCount <= setp) { double rx = random(xMax, xMin); double ry = random(yMax, yMin); Point nowPoint = op.createPointByWkt("POINT(" + rx + " " + ry + ")"); boolean contains = polygon.contains(nowPoint); if (contains) { pointArrayList.add(nowPoint); pointCount++; } } else { break; } } // k-means 数据 构造 double[][] kmData = new double[pointArrayList.size()][2]; for (int i = 0; i < pointArrayList.size(); i++) { Point point = pointArrayList.get(i); double[] oneData = new double[2]; oneData[0] = point.getX(); oneData[1] = point.getY(); kmData[i] = oneData; } // k-means 结果 Kmeans kmeans = new Kmeans(kmData, k); // 构造泰森多边形 VoronoiInterface vo = new VoronoiInterfaceImpl(); List voronoi = vo.voronoi(kmeans.getCentroids()); result.setPolygon(polygon); result.setPointList(pointArrayList); result.setAssignments(kmeans.getAssignments()); result.setCentroids(kmeans.getCentroids()); result.setXlist(xList); result.setYlist(yList); result.setVoronoi(voronoi); return result; } }
结果展示

本文代码及可视化代码均放在 gitee 码云上 欢迎star & fork

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73041.html

相关文章

  • CSS-蜂窝状展示区域(多个六边形)的一种实现方式

    摘要:网上已经有很多关于正六边形的画法,主要是利用一个矩形和前后的两个三角形组合而成。是内容区,是一个菱形切割区,将切割成六边形。的高度,多排六边形的情况下,的高度与排与排之间的间隙有关。的高度,六边形对应顶点间的距离。网上已经有很多关于正六边形的CSS画法,主要是利用一个矩形和前后的两个三角形组合而成。 之前在看四维图新的官网的时候,发现了一种六边形的画法,比较适合多排六边形组合成蜂窝状的展示区...

    ideaa 评论0 收藏0
  • 自然语言处理真实项目实战

    摘要:在自然语言处理中,一个很重要的技术手段就是将文档转换为一个矢量,这个过程一般是使用这个库进行处理的。自然语言处理中,一般来说,代表词。自然语言预处理中,一个很重要的步骤就是将你收集的句子进行分词,将一个句子分解成词的列表。 前言 本文根据实际项目撰写,由于项目保密要求,源代码将进行一定程度的删减。本文撰写的目的是进行公司培训,请勿以任何形式进行转载。由于是日语项目,用到的分词软件等,在...

    王岩威 评论0 收藏0
  • 机器学习从入门到放弃K-Means聚类

    摘要:其实聚类算法还有一个妙用就是,当数据集过于庞大,并且原始数据并不存在信息,你又需要跑一个有监督学习的算法的时候,你想要人为的给数据打显然是不合适的,这时先跑一次聚类,记录好聚类的情况,再直接跑有监督学习的算法就可以了。 前言 在本系列前面的内容中,讲述了一系列的机器学习方法。要知道机器学习算法中,比较常用的主要分成有监督学习和无监督学习(其实还有一个叫半监督学习,在这里先不作讨论),简...

    张春雷 评论0 收藏0

发表评论

0条评论

haobowd

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<