Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ValueError: No Shapely geometry can be created from null value

Tags:

python

shapely

I get this error while using cascaded_union (I have also tried unary_union which produces the same error):

ValueError: No Shapely geometry can be created from null value

I have validated that my polygons are valid. Initially polyB isn't valid, but it is converted to a valid polygon using buffer(0).

Any idea on what I am doing wrong? Here's my code:

from shapely.geometry import Polygon
from shapely.ops import cascaded_union

def combineBorders(a, b):
    polyA = Polygon(a)
    polyB = Polygon(b)
    pols = [polyA, polyB]

    for p in pols:
        if p.is_valid == False:
            p = p.buffer(0)
        print(p.is_valid)
True
True
    newShape = cascaded_union(pols) # THIS IS WHERE THE ERROR KEEPS SHOWING UP
    return newShape

Here is a link to the values for polyA, polyB and pols (after they are confirmed to be valid). I have the following versions installed on my Ubuntu 14.04 server:

  • python-shapely 1.3.0
  • libgeos 3.4.2
  • python 2.7
like image 801
Mark Hebert Avatar asked Dec 24 '22 17:12

Mark Hebert


2 Answers

The problem in the question is that the buffered polygon was not put back in the list pols, so the invalid geometry was passed to cascaded_union

You could make this much simpler and versatile with the following, which can take any number of polygon geometries (not just two).

def combineBorders(*geoms):
    return cascaded_union([
        geom if geom.is_valid else geom.buffer(0) for geom in geoms
    ])

polyC = combineBorders(polyA, polyB)
like image 119
Mike T Avatar answered Jan 21 '23 17:01

Mike T


Found out the problem. Not sure why this matters (I've seen examples showing it both ways), but it works after putting the polygons directly into cascaded_union like so: newShape = cascaded_union([polyA, polyB]). Here is the fully revised code that works:

from shapely.geometry import Polygon
from shapely.ops import cascaded_union

def combineBorders(a, b):
    polyA = Polygon(a)
    polyB = Polygon(b)
    polyBufA = polyA.buffer(0)
    polyBufB = polyB.buffer(0)
    newShape = cascaded_union([polyBufA, polyBufB])
    return newShape

This also works with unary_union

like image 42
Mark Hebert Avatar answered Jan 21 '23 18:01

Mark Hebert