Search code examples
javascriptarraysgoogle-mapspolygonarea

How can I find area of multiple polygons individually in Google Map JavaScript?


My code constructs multiple polygons on Google Map using

new google.maps.Polygon()

As you can see in the code, I get the latLng array of polygon paths from Backend i.e. PHP in JSON format. Then pass that array to construct_polygon() function. That function receives the array and make multiple polygons.

I can see all the polygons that are constructed but what the problem is that I have click event listener addListener('click', showArrays) on polygon in order to find it's AREA.

When a user click on polygon, it returns me the same area for all polygons. How can I get the area of every individual respecting polygon?

Here is my Javascript code.

//loading map
   var marker = null;  
   var lat = lon = "";
   var infoWindow;
   var map;
   function myMap() {
    var myCenter = new google.maps.LatLng(34.0151, 71.5249);
    var mapCanvas = document.getElementById("map");
    var mapOptions = {center: myCenter, zoom: 12, mapTypeId: 'terrain'};
    map = new google.maps.Map(mapCanvas, mapOptions);
    polygon_latlng = [];
    $.ajax({
      type:'post',
      url : 'map/get_polygons',
      success:function(r){
        r = JSON.parse(r);
        for (i=0; i<r.length; i++){
          polygon_latlng.push(r[i].latLng);
        }
        construct_polygon(polygon_latlng);
      },
      error:function(e){
        alert("Error");
      }
    });
    }

  function construct_polygon(data){
  // Construct the polygon.
    var testingPolygon = new google.maps.Polygon({
      paths: data,
      strokeColor: '#FF0000',
      strokeOpacity: 0.8,
      strokeWeight: 2,
      fillColor: '#FF0000',
      fillOpacity: 0.4
    });
    testingPolygon.setMap(map); 
    // Add a listener for the click event.
    testingPolygon.addListener('click', showArrays);
    //create infowindow
    infoWindow = new google.maps.InfoWindow;
}

function showArrays(event) { 
  // Since this polygon has only one path, we can call getPath() to return the
  // MVCArray of LatLngs.
  var vertices = this.getPath().getArray(); //@this {google.maps.Polygon} 
  var contentString = '<b>Polygon Details</b><br>' +
      'Clicked location: <br>' + event.latLng.lat() + ' , ' + event.latLng.lng() +
      '<br>';
      
  //the problem is here, it giving me the same area for everyone
  var z = google.maps.geometry.spherical.computeArea(vertices);
  contentString += z;
  // Replace the info window's content and position.
  infoWindow.setContent(contentString);
  infoWindow.setPosition(event.latLng);
  infoWindow.open(map);
}

This is the array that I get from PHP in ajax request (The value of r in success:function() ).

0:
area: "1316.7751419101814"
latLng: Array(11)
0: {lat: 33.9965305977199, lng: 71.4112489764657}
1: {lat: 33.996527415166, lng: 71.4114112549491}
2: {lat: 33.9962570877556, lng: 71.4114036127513}
3: {lat: 33.9962602702772, lng: 71.411241334781}
4: {lat: 33.9961251065509, lng: 71.4112375139768}
5: {lat: 33.9961219240454, lng: 71.4113997916906}
6: {lat: 33.9959867603318, lng: 71.4113959706554}
7: {lat: 33.9959931250968, lng: 71.4110714157155}
8: {lat: 33.9963986163242, lng: 71.4110828773583}
9: {lat: 33.9963954340002, lng: 71.4112451556106}
10: {lat: 33.9965305977199, lng: 71.4112489764657}

1:
area: "877.843869046241"
latLng: Array(5)
0: {lat: 33.9953999683516, lng: 71.4068331233525}
1: {lat: 33.9953936148645, lng: 71.4071576770502}
2: {lat: 33.9951232865572, lng: 71.4071500486501}
3: {lat: 33.99512963998, lng: 71.4068254959785}
4: {lat: 33.9953999683516, lng: 71.4068331233525}

I expect the output to show me an area of a polygon which is clicked, but it's giving me the same value (area) i.e. 1352.49478249 for every polygon that is clicked.

Here is a minimal reproducible example

var pathArr = [{"area" : "1316.7751419101814", "latLng" : [
        {lat: 33.9965305977199, lng: 71.4112489764657},
        {lat: 33.996527415166, lng: 71.4114112549491},
        {lat: 33.9962570877556, lng: 71.4114036127513},
        {lat: 33.9962602702772, lng: 71.411241334781},
        {lat: 33.9961251065509, lng: 71.4112375139768},
        {lat: 33.9961219240454, lng: 71.4113997916906},
        {lat: 33.9959867603318, lng: 71.4113959706554},
        {lat: 33.9959931250968, lng: 71.4110714157155},
        {lat: 33.9963986163242, lng: 71.4110828773583},
        {lat: 33.9963954340002, lng: 71.4112451556106},
        {lat: 33.9965305977199, lng: 71.4112489764657}
                                                                ] 
                  },
                  {"area" : "877.843869046241", "latLng" : [
        {lat: 33.9953999683516, lng: 71.4068331233525},
        {lat: 33.9953936148645, lng: 71.4071576770502},
        {lat: 33.9951232865572, lng: 71.4071500486501},
        {lat: 33.99512963998, lng: 71.4068254959785},
        {lat: 33.9953999683516, lng: 71.4068331233525}
                                                                ] 
                  }
          ];

    var infoWindow;
    var map;
    function myMap() {
      var myCenter = new google.maps.LatLng(33.9951232865572, 71.4071500486501);
      var mapCanvas = document.getElementById("map");
      var mapOptions = {center: myCenter, zoom: 16, mapTypeId: 'terrain'};
      map = new google.maps.Map(mapCanvas, mapOptions);
      polygon_latlng = [];
      for (i=0; i<pathArr.length; i++){
        polygon_latlng.push(pathArr[i].latLng);
      }
      construct_polygon(polygon_latlng);
    }

    function construct_polygon(data){
      //Construct the polygon.
      console.log(data)
      var testingPolygon = new google.maps.Polygon({
        paths: data,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.4
      });
      testingPolygon.setMap(map); 
      // Add a listener for the click event.
      testingPolygon.addListener('click', showArrays);
      //create infowindow
      infoWindow = new google.maps.InfoWindow;
    }

    function showArrays(event) { 
      // Since this polygon has only one path, we can call getPath() to return the
      // MVCArray of LatLngs.
      var vertices = this.getPath().getArray(); //@this {google.maps.Polygon} 
      var contentString = '<b>Polygon Details</b><br>' +
          'Clicked location: <br>' + event.latLng.lat() + ' , ' + event.latLng.lng() +
              '<br>Area: ';
      //the problem is here, it giving me the same area for everyone
      var z = google.maps.geometry.spherical.computeArea(vertices);
      contentString += z;
      // Replace the info window's content and position.
      infoWindow.setContent(contentString);
      infoWindow.setPosition(event.latLng);
      infoWindow.open(map);
    }
#map {
    width:100%;
    height:100%;
    position: absolute;
    top: 0px;
    left: 0px;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title></title>
</head>
<body>
        <div id="map" style="width: 600px;height: 400px;"></div>
      
      <script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous"></script>
    <script src="https://maps.googleapis.com/maps/api/js?key=&callback=myMap" async defer></script>
</body>
</html>


Solution

  • I found solution to my problem. Passing multiple paths and making many polygons with a single: new google.maps.Polygon() will create the problem of giving a single area for all.

    While creating polygon one by one using new google.maps.Polygon() will solve this problem and will give you relevant area of a polygon which is clicked.

    So I just put my construct_polygon() function inside the for loop and it worked.

    $.ajax({
      type:'post',
      url : 'map/get_polygons',
      success:function(r){
        r = JSON.parse(r);
        for (i=0; i<r.length; i++){
          construct_polygon(r[i].latLng);
        }
      },
      error:function(e){
        alert("Error");
      }
    });