-4

I'm using vue2 google map package and I have object of arrays like this:

markers:[
 { lat: 14.692734621176195, lng: 120.9642877585083 },
 { lat: 14.691963317641529, lng: 120.9715473253784 },
 { lat: 14.702160611177580, lng: 120.9621292582138 }
]

also, the object markers is dynamic so it can contain more/less than 3 objects.

Problem: the google map is not aligned center when rendered because I don't know how can I find the center coordinate. Any work around or suggestion how can I aligned center the google map?

tao
  • 82,996
  • 16
  • 114
  • 150
Ghed Mendiola
  • 59
  • 2
  • 6
  • What is "*the center coordinate*" in this case? – esqew Aug 23 '21 at 00:20
  • You can see the difference between the two methods here: https://q2k0r.csb.app/. You marked the blue method as correct "center". – tao Aug 23 '21 at 04:19
  • Duplicate of [Center/Set Zoom of Map to cover all visible Markers?](https://stackoverflow.com/questions/19304574/center-set-zoom-of-map-to-cover-all-visible-markers) – MrUpsidown Aug 23 '21 at 20:21
  • @MrUpsidown, technically, this question does not ask for `fitBounds`, which implies changing the zoom level. It only asks for a formula to find the center point of a group of markers. The question you indicated contains no such formula. – tao Aug 23 '21 at 21:15
  • Technically the question is vague and provides no context or details. `fitBounds` is *usually* the way to go to "center" markers on the map. – MrUpsidown Aug 23 '21 at 21:45
  • Otherwise possible duplicate of https://stackoverflow.com/questions/6671183/calculate-the-center-point-of-multiple-latitude-longitude-coordinate-pairs – MrUpsidown Aug 23 '21 at 21:46

2 Answers2

5

If what you want to do is fit the current markers selection on the screen, you're probably looking for fitBounds method. Also see these two answers:

Thank you, @MrUpsidown.


If you're interested in finding the "middle" of a marker selection without changing zoom level, here's my original answer:


"Finding the center" can be a complex geometrical problem but, in your case, it looks like you want to find the intersection of diagonals of the smallest NS/EW rectangle containing all points.

Which means you should to get the min and the max of both lat and lng arrays and find the median of those limits, for each array.

// this fails when polygon crosses 180th meridian!
function findCenter(markers) {
  const lats = markers.map(m => m.lat);
  const lngs = markers.map(m => m.lng);
  return {
    lat: (Math.min(...lats) + Math.max(...lats)) / 2,
    lng: (Math.min(...lngs) + Math.max(...lngs)) / 2
  };
}

However, the above code produces wrong results for polygons crossing the 180th meridian, as @MrUpsidown noted. The correct code to include that case is:

function getMiddle(prop, markers) {
  let values = markers.map(m => m[prop]);
  let min = Math.min(...values);
  let max = Math.max(...values);
  if (prop === 'lng' && (max - min > 180)) {
    values = values.map(val => val < max - 180 ? val + 360 : val);
    min = Math.min(...values);
    max = Math.max(...values);
  }
  let result = (min + max) / 2;
  if (prop === 'lng' && result > 180) {
    result -= 360
  }
  return result;
}

function findCenter(markers) {
  return {
    lat: getMiddle('lat', markers),
    lng: getMiddle('lng', markers)
  }
}


// tests: 
console.log(findCenter([
  { lat: 14.692734621176195, lng: 120.9642877585083 },
  { lat: 14.691963317641529, lng: 120.9715473253784 },
  { lat: 14.702160611177580, lng: 120.9621292582138 },
])); 
// => { "lat": 14.697061964409555,  "lng": 120.96683829179611 }

console.log(findCenter([
  { lat: 50, lng: 45 },
  { lat: 0, lng: 125 },
  { lat: -50, lng: -100 }
]))
// => { "lat": 0,  "lng": 152.5 }

The difference between my answer (green) and tugrul's answer (blue) is depicted graphically here: https://q2k0r.csb.app/


As pointed out by @mrupsidown, Google maps API provides utilities to calculate the center of collection of points:

  • create a LatLngBounds object and extend it from the markers collection
  • use .getCenter() on the created bounds object.
tao
  • 82,996
  • 16
  • 114
  • 150
  • I'd be more than happy to improve it, if you find any failing cases. Thanks for looking into it. – tao Aug 23 '21 at 22:23
  • http://jsfiddle.net/upsidown/sj8v7phc/ - yellow center marker is calculated with a bounds object - blue one with your function - red rectangle is the bounds object. I think the *issue* is just related to which point is considered on the outer edge of the rectangle. Earth being round... – MrUpsidown Aug 23 '21 at 22:36
  • Fair point, I'll update with a disclamer. After all, the world is round :) Why not add your own answer? In fairness, I should have thought maps API should have some utilities covering this. – tao Aug 23 '21 at 22:39
  • One more thing that a `LatLng` object does is that it clamps the latitudes and wraps longitudes to handle wrong / out of range values as explained [here](https://developers.google.com/maps/documentation/javascript/reference/coordinates#LatLng). – MrUpsidown Aug 23 '21 at 23:48
  • @MrUpsidown, I know Google maps is fantastic. One small thing my answer does and Google maps does not is that it provides a useful method to get the "center" for users of any map product (mapbox, leaflet, openstreetmaps, maplibre). But you're right, my custom method doesn't work with invalid coordinates. Thanks for the valuable feedback and suggestions. – tao Aug 24 '21 at 00:33
  • Fair point. It wouldn't be too hard to create another function that would do that... – MrUpsidown Aug 26 '21 at 09:03
-2

This website provides a function to find the center of coordinates.

function findCenter(markers) {
    let lat = 0;
    let lng = 0;
    
    for(let i = 0; i < markers.length; ++i) {
        lat += markers[i].lat;
        lng += markers[i].lng;
    }

    lat /= markers.length;
    lng /= markers.length;

    return {lat: lat, lng: lng}
}

The output is

{
  lat: 14.695619516665102,
  lng: 120.96598811403351
}

jsfiddle

Edit for Arbitrary Shapes the Coordinates Make As tao mentioned, this formula is not perfect for "any kind of coordinate array". This and this links have a better explanation and formula of how to achieve what you wanted.

tugrul
  • 135
  • 3
  • That method is wrong, it calculates the median. Assuming you have 9 points with a `lat` of `10` and one point with a `lat` of `20` the "center", according to your formula will have a `lat` of `11`. But in reality it should be `15`. You want a function which gets the `min` and the `max` of both `lat` and `lng` arrays and gets the middle value in between those limits. That's the "center". – tao Aug 23 '21 at 00:30
  • @tao yes, you have a point. I've checked again and seems like this method is told to be working properly when "the coordinates create a triangle or a regular polygon". See https://gis.stackexchange.com/questions/12120/calculate-midpoint-from-a-series-of-latitude-and-longitude-coordinates and https://en.wikipedia.org/wiki/Centroid#By_geometric_decomposition – tugrul Aug 23 '21 at 00:37
  • Here's a triangle example failing: `[{lat: 10, lng: 120}, {lat: 10, lng: 130}, {lat: 20, lng: 120}]`. Your method returns `{lat: 13.333333333333334, lng: 123.33333333333333}`. The correct result is `{ lat: 15, lng: 125 }`. – tao Aug 23 '21 at 01:02
  • Your formula calculates what's called "centroid" or "center of gravity" or "center of mass". Which means if you have more points closer to one side, they pull the "center of gravity" towards that side. Whereas we don't want this here. We just want to find the middle of a screen (rectangle) which would contain all points, regardless of how many points are closer to one side. – tao Aug 23 '21 at 01:09
  • I've made a codesandbox to provide a graphical (and more intuitive) explanation of my comments above: https://q2k0r.csb.app/. Blue (center of gravity) is the method in your answer and Green (median of limits) is the method I outlined in my answer. Happy coding! – tao Aug 23 '21 at 04:03
  • After playing with it for a bit, I realized the centroid cannot overlap with the center of the smallest window containing all points for any polygon having an odd number of points, even if it's an equilateral polygon, and regardless of the polygon's rotation. Which means the centroid method cannot technically produce the correct result for any triangle, pentagon, heptagon, and so on. – tao Aug 23 '21 at 13:56