Nxlevel Nxlevel - 14 days ago 7
HTML Question

Finding the center of Leaflet polygon?

I have a bunch of leaflet polygons on a map I created. Each polygon represents something different. A specific set of information is displayed in a popup depending on the page the user is on. I need to find a way to make the "popup" bubble open in the center of the polygon it represents.

Each polygon is drawn using the following code:

var L20 = [
[74.0995, -99.92615],
[74.14008, -99.4043],
[74.07691, -99.33838],
[74.03617, -99.86023]
];



var L19 = [
[74.02559, -99.84924],
[74.06636, -99.32739],
[74.0029, -99.26147],
[73.96197, -99.77783]
];

var L18 = [
[73.95142, -99.76684],
[73.99235, -99.25048],
[73.92889, -99.18456],
[73.8878, -99.69543]
];

var set1 = L.polygon([L20, L19, L18], {
color: "#fff",
weight: 1,
stroke: true,
opacity: 0.05,
fillColor: "#346B1F",

}).addTo(map);


The popup is drawn using the following code:

var popup = L.popup({})
.setLatLng([73.64017, -100.32715])
.setContent(content).openOn(map);
var popup = L.popup();


So I need to find a way for
.setLatLang
to determin or be given the center of the polygon.

I came up with 3 solutions that may work, not sure how to go about it.


  1. find a way to use the coordinates of a polygon to determine the center of the polygon where the popup will open.

  2. call one point of the polygon, then offset the position of the popup.

  3. Use an id for each polygon, so each popup knows the box area (polygon) it can be opened in.



Can someone help me please?

Answer

There are a few ways to approximate the centroid of a polygon.

The easiest (but least accurate method) is to get the center of the bounding box that contains the polygon, as yarl suggested, using polygon.getBounds().getCenter();

I originally answered the question with the formula for finding the centroid of the points, which can be found by averaging the coordinates of its vertices.

var getCentroid = function (arr) { 
    return arr.reduce(function (x,y) {
        return [x[0] + y[0]/arr.length, x[1] + y[1]/arr.length] 
    }, [0,0]) 
}

centerL20 = getCentroid(L20);

While the centroid of the points is a close enough approximation to trick me, a commenter pointed out that it is not the centroid of the polygon.

An implementation based on the formula for a centroid of a non-self-intersecting closed polygon gives the correct result:

var getCentroid2 = function (arr) {
    var twoTimesSignedArea = 0;
    var cxTimes6SignedArea = 0;
    var cyTimes6SignedArea = 0;

    var length = arr.length

    var x = function (i) { return arr[i % length][0] };
    var y = function (i) { return arr[i % length][1] };

    for ( var i = 0; i < arr.length; i++) {
        var twoSA = x(i)*y(i+1) - x(i+1)*y(i);
        twoTimesSignedArea += twoSA;
        cxTimes6SignedArea += (x(i) + x(i+1)) * twoSA;
        cyTimes6SignedArea += (y(i) + y(i+1)) * twoSA;
    }
    var sixSignedArea = 3 * twoTimesSignedArea;
    return [ cxTimes6SignedArea / sixSignedArea, cyTimes6SignedArea / sixSignedArea];        
}
Comments