mapbox / geojson.io

A quick, simple tool for creating, viewing, and sharing spatial data
http://geojson.io/
ISC License
1.9k stars 565 forks source link

MultiPolygon and right hand rule #782

Closed FitzCarraldo-it closed 1 year ago

FitzCarraldo-it commented 1 year ago

Hi,

Thank you for your work. I have an issue about multipolygon. I create some map with multipoly last week, but now if i try to do the same thing i get the right hand rule error and i don see anything. So i load the old file and i get the same error but i can see and edit the multipolygon. I miss something?

chriswhong commented 1 year ago

Any way you can share the file? What did you use to create the geojson with Multipolygons?

FitzCarraldo-it commented 1 year ago

Hi Chris,

I used geojson.io for the geojson creation; starting from a single polygon i change type from polygon to multipolygon and then i've placed the second poly array. No problem. But today when i try to do the same, i've got this error:

image

This is the whole GeoJSON:

{ "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "id": "01", "name": "spara", "cap": [ "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" ] }, "geometry": { "coordinates": [ [ [ [ 10.054115864565517, 42.26090627280195 ], [ 10.054115864565517, 41.36139362268415 ], [ 10.936127216436944, 41.36139362268415 ], [ 10.936127216436944, 42.26090627280195 ], [ 10.054115864565517, 42.26090627280195 ] ], [ [ 11.732750376967573, 42.07091206517259 ], [ 12.746113089809938, 42.014470439676046 ], [ 12.594475367391851, 41.496275845578 ], [ 11.843562558734305, 41.49592342463356 ], [ 11.732750376967573, 42.07091206517259 ] ], [ [ 10.39092142845297, 40.935511886112124 ], [ 10.39092142845297, 40.13363469371467 ], [ 11.155195061855636, 40.13363469371467 ], [ 11.155195061855636, 40.935511886112124 ], [ 10.39092142845297, 40.935511886112124 ] ] ] ], "type": "MultiPolygon" } } ] }

I also used https://mapstertech.github.io/mapster-right-hand-rule-fixer/ to parse point in the correct order. And it works. I'not a programmer but i understand that right hand rule stand for the point order if a polygon it's inside or outside the other poly in the multipolygon array. So i try to do that but it'doesn't work

kuanb commented 1 year ago

@chriswhong I think this is going to come up more often. There's new GeoJSON spec that came out in July about winding order of polygons (counter-clockwise). A variety of tools do not conform with that (esp. older versions) and will output clockwise-winding-ordered GeoJSON. The result is that the above situation the OP shared will occur.

An example of this is something I found w/ mercantile, where it outputs the wrong winding order which will get rejected from geojson.io now: https://github.com/mapbox/mercantile/issues/148

kuanb commented 1 year ago

image

@FitzCarraldo-it you can visualize the 2 polygons you have that are in the wrong winding order (as in the above image). A script to generate the above is shared below.

In the image, polygons A and B have their polygons in clockwise order whereas C has its in counter-clockwise order, which is correct. As a result, both A and B need to be reversed to become valid GeoJSON.

Script:

import json
from shapely.geometry import Point, Polygon, box

# this is the OP's original MultiPolygon FeatureCollection
example_gj = { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": { "id": "01", "name": "spara", "cap": [ "01", "02", "03", "04", "05", "06", "07", "08", "09", "10" ] }, "geometry": { "coordinates": [ [ [ [ 10.054115864565517, 42.26090627280195 ], [ 10.054115864565517, 41.36139362268415 ], [ 10.936127216436944, 41.36139362268415 ], [ 10.936127216436944, 42.26090627280195 ], [ 10.054115864565517, 42.26090627280195 ] ], [ [ 11.732750376967573, 42.07091206517259 ], [ 12.746113089809938, 42.014470439676046 ], [ 12.594475367391851, 41.496275845578 ], [ 11.843562558734305, 41.49592342463356 ], [ 11.732750376967573, 42.07091206517259 ] ], [ [ 10.39092142845297, 40.935511886112124 ], [ 10.39092142845297, 40.13363469371467 ], [ 11.155195061855636, 40.13363469371467 ], [ 11.155195061855636, 40.935511886112124 ], [ 10.39092142845297, 40.935511886112124 ] ] ] ], "type": "MultiPolygon" } } ] }

fc = {
  "type": "FeatureCollection",
  "features": []
}
for feat in example_gj["features"]:
    for cs in feat["geometry"]["coordinates"][0]:
        as_poly = Polygon(cs)
        gi = as_poly.__geo_interface__
        cs = gi["coordinates"][0]
        cs_r = list(reversed(cs))

        fc["features"].append({
            "type": "Feature",
            "properties": {
                "stroke-width": 0.3
            },
            "geometry": {
                "coordinates": cs_r,
                "type": "LineString"
            }
        })

        for c, hex_col in zip(cs_r[:4], ["#e9507d", "#f38b83", "#fcd384", "#edfbe6"]):
            buffered = Point(c).buffer(0.01)
            as_box = box(*buffered.bounds)
            coords = as_box.exterior.coords.xy
            xs = list(coords[0])
            ys = list(coords[1])
            p = Polygon(list(zip(xs, ys)))
            feat = {
                "type": "Feature",
                "properties": {
                    "fill": hex_col,
                    "fill-opacity": 0.8,
                    "stroke-width": "0"
                }
            }
            feat["geometry"] = p.__geo_interface__
            fc["features"].append(feat)

print(json.dumps(fc))
chriswhong commented 1 year ago

The error is showing up because geojsonhint was upgraded in #735, looks like the prior version 0.3.4 was from 2014 and did not include this rule.

However, geojson.io has always been using geojson-rewind, which will set the counterclockwise winding order for any polygon drawn in the app. This was also updated recently but to my knowledge the previous version was also doing the same.

In any case, I think geojson.io is working as expected and showing an error/not rendering invalid geojson in the code editor.

@FitzCarraldo-it FYI the sample geojson data you provided includes coordinates for three polygons that do not intersect, but they are nested in the geojson as only one polygon with an exterior ring and two interior rings. If all three were drawn in geojson.io, they would be counterclockwise, but placing them where they are in the geojson means it expects the 2nd and 3rd to be clockwise because they are inner rings.

"geometry": {
                "coordinates": [ // array to hold all of the polygons in this MultiPolygon
                    [ // first Polygon
                        [ // outer ring
                            ... 
                        ],
                        [ // first inner ring (your 2nd polygon)
                            ...
                        ],
                        [ // second inner ring (your 3rd polygon)
                            ...
                        ]
                    ]
                    // your 2nd and 3rd polygons should be here where they are treated as Polygons in the MultiPolygon
                ],
                "type": "MultiPolygon"
            }
FitzCarraldo-it commented 1 year ago

Thank you for the answer. I still have issue but i understand the question. I use map for my Einstein Analytics exam and i find that what works on geojson.io doesn't in Analytics and viceversa.I think i must investigate geojson implementation in Salesforce!!!

chriswhong commented 1 year ago

Thanks for raising this! Closing as there is no immediate action to take.

chriswhong commented 1 year ago

Hi, based on some other discussions it was determined that the right hand rule should be a warning instead of an error. This was implemented in https://github.com/mapbox/geojson.io/pull/786, so you should be able to use the geojson you were trying earlier now.

FitzCarraldo-it commented 1 year ago

Him Chris. Tank you for the info!!!