Getting a GeoJSON from a Google Maps drawing manager polygon

Viewed 7009

I'm building a React app which allows users to define plots through a Google Maps component by drawing overlay polygons. I'd like to push a GeoJSON up every time that the user draws a polygon.

The documentation is vague on this point. I'm using this sort of function:

onPolygonComplete={polygon => {
                console.log(JSON.stringify(polygon.getPaths().b[0].b));
            }}

...which produces this sort of thing:

[{"lat":32.22020791674245,"lng":35.22491455078125},{"lat":31.98754909816049,"lng":35.20294189453125},{"lat":32.0201569982896,"lng":35.43365478515625},{"lat":32.22485504316297,"lng":35.30731201171875}]

A good start-but is there anything built in that will produce an actual GeoJSON?

I can always use .map to go through this array and vivsect an GeoJSON object out of it...but wanted to ask if anyone knew of something already baked into the API.

4 Answers

Alright, I've got it figured out.

First, declare a GeoJSON template variable:

let GeoJSON = {
    type: 'Feature',
    geometry: {
        type: 'Polygon',
        coordinates: []
    },
    properties: {}
};

Then, in your drawing manager, do this:

onPolygonComplete={polygon => {
                for (let point of polygon.getPath().getArray()) {
                    GeoJSON.geometry.coordinates.push([point.lng(), point.lat()]);
                }

Now, you have a perfect GeoJSON polygon object. Voila!

Based on @Boris_K's answer, here is a more robust solution that:

  1. Extends google.maps.Polygon.
  2. Conforms to rfc7946 such that the first and last point are identical.
  3. Should also work for Polygons with holes.
google.maps.Polygon.prototype.getGeoJSON = function()  {
    let geoJSON = {
        type: "Polygon",
        coordinates: []
    };

    let paths = this.getPaths().getArray();

    for (path of paths)  {
        let pathArray = [];
        let points = path.getArray();
        let firstPoint = false;

        for (point of points)  {
            if (firstPoint === false)  {
                firstPoint = point;
            }

            pathArray.push([point.lng(), point.lat()])
        }

        pathArray.push([firstPoint.lng(), firstPoint.lat()]);

        geoJSON.coordinates.push(pathArray);
    }

    return geoJSON;
};

You can resort to conversion libraries such as Wicket to convert between google overlay objects and geojson valid literals. (Disclaimer: I've made a few contributions to Wicket in the past to suit my own use cases)

I made a fiddle showing this based on the example Simple Polygons

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 bermudaTriangle = new google.maps.Polygon({
  paths: triangleCoords,
  strokeColor: '#FF0000',
  strokeOpacity: 0.8,
  strokeWeight: 2,
  fillColor: '#FF0000',
  fillOpacity: 0.35
});

bermudaTriangle.setMap(map);

 var wicket=new Wkt.Wkt(),
     wktpolygon= wicket.fromObject(bermudaTriangle);

 console.log(wktpolygon.toJson());

make sure to open the console to see the converted polygon

Worth mentioning that the above solutions with custom code work, but they’re not really production tested. There is a solution that builds upon existing Google’s code, so I think there is no need to re-invent the wheel here.

Related