Find which Shapely Polygon contains an intersection

polygonshapely

Intersection between a line and a Polygon is not inside the Polygon(this). Polygon does not have any interiors. My intention is to find which Polygon contains the intersection, if there are multiple(10) polygons overlapping. I tried projecting on to the polygon, however, it does not work. Is there any way to handle this?

shapely version: 1.8.5.post1 | descartes version: 1.1.0

#!/usr/bin/python3
import numpy as np
import matplotlib.pyplot as plt
from shapely.geometry import Point, Polygon, LineString
from descartes import PolygonPatch

fig, ax = plt.subplots()

polygon = Polygon([[0.07, 0.0], [0.13, 0.0], [0.13, 0.04], [0.07, 0.04]])
patch = PolygonPatch(polygon, edgecolor='blue', facecolor='none', alpha=1.0)
ax.add_patch(patch)

line = LineString([(0.10,0.03), (0.14,0.03)])
ax.plot(*line.xy, color='black')

print("Intersection points <before> projection, Polygon.contains?")
interesection_points = np.array(polygon.boundary.intersection(line))
ax.plot(interesection_points[0], interesection_points[1], color='blue', marker='h', linestyle='', markersize=15, fillstyle='none', label='intersection before projection')
print (interesection_points, "contains:", polygon.contains(Point(interesection_points)))

print("Intersection points <after> projection, Polygon.contains?")
interesection_points_after_projection_case = polygon.boundary.intersection(line)
project_points = []
if not polygon.contains(interesection_points_after_projection_case):
    nearest_point = np.array(polygon.boundary.interpolate(polygon.boundary.project(interesection_points_after_projection_case)))
    project_points.append(nearest_point)
    print(nearest_point, "contains:", polygon.contains(Point(nearest_point)))

project_points = np.asarray(project_points)
ax.plot(project_points[:,0], project_points[:,1], color='green', marker='^', linestyle='', markersize=15, fillstyle='none', label='intersection after projection')

ax.legend()
plt.show()
Intersection points <before> projection, Polygon.contains?
[0.13 0.03] contains: False

Intersection points <after> projection, Polygon.contains?
[0.13 0.03] contains: False

enter image description here

Best Answer

The definition of the "contains" predicate is as follows (source):

Returns True if no points of other lie in the exterior of the object and at least one point of the interior of other lies in the interior of object.

At least one point needs to be in the interior of the other is the issue here. The point you are comparing is on the boundary of the polygon, not in the interior of the polygon.

So, for this example if the point being on the boundary is already OK you could use e.g.

  • intersects: point is in the interior or on the boundary of the polygon
  • touches: point is on the boundary of the polygon