欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-05-11 13:07:31
...

目录

地图屏占比

屏占比算法

矩形求重叠面积算法

聚合计算工具类

聚合效果图


地图聚合屏幕占比 = 政区四至面积/屏幕四至面积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

聚合效果图

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

相关标签: LBS位置服务