geopandas: BUG: `TopologyException: found non-noded intersection` error from overlay
- I have searched the [geopandas] tag on StackOverflow and GIS StackExchange for similar questions.
This question is the same, but hasn’t been answered
- I have asked my usage related question on StackOverflow or GIS StackExhange.
No because already asked and unanswered.
Does anyone have experience fixing TopologyException: found non-noded intersection
error in an overlay? My understanding is that it comes from floating point errors and nearly parallel lines, but I can’t find a way to play with floating point precision tolerances in geopandas.
The usual .buffer(0)
trick doesn’t seem to be helping either.
Full traceback if helpful:
TopologyException: found non-noded intersection between LINESTRING (-193712 361959, -193779 362021) and LINESTRING (-193712 361959, -193712 361959) at -193712.19705318063 361958.71668422205
---------------------------------------------------------------------------
TopologicalError Traceback (most recent call last)
<ipython-input-7-84d76b98e9c5> in <module>
----> 1 county_overlay = gp.overlay(county_rp, dist_rp, how="identity")
~/miniconda3/lib/python3.7/site-packages/geopandas/tools/overlay.py in overlay(df1, df2, how, make_valid, keep_geom_type)
217 result = _overlay_union(df1, df2)
218 elif how == "identity":
--> 219 dfunion = _overlay_union(df1, df2)
220 result = dfunion[dfunion["__idx1"].notnull()].copy()
221
~/miniconda3/lib/python3.7/site-packages/geopandas/tools/overlay.py in _overlay_union(df1, df2)
129 """
130 dfinter = _overlay_intersection(df1, df2)
--> 131 dfsym = _overlay_symmetric_diff(df1, df2)
132 dfunion = pd.concat([dfinter, dfsym], ignore_index=True, sort=False)
133 # keep geometry column last
~/miniconda3/lib/python3.7/site-packages/geopandas/tools/overlay.py in _overlay_symmetric_diff(df1, df2)
99 Overlay Symmetric Difference operation used in overlay function
100 """
--> 101 dfdiff1 = _overlay_difference(df1, df2)
102 dfdiff2 = _overlay_difference(df2, df1)
103 dfdiff1["__idx1"] = range(len(dfdiff1))
~/miniconda3/lib/python3.7/site-packages/geopandas/tools/overlay.py in _overlay_difference(df1, df2)
83 for geom, neighbours in zip(df1.geometry, sidx):
84 new = reduce(
---> 85 lambda x, y: x.difference(y), [geom] + list(df2.geometry.iloc[neighbours])
86 )
87 new_g.append(new)
~/miniconda3/lib/python3.7/site-packages/geopandas/tools/overlay.py in <lambda>(x, y)
83 for geom, neighbours in zip(df1.geometry, sidx):
84 new = reduce(
---> 85 lambda x, y: x.difference(y), [geom] + list(df2.geometry.iloc[neighbours])
86 )
87 new_g.append(new)
~/miniconda3/lib/python3.7/site-packages/shapely/geometry/base.py in difference(self, other)
670 def difference(self, other):
671 """Returns the difference of the geometries"""
--> 672 return geom_factory(self.impl['difference'](self, other))
673
674 def intersection(self, other):
~/miniconda3/lib/python3.7/site-packages/shapely/topology.py in __call__(self, this, other, *args)
68 err = TopologicalError(
69 "This operation could not be performed. Reason: unknown")
---> 70 self._check_topology(err, this, other)
71 return product
72
~/miniconda3/lib/python3.7/site-packages/shapely/topology.py in _check_topology(self, err, *geoms)
37 "Likely cause is invalidity of the geometry %s" % (
38 self.fn.__name__, repr(geom)))
---> 39 raise err
40
41
TopologicalError: This operation could not be performed. Reason: unknown
About this issue
- Original URL
- State: open
- Created 4 years ago
- Comments: 16 (13 by maintainers)
It looks this can be corrected by reducing the precision of the geometries.
We currently have a PR in pygeos to set precision: https://github.com/pygeos/pygeos/pull/257 If possible, you may be able to check out that branch, build pygeos, and use the fix below.
It looks like this is an open issue to resolve in shapely: https://github.com/Toblerity/Shapely/issues/110
Overlap appears to function correctly after setting the precision.
It may also be possible to round the coordinates in the geometries using the
[apply](https://pygeos.readthedocs.io/en/latest/coordinates.html#pygeos.coordinates.apply)
function in pygeos: (untested!)The solution given by @brendan-ward did not work for me, but the following seemed to work:
Cheers!
At one point during the operation, shapely/pygeos returns invalid polygon. The next step after that fails. Sometimes it helps to round coordinates but not in this case (code for that below for someone else who may find this).
I am not sure how to fix that to be honest apart from adding intentional validity check to overlay and doing
buffer(0)
inside overlay. What are you trying to do? Maybe we can come up with another way.The code for rounding: