将地图区域划分为给定半径的重叠圆

Divide map area into overlapping circles of given radius

提问人:Rolf W. 提问时间:8/19/2019 最后编辑:Rolf W. 更新时间:8/20/2019 访问量:521

问:

我正在尝试将给定半径的地图区域与给定坐标划分为另一个给定半径的较小重叠地图,确保整个原始地图被较小的地图覆盖,同时最大限度地减少重叠。

我需要找到覆盖整个原始区域的所有较小地图的中心纬度/经度。较小地图的总面积可能会稍加扩展,以确保覆盖整个表面。

我尝试了各种方法,直到我意识到这是一个复杂的问题,我的数学似乎是不够的。

代码示例

public class Main {

    public static void main(String[] args) {

        // ====  Parameters  =====
        /* These are just example values; Should work with any sensible input */
        LatLng outerAreaCenter = new LatLng(40.689259, -74.044538);
        double outerAreaRadiusInMeters = 1000;
        double divisionsRadiusInMeters = 125;

        // ====  Divide area  =====
        List<LatLng> divisionCenters;
        divisionCenters = divideArea(outerAreaCenter, outerAreaRadiusInMeters, divisionsRadiusInMeters);

        // ====  Draw large area  =====
        drawCircleOnMap(outerAreaCenter, outerAreaRadiusInMeters);

        // ====  Draw division circles within large area  =====
        /* These circles should cover the entire surface of the outer area, and
         * may extend a little bit outside of the outer circle if needed */
        for (LatLng divisionCenter : divisionCenters) {

            drawCircleOnMap(divisionCenter, divisionsRadiusInMeters);
        }
    }

    /**
     * Divides a large area into divisions/smaller areas that, together, cover the entire surface of the large area with minimal overlap.
     *
     * @param outerAreaCenter the center coordinates of the area that needs to be divided
     * @param outerAreaRadiusInMeter the radius of the area that needs to be divided
     * @param divisionsRadiusInMeter the maximum radius of each division/smaller area
     *
     * @return a list of center coordinates for each of the smaller areas that, which can be used with {@param divisionsRadiusInMeter} to make new areas that together cover the entire large area surface
     */
    private static List<LatLng> divideArea(LatLng outerAreaCenter, double outerAreaRadiusInMeter, double divisionsRadiusInMeter) {

        // ====  Check preconditions  =====
        if (divisionsRadiusInMeter > outerAreaRadiusInMeter) { throw new IllegalArgumentException("Divisions radius cannot be larger than radius of outer area."); }

        // ====  Calculate center lat/lng for each division  =====
        /* This is what my question is about. */
    }

    private static void drawCircleOnMap(LatLng circleCenter, double radiusInMeters) {

        /* Some code to draw this circle on a map (not relevant to the question) */

        // To visualize points, add a new layer on https://mapmakerapp.com by pasting the console output
        System.out.println(circleCenter.latitude + "," + circleCenter.longitude + ",,#FF0000");

    }

    private static class LatLng {

        private final double latitude;
        private final double longitude;

        private LatLng(double latitude, double longitude) {

            this.latitude = latitude;
            this.longitude = longitude;
        }
    }
}

问题

如何计算每个分区区域的中心纬度/经度,确保整个外部区域覆盖最小重叠?我基本上是在上面的代码示例中寻找方法体。divideArea(LatLng outerAreaCenter, double outerAreaRadiusInMeter, double divisionsRadiusInMeter)

注意

为了使重叠最小化,划分区域的半径可能也应是输出。如果是这种情况,则参数应为 .divisionsRadiusInMetersdivisionsMaxRadiusInMeters

编辑

按照 Avi 的建议,我添加了一个代码示例并澄清了问题。

与 Java 语言无关 的计算几何几何 geometry-surface

评论

0赞 Avi 8/20/2019
125 m. 半径还是直径?不清楚你在这里问什么。请提供一个最小的可重现示例,以便我们更好地了解您正在尝试做什么。此外,如果您提供一些示例输入/输出,将非常有帮助。
0赞 Rolf W. 8/20/2019
你是对的,我已经编写了一些代码,并添加到我的问题中。输出丢失是因为我的数学不足以弄清楚输出的中心坐标应该是多少。但希望代码能清楚地表达我的意思。
0赞 Rolf W. 8/20/2019
125m 示例是半径。我使用了半径,因为这在地图工具中似乎很常见,但我愿意接受建议。
0赞 Rolf W. 8/20/2019
我意识到,如果重叠应该最小,则划分区域的半径也可能是输出。如果是这样的话,那么应该是.divisionsRadiusInMetersdivisionsMaxRadiusInMeters
1赞 Avi 8/20/2019
我也算不上数学:(但是,我确实找到了这个维基百科页面,它涵盖了完全相同的问题。您所要做的就是将输入圆盘半径除以本身(成为单位圆盘),将较小的圆盘半径除以较大的圆盘半径(成为)。一旦你有了解决方案,你就把两者乘以它们的原始大小/位置。不过,这可能不是一个已解决的问题,所以你最好使用近似值(例如遗传算法)或默认使用一些你已经证明有效的固定近似值。r(n)

答: 暂无答案