政区四至与地图四至范围聚合效果计算方法

目录

地图屏占比

屏占比算法

矩形求重叠面积算法

聚合计算工具类

聚合效果图


地图聚合屏幕占比 = 政区四至面积/屏幕四至面积x100%. 两个矩形确定一个同位点然后计算两点相交部分的长宽面积即可。

地图屏占比

图形面积与当前四至面积比对占比值,合理的比重是20%。

 

屏占比算法

https://blog.csdn.net/liuzhenya1994/article/details/80870830?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.edu_weight

F= 矩形面积/地图四至面积* 100%

矩形集已知,轮询计算

  • 小于20% 显示聚合-计算结束
  • 大于20% 继续下级计算,直到计算占比面积小于20%结束,没有下级结束,显示空间点。

两点确定一条直线,两线确定一面

矩形的面积= 长* 宽

geometry多边形的面积 = geometry直接求算 Postgresql有函数

矩形求重叠面积算法

定义矩形

package com.boonya.beans.gis;

import java.io.Serializable;

/**
 * @Copyright: 2019-2021
 * @FileName: Rectangle.java
 * @Author: PJL
 * @Date: 2020/7/14 18:19
 * @Description: 矩形
 */
public class Rectangle implements Comparable<Rectangle>, Serializable {
    private double x; //矩形左下角的x坐标
    private double y; //矩形左下角的y坐标
    private double length;
    private double width;

    public Rectangle(double x, double y, double length, double width) {
        this.x = x;
        this.y = y;
        this.length = length;
        this.width = width;
    }

    public double getArea() {
        return length * width;
    }

    public double getX() {
        return x;
    }

    public double getY() {
        return y;
    }

    public double getLength() {
        return length;
    }

    public double getWidth() {
        return width;
    }

    @Override
    public int compareTo(Rectangle o) {
        return Double.compare(this.getArea(), o.getArea());
    }
}

定义计算面积方法

package com.boonya.beans.gis;

/**
 * @Copyright: 2019-2021
 * @FileName: RectangleOverlap.java
 * @Author: PJL
 * @Date: 2020/7/14 18:21
 * @Description: 矩形重叠面积
 */
public class RectangleOverlap {

    /**
     * 计算重叠区域面积
     *
     * @param rect1
     * @param rect2
     * @return
     */
    public double calculateOverlapArea(Rectangle rect1, Rectangle rect2) {
        if (rect1 == null || rect2 == null) {
            return -1;
        }
        double p1_x = rect1.getX(), p1_y = rect1.getY();
        double p2_x = p1_x + rect1.getLength(), p2_y = p1_y + rect1.getWidth();
        double p3_x = rect2.getX(), p3_y = rect2.getY();
        double p4_x = p3_x + rect2.getLength(), p4_y = p3_y + rect2.getWidth();

        if (p1_x > p4_x || p2_x < p3_x || p1_y > p4_y || p2_y < p3_y) {
            return 0;
        }
        double Len = Math.min(p2_x, p4_x) - Math.max(p1_x, p3_x);
        double Wid = Math.min(p2_y, p4_y) - Math.max(p1_y, p3_y);
        return Len * Wid;
    }

    public static void main(String[] args) {
        Rectangle rect1 = new Rectangle(0, 1, 3, 2);
        Rectangle rect2 = new Rectangle(2, 0, 2, 2);
        RectangleOverlap overlap = new RectangleOverlap();
        System.out.println(overlap.calculateOverlapArea(rect1, rect2));
    }
}

 

聚合计算工具类

package com.boonya.beans.util;

import com.alibaba.fastjson.JSONArray;
import com.boonya.beans.Constants;
import com.boonya.beans.gis.Rectangle;
import com.boonya.beans.gis.RectangleOverlap;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;

import java.util.List;
import java.util.Map;

/**
 * @Copyright: 2019-2021
 * @FileName: LogicUtil.java
 * @Author: PJL
 * @Date: 2020/6/29 15:34
 * @Description: 逻辑处理工具类
 */
@Slf4j
public class LogicUtil {

    /**
     * 获取四至范围数组
     *
     * @param extentArray
     * @return
     */
    public static Double[] getExtent(JSONArray extentArray) {
        int count = extentArray.size();
        Double[] extent = new Double[count];
        for (int i = 0; i < count; i++) {
            extent[i] = extentArray.getDouble(i);
        }
        return extent;
    }

    /**
     * 解析组织机构数组
     *
     * @param list
     * @return
     */
    public static String[] getOrgIds(List<Map<String, Object>> list) {
        if (ObjectUtils.isEmpty(list)) {
            return new String[]{};
        }
        String[] orgIds = new String[list.size()];
        int index = 0;
        for (Map<String, Object> map : list) {
            orgIds[index] = null == map.get("I_ORGID") ? map.get("i_orgid").toString() : map.get("I_ORGID").toString();
            index++;
        }
        return orgIds;
    }

    /**
     * 组织机构过滤条件
     *
     * @param orgIds
     * @return
     */
    public static String getOrgFilterString(String[] orgIds) {
        if (ObjectUtils.isEmpty(orgIds)) {
            return "-1";
        }
        StringBuffer sb = new StringBuffer();
        for (int i = 0, j = orgIds.length; i < j; i++) {
            if (i == 0) {
                sb.append(orgIds[i]);
            } else {
                sb.append(",").append(orgIds[i]);
            }
        }
        return sb.toString();
    }

    /**
     * 根据地图缩放层级获取组织机构编号长度条件位数
     *
     * @param level
     * @param isAll
     * @return
     */
    public static int getOrgCodeLengthByLevel(Integer level, boolean isAll) {
        int result = 0;
        switch (level) {
            /****************一级*****************/

            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
                if (isAll) {
                    /****************全国*****************/
                    result = 1;
                } else {
                    result = 4;
                }
                break;
            /****************二级*****************/
            case 7:
            case 8:
                result = 4 * 2;
                break;
            /****************三级级*****************/
            case 9:
            case 10:
                result = 4 * 3;
                break;
            /****************四级*****************/
            case 11:
            case 12:
                result = 4 * 4;
                break;
            /****************五级*****************/
            case 13:
            case 14:
                result = 4 * 5;
                break;
            /****************默认*****************/
            default:
                result = 4 * 5;
                break;
        }
        return result;
    }

    /**
     * 四至范围扩大计算
     *
     * @param zoom
     * @param extent
     * @return
     */
    public static Double[] extentBetter(Integer zoom, Double[] extent) {
        // 15级之前四至范围扩大百分之20(解决四至范围没有组织机构中心点问题)
        if (zoom.intValue() <= Constants.MAP_AGGREGATION_MAX_ZOOM_NUMBER) {
            double factor = 1.2;
            extent[0] /= factor;// 左下角点X缩小
            extent[1] /= factor;// 左下角点Y缩小
            extent[2] *= factor;// 右上角点X扩大
            extent[3] *= factor;// 右上角点Y扩大
        }
        return extent;
    }

    /**
     * 获取重叠部分面积值
     *
     * @param screenExtent
     * @param orgExtent
     * @return
     */
    public static double getRectangleArea(Double[] screenExtent, Double[] orgExtent) {
        double screenLength = Math.abs(screenExtent[2] - screenExtent[0]);
        double screenWidth = Math.abs(screenExtent[3] - screenExtent[1]);
        double orgLength = Math.abs(orgExtent[2] - orgExtent[0]);
        double orgWidth = Math.abs(orgExtent[3] - orgExtent[1]);
        Rectangle rectangle = new Rectangle(screenExtent[0], screenExtent[1], screenLength, screenWidth);
        Rectangle rectangle2 = new Rectangle(orgExtent[0], orgExtent[1], orgLength, orgWidth);
        RectangleOverlap overlap = new RectangleOverlap();
        return overlap.calculateOverlapArea(rectangle, rectangle2);
    }

    /**
     * 矩形相交屏幕占比计算(百分数值)
     *
     * @param screenExtent
     * @param orgExtent
     * @return
     */
    public static long getShadowRateOfRectangle(Double[] screenExtent, Double[] orgExtent) {
        double screenLength = Math.abs(screenExtent[2] - screenExtent[0]);
        double screenWidth = Math.abs(screenExtent[3] - screenExtent[1]);
        double areaScreen = screenLength * screenWidth;
        double overlayArea = getRectangleArea(screenExtent, orgExtent);
        long percentage = Math.round(overlayArea / areaScreen * 100);
        log.info(">>>>LogicUtil overlayArea={}  percentage = {}", overlayArea, percentage);
        return percentage;
    }

    /**
     * 判断两个矩形是否有重叠部分
     *
     * @param screenExtent
     * @param orgExtent
     * @return
     */
    public static boolean isIntersected(Double[] screenExtent, Double[] orgExtent) {
        boolean flag = false;
        double overlayArea = getRectangleArea(screenExtent, orgExtent);
        if (overlayArea > 0) {
            flag = true;
        }
        log.info(">>>>LogicUtil overlayArea={} isIntersected = {}", overlayArea, flag);
        return flag;
    }
}

政区聚合递归算法:

  /**
     * 根据四至计算地图显示数据方式【聚合/散点】==返回组织机构标识
     *
     * @param org
     * @param screenExtent
     * @param orgMap       k-v = 组织机构ID-组织机构编码:是否聚合(true|false)
     * @return
     */
    public Map<String, Boolean> calculateOrgAggregationData(Org org, Double[] screenExtent, Map<String, Boolean> orgMap) {
        Double[] orgExtent = org.getExtent();
        // 第一步: 屏幕四至求交组织机构四至
        boolean intersected = LogicUtil.isIntersected(screenExtent, orgExtent);
        if (intersected) {
            // 计算当前组织机构占比
            long rate = LogicUtil.getShadowRateOfRectangle(screenExtent, orgExtent);
            String key = new StringBuffer(org.getId()).append("-").append(org.getCode()).toString();
            if (rate < Constants.MAP_AGGREGATION_SCREEN_RATE) {
                orgMap.put(key, true);// 设置是否聚合
            } else {
                try {
                    List<Map<String, Object>> list = this.getDirectChildrenOrgListById(org.getId());
                    if (ObjectUtils.isNotEmpty(list)) {
                        for (Map<String, Object> childOrg : list) {
                            Org tempOrg = this.getOrgPositionByMap(childOrg);
                            // 递归获取下级单位占比值
                            calculateOrgAggregationData(tempOrg, screenExtent, orgMap);
                        }
                    } else {
                        // 没有下级单位 但面积大于MAP_AGGREGATION_SCREEN_RATE
                        orgMap.put(key, false);// 设置是否聚合
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        return orgMap;
    }

 Constants.MAP_AGGREGATION_SCREEN_RATE =20

聚合效果图

注:本文介绍算法适用于组织机构有中心点和四至范围的情况。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值