[google-maps] Polygon Drawing and Getting Coordinates with Google Map API v3

I'm trying to develop an application by using Google Maps API v3. What I'm trying to do is; first let the user draw a polygon on a Google Map and get his/her polygon's coordinates and save them into a database. I will then show the user saved coordinates.

I don't know how to let users draw polygon on a Google Map with API v3 and then get the coordinates. If I can get those coordinates, it's easy to save them into a database.

http://gmaps-samples.googlecode.com/svn/trunk/poly/mymapstoolbar.html is nearly the exact example but it uses API v2 and doesn't give coordinates. I want to use API v3 and be able to get all coordinates.

Is there any examples of drawing polygon and getting its coordinates with API v3?

This question is related to google-maps polygon

The answer is


here you have the example above using API V3

http://nettique.free.fr/gmap/toolbar.html


to accomplish what you want, you must getPaths from the polygon. Paths will be an array of LatLng points. you get the elements of the array and split the LatLng pairs with the methods .lat and .lng in the function below, i have a redundant array corresponding to a polyline that marks the perimeter around the polygon.

saving is another story. you can then opt for many methods. you may save your list of points as a csv formatted string and export that to a file (easiest solution, by far). i highly recommend GPS TXT formats, like the ones (there are 2) readable by GPS TRACKMAKER (great free version software). if you are competent to save them to a database, that is a great solution (i do both, for redundancy).

function areaPerimeterParse(areaPerimeterPath) {
    var flag1stLoop = true;
    var areaPerimeterPathArray = areaPerimeterPath.getPath();
    var markerListParsedTXT = "Datum,WGS84,WGS84,0,0,0,0,0\r\n";

    var counter01 = 0;
    var jSpy = "";
    for (var j = 0;j<areaPerimeterPathArray.length;j++) {
        counter01++;
        jSpy += j+"  ";
        if (flag1stLoop) {
            markerListParsedTXT += 'TP,D,'+[ areaPerimeterPathArray.getAt(j).lat(), areaPerimeterPathArray.getAt(j).lng()].join(',')+',00/00/00,00:00:00,1'+'\r\n';
            flag1stLoop = false;
        } else {
            markerListParsedTXT += 'TP,D,'+[ areaPerimeterPathArray.getAt(j).lat(), areaPerimeterPathArray.getAt(j).lng()].join(',')+',00/00/00,00:00:00,0'+'\r\n';
        }

    }
    // last point repeats first point
    markerListParsedTXT += 'TP,D,'+[ areaPerimeterPathArray.getAt(0).lat(), areaPerimeterPathArray.getAt(0).lng()].join(',')+',00/00/00,00:00:00,0'+'\r\n';
    return markerListParsedTXT;
}

attention, the line that ends with ",1" (as opposed to ",0") starts a new polygon (this format allows you to save multiple polygons in the same file). i find TXT more human readable than the XML based formats GPX and KML.


The other answers show you to create the polygons, but not how to get the coordinates...

I'm not sure the best way to do it, but heres one way.. It seems like there should be a method to get the paths from the polygon, but I can't find one, and getPath() doesn't seem to work for me. So here's a manual approach that worked for me..

Once you've finished drawing your polygon, and pass in your polygon to the overlay complete function, you can find the coordinates in the polygon.overlay.latLngs.b[0].b

google.maps.event.addListener(drawingManager, 'overlaycomplete', function(polygon) {
        $.each(polygon.overlay.latLngs.b[0].b, function(key, latlng){
            var lat = latlng.d;
            var lon = latlng.e;
            console.log(lat, lon); //do something with the coordinates
        });
});

note, i'm using jquery to loop over the list of coordinates, but you can do loop however.


Since Google updates sometimes the name of fixed object properties, the best practice is to use GMaps V3 methods to get coordinates event.overlay.getPath().getArray() and to get lat latlng.lat() and lng latlng.lng().

So, I just wanted to improve this answer a bit exemplifying with polygon and POSTGIS insert case scenario:

google.maps.event.addListener(drawingManager, 'overlaycomplete', function(event) {
    var str_input ='POLYGON((';
    if (event.type == google.maps.drawing.OverlayType.POLYGON) {
      console.log('polygon path array', event.overlay.getPath().getArray());
      $.each(event.overlay.getPath().getArray(), function(key, latlng){
        var lat = latlng.lat();
        var lon = latlng.lng();
        console.log(lat, lon); 
        str_input += lat +' '+ lon +',';
      });
    }
    str_input = str_input.substr(0,str_input.length-1) + '))';
    console.log('the str_input will be:', str_input);

    // YOU CAN THEN USE THE str_inputs AS IN THIS EXAMPLE OF POSTGIS POLYGON INSERT
    // INSERT INTO your_table (the_geom, name) VALUES (ST_GeomFromText(str_input, 4326), 'Test')

  });

try this

In your controller use

> $scope.onMapOverlayCompleted = onMapOverlayCompleted;
> 
>  function onMapOverlayCompleted(e) {
> 
>                 e.overlay.getPath().getArray().forEach(function (position) {
>                     console.log('lat', position.lat());
>                     console.log('lng', position.lng());
>                 });
> 
>  }

**In Your html page , include drawning manaer** 


    <ng-map id="geofence-map" zoom="8" center="current" default-style="true" class="map-layout map-area"
                        tilt="45"
                        heading="90">

                    <drawing-manager
                            on-overlaycomplete="onMapOverlayCompleted()"
                            drawing-control-options="{position: 'TOP_CENTER',drawingModes:['polygon','circle']}"
                            drawingControl="true"
                            drawingMode="null"
                            markerOptions="{icon:'www.example.com/icon'}"
                            rectangleOptions="{fillColor:'#B43115'}"
                            circleOptions="{fillColor: '#F05635',fillOpacity: 0.50,strokeWeight: 5,clickable: false,zIndex: 1,editable: true}">
                    </drawing-manager>
    </ng-map>

It's cleaner/safer to use the getters provided by google instead of accessing the properties like some did

google.maps.event.addListener(drawingManager, 'overlaycomplete', function(polygon) {
    var coordinatesArray = polygon.overlay.getPath().getArray();
});

If all you need is the coordinates here is a drawing tool I like to use - move the polygon or re-shape it and the coordinates will display right below the map: jsFiddle here.

Also, here is a Codepen

JS

var bermudaTriangle;
function initialize() {
    var myLatLng = new google.maps.LatLng(33.5190755, -111.9253654);
    var mapOptions = {
        zoom: 12,
        center: myLatLng,
        mapTypeId: google.maps.MapTypeId.RoadMap
    };

    var map = new google.maps.Map(document.getElementById('map-canvas'),
                                  mapOptions);


    var triangleCoords = [
        new google.maps.LatLng(33.5362475, -111.9267386),
        new google.maps.LatLng(33.5104882, -111.9627875),
        new google.maps.LatLng(33.5004686, -111.9027061)

    ];

    // Construct the polygon
    bermudaTriangle = new google.maps.Polygon({
        paths: triangleCoords,
        draggable: true,
        editable: true,
        strokeColor: '#FF0000',
        strokeOpacity: 0.8,
        strokeWeight: 2,
        fillColor: '#FF0000',
        fillOpacity: 0.35
    });

    bermudaTriangle.setMap(map);
    google.maps.event.addListener(bermudaTriangle, "dragend", getPolygonCoords);
    google.maps.event.addListener(bermudaTriangle.getPath(), "insert_at", getPolygonCoords);
    google.maps.event.addListener(bermudaTriangle.getPath(), "remove_at", getPolygonCoords);
    google.maps.event.addListener(bermudaTriangle.getPath(), "set_at", getPolygonCoords);
}

function getPolygonCoords() {
    var len = bermudaTriangle.getPath().getLength();
    var htmlStr = "";
    for (var i = 0; i < len; i++) {
        htmlStr += bermudaTriangle.getPath().getAt(i).toUrlValue(5) + "<br>";
    }
    document.getElementById('info').innerHTML = htmlStr;
}

HTML

<body onload="initialize()">
    <h3>Drag or re-shape for coordinates to display below</h3>
    <div id="map-canvas">
    </div>
    <div id="info">
    </div>
</body>

CSS

#map-canvas {
    width: auto;
    height: 350px;
}
#info {
    position: absolute;
    font-family: arial, sans-serif;
    font-size: 18px;
    font-weight: bold;
}

Adding to Gisheri's answer

Following code worked for me

 var drawingManager = new google.maps.drawing.DrawingManager({
    drawingMode: google.maps.drawing.OverlayType.MARKER,
    drawingControl: true,
    drawingControlOptions: {
      position: google.maps.ControlPosition.TOP_CENTER,
      drawingModes: [
        google.maps.drawing.OverlayType.POLYGON
      ]
    },
    markerOptions: {
      icon: 'images/beachflag.png'
    },
    circleOptions: {
      fillColor: '#ffff00',
      fillOpacity: 1,
      strokeWeight: 5,
      clickable: false,
      editable: true,
      zIndex: 1
    }

  });

  google.maps.event.addListener(drawingManager, 'overlaycomplete', function(polygon) {
      //console.log(polygon.overlay.latLngs.j[0].j);return false;
        $.each(polygon.overlay.latLngs.j[0].j, function(key, LatLongsObject){
            var LatLongs    =   LatLongsObject;

            var lat = LatLongs.k;
            var lon = LatLongs.B;
           console.log("Lat is: "+lat+" Long is: "+lon); //do something with the coordinates

        });

Well, unfortunately it seems that one cannot place custom markers and draw (and obtain coordinates) directly from maps.google.com if one is anonymous/not logged in (as it was possible some years ago, if I recall correctly). Still, thanks to the answers here, I managed to make a combination of examples that has both the Google Places search, and allows drawing via the drawing library, and dumps coordinates upon making a selection of any type of shape (including coordinates for polygon) that can be copypasted; the code is here:

This is how it looks like:

test.png

(The Places markers are handled separately, and can be deleted via the DEL "button" by the search input form element; "curpos" shows the current center [position] and zoom level of the map viewport).


Cleaned up what chuycepeda has and put it into a textarea to send back in a form.

google.maps.event.addListener(drawingManager, 'overlaycomplete', function (event) {
    var str_input = '{';
    if (event.type == google.maps.drawing.OverlayType.POLYGON) {
        $.each(event.overlay.getPath().getArray(), function (key, latlng) {
            var lat = latlng.lat();
            var lon = latlng.lng();
            str_input += lat + ', ' + lon + ',';
        });
    }
    str_input = str_input.substr(0, str_input.length - 1) + '}';

    $('textarea#Geofence').val(str_input);
});