Quirky behaviour with predicates
See original GitHub issueI have noticed some behaviour which does not seem to match with the Shapely documents. I don’t know if it is a bug, if the documentation is wrong, or I’m misunderstanding something about the package.
I’m going to set up three linestrings:
>>> Square = shapely.geometry.LineString([(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)])
>>> Triangle = shapely.geometry.LineString([(1, 0), (0.5, 1), (1.5, 1), (1, 0)])
>>> TriangleMinusClosure = shapely.geometry.LineString([(1, 0), (0.5, 1), (1.5, 1)])
The triangle intersects the square in the middle of the bottommost segment. The TriangleMinusClosure
is simply
two legs of the triangle without the closing segment; it still intersects the square in the middle of the bottommost segment.
>>> Int1 = Square.intersection(Triangle)
>>> Int2 = Square.intersection(TriangleMinusClosure)
>>> type(Int1)
<class 'shapely.geometry.point.Point'>
>>> type(Int2)
<class 'shapely.geometry.point.Point'>
>>> Int1 == Int2
True
So far, so good. It falls apart when I try to apply .touches()
:
>>> Triangle.touches(Square)
False
>>> TriangleMinusClosure.touches(Square)
True
Both Triangle
and TriangleMinusClosure
have at least one point in common with Square
. To fulfill the other half of the .touches()
requirement, they must not have interior points intersecting with Square
. Since the interior, boundary, and exterior of a given object are mutually exclusive, and the boundary of a linestring is its two endpoints, I would expect both to touch the square–their only interaction with the square is a boundary point.
I see that the closed linestring is reporting an empty boundary, which would imply (?) that the interior is is everything on the triangle, which would explain the False
touch result.
>>> list(Triangle.boundary)
[]
>>> list(TriangleMinusClosure.boundary)
[<shapely.geometry.point.Point object at 0x00000223AC54A880>, <shapely.geometry.point.Point object at 0x00000223AC54A7F0>]
The DE-9IM code does seem to indicate a pointwise intersection of the triangle’s interior with the square’s interior:
>>> Triangle.relate(Square)
'0F1FFF1F2'
>>> TriangleMinusClosure.relate(Square)
'FF10F01F2'
Windows 10 Home 21H1
Shapely version 1.8.1.post1 via pip
Issue Analytics
- State:
- Created a year ago
- Comments:9 (6 by maintainers)
Top GitHub Comments
Thanks! I see, and indeed a Point also doesn’t touch another identical Point (
shapely.Point(1, 1).touches(shapely.Point(1, 1))
gives False), because in those case it are the interiors that intersect.Here’s the definition of Touches from the SFS: It requires that the geometries intersect, but their interiors are disjoint. This is the case in the Polygon/Point case above - the Interior of the Point intersects the Boundary of the Polygon, but not its Interior.