Description
I have the problem to decide if a region A is inside a region B. These regions are defined by a list of vertices polyA and polyB:
- If the vertices
polyAare counter-clockwise,- then
Ais the interior region (purple) andareaA > 0(positive polygon)
- then
- Else,
Ais the exterior region (pink) andareaA < 0(negative polygon)
I got in this SO question which is a sub-problem of mine: It solves when areaA > 0 and areaB > 0. Since my problem is more general, the given solution is not enough.
Problem
So far, I verify if all the vertices polyA are inside polyB and if there are intersections, but it gives wrong results when
- The 'minor' polygon is negative and 'major' polygon is positive, with same center
polyA = [(1, 1), (1, 2), (2, 2), (2, 1)] # Clockwise square of side 1
polyB = [(0, 0), (3, 0), (3, 3), (0, 3)] # Counter-clockwise square of side 3
polygon_in_polygon(polyA, polyB) # Expect False
# Gives True since all vertices polyA are inside B
polyAis the inverse ofpolyB
polyA = [(0, 0), (1, 0), (1, 1), (0, 1)] # Counter-clockwise square of side 1
polyB = [(0, 0), (0, 1), (1, 1), (1, 0)] # Clockwise square of side 1
polygon_in_polygon(polyA, polyB) # Expect False
# Gives True, cause all the vertices polyA are in the boundary of B
Can anyone help me finding an algorithm for it?
Current algorithm
So far my algorithm (in python) is
def polygon_and_polygon(polyA: tuple[Point], polyB: tuple[Point]) -> bool:
"""Checks the intersections of polyA and polyB
Returns False if there are any point in each segment of A which is outside B
"""
...
def point_in_polygon(point: Point, polygon: tuple[Point]) -> bool:
"""Checks if given point is inside the region made by polygon"""
area = compute_area(polygon) # area > 0 if polygon is counter-clockwise
# area < 0 else
wind = winding_number(point, polygon)
return wind == 1 if area > 0 else wind == 0
def polygon_in_polygon(polyA: tuple[Point], polyB: tuple[Point]) -> bool:
"""Checks if polyA is completely inside polyB"""
for point in polyA:
if not point_in_polygon(point, polyB):
return False
if polygon_and_polygon(polyA, polyB):
return False
# Insert code here
return True
I expect hints or an algorithm so the function polygon_in_polygon is able to treat the 2 presented cases, or also some problems which may arrive and I don't see them yet.
I thought about creating some random points rand_point which are inside A, and verify if they are inside B. But it's possible to have a bad luck and get (0, 1) in the first example which is indeed inside B, but A is not inside B.
Additional info
Note 1: Consider the coordinates of each point are integers: disregard float precision problem
Note 2: The regions A and B are closed sets. That means, if an edge edgeA touches an edge edgeB, but doesn't cross edgeB, we consider edgeA is inside B. Therefore
polyA = [(0, 0), (1, 0), (0, 1)] # Positive triangle of side 1
polyB = [(0, 0), (1, 0), (1, 1), (0, 1)] # Positive square of side 1
polygon_in_polygon(polyA, polyB) # Expect True
polyA = [(0, 0), (0, 1), (1, 1), (1, 0)] # Negative square of side 1
polyB = [(0, 0), (0, 1), (1, 0)] # Negative triangle of side 1
polygon_in_polygon(polyA, polyB) # Expect True