2016-04-21 28 views
2

我想在android中获取一个形状的中心。形状在地图上由手绘制。我拥有所有的坐标,但平均值比我想象的要复杂。我想在平均经度和纬度上绘制一个标记。谷歌地图中经纬度点集群的中心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)); 
} 
+0

您所描述的方法应该可行,但可能在经度接近国际日期的情况下,或者位置靠近极点的情况下。也许你应该分享你的代码。 – JerryM

回答

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); 
    } 

} 

enter image description here

而且,请注意,该质心可以是多边形的外:

enter image description here

Full source codeusage

+0

此方法仅适用于第一次迭代。如果绘制另一个多边形,我还没弄明白为什么它不起作用。标记跟在我的代码的以前版本中落后。 –

+0

不要忘记像我一样重置坐标列表。 –

+0

>“marker trails behind”我想你应该注意[Z-ordering](https://stackoverflow.com/questions/14771569/google-maps-v2-marker-zordering-set-to-top),if你总是想在顶部显示一些叠加层。 –

1
  1. 实际上,你需要计算所谓的质心。这不是一件简单的事情,看看这里: http://www.spatialanalysisonline.com/HTML/index.html?centroids_and_centers.htm
  2. 注意所谓的GREAT CIRCLE,召回飞机地图上的飞行计划...因此,如果距离相对较大,则需要考虑到这种现象。
  3. 这是一个经典的GIS问题,你就明白了算法的伪代码之后,这是简单的编码任务...尝试gis.stackexchange.com
+0

我一直在使用的代码如何不起作用?像我所做的那样计算平均值是非常合理的?您提供的链接中的第一种方法是我最初尝试的方法,但也一直落后。需要计算面积的方法将变得非常复杂 –

+0

是的,这种算法的低级代码确实很复杂...通常一个人使用gis库来处理这类任务,或者如果存储在数据库中的位置与postgis,所以postgis也有这种查询方法。 – michael

相关问题