如何在谷歌地图Android API v2中计算多边形的中心?

如何在谷歌地图Android API v2中计算多边形的中心?,android,google-maps-android-api-2,android-maps-v2,Android,Google Maps Android Api 2,Android Maps V2,我在谷歌地图上用几个纬度和经度点画了一个多边形。但是现在我需要在多边形的中心放置一个标记,我需要它的中心坐标。我如何计算中心点 下面是在地图上添加多边形的代码: for (Warning w : warningsList) { // Instantiates a new Polygon object and adds points PolygonOptions rectOptions = new PolygonOptions();

我在谷歌地图上用几个纬度和经度点画了一个多边形。但是现在我需要在多边形的中心放置一个标记,我需要它的中心坐标。我如何计算中心点

下面是在地图上添加多边形的代码:

for (Warning w : warningsList) {
            // Instantiates a new Polygon object and adds points
            PolygonOptions rectOptions = new PolygonOptions();
            List<PolyPoints> pp = w.getPolyPoints();
            for (PolyPoints p : pp) {
                rectOptions.add(new LatLng(Double.valueOf(p.getLatitude()),
                        Double.valueOf(p.getLongitude())));
            }

                mMap.addPolygon(rectOptions.strokeColor(Color.GREEN)
                        .fillColor(Color.RED).strokeWidth(STROKE_WIDTH));

        }
for(警告w:警告列表){
//实例化新多边形对象并添加点
PolygonOptions rectOptions=新PolygonOptions();
List pp=w.getPolyPoints();
用于(多点p:pp){
rectOptions.add(新LatLng(Double.valueOf(p.getLatitude()),
Double.valueOf(p.getLongitude());
}
mMap.addPolygon(rectOptions.strokeColor(Color.GREEN)
.fillColor(Color.RED).strokeWidth(STROKE_WIDTH));
}

我发现类似的问题已经得到了回答,但这是针对JavaScript Api的。在我的案例中,他们有没有使用相同的解决方案?

下面是我现在用来查找多边形中心的代码:-

public static double[] centroid(List<PolyPoints> points) {
        double[] centroid = { 0.0, 0.0 };

        for (int i = 0; i < points.size(); i++) {
            centroid[0] += points.get(i).getLatitude();
            centroid[1] += points.get(i).getLongitude();
        }

        int totalPoints = points.size();
        centroid[0] = centroid[0] / totalPoints;
        centroid[1] = centroid[1] / totalPoints;

        return centroid;
    }
公共静态双[]形心(列表点){
双[]质心={0.0,0.0};
对于(int i=0;i
下面是我用来找到多边形中心点的代码。它对我也有用

private LatLng getPolygonCenterPoint(ArrayList<LatLng> polygonPointsList){
        LatLng centerLatLng = null;
        Builder builder = new LatLngBounds.Builder(); 
        for(int i = 0 ; i < polygonPointsList.size() ; i++) 
        {          
            builder.include(polygonPointsList.get(i));
        }
        LatLngBounds bounds = builder.build();
        centerLatLng =  bounds.getCenter();

        return centerLatLng;
    }
private LatLng getPolygonCenterPoint(ArrayList PolygonConPointsList){
LatLng centerLatLng=null;
Builder=new LatLngBounds.Builder();
对于(int i=0;i
专用静态LatlngGetCenterofPolygon(列出latLngList){
双[]质心={0.0,0.0};
对于(int i=0;i
我使用了两种方法。但它适用于任何形状

private static double area(ArrayList<LatLng> arr) {
    double area=0;
    int nPts = arr.size();
    int j=nPts-1;
    LatLng p1; LatLng p2;
    for (int i=0;i<nPts;j=i++) {

        p1=arr.get(i); p2=arr.get(j);
        area+=p1.latitude*p2.longitude;
        area-=p1.longitude*p2.latitude;
    }
    area/=2;

    return area;
};

public static LatLng Centroid (ArrayList<LatLng> pts) {
    int nPts = pts.size();
    double x=0; double y=0;
    double f;
    int j=nPts-1;
    LatLng p1; LatLng p2;

    for (int i=0;i<nPts;j=i++) {
        p1=pts.get((i)); p2=pts.get(j);
        f=p1.latitude*p2.longitude-p2.latitude*p1.longitude;
        x+=(p1.latitude+p2.latitude)*f;
        y+=(p1.longitude+p2.longitude)*f;
    }

    f=area(pts)*6;

    return new LatLng(x/f, y/f);
};
专用静态双区(ArrayList arr){
双面积=0;
int nPts=阵列大小();
int j=nPts-1;
板条p1;板条p2;
对于(inti=0;i,在此之后,我创建了一个Kotlin版本。
我将其实现为
多边形
扩展

package com.example.diman.googlemapsplayground

import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.Polygon
import com.google.maps.android.PolyUtil
import com.google.maps.android.SphericalUtil

/**
 * Find approximate center of a polygon.
 * Reference: https://moduscreate.com/blog/placing-markers-inside-polygons-with-google-maps/
 *
 * Algorithm:
 * If the bounding box center point is inside the polygon, return center point.
 * Otherwise, sample points at fixed percentages of the bounding box’s height North and South of the center point.
 * Sample points at fixed percentages of the bounding box’s width East and West of the center point.
 * Stop when we find the first point that is inside the area of the polygon, and drop the marker there.
 */
fun Polygon.getApproximateCenter(): LatLng {
  // Calc bounds first
  val boundsBuilder = LatLngBounds.builder()
  points.forEach {
    boundsBuilder.include(it)
  }
  val polygonBounds = boundsBuilder.build()

  val centerPoint = polygonBounds.center

  // Center point is inside the polygon, return it
  if (PolyUtil.containsLocation(centerPoint, points, true)) {
    return centerPoint
  }

  // Center point is out of bounds
  // Sample points at fixed percentages of the bounding box’s width East and West of the center point.
  val maxSearchSteps = 10
  var testPos: LatLng = centerPoint

  // Calculate NorthWest point so we can work out height of polygon NW->SE
  val northWest = LatLng(polygonBounds.northeast.latitude, polygonBounds.southwest.longitude)

  // Work out how tall and wide the bounds are and what our search
  // increment will be
  val boundsHeight = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.southwest)
  val heightIncr = boundsHeight / maxSearchSteps

  val boundsWidth = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.northeast)
  val widthIncr = boundsWidth / maxSearchSteps

  // Expand out from Centroid and find a point within polygon at
  // 0, 90, 180, 270 degrees
  for (n in 1..maxSearchSteps) {
    // Test point North of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (heightIncr * n),
        0.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point East of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (widthIncr * n),
        90.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point South of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (heightIncr * n),
        180.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point West of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (widthIncr * n),
        270.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }
  }

  return testPos
}
注意,通过添加到gradle,添加
PolyUtil
SphericalUtil


implementation'com.google.maps.android:android-maps-utils:0.4.3'

您可以为我们提供任何代码吗?@kolonelpeteruk我添加了一些代码,展示了如何在地图上添加多边形。您想实现什么样的中心?重心?边界中心?您尝试过实现哪一个?@MaciejGórski Cen界限的界限。
private static double area(ArrayList<LatLng> arr) {
    double area=0;
    int nPts = arr.size();
    int j=nPts-1;
    LatLng p1; LatLng p2;
    for (int i=0;i<nPts;j=i++) {

        p1=arr.get(i); p2=arr.get(j);
        area+=p1.latitude*p2.longitude;
        area-=p1.longitude*p2.latitude;
    }
    area/=2;

    return area;
};

public static LatLng Centroid (ArrayList<LatLng> pts) {
    int nPts = pts.size();
    double x=0; double y=0;
    double f;
    int j=nPts-1;
    LatLng p1; LatLng p2;

    for (int i=0;i<nPts;j=i++) {
        p1=pts.get((i)); p2=pts.get(j);
        f=p1.latitude*p2.longitude-p2.latitude*p1.longitude;
        x+=(p1.latitude+p2.latitude)*f;
        y+=(p1.longitude+p2.longitude)*f;
    }

    f=area(pts)*6;

    return new LatLng(x/f, y/f);
};
package com.example.diman.googlemapsplayground

import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.LatLngBounds
import com.google.android.gms.maps.model.Polygon
import com.google.maps.android.PolyUtil
import com.google.maps.android.SphericalUtil

/**
 * Find approximate center of a polygon.
 * Reference: https://moduscreate.com/blog/placing-markers-inside-polygons-with-google-maps/
 *
 * Algorithm:
 * If the bounding box center point is inside the polygon, return center point.
 * Otherwise, sample points at fixed percentages of the bounding box’s height North and South of the center point.
 * Sample points at fixed percentages of the bounding box’s width East and West of the center point.
 * Stop when we find the first point that is inside the area of the polygon, and drop the marker there.
 */
fun Polygon.getApproximateCenter(): LatLng {
  // Calc bounds first
  val boundsBuilder = LatLngBounds.builder()
  points.forEach {
    boundsBuilder.include(it)
  }
  val polygonBounds = boundsBuilder.build()

  val centerPoint = polygonBounds.center

  // Center point is inside the polygon, return it
  if (PolyUtil.containsLocation(centerPoint, points, true)) {
    return centerPoint
  }

  // Center point is out of bounds
  // Sample points at fixed percentages of the bounding box’s width East and West of the center point.
  val maxSearchSteps = 10
  var testPos: LatLng = centerPoint

  // Calculate NorthWest point so we can work out height of polygon NW->SE
  val northWest = LatLng(polygonBounds.northeast.latitude, polygonBounds.southwest.longitude)

  // Work out how tall and wide the bounds are and what our search
  // increment will be
  val boundsHeight = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.southwest)
  val heightIncr = boundsHeight / maxSearchSteps

  val boundsWidth = SphericalUtil.computeDistanceBetween(northWest, polygonBounds.northeast)
  val widthIncr = boundsWidth / maxSearchSteps

  // Expand out from Centroid and find a point within polygon at
  // 0, 90, 180, 270 degrees
  for (n in 1..maxSearchSteps) {
    // Test point North of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (heightIncr * n),
        0.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point East of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (widthIncr * n),
        90.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point South of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (heightIncr * n),
        180.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }

    // Test point West of Centroid
    testPos = SphericalUtil.computeOffset(
        centerPoint,
        (widthIncr * n),
        270.0
    )
    if (PolyUtil.containsLocation(testPos, points, true)) {
      break
    }
  }

  return testPos
}