经纬度点是否属于一个经纬度串(指定误差范围)

1. 使用场景

1.根据一个经纬度点,自动匹配周围一公里经纬度串(可指定误差范围)
2.计算两个经纬度之间的距离
3.判断一个经纬度点是否属于一个经纬度串,可指点误差范围

2.应用步骤

1.引入依赖

   <dependency>
      <groupId>org.gavaghan</groupId>
      <artifactId>geodesy</artifactId>
      <version>1.1.3</version>
   </dependency>

2.工具类引入

package com.gc.tocc.ruralroad.utils;

import com.gc.tocc.ruralroad.vo.JqPoint;
import org.gavaghan.geodesy.Ellipsoid;
import org.gavaghan.geodesy.GeodeticCalculator;
import org.gavaghan.geodesy.GeodeticCurve;
import org.gavaghan.geodesy.GlobalCoordinates;

import java.util.List;


public class MapUtils {

    /**
     * 计算经纬度串的长度
     *
     * @param gpsStr 经纬度串,格式形如:116.307852,40.057031;116.307852,40.057031
     * @return 返回距离,单位:千米,保留两位小数
     */

    public static double getDistanceLine(String gpsStr) {
        //根据;分割经纬度串
        String[] gpsArray = gpsStr.split(";");
        //创建GeodeticCalculator,用于计算两个经纬度之间的距离
        Double totalDistance = 0.0;
        for (int i = 0; i < gpsArray.length - 1; i++) {
            String[] gpsFromStr = gpsArray[i].split(",");
            String[] gpsToStr = gpsArray[i + 1].split(",");
            //创建GlobalCoordinates对象,传入经纬度
            GlobalCoordinates gpsFrom = new GlobalCoordinates(Double.parseDouble(gpsFromStr[1]),
                Double.parseDouble(gpsFromStr[0]));
            GlobalCoordinates gpsTo = new GlobalCoordinates(Double.parseDouble(gpsToStr[1]),
                Double.parseDouble(gpsToStr[0]));
            //调用计算方法,传入坐标系、经纬度用于计算距离
            double meter2 = getDistancePoint(gpsFrom, gpsTo, Ellipsoid.WGS84);
            totalDistance += meter2;
        }
        return (double) Math.round(totalDistance / 1000 * 100) / 100;
    }


    /**
     * 计算两个经纬度之间的距离
     */

    private static double getDistancePoint(GlobalCoordinates gpsFrom, GlobalCoordinates gpsTo, Ellipsoid ellipsoid) {
        //创建GeodeticCalculator,调用计算方法,传入坐标系、经纬度用于计算距离
        GeodeticCurve geoCurve = new GeodeticCalculator().calculateGeodeticCurve(ellipsoid, gpsFrom, gpsTo);
        return geoCurve.getEllipsoidalDistance();
    }


    /**
     *  计算两点之间的距离
     * */
    private static double haversineDistance(double lon1, double lat1, double lon2, double lat2) {
        double R = 6371000.0; // Earth's radius in meters
        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);
        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                Math.sin(dLon / 2) * Math.sin(dLon / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        return R * c;
    }

    /**
     * 判断某一个经纬度点是否在一个经纬度串上
     * */
    public static boolean isPtInPoly(double ALon, double ALat, double errorMeters, List<JqPoint> ps) {
        for (int i = 0, j = ps.size() - 1; i < ps.size(); j = i++) {
            JqPoint vertexA = ps.get(i);
            JqPoint vertexB = ps.get(j);

            // Check if the point is close enough to the current vertex
            if (haversineDistance(vertexA.lon, vertexA.lat, ALon, ALat) <= errorMeters) {
                return true;
            }

            // Check if the point lies on the edge AB
            if (isPointOnEdge(ALon, ALat, vertexA.lon, vertexA.lat, vertexB.lon, vertexB.lat, errorMeters)) {
                return true;
            }
        }

        return false;
    }


    /**
     *   判断某个点是否属于ps,如果属于则返回最小距离
     */

    public static Double pointToPolyMinDistance(double ALon, double ALat, double errorMeters, List<JqPoint> ps) {
        boolean isInsidePolygon = false;
        double minDistance = Double.POSITIVE_INFINITY;

        for (int i = 0, j = ps.size() - 1; i < ps.size(); j = i++) {
            JqPoint vertexA = ps.get(i);
            JqPoint vertexB = ps.get(j);

            double distanceToVertexA = haversineDistance(ALon, ALat, vertexA.lon, vertexA.lat);

            if (distanceToVertexA <= errorMeters) {
                isInsidePolygon = true;
                // minDistance = 0.0;
            }

            double distanceToEdge = pointToEdgeDistance(ALon, ALat, vertexA.lon, vertexA.lat, vertexB.lon, vertexB.lat);

            if (distanceToEdge <= errorMeters) {
                isInsidePolygon = true;
                // minDistance = 0.0; // Point is on the edge
            }

            minDistance = Math.min(minDistance, Math.min(distanceToVertexA, distanceToEdge));
        }

        return isInsidePolygon ? minDistance : null;
    }

    public static boolean isPointOnEdge(double px, double py, double ax, double ay, double bx, double by, double errorMeters) {
        double distance = haversineDistance(ax, ay, bx, by);
        double d1 = haversineDistance(px, py, ax, ay);
        double d2 = haversineDistance(px, py, bx, by);

        return Math.abs(d1 + d2 - distance) <= errorMeters;
    }

    public static double pointToEdgeDistance(double px, double py, double ax, double ay, double bx, double by) {
        double distance = haversineDistance(ax, ay, bx, by);
        double d1 = haversineDistance(px, py, ax, ay);
        double d2 = haversineDistance(px, py, bx, by);

        return Math.abs(d1 + d2 - distance);
    }

}




@Data
public class JqPoint {

    public double lon;
    public double lat;

    public JqPoint(double lon, double lat) {
        this.lon = lon;
        this.lat = lat;
    }

}

3.使用

// error:允许的误差范围 
// 如果在误差范围内属于jqPointList则返回最近距离,如果不属于则返回null
Double minDistance=MapUtils.pointToPolyMinDistance(lon,lat,error, jqPointList);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值