ClosestPoint.java 2.91 KB
package com.bsth.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.bsth.util.TransGPS.Location;

public class ClosestPoint {

    public static Location getVerticalPoint(Location loc1, Location loc2, Location loc3) {
        // 第一步:求得直线方程相关参数y=kx+b | kx-y+b=0
        double k = (loc1.getLat() - loc2.getLat()) * 1.0 / (loc1.getLng() - loc2.getLng());// 坐标直线斜率k
        double b = loc1.getLat() - k * loc1.getLng();// 坐标直线b
        // 第一种: 设直线方程为ax+by+c=0,点坐标为(m,n)
        // 则垂足为((b*b*m-a*b*n-a*c)/(a*a+b*b),(a*a*n-a*b*m-b*c)/(a*a+b*b))
        Location loc4 = TransGPS.LocationMake(((-1) * (-1) * loc3.getLng() - k * (-1) * loc3.getLat() - k * b) / (k * k + (-1) * (-1)),
                (k * k * loc3.getLat() - k * (-1) * loc3.getLng() - (-1) * b) / (k * k + (-1) * (-1)));
        return loc4;
    }

    // 获取两点间距离
    static double GetPointDistance(Location p1, Location p2) {
        return Math.sqrt((p1.getLng() - p2.getLng()) * (p1.getLng() - p2.getLng()) + (p1.getLat() - p2.getLat()) * (p1.getLat() - p2.getLat()));
    }

    // 求点到线段距离的最近点
    static Map<Double, List<Location>> GetNearestDistance(Location PA, Location PB, Location P3) {
        Map<Double, List<Location>> point = new HashMap<>();
        List<Location> locations = new ArrayList<>();
        locations.add(PA);
        locations.add(PB);
        // 点在线段上
        double a, b, c;
        a = GetPointDistance(PB, P3);
        if (a <= 0.000000001) {
            locations.add(P3);
            point.put(a, locations);
            return point;
        }
        b = GetPointDistance(PA, P3);
        if (b <= 0.000000001) {
            locations.add(P3);
            point.put(b, locations);
            return point;
        }
        c = GetPointDistance(PA, PB);
        if (c <= 0.000000001) {
            locations.add(PA);
            point.put(b, locations);// 如果PA和PB坐标相同,则退出函数,并返回距离
            return point;
        }
        // 点和线段组成钝角三角形
        if (a * a >= b * b + c * c) {
            locations.add(PA);
            point.put(b, locations);
            return point;// 如果是钝角返回b
        }
        if (b * b >= a * a + c * c) {
            locations.add(PB);
            point.put(a, locations);// 如果是钝角返回a
            return point;
        }

        // 点和线段组成锐角三角形
        double l = (a + b + c) / 2; // 周长的一半
        double s = Math.sqrt(l * (l - a) * (l - b) * (l - c)); // 海伦公式求面积,也可以用矢量求
        Location location = getVerticalPoint(PA, PB, P3);
        locations.add(location);
        point.put(2 * s / c, locations);
        return point;
    }
}