Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getCenter of Polygon (Centroid) #1196

Closed
ximex opened this issue Dec 3, 2012 · 7 comments
Closed

getCenter of Polygon (Centroid) #1196

ximex opened this issue Dec 3, 2012 · 7 comments
Assignees
Labels
Milestone

Comments

@ximex
Copy link

ximex commented Dec 3, 2012

Example:
If i want to get draw in the middle of a polygon a icon, i need the center of this polygon.

Samplecode:

L.Polygon.prototype.getCenter = function(){
var pts = this._latlngs;

var twicearea = 0;
var p1, p2, f;
var x = 0, y = 0;
var nPts = pts.length;

for(var i=0, j=nPts-1;i<nPts;j=i++) {
    p1=pts[i];
    p2=pts[j];
    twicearea+=p1.lat*p2.lng;
    twicearea-=p1.lng*p2.lat;

    f=p1.lat*p2.lng-p2.lat*p1.lng;

    x+=(p1.lat+p2.lat)*f;
    y+=(p1.lng+p2.lng)*f;
}
f=twicearea*3;
return {lat: x/f,lng: y/f};

}

Problem: This code only works for a non-self-intersecting closed polygon

Rectangle: Much easier and no problems with self-intersection!

Source: https://en.wikipedia.org/wiki/Centroid#Centroid_of_polygon

@ghost ghost assigned mourner Dec 10, 2012
@mourner
Copy link
Member

mourner commented Dec 10, 2012

Nice suggestion, will consider this. Thanks!

@ximex
Copy link
Author

ximex commented Dec 10, 2012

We found a little mistake in the function. Here you can read the small discussion: https://plus.google.com/u/0/108220049326938062364/posts/beV4PQYM58x

The problem only exits if the polygon is very small (~5x5meters). This code works with very small polygons too.

var pts = this._latlngs;
var off = pts[0];
var twicearea = 0;
var x = 0;
var y = 0;
var nPts = pts.length;
var p1,p2;
var f;
for (var i = 0, j = nPts - 1; i < nPts; j = i++) {
p1 = pts[i];
p2 = pts[j];
f = (p1.lat - off.lat) * (p2.lng - off.lng) - (p2.lat - off.lat) * (p1.lng - off.lng);
twicearea += f;
x += (p1.lat + p2.lat - 2 * off.lat) * f;
y += (p1.lng + p2.lng - 2 * off.lng) * f;
}
f = twicearea * 3;
return {
lat: x / f + off.lat,
lng: y / f + off.lng
};

@ximex
Copy link
Author

ximex commented Dec 22, 2012

Another little improvment: return value should be a L.LatLng() object.

return new L.LatLng(
x / f + off.lat,
y / f + off.lng
);

@hampelm
Copy link

hampelm commented Feb 13, 2013

Just wanted to note that this fn would be very helpful for the mapping I've been doing recently -- would love to see it in Leaflet.

@whyvez
Copy link

whyvez commented Mar 28, 2013

same here! Love your work... thank you!

@mourner
Copy link
Member

mourner commented Dec 11, 2013

Just a quick note on this: I started getting this into Leaflet core 88ad667 but eventually decided that I'd better do that after the vectors refactoring that I'm doing now #155

@mourner
Copy link
Member

mourner commented Dec 18, 2013

Done as a part of #2290, along with polyline centroids

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants