基于平面空间坐标系,或者是地图区域中,存在若干的散点数据,需要根据坐标系的比例或者是地图的比例大小,做空间的聚合,将多个散点聚合到一个点位中时,用到蜂窝网格的计算。
1.获取一个区域的坐标数组
public static Coordinate[] getCoordinate(String geomStr){
GeometryFactory geometryFactory = new GeometryFactory();
WKTReader reader = new WKTReader(geometryFactory );
//获取polygon对象
Polygon polygon= (Polygon) reader.read(geomStr);
//获取坐标点位数组
return polygon.getCoordinates();
}
2.根据坐标数组获取该区域最大最小经纬度坐标
public static Coordinate[] getMaxAndMinPoint(Coordinate[] coordinates) {
Double max_x = Double.MIN_VALUE;
Double max_y = Double.MIN_VALUE;
Double min_x = Double.MAX_VALUE;
Double min_y = Double.MAX_VALUE;
for (Coordinate coordinate : coordinates) {
if (coordinate.x > max_x) max_x = coordinate.x;
if (coordinate.x < min_x) min_x = coordinate.x;
if (coordinate.y > max_y) max_y = coordinate.y;
if (coordinate.y < min_y) min_y = coordinate.y;
}
Coordinate[] points = new Coordinate[2];
points[0] = new Coordinate(max_x, max_y);
points[1] = new Coordinate(min_x, min_y);
return points;
}
3.根据最大最小坐标,以及所需的蜂窝网格边长,计算所有蜂窝点位数据
3.1 地图比例对应蜂窝边长
public enum MapLevelEnum {
Level_1(1,26.2144),
Level_2(2,13.1072),
Level_3(3,6.5536),
Level_4(4,3.2768),
Level_5(5,1.6384),
Level_6(6,0.8192),
Level_7(7,0.4096),
Level_8(8,0.2048),
Level_9(9,0.1024),
Level_10(10,0.0512),
Level_11(11,0.0256),
Level_12(12,0.0128),
Level_13(13,0.0064),
Level_14(14,0.0032),
Level_15(15,0.0016),
Level_16(16,0.0008),
Level_17(17,0.0004),
Level_18(18,0.0002),
Level_19(19,0.0001);
private Integer level;
private Double precision;
MapLevelEnum(Integer level, Double precision) {
this.level = level;
this.precision = precision;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Double getPrecision() {
return precision;
}
public void setPrecision(Double precision) {
this.precision = precision;
}
public static MapLevelEnum getMapLevel(Integer level){
for (MapLevelEnum value : MapLevelEnum.values()) {
if (value.level==level){
return value;
}
}
return null;
}
}
3.2计算蜂窝
3.2.1 蜂窝对象
public class CellularGrid{
// 边长
double sideLenth;
// 中心
double centerX;
double centerY;
// 六顶点
double x1;
double x2;
double x3;
double x4;
double x5;
double x6;
double y1;
double y2;
double y3;
double y4;
double y5;
double y6;
Polygon polygon;
public CellularGrid(double centerX, double centerY, double sideLenth, GeometryFactory geometryFactory) {
this.centerX = centerX;
this.centerY = centerY;
this.sideLenth = sideLenth;
double H = Math.sin(Math.PI / 3) * sideLenth;
this.x1 = this.centerX - 0.5 * sideLenth;
this.x2 = this.centerX + 0.5 * sideLenth;
this.x3 = this.centerX + sideLenth;
this.x4 = this.centerX + 0.5 * sideLenth;
this.x5 = this.centerX - 0.5 * sideLenth;
this.x6 = this.centerX - sideLenth;
this.y1 = this.centerY + H;
this.y2 = this.centerY + H;
this.y3 = this.centerY;
this.y4 = this.centerY - H;
this.y5 = this.centerY - H;
this.y6 = this.centerY;
Coordinate c1 = new Coordinate(x1, y1);
Coordinate c2 = new Coordinate(x2, y2);
Coordinate c3 = new Coordinate(x3, y3);
Coordinate c4 = new Coordinate(x4, y4);
Coordinate c5 = new Coordinate(x5, y5);
Coordinate c6 = new Coordinate(x6, y6);
Coordinate[] coordinateArray = (Coordinate[]) Arrays.asList(c1, c2, c3, c4, c5, c6, c1).toArray();
this.polygon = geometryFactory.createPolygon(coordinateArray);
}
public double getSideLenth() {
return sideLenth;
}
public void setSideLenth(double sideLenth) {
this.sideLenth = sideLenth;
}
public double getCenterX() {
return centerX;
}
public void setCenterX(double centerX) {
this.centerX = centerX;
}
public double getCenterY() {
return centerY;
}
public void setCenterY(double centerY) {
this.centerY = centerY;
}
public double getX1() {
return x1;
}
public void setX1(double x1) {
this.x1 = x1;
}
public double getX2() {
return x2;
}
public void setX2(double x2) {
this.x2 = x2;
}
public double getX3() {
return x3;
}
public void setX3(double x3) {
this.x3 = x3;
}
public double getX4() {
return x4;
}
public void setX4(double x4) {
this.x4 = x4;
}
public double getX5() {
return x5;
}
public void setX5(double x5) {
this.x5 = x5;
}
public double getX6() {
return x6;
}
public void setX6(double x6) {
this.x6 = x6;
}
public double getY1() {
return y1;
}
public void setY1(double y1) {
this.y1 = y1;
}
public double getY2() {
return y2;
}
public void setY2(double y2) {
this.y2 = y2;
}
public double getY3() {
return y3;
}
public void setY3(double y3) {
this.y3 = y3;
}
public double getY4() {
return y4;
}
public void setY4(double y4) {
this.y4 = y4;
}
public double getY5() {
return y5;
}
public void setY5(double y5) {
this.y5 = y5;
}
public double getY6() {
return y6;
}
public void setY6(double y6) {
this.y6 = y6;
}
public Polygon getPolygon() {
return polygon;
}
public void setPolygon(Polygon polygon) {
this.polygon = polygon;
}
}
3.2.2 计算蜂窝
public static List<HexagonBO> getHexagonBOList(){
int level=15;
String geomStr="POLYGON((121.32506989602659 31.223014372314935,121.48366224813478 31.228140808580477,121.5190866566813 31.120893846786345,121.31144512350873 31.089162799223104,121.25422107893358 31.172667326376356,121.32506989602659 31.223014372314935))";
Coordinate[] coordinates = getCoordinate(geomStr);
Coordinate[] maxAndMinPointCoordinates =getMaxAndMinPoint(coordinates);
return createCellularGridList(maxAndMinPoint[1].x, maxAndMinPoint[0].y, maxAndMinPoint[0].x, maxAndMinPoint[1].y,MapLevelEnum.getMapLevel(level).getPrecision());
}
public static List<CellularGrid> createCellularGridList(Double minx, Double maxy, Double maxx, Double miny,
Double gridSideLength) {
List<CellularGrid> cellularGridList = new ArrayList<HexagonBO>();
for (double i = 0; ; i++) {
//中心X
Double centerx = minx + i * 1.5 * gridSideLength + gridSideLength * 0.5;
for (double j = 0; ; j++) {
//中心Y
Double centery;
if (i % 2 == 0) {
centery = maxy - j * Math.sin(PI / 3) * 2.0 * gridSideLength;
} else {
centery = maxy - (j * Math.sin(PI / 3) * 2.0 * gridSideLength
+ Math.sin(PI / 3) * gridSideLength);
}
CellularGrid cellularGrid= new CellularGrid (centerx , centery, gridSideLength, new GeometryFactory());
cellularGridList .add(cellularGrid);
//从左上角开始绘制六边形,判断Y5的Y左边和最小Y坐标关系
if (cellularGrid.getY5() < miny) {
break;
}
}
//判断中心X+0.5倍边长和最大X坐标关系
if (centerx + gridSideLength * 0.5 > maxx) {
break;
}
}
return cellularGridList ;
}
至此,能获取geomStr这个空间区域内的蜂窝网格数据,cellularGridList 中的每一个对象,都是一个正六边形区域,属性包含中心点、六边形的6个点位的经纬度,以及六边形区域的Ploygon对象和坐标数组。在后续查询散点坐标时,将六边形的Ploygon作为空间查询条件,将Ploygon内的所有散点数量统计出来,作为聚合的数据。