All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fun.bigtable.kraken.util.FenceUtils Maven / Gradle / Ivy

There is a newer version: 2.0.9.1
Show newest version
package fun.bigtable.kraken.util;

import cn.hutool.http.HttpUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import fun.bigtable.kraken.trace.ITrace;
import fun.bigtable.kraken.trace.bean.DefaultTrace;
import fun.bigtable.kraken.util.fence.FenceTypeEnum;
import fun.bigtable.kraken.util.fence.GPSUtils;
import fun.bigtable.kraken.util.fence.WarningRuleFence;

import java.util.ArrayList;
import java.util.List;

public class FenceUtils {

    /**
     * 回转数法判断点是否在多边形内部
     *
     * @see  GEOJSON标准格式
     * @see dataV
     * @see 算法来源
     *
     * @param p    待判断的点
     * @param poly 多边形顶点,
     * @return 点 p 和多边形 poly 的几何关系,是否在多边形内部
     */
    public static boolean windingNumber(ITrace p, List poly) {
        double px = Double.parseDouble(p.getLon());
        double py = Double.parseDouble(p.getLat());
        double sum = 0;

        for (int i = 0, l = poly.size(), j = l - 1; i < l; j = i, i++) {
            double sx = Double.parseDouble(poly.get(i).getLon());
            double sy = Double.parseDouble(poly.get(i).getLat());
            double tx = Double.parseDouble(poly.get(j).getLon());
            double ty = Double.parseDouble(poly.get(j).getLat());

            // 点与多边形顶点重合或在多边形的边上
            if ((sx - px) * (px - tx) >= 0 && (sy - py) * (py - ty) >= 0 && (px - sx) * (ty - sy) == (py - sy) * (tx - sx)) {
                return false;
            }

            // 点与相邻顶点连线的夹角
            double angle = Math.atan2(sy - py, sx - px) - Math.atan2(ty - py, tx - px);

            // 确保夹角不超出取值范围(-π 到 π)
            if (angle >= Math.PI) {
                angle = angle - Math.PI * 2;
            } else if (angle <= -Math.PI) {
                angle = angle + Math.PI * 2;
            }
            sum += angle;
        }

        // 计算回转数并判断点和多边形的几何关系
        return Math.round(sum / Math.PI) != 0;
    }

    /**
     * 圆形围栏判断位置点是否在围栏内部
     *
     * @param center 中心点位置
     * @param p      需判断的点的位置
     * @param radius 判断半径
     */
    public static boolean circleFence(ITrace center, ITrace p, int radius) {
        return GPSUtils.GetDistance(Double.parseDouble(center.getLat()), Double.parseDouble(center.getLon()), Double.parseDouble(p.getLat()), Double.parseDouble(p.getLon())) < radius;

    }

    /**
     * 位置点是否在围栏中
     * @param position 位置点
     * @param warningRuleFence 围栏配置
     * @return 是否在围栏中
     */
    public static boolean checkInFence(ITrace position, WarningRuleFence warningRuleFence) {
        switch (FenceTypeEnum.getTypeByCode(warningRuleFence.getFenceType())) {
            case ROUND:
                String[] split = warningRuleFence.getCenterPosition().split(",");
                DefaultTrace center = new DefaultTrace();
                center.setLat(split[1]);
                center.setLon(split[0]);
                return FenceUtils.circleFence(center, position, warningRuleFence.getRadius());
            case CUSTOM:
                JsonParser parser = new JsonParser();
                JsonArray jsonArray = parser.parse(warningRuleFence.getFenceBorder()).getAsJsonObject().getAsJsonArray("position");

                List poly = new ArrayList<>();

                for (JsonElement jsonElement : jsonArray) {
                    poly.add(DefaultTrace.DefaultTraceBuilder.aDefaultTrace().lon(jsonElement.getAsJsonArray().get(0).getAsString()).lat(jsonElement.getAsJsonArray().get(1).getAsString()).build());
                }

                return FenceUtils.windingNumber(position, poly);
            case AREA:
                parser = new JsonParser();
                String areaStr = HttpUtil.get("https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=" + warningRuleFence.getAreaCode());
                jsonArray = parser.parse(areaStr).getAsJsonObject().getAsJsonArray("features").get(0).getAsJsonObject().getAsJsonObject("geometry").getAsJsonArray("coordinates").get(0).getAsJsonArray().get(0).getAsJsonArray();

                poly = new ArrayList<>();

                for (JsonElement jsonElement : jsonArray) {
                    poly.add(DefaultTrace.DefaultTraceBuilder.aDefaultTrace().lon(jsonElement.getAsJsonArray().get(0).getAsString()).lat(jsonElement.getAsJsonArray().get(1).getAsString()).build());
                }

                poly.remove(0);
                return FenceUtils.windingNumber(position, poly);
            default:
                return false;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy