java 蜂窝算法用于地图或者坐标系聚合计算

基于平面空间坐标系,或者是地图区域中,存在若干的散点数据,需要根据坐标系的比例或者是地图的比例大小,做空间的聚合,将多个散点聚合到一个点位中时,用到蜂窝网格的计算。

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内的所有散点数量统计出来,作为聚合的数据。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值