【问题标题】:Bounding Box Given 4 Lat/Long and Bearing给定 4 纬度/经度和方位角的边界框
【发布时间】:2013-10-27 15:04:50
【问题描述】:

我需要找到一个给定 4 个纬度/经度点和一个方位的边界框(如示例图片所示)。我总是知道哪两个点被方位角对齐(示例中的 1 和 2),所以我总是会知道边界框的长度。然而,宽度是任意的,点位于沿线的任意位置(示例中为 3 和 4)。

我的第一个想法是我必须计算点之间的角度(1 & 3, 1 & 4, 2 & 3, 2 & 4),然后使用一系列“余弦定律”方程来计算角点。有没有更简单的方法?那还能用吗?

【问题讨论】:

    标签: java android latitude-longitude bounding-box


    【解决方案1】:

    因此环顾四周,甚至询问可能更合适的网站(此处),我找到了一个基于 Chris Veness (here) 的解决方案,以找到给定两个点及其方位的交点。因此,为了获得边界框的角,我只需采用上/下和左/右(1 & 3、1 & 4、2 & 3、2 & 4)的每个组合,并使用已知方位找到交叉点并进行相应调整.例如,要找到图像的右下角,我会使用方位角 + 90 表示点 1 的方向,使用方位角 - 180 表示点 3 的方向来计算点 1 和 3 的交点。

    我不能把算法归功于这个算法,甚至不能真正解释它是如何在几何上工作的,但它在我的测试中是有效的。下面是我从 Chris 提供的 javascript 版本的 java 翻译

    public static CoordD getIntersection(CoordD point1, double bearing1, CoordD point2, double bearning2) {
        double lat1 = rad(point1.latitude); double lon1 = rad(point1.longitude);
        double lat2 = rad(point2.latitude); double lon2 = rad(point2.longitude);
        double bearing13 = rad(bearing1); double bearing 23 = rad(bearing2);
        double dLat = lat2 - lat1; double dLon = lon2 - lon1;
    
        double dist12 = 2 * Math.asin( Math.sqrt( Math.sin(dLat / 2) * Math.sin(dLat / 2) +
            Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon / 2) * Math.sin(dLon / 2) ) );
        if (dist12 == 0) return null;
    
        double bearingA = Math.acos( ( Math.sin(lat2) - Math.sin(lat1) * Math.cos(dist12) ) /
            ( Math.sin(dist12) * Math.cos(lat1) ) );
        double bearingB = Math.acos( ( Math.sin(lat1) - Math.sin(lat2) * Math.cos(dist12) ) /
            ( Math.sin(dist12) * Math.cos(lat2) ) );
        if (Double.isNaN(bearingA)) bearingA = 0;
        if (Double.isNaN(bearingB)) bearingB = 0;
    
        double bearing12, bearing21;
        if (Math.sin(dLon) > 0) {
            bearing12 = bearingA;
            bearing21 = 2 * Math.PI - bearingB;
        } else { 
            bearing12 = 2 * Math.PI - bearingA;
            bearing21 = bearingB;
        }
    
        double alpha1 = (bearing13 - bearing12 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 2-1-3
        double alpha2 = (bearing21 - bearing23 + Math.PI) % (2 * Math.PI) - Math.PI; // Angle 1-2-3
    
        if (Math.sin(alpha1) == 0 && Math.sin(alpha2) == 0) return null; // Infinite intersections
        if (Math.sin(alpha1) * Math.sin(alpha2) < 0) return null; // Ambiguous intersection
    
        // needed?
        // alpha1 = Math.abs(alpha1);
        // alpha2 = Math.abs(alpha2);
    
        double alpha3 = Math.acos( -Math.cos(alpha1) * Math.cos(alpha2) +
            Math.sin(alpha1) * Math.sin(alpha2) * Math.cos(dist12) );
        double dist13 = Math.atan2( Math.sin(dist12) * Math.sin(alpha1) * Math.sin(alpha2),
            Math.cos(alpha2) + Math.cos(alpha1) * Math.cos(alpha3) );
    
        double lat3 = Math.asin( Math.sin(lat1) * Math.cos(dist13) +
            Math.cos(lat1) * Math.sin(dist13) * Math.cos(bearing13) );
    
        double dLon13 = Math.atan2( Math.sin(bearing13) * Math.sin(dist13) * Math.cos(lat1),
            Math.cos(dist13) - Math.sin(lat1) * Math.sin(lat3) );
        double lon3 = lon1 + dLon3;
        lon3 = (lon3 + 3 * Math.PI) % ( 2* Math.PI) - Math.PI // normalize to +/-180
    
        return new CoordD(deg(lat3), deg(lon3));
    }
    

    rad()deg() 只是在弧度和度数之间转换的辅助函数。 CoordD 是一个辅助类,它只包含两个用于存储纬度/经度点的双精度值。

    【讨论】:

    • 感谢您发布您自己问题的答案。这不是我想要的,因为我只有第 1 点和第 2 点。但我根据你的 sn-p 计算计算从点 1 和 2 到距离 X 的四个角。
    • 我不认为这个解决方案会给出一个旋转的矩形。如果我错了,请纠正我。
    猜你喜欢
    • 2010-09-19
    • 2011-03-17
    • 2016-11-21
    • 2020-05-04
    • 2011-07-29
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多