谷歌地图android中一组经纬度点的中心

Posted

技术标签:

【中文标题】谷歌地图android中一组经纬度点的中心【英文标题】:Center of a cluster of latitude and longitude points in Google map android 【发布时间】:2016-04-21 20:57:28 【问题描述】:

我正在尝试在 android 中获取形状的中心。形状是在地图上手工绘制的。我有所有的坐标,但平均值比我想象的要复杂。我想在平均纬度和经度上绘制一个标记。

我尝试过分别将纬度和经度相加,然后除以点数。这并没有给出正确的答案。标记似乎总是落后于绘图人物。我也尝试过使用该实现,但它给出了相同的答案,之前的 SO 问题,Calculate the center point of multiple latitude/longitude coordinate pairs

我一直在使用的代码:

private void calculateFreeHandPolygonParameters()

    double xValues = 0;
    double yValues = 0;
    double zValues = 0;
    int count = 0;

    // linesForPolygon a list of the lines in the polygon
    for(Polyline line : linesForPolygon)
        for (LatLng point : line.getPoints()) 
            xValues += Math.cos(Math.toRadians(point.latitude)) * Math.cos(Math.toRadians(point.longitude));
            yValues += Math.cos(Math.toRadians(point.latitude)) * Math.sin(Math.toRadians(point.longitude));
            zValues += Math.sin(Math.toRadians(point.latitude));
            count++;
        
    

    double meanX = xValues/count;
    double meanY = yValues/count;
    double meanZ = zValues/count;

    double centralLongitude = Math.atan2(meanY, meanX);
    double centralSquareRoot = Math.sqrt(Math.pow(meanX, 2) + Math.pow(meanX, 2) + Math.pow(meanX, 2));
    double centralLatitude = Math.atan2(meanZ, centralSquareRoot);

    double latitude = Math.toDegrees(centralLatitude);
    double longitude = Math.toDegrees(centralLongitude);

    Log.i("MAPS", "Freehand Parameters: x mean -> " + latitude + " y mean -> " + longitude);

    testMarker = mMap.addMarker(new MarkerOptions()
            .position(new LatLng(latitude, longitude))
            .title("Polygon center")
            .snippet("lat: " + latitude + " long: " + longitude));

【问题讨论】:

您描述的方法应该有效,除非经度靠近国际日期变更线,或者位置靠近两极。也许你应该分享你的代码。 【参考方案1】:

这是我的质心代码:

public class PolygonCentroid 

    private List<GeoPoint> points;
    private int pointsSize;

    public PolygonCentroid(List<GeoPoint> points) 
        this.points = points;
        this.pointsSize = points.size();
    

    protected double polygonArea() 
        double area = 0;
        for (int i = 0, j; i < pointsSize; i++) 
            j = (i + 1) % pointsSize;
            area += points.get(i).getLongitude() * points.get(j).getLatitude();
            area -= points.get(i).getLatitude() * points.get(j).getLongitude();
        
        area /= 2.0;
        return area;
    

    public GeoPoint centroid() 
        double cx = 0, cy = 0;
        double factor;
        for (int i = 0, j; i < pointsSize; i++) 
            j = (i + 1) % pointsSize;
            factor = (points.get(i).getLongitude() * points.get(j).getLatitude() - points.get(j).getLongitude() * points.get(i).getLatitude());
            cx += (points.get(i).getLongitude() + points.get(j).getLongitude()) * factor;
            cy += (points.get(i).getLatitude() + points.get(j).getLatitude()) * factor;
        
        double A = polygonArea();
        factor = 1.0 / (6.0 * A);
        cx *= factor;
        cy *= factor;
        return new GeoPoint(cy, cx);
    


另外,请注意质心可以在多边形之外:

Full source code 和 usage。

【讨论】:

此方法有效,但仅适用于第一次迭代。我还没有弄清楚为什么如果我绘制另一个多边形它不起作用。标记落后于我的代码的先前版本。 别忘了像我一样重置坐标列表。 >"marker trails behind" 我想您应该注意Z-ordering,如果您想始终在顶部显示一些叠加层。【参考方案2】:
    您实际上需要计算所谓的 CENTROID。这不是一件小事,看这里: http://www.spatialanalysisonline.com/html/index.html?centroids_and_centers.htm 注意所谓的GREAT CIRCLE,在飞机地图上回忆飞行计划......因此,如果距离相对较大,您需要记住这种现象。 这是一道经典的GIS问题,在你理解了算法的伪代码之后,就是简单的编码任务了……试试gis.stackexchange.com

【讨论】:

我一直使用的代码怎么不起作用?像我所做的那样计算平均值非常有意义吗?您提供的链接中的第一种方法是我最初尝试过的,但也一直落后。需要计算面积的方法会变得异常复杂 是的,这种算法的底层代码确实很复杂......通常使用gis库来完成这种任务,或者如果使用postgis存储在数据库中的位置,那么postgis就有这个还有一种查询方法。

以上是关于谷歌地图android中一组经纬度点的中心的主要内容,如果未能解决你的问题,请参考以下文章

PHP:如何从数据库中设置中心谷歌地图的经纬度?

百度与谷歌地图瓦片组织方式对比

应用启动时在 android 谷歌地图中获取当前位置(纬度,经度)

如何将谷歌地图标记的纬度和经度发送到 Firebase - android? [关闭]

试图从谷歌地图获取纬度是通过 Android 中的意图返回 null

在php里面 怎么根据地址取得经纬度。google。 地址是在一组数值(很多个地址,要批量处理)