Reputation: 2396
I have drawn a polygon on google map using several Latitude,Longitude points.But now I need to place a marker at the center of the polygon for which I need the center coordinates.How do I calculate the center point.
Below is the code for adding polygons on map:
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));
}
I found similar question which has been answered but thats for JavaScript Api.Is their any way of using the same solution in my case?
Upvotes: 9
Views: 18223
Reputation: 429
Following this blogpost, i have created a Kotlin version.
I implemented it as a Polygon
extension.
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
}
Note, add PolyUtil
and SphericalUtil
by adding to gradle:
implementation 'com.google.maps.android:android-maps-utils:0.4.3'
Upvotes: 0
Reputation: 21
I have done it using two methods. but it works with any shape...
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);
};
Simply call the Centroid Method within your class and pass in your LatLng Array as a parameter. make sure the Array list you are passing is LatLng Array List
LatLng polyCentroid = Centroid(list);
mMap.addMarker(new MarkerOptions() .position(polyCentroid));
Upvotes: 1
Reputation: 1554
private static LatLng getCenterOfPolygon(List<LatLng> latLngList) {
double[] centroid = {0.0, 0.0};
for (int i = 0; i < latLngList.size(); i++) {
centroid[0] += latLngList.get(i).latitude;
centroid[1] += latLngList.get(i).longitude;
}
int totalPoints = latLngList.size();
return new LatLng(centroid[0] / totalPoints, centroid[1] / totalPoints);
}
Upvotes: 3
Reputation: 555
Below code I am using to find the center point of the polygon. its working for me too
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;
}
Upvotes: 32
Reputation: 2396
Below is the code which I am using now to find the center of polygon:-
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;
}
Upvotes: 12