Skip to content

Incorrect fix_geojson result for a geometry in Saudi ArabiaΒ #182

@ianthetechie

Description

@ianthetechie

I've been trying out this library to help clean up a data source (Who's on First) which I know has a bunch of abnormal GeoJSON. I'm actually not 100% sure what specific cases fix_geojson is supposed to addressed, so I just ran it on the entire dataset to see what'd happen and I found some cases where it will invert a geometry so it covers the entire world, sans the original area it was supposed to cover πŸ˜…

This neighbourhood in Saudi Arabia stood out as a minimal reproducible example as it's a fairly simple polygon.

{
  "id": 1361026217,
  "type": "Feature",
  "properties": {
    "edtf:cessation":"uuuu",
    "edtf:inception":"uuuu",
    "geom:area":0.000548,
    "geom:area_square_m":0.0,
    "geom:bbox":"41.661835,27.536652,41.701686,27.556499",
    "geom:latitude":27.547189,
    "geom:longitude":41.683172,
    "gn:admin1_code":"13",
    "gn:asciiname":"Sadyan",
    "gn:country_code":"SA",
    "gn:dem":990,
    "gn:feature_class":"P",
    "gn:feature_code":"PPL",
    "gn:geonameid":395249,
    "gn:latitude":27.5463,
    "gn:longitude":41.69747,
    "gn:modification_date":"2018-03-08",
    "gn:name":"\u015eady\u0101n",
    "gn:population":0,
    "gn:timezone":"Asia/Riyadh",
    "iso:country":"SA",
    "lbl:latitude":27.547922,
    "lbl:longitude":41.683172,
    "lbl:max_zoom":18.0,
    "mz:hierarchy_label":1,
    "mz:is_current":1,
    "mz:min_zoom":15.0,
    "name:ara_x_preferred":[
        "\u0633\u062f\u064a\u0627\u0646"
    ],
    "name:ara_x_variant":[
        "\u0635\u062f\u064a\u0627\u0646"
    ],
    "name:eng_x_preferred":[
        "Sadyan"
    ],
    "name:und_x_variant":[
        "\u015eady\u0101n"
    ],
    "reversegeo:latitude":27.547922,
    "reversegeo:longitude":41.683172,
    "src:geom":"whosonfirst",
    "src:geom_alt":[
        "geonames"
    ],
    "src:lbl_centroid":"whosonfirst",
    "wof:belongsto":[
        102191569,
        85632253,
        421190323,
        1108720703,
        85676831
    ],
    "wof:breaches":[],
    "wof:concordances":{
        "gn:id":395249
    },
    "wof:country":"SA",
    "wof:geomhash":"8f0c280a5d19b116d263f4942ff95891",
    "wof:hierarchy":[
        {
            "continent_id":102191569,
            "country_id":85632253,
            "county_id":1108720703,
            "locality_id":421190323,
            "neighbourhood_id":1361026217,
            "region_id":85676831
        }
    ],
    "wof:id":1361026217,
    "wof:lastmodified":1660235491,
    "wof:name":"Sadyan",
    "wof:parent_id":421190323,
    "wof:placetype":"neighbourhood",
    "wof:repo":"whosonfirst-data-admin-sa",
    "wof:superseded_by":[],
    "wof:supersedes":[
        1209293959
    ],
    "wof:tags":[]
},
  "bbox": [
    41.661835,
    27.536652,
    41.701686,
    27.556499
],
  "geometry": {"coordinates":[[[41.701686,27.555683],[41.677091,27.556499],[41.701686,27.555683],[41.701676,27.552681],[41.694555,27.537487],[41.69456,27.536652],[41.684332,27.538833],[41.683195,27.539543],[41.674979,27.541187],[41.672853,27.540324],[41.671549,27.538989],[41.671067,27.537625],[41.665152,27.538274],[41.664217,27.538102],[41.661835,27.538401],[41.66299,27.541284],[41.667426,27.54781],[41.67182,27.554058],[41.674274,27.555888],[41.677091,27.556499],[41.701686,27.555683]]],"type":"Polygon"}
}

If you paste this into geojson.io, everything displays fine, but of you look closely (scroll down to the coordinates) there's a little warning that it doesn't follow the right hand rule. Basically, winding order is wrong.

If you feed this into antimeridian.fix_geojson, it does print a FixWindingWarning to the console to this effect. However, if you look at the coordinates, it's clear something is a bit off. Basically it inverts the intended shape.

{
  "id": 1361026217,
  "type": "Feature",
  "properties": {},
  "bbox": [41.661835, 27.536652, 41.701686, 27.556499],
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [-180.0,  90.0],
        [-180.0, -90.0],
        [ 180.0, -90.0],
        [ 180.0,  90.0],
        [-180.0,  90.0]
      ],
      [
        [41.701685999999995, 27.555683],
        [41.67709099999999,  27.556499],
        [41.674274,          27.555888],
        [41.67182,           27.554058],
        [41.667426000000006, 27.54781 ],
        [41.66299000000001,  27.541284],
        [41.661834999999996, 27.538401],
        [41.66421700000001,  27.538102],
        [41.665152000000006, 27.538274],
        [41.671066999999994, 27.537625],
        [41.671549,          27.538989],
        [41.672853,          27.540324],
        [41.67497900000001,  27.541187],
        [41.68319500000001,  27.539543],
        [41.68433199999998,  27.538833],
        [41.694559999999996, 27.536652],
        [41.69455500000001,  27.537487],
        [41.70167599999999,  27.552681],
        [41.701685999999995, 27.555683],
        [41.67709099999999,  27.556499],
        [41.701685999999995, 27.555683]
      ]
    ]
  }
}

I can definitely understand the behavior here since it's not exactly correct GeoJSON, but it's a bit surprising to say the least! I sort of thought the winding order fix would... not break it like that, and rather behave more like GeoJSON.io.

So, to address this, I tried running the geometry through the rewind module: https://github.com/chris48s/geojson-rewind. Here's the re-wound geometry:

{
  "id": 1361026217,
  "type": "Feature",
  "properties": {},
  "bbox": [41.661835, 27.536652, 41.701686, 27.556499],
  "geometry": {
    "coordinates": [
      [
        [41.701686, 27.555683],
        [41.677091, 27.556499],
        [41.674274, 27.555888],
        [41.67182,  27.554058],
        [41.667426, 27.54781 ],
        [41.66299,  27.541284],
        [41.661835, 27.538401],
        [41.664217, 27.538102],
        [41.665152, 27.538274],
        [41.671067, 27.537625],
        [41.671549, 27.538989],
        [41.672853, 27.540324],
        [41.674979, 27.541187],
        [41.683195, 27.539543],
        [41.684332, 27.538833],
        [41.69456,  27.536652],
        [41.694555, 27.537487],
        [41.701676, 27.552681],
        [41.701686, 27.555683],
        [41.677091, 27.556499],
        [41.701686, 27.555683]
      ]
    ],
    "type": "Polygon"
  }
}

This does not raise any warnings when I paste it into geojson.io. However, if I put this geometry through antimeridian.fix_geojson, it still comes up with the inverted geometry and logs a winding warning πŸ€” Even more confusing is that when I pass fix_winding=False, it still inverts the geometry (though it does not emit a warning)!

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions