Search code examples
androidgoogle-mapsmapboxgeojsonmapbox-gl

Mapbox Android - How to draw GeoJSON polygon with holes


I need to draw a GeoJSON poly with holes on a Mapbox Android SDK map.

As the GeoJSON spec says,

For type "Polygon", the "coordinates" member must be an array of LinearRing coordinate arrays. For Polygons with multiple rings, the first must be the exterior ring and any others must be interior rings or holes.

In Leaflet, Mapbox JS and Mapbox GL JS, loading GeoJSONs is handled by the library itself. As it can be seen in this fiddle, the lib takes in account inner rings and thus draws holes correctly.

      [ //Outer ring
        [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]
      ],
      [ //Inner ring (hole)
        [100.35, 0.35], [100.65, 0.35], [100.65, 0.65], [100.35, 0.65], [100.35, 0.35]
      ]

When I look at the Android docs about drawing polys, there is no info whatsoever about holes. The example they give just loops over all the points and builds a PolyOptions with it : Polygon drawing in Mapbox Android.

I have been trying building a polyOptions by adding all the points from the outer ring, then the inner rings, one after the other. With the simple geoJSON from JSFiddle it works, it makes a hole. But with my more complex geoJSON the whole rendering is broken (the shape doesn't look like what it should).

After that, I tried building one separate poly for every ring of the geoJSON. Of course the shape is fine, but there are no holes, but stacked polys instead of them.

I have been looking for other options to PolygonOptions constructor but nothing else than points can be sent. I thought about drawing all the polys and then substracting shapes but I found no such feature.

Here is my GeoJSON. It draws fine on mapbox JS. I am wondering if something is wrong with my GeoJSON, but I do not think so as it draws fine on geojson.io. Maybe I am missing something about geoJSON or mapbox. I did not find any documentation about that. I am considering switching to google maps, but that would mean restart the whole project from scratch.

Any idea ?


Solution

  • After a very long step by step process, I am now able to display holes in a polygon from a GeoJson data.

    I am using this version of mapbox :

    compile("com.mapbox.mapboxsdk:mapbox-android-sdk:5.0.1@aar")
    

    I use the layer system of Mapbox (FillLayer) combined with GeoJsonSource. Here are few lines of code to help:

    //first create a feature
    Feature polygon = Feature.fromJson("{\"type\":\"Feature\",\"properties\":{\"name\":\"Home Zone\"},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]],[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],[[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]}}");
    
    //Then create a Feature Collection from it
    FeatureCollection collection = FeatureCollection.fromFeatures(new Feature[]{polygon});
    
    //Finally you  just need to use the collection to update your layer Source.
    GeoJsonSource geoJsonSource = map.getSourceAs("yourSourceId");
    geoJsonSource.setGeoJson(collection);
    

    As a sample you can check the GeoJson here: http://geojson.io/

    GeoJson Format : https://geojson.org/geojson-spec.html#id4

    The GeoJson in plain text (Huge Square with hole in Malasya) : {"type":"Feature","properties":{"name":"Home Zone"},"geometry":{"type":"Polygon","coordinates":[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]],[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]],[[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]]]}}