How to center the map in the middle of the polygon?

3

I have a polygon formed, at first, with 3 edges, basically created using 3 locations: Maiami, Puerto Rico and Bermuda. I took the example in the documentation that shows you how to create a simple polygon . However, by API required standard, you have to centralize the map somewhere (or even open the map), in which I centralized in Rio de Janeiro, through the coordinates. See below and zoom in:

function initialize() {
  var map = new google.maps.Map(document.getElementById("map_canvas"), {
    zoom: 10,
    center: new google.maps.LatLng(-22.91711261458102, -43.16944599151611),
    mapTypeId: "roadmap"
  });

  // Define the LatLng coordinates for the polygon's path.
  var triangleCoords = [{
      lat: 25.774,
      lng: -80.190
    },
    {
      lat: 18.466,
      lng: -66.118
    },
    {
      lat: 32.321,
      lng: -64.757
    },
    {
      lat: 25.774,
      lng: -80.190
    }
  ];

  // Construct the polygon.
  var bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35
  });
  bermudaTriangle.setMap(map);
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script><bodyonload="initialize()">
  <div id="map_canvas" style="height: 100vh; width:100vw"></div>
</body>

One way I found it was to point the center of the map to any point in the polygon, but it will not be fully centered (beat perfectionism). The point is, I'd like to center the map in the middle of the polygon, where I'll be creating dynamically.

What would be the best way to do this? How to center map in the middle of the polygon?

    
asked by anonymous 22.06.2017 / 04:07

1 answer

6

The idea is to calculate the barycentre of a polygon and use this as a map coordinate.

The barycentre of a polygon is given by the arithmetic mean of the coordinates (Cartesian !, important detail for later) of the polygon points. In general, the following algorithm computes this:

x_baricentro = somatório (x dos pontos) / tamanho(pontos)
y_baricentro = somatório (y dos pontos) / tamanho(pontos)

The problem, however, is that the coordinates are given by spherical coordinates in degrees! To solve this, we need to transform these coordinates into radians ( 180 degrees is pi radians). The general formula is this:

theta_rad = theta_graus * pi / 180

The opposite conversion is:

theta_graus = theta_rad *180/pi

Ok, now we have the conversion to radians. Now, we need to convert from radians to a point in Cartesian space. I used the formulas contained in that international OS question .

x = cos(lat) * cos(lon)
y = cos(lat) * sin(lon)
z = sin(lat)

With this, I get the average of (x,y,z) , I'll call (x_c,y_c,z_c) here in the explanation. From these values, I need to convert back to radians:

lon_rad = atan2(y, x)
hyp_rad = sqrt(x * x + y * y)
lat_rad = atan2(z, hyp)

Hence, just turn to degrees and be happy. The code below is a bit dirty and polluted, but it does these calculations the way it was shown.

function initialize() {
  // Define the LatLng coordinates for the polygon's path.
  var triangleCoords = [{
      lat: 25.774,
      lng: -80.190
    },
    {
      lat: 18.466,
      lng: -66.118
    },
    {
      lat: 32.321,
      lng: -64.757
    },
    {
      lat: 25.774,
      lng: -80.190
    }
  ];

  var x_cart = 0;
  var y_cart = 0;
  var z_cart = 0;
  var i;

  // ignorando primeiro elemento
  for (i = 1; i < triangleCoords.length; i++) {
      var x, y, z;
      var lat, lon;

      lat = triangleCoords[i].lat * Math.PI / 180; // transforma para radianos
      lon = triangleCoords[i].lng * Math.PI / 180; // transforma para radianos

      // obtém as coordenadas cartesianas
      x = Math.cos(lat) * Math.cos(lon);
      y = Math.cos(lat) * Math.sin(lon);
      z = Math.sin(lat);

      x_cart += x;
      y_cart += y;
      z_cart += z;
  }

  // média das coordenadas cartesianas
  x_cart = x_cart/(triangleCoords.length - 1.0);
  y_cart = y_cart/(triangleCoords.length - 1.0);
  z_cart = z_cart/(triangleCoords.length - 1.0);

  // processo para voltar a coordenadas esféricas
  var lng_c, hyp, lat_c;

  lng_c = Math.atan2(y_cart, x_cart);
  hyp = Math.sqrt(x_cart * x_cart + y_cart * y_cart);
  lat_c = Math.atan2(z_cart, hyp);

  // de volta para graus, saindo dos radianos

  lng_c = lng_c * 180.0/Math.PI;
  lat_c = lat_c * 180.0/Math.PI;

  var center = {
     lat: lat_c,
     lng: lng_c
 };
 console.log('lat lng' + lat_c + ',' + lng_c);

  var map = new google.maps.Map(document.getElementById("map_canvas"), {
    zoom: 4,
    center: new google.maps.LatLng(center.lat, center.lng),
    mapTypeId: "roadmap"
  });

  // Construct the polygon.
  var bermudaTriangle = new google.maps.Polygon({
    paths: triangleCoords,
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35
  });
  bermudaTriangle.setMap(map);
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script><bodyonload="initialize()">
  <div id="map_canvas" style="height: 100vh; width:100vw"></div>
</body>
  

UPDATE

The @acklay later discovered the function of the GoogleMaps API itself that calculates the barycentre.

This function is bounds.getCenter() , being var bounds = new google.maps.LatLngBounds() . Note that it is necessary to add the desired points on this border to get the center.

function initialize() {
  // Define the LatLng coordinates for the polygon's path.
  var bounds = new google.maps.LatLngBounds();
  var i;

  var polygonCoords = [
     new google.maps.LatLng(25.774252, -80.190262),
     new google.maps.LatLng(18.466465, -66.118292),
     new google.maps.LatLng(32.321384, -64.757370),
     new google.maps.LatLng(25.774252, -80.190262)
  ];

  // ignorando o primeiro elemento
  for (i = 1; i < polygonCoords.length; i++) {
     bounds.extend(polygonCoords[i]);
  }

  // Aqui imprime a coordenada central em relação ao poligono - (25.3939245, -72.473816)
  console.log(bounds.getCenter());

  var map = new google.maps.Map(document.getElementById("map_canvas2"), {
    zoom: 4,
    center: bounds.getCenter(),
    mapTypeId: "roadmap"
  });

  // Construct the polygon.
  var bermudaTriangle = new google.maps.Polygon({
    paths: polygonCoords,
    strokeColor: '#FF0000',
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: '#FF0000',
    fillOpacity: 0.35
  });
  bermudaTriangle.setMap(map);
}
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script><bodyonload="initialize()">
  <div id="map_canvas2" style="height: 100vh; width:100vw"></div>
</body>
    
22.06.2017 / 05:09