marceloprates / prettymaps

A small set of Python functions to draw pretty maps from OpenStreetMap data. Based on osmnx, matplotlib and shapely libraries.
GNU Affero General Public License v3.0
11.04k stars 516 forks source link

shapely.geos:TopologyException: depth mismatch at at 552100 5277600 #27

Open bburghaus opened 2 years ago

bburghaus commented 2 years ago
ERROR:shapely.geos:TopologyException: depth mismatch at  at 552100 5277600
Traceback (most recent call last):
  File "maps.py", line 18, in <module>
    layers = plot(
  File "/home/***/.local/lib/python3.8/site-packages/prettymaps/draw.py", line 189, in plot
    layers = {
  File "/home/***/.local/lib/python3.8/site-packages/prettymaps/draw.py", line 190, in <dictcomp>
    layer: get_layer(
  File "/home/***/.local/lib/python3.8/site-packages/prettymaps/fetch.py", line 146, in get_layer
    return get_streets(**kwargs, layer = layer)
  File "/home/***/.local/lib/python3.8/site-packages/prettymaps/fetch.py", line 109, in get_streets
    streets = unary_union([
  File "/home/***/.local/lib/python3.8/site-packages/prettymaps/fetch.py", line 111, in <listcomp>
    MultiLineString(
  File "/home/***/.local/lib/python3.8/site-packages/shapely/geometry/base.py", line 637, in buffer
    return geom_factory(self.impl['buffer_with_params'](self, params, distance))
  File "/home/***/.local/lib/python3.8/site-packages/shapely/geometry/base.py", line 78, in geom_factory
    raise ValueError("No Shapely geometry can be created from null value")
ValueError: No Shapely geometry can be created from null value

To reproduce:

jacopofar commented 2 years ago

Same with Milan, Italy and radius=4000, but not with radius=3000.

As a workaround, I modified the code to catch the exception, log and continue, but cannot find the root cause.

This is my change, at line 310 of fetch.py:

``` multiline_strings = [] for highway, w in width.items(): try: multiline_strings.append( MultiLineString( streets[ [highway in value for value in streets[layer]] & (streets.geometry.type == "LineString") ].geometry.tolist() + list( reduce( lambda x, y: x + y, [ list(lines) for lines in streets[ [highway in value for value in streets[layer]] & (streets.geometry.type == "MultiLineString") ].geometry ], [], ) ) ).buffer(w) ) except ValueError as e: print('Error', e) print('Offending object:', highway, w) streets = unary_union(multiline_strings) ```

I simply moved the list comprehension to a normal for where I can use a try...except and print the error and keep running. In my case it was:

Error No Shapely geometry can be created from null value
Offending object: footway 1

and then the map was generated

smilebasti commented 2 years ago

I also came to this error.

I tried your solution @jacopofar.
It shows me this:

Error No Shapely geometry can be created from null value
Offending object: footway 1

but then the error came, after that, again.

Any thoughts on that?

jacopofar commented 2 years ago

My workaround simply skips the geometry causing the issue, the fact you are seeing that message means the exception was handled. Do you mean that after that you still got a stacktrace and the script was terminated? If so it must be a different error, you can paste the output

smilebasti commented 2 years ago

Washington (1).pdf

It's somehow the same Error

jacopofar commented 2 years ago

It's easier if you paste the error as text rather than a PDF :)

I see the error is in a different piece of code, the one that is dilating the streets. It's a bit hard to fix because with the reduce and list comprehension I cannot tell where exactly the error is coming from. You can try to wrap the whole else at lines 341-355 in a try..catch to ignore the offending data and see whether the result looks good