Check if (pos/neg) polygon is inside another (pos/neg) polygon

62 Views Asked by At

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 polyA are counter-clockwise,
    • then A is the interior region (purple) and areaA > 0 (positive polygon)
  • Else,
    • A is the exterior region (pink) and areaA < 0 (negative polygon)

Example of internal and external regions

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

  1. 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
  1. polyA is the inverse of polyB
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
0

There are 0 best solutions below