7

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.

Boris K
  • 3,442
  • 9
  • 48
  • 87

5 Answers5

8

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!

Boris K
  • 3,442
  • 9
  • 48
  • 87
  • 3
    Not sure, from: https://tools.ietf.org/html/rfc7946 Polygon: The first and last positions are equivalent, and they MUST contain identical values; – kodisha Jul 27 '18 at 09:29
7

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;
};
mcmurphy
  • 781
  • 16
  • 30
4

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

ffflabs
  • 17,166
  • 5
  • 51
  • 77
1

Since this is a top result in Google, here is a more concise example of doing the conversion written in Typescript:

export function googleMapsPolygonToGeoJsonFeature(polygon: google.maps.Polygon) {
  const geometry: Polygon = {
    type: "Polygon" as const,
    coordinates: [],
  };

  const coords = polygon
    .getPath()
    .getArray()
    .map((el) => {
      return [el.lng(), el.lat()];
    });

  geometry.coordinates = [coords];

  const feature: Feature = {
    geometry,
    type: "Feature" as const,
    properties: {},
  };

  return feature;
}

The geojson types I used are from TurfJS, but you could use the GeoJson package as well. Which would then be GeoJSON.Feature/GeoJSON.Polygon.

BradGreens
  • 1,357
  • 4
  • 15
  • 31
0

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.

mykhailoklym94
  • 577
  • 6
  • 13