根据经纬度获取点与区域,点与道路的距离

原理:一、点与区域的距离,根据回转数法判断,点到区域所有点形成的角度和为0,注意旋转方向要向一个方向,具体原理请百度

二、点与道路,根据点与线段的距离判断,获取点到所有线段的最小距离

1.实体类,存放点数据

public class Point{
 
    /**
     * x轴坐标 经度
     */
    double x;
    /**
     * y轴坐标 纬度
     */
    double y;
 
    public Point setPoint(Point point){
        this.x = point.getX();
        this.y = point.getY();
        return this;
    }
 
    public Point() {
    }
 
    public Point(Float[] point){
        this.x = point[0];
        this.y = point[1];
    }
 
    public Point(Double[] point) {
        this.x = point[0];
        this.y = point[1];
    }
 
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
 
    public double getX() {
        return x;
    }
 
    public void setX(double x) {
        this.x = x;
    }
 
    public double getY() {
        return y;
    }
 
    public void setY(double y) {
        this.y = y;
    }
 
 
}

2.枚举类,存放默认参数

public enum PointRelationEnum {

    POINT_IN_SCOPE(1,"在区域内"),
    POINT_OUT_SCOPE(2,"在区域外"),
    POINT_ON_BORDER(3,"在区域边界上");
    /**
     * 编码
     */
    private int code;
    /**
     * 描述
     */
    private String description;

    PointRelationEnum(int code,String description){
        this.code = code;
        this.description = description;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

3.工具类

public class testUtil{
 
 private static double earth_radius = 6378245.0;


    /**
     判断点与多边形的关系
     根据回转法
     **/
    public static PointRelationEnum poinWithPolygon(Point point, List<Point> points) {
        double px = point.getX(), py = point.getY(), sum = 0;
        for (int i = 0, l = points.size(), j = l - 1; i < l; j = i, i++) {
            double sx = points.get(i).getX(), sy = points.get(i).getY(), tx = points
                    .get(j).getX(), ty = points.get(j).getY();
            // 点与多边形定点重合或多边形的边上
            if ((sx - px) * (px - tx) >= 0 && (sy - px) * (px - tx) >= 0
                    && (px - sx) * (ty - sy) == (py - sy) * (tx - sx)) {
                return PointRelationEnum.POINT_ON_BORDER;
            }
            // 点与相邻顶点连线的夹角
            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 ? PointRelationEnum.POINT_OUT_SCOPE: PointRelationEnum.POINT_IN_SCOPE;
    }



    // 计算地球上两点的距离
    private static double getTwoPointsDistance(Point pointA, Point pointB) {
        double distance = 0.0;
        if (pointA != null && pointB != null) {
            double x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, dx1 = 0.0, dy1 = 0.0, dx2 = 0.0, dy2 = 0.0, a = earth_radius;
            x1 = getLoop(pointA.getX(), -180, 180);
            y1 = getRange(pointA.getY(), -90, 90);
            x2 = getLoop(pointB.getX(), -180, 180);
            y2 = getRange(pointB.getY(), -90, 90);
            dx1 = degreeToRad(x1);
            dy1 = degreeToRad(y1);
            dx2 = degreeToRad(x2);
            dy2 = degreeToRad(y2);
            distance = a*Math.acos((Math.sin(dy1)*Math.sin(dy2) + Math.cos(dy1) * Math.cos(dy2) * Math.cos(dx2 - dx1)));

        }
        return distance;
    }

    /** 计算地球上一点与区域边界的最小距离 **/
    private static double getPointRangeDistance(Point point, List<Point> points) {
        double mindis = -1.0;
        if (point != null && points != null && points.size() > 0) {
            double a = 0.0;
            double b = 0.0;
            double c = 0.0;
            double dis = 0.0;
            for (int i = 0; i < points.size(); i++) {
                if (i < points.size() - 1) {
                    a = get2PointsDistance(points.get(i), points.get(i + 1));
                    b = get2PointsDistance(points.get(i), point);
                    c = get2PointsDistance(points.get(i + 1), point);
                }else{
                    a = get2PointsDistance(points.get(i), points.get(0));
                    b = get2PointsDistance(points.get(i), point);
                    c = get2PointsDistance(points.get(0), point);
                }
                dis = pointToLine(a, b, c);
                if (mindis < 0) {
                    mindis = dis;
                } else if (dis < mindis) {
                    mindis = dis;
                }
            }
        }
        return mindis;
    }

    /**
     * 计算地球上一点与一段道路的最小距离
     */

    public static double getPointLineDistance(Point point, List<Point> points) {
        double mindis = -1.0;
        if (point != null && points != null && points.size() > 0) {
            double a = 0.0;
            double b = 0.0;
            double c = 0.0;
            double dis = 0.0;
            for (int i = 0; i < points.size()-1; i++) {
                a = get2PointsDistance(points.get(i), points.get(i + 1));
                b = get2PointsDistance(points.get(i), point);
                c = get2PointsDistance(points.get(i + 1), point);
                dis = pointToLine(a, b, c);
                if (mindis < 0) {
                    mindis = dis;
                } else if (dis < mindis) {
                    mindis = dis;
                }
            }
        }
        return mindis;
    }


    /**
     * 计算点到线的距离
     */
    private static double pointToLine(double a, double b, double c) {
        double space = 0;
        if (c <= 0.000001 || b <= 0.000001) {
            space = 0;
            return space;
        }
        if (c * c >= a * a + b * b) {
            space = b;
            return space;
        }
        if (b * b >= a * a + c * c) {
            space = c;
            return space;
        }
        /** 半周长 */
        double p = (a + b + c) / 2;
        /** 海伦公式算面积 **/
        double s = Math.sqrt(p * (p - a) * (p - b) * (p - c));
        space = 2 * s / a;
        return space;

    }

    // 经度用
    private static double getLoop(double lng, double a, double b) {
        while (lng > b) {
            lng -= b - a;
        }
        while (lng < a) {
            lng += b - a;
        }
        return lng;
    }

    // 纬度用
    private static double getRange(double lat, double a, double b) {
        if (a != 0) {
            lat = Math.max(lat, a);
        }
        if (b != 0) {
            lat = Math.min(lat, b);
        }
        return lat;
    }

    // 将弧度转化为度
    private static double degreeToRad(double n) {
        return Math.PI * n / 180;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值