Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Covers predicate incorrect for Line/Point due to geometric robustness #968

Open
cuteDen-ECNU opened this issue Oct 3, 2023 · 11 comments
Open
Labels

Comments

@cuteDen-ECNU
Copy link

Consider the following code:

from shapely.geometry import LineString, Point

a = LineString([(1, 0), (0, 2)])

b = Point(0.9, 0.2)

covers = a.covers(b)
# expected - {True}; actual - {False}

a1 = LineString([(10, 0), (0, 20)])

b1 = Point(9, 2)

covers = a1.covers(b1)
# True

Line a should cover point b because the distance between point b and line a is 0.
But Shapely doesn't consider line a covers point b.
The issue cannot be reproduced with integers only, indicating a potential floating-point issue. After all coordinate points are magnified ten times, the results are in line with expectations.

@cuteDen-ECNU cuteDen-ECNU reopened this Oct 3, 2023
@dr-jts dr-jts added the Bug label Oct 3, 2023
@dr-jts dr-jts reopened this Oct 3, 2023
@dr-jts
Copy link
Contributor

dr-jts commented Oct 3, 2023

This is indeed a bug. Ironically it's due to the high-precision evaluation of the line-point orientation predicate.

Not sure what a suitable fix is at the moment. Likely it will involve some sort of precision rounding, but that needs to be done carefully to ensure there are no other impacts.

See also https://trac.osgeo.org/postgis/ticket/5563

@dr-jts dr-jts changed the title Potential bug in function covers Covers predicate fails on obviously correct simple case Oct 3, 2023
@cuteDen-ECNU
Copy link
Author

cuteDen-ECNU commented Oct 4, 2023

Thank you for your prompt response. It's greatly appreciated.
Could you help me see whether this potential bug has the same core reason as it?
Once again, thank you for your expertise and assistance in addressing this bug. :·)

@dr-jts
Copy link
Contributor

dr-jts commented Oct 5, 2023

Could you help me see whether this potential bug has the same core reason as it?

The PostGIS ST_3DIntersects issue has the same basic cause: the inaccuracy of finite-precision floating point arithmetic. But it's much less surprising in that case, since there's a lot of arithmetic being carried out, so the likelihood of 2 lines NOT intersecting in 3D is very high.

The bottom line is that you can't rely on topological relationships being preserved through floating-point operations. This is the essence of the well-known issue of geometrical robustness failures. The solution is usually either to use exact arithmetic (often impractical) or use tolerance values (not a panacea, but very often works).

@cuteDen-ECNU
Copy link
Author

Thank you for your prompt response.
The explanation of geometrical robustness failures is very clear.
The 'tolerance values' recommendation is very inspiring to me. 😊

@dr-jts
Copy link
Contributor

dr-jts commented Oct 6, 2023

The 'tolerance values' recommendation is very inspiring to me. 😊

I'm working on a new implementation of spatial predicate evaluation that should allow for a tolerance value. So stay tuned!

@cuteDen-ECNU
Copy link
Author

The tolerance value for predicate evaluation sounds good!
We are excited about the new ideas.

@dr-jts dr-jts changed the title Covers predicate fails on obviously correct simple case Covers predicate fails for Line/Point due to geometric robustness Nov 8, 2023
@strk
Copy link
Member

strk commented Mar 25, 2024

Could this be the same problem reported in https://lists.osgeo.org/pipermail/geos-devel/2024-March/011012.html ?

@dr-jts
Copy link
Contributor

dr-jts commented Apr 6, 2024

Could this be the same problem reported in https://lists.osgeo.org/pipermail/geos-devel/2024-March/011012.html ?

Yes, it's the same issue. In this case, the intersection of the two lines is computed as being equal to the endpoint of one of the lines, due to roundoff error. So the relate result for two lines is inconsistent with the result for the boundary points. Unfortunately the new relate algorithm doesn't fix this.

@dr-jts dr-jts changed the title Covers predicate fails for Line/Point due to geometric robustness Covers predicate incorrect for Line/Point due to geometric robustness Apr 18, 2024
@Scheggetta
Copy link

This exact thing is happening also with GEOS C++ API v3.12.1 using within instead of covers, but I guess it is related to the same issue.

Is there currently any fast and easy workaround? I thought about these two solutions:

  • isWithinDistance method of Geometry class
  • using within on a buffered LineString

I think the first workaround is more efficient, but could you give me your opinion?

@dr-jts
Copy link
Contributor

dr-jts commented May 23, 2024

Is there currently any fast and easy workaround? I thought about these two solutions:

  • isWithinDistance method of Geometry class
  • using within on a buffered LineString

I think the first workaround is more efficient, but could you give me your opinion?

Yes, using isWithinDistance is more efficient when it can be used instead of buffer for proximity queries.

That's a good work-around for this issue. Perhaps in the future RelateNG will support a distance tolerance, which will have the same effect.

@dr-jts
Copy link
Contributor

dr-jts commented May 23, 2024

One possible for for this is to use FP computation in the Orientation predicate, and use the result if the point and line are collinear; otherwise use the DD computation for more accuracy. This changes a whole bunch of unit test results, however (which may not indicate a problem, just different results).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants