Пример #1
0
def intersect_aabb_polygon(aabb: AABB, polygon: Polygon) -> Manifold:
    """ Will use the Separating Axes Test for this. The axes can be one of:
        * 2 normals for aabb edges
        * n normals for polygon edges
    """
    aabb_min, aabb_max = aabb._min, aabb._max
    points = polygon.points
    # Test X axis separation
    p_x = [p.x for p in points]
    if max(p_x) < aabb_min.x or min(p_x) > aabb_max.x:
        return None
    # Test Y axis separation
    p_y = [p.y for p in points]
    if max(p_y) < aabb_min.y or min(p_y) > aabb_max.y:
        return None

    # Next test all polygon's normals
    aabb_a, aabb_b = Vector(aabb_min.x, aabb_max.y), \
        Vector(aabb_max.x, aabb_min.y)
    aabb_points = [aabb_min, aabb_a, aabb_max, aabb_b]

    prev_point = points[-1]
    for point in points:
        normal = (point - prev_point).rotate_deg(90)
        if not _sat_test(points, aabb_points, normal):
            return None
        prev_point = point

    return Manifold()
Пример #2
0
def intersect_aabb_triangle(aabb: AABB, triangle: Triangle) -> Manifold:
    """ Will use the Separating Axes Test for this. The axes can be one of:
        * 2 normals for aabb edges
        * 3 normals for triangle edges
    """
    a, b, c = triangle._a, triangle._b, triangle._c
    aabb_min, aabb_max = aabb._min, aabb._max
    # Test X axis separation
    t_min = min(a.x, b.x, c.x)
    t_max = max(a.x, b.x, c.x)
    if t_max < aabb_min.x or t_min > aabb_max.x:
        return None
    # Test Y axis separation
    t_min = min(a.y, b.y, c.y)
    t_max = max(a.y, b.y, c.y)
    if t_max < aabb_min.y or t_min > aabb_max.y:
        return None

    # Next test 3 triangle normals
    aabb_a, aabb_b = Vector(aabb_min.x, aabb_max.y), \
        Vector(aabb_max.x, aabb_min.y)
    points = [aabb_min, aabb_a, aabb_max, aabb_b]
    # Test AB's normal
    ab_normal = (b - a).rotate_deg(90)
    proj = [ab_normal.dot(p) for p in points]
    if max(proj) < ab_normal.dot(a):
        return None
    # C will always be positive, as triangle is ordered clockwise
    if min(proj) > ab_normal.dot(c):
        return None

    # Test BC's normal
    bc_normal = (c - b).rotate_deg(90)
    proj = [bc_normal.dot(p) for p in points]
    if max(proj) < bc_normal.dot(b):
        return None
    if min(proj) > bc_normal.dot(a):
        return None

    # Test CA's normal
    ca_normal = (a - c).rotate_deg(90)
    proj = [ca_normal.dot(p) for p in points]
    if max(proj) < ca_normal.dot(c):
        return None
    if min(proj) > ca_normal.dot(b):
        return None

    return Manifold()
Пример #3
0
def intersect_circle_circle(a: Circle, b: Circle) -> Manifold:
    d = a._c.distance(b._c)
    r = a._r + b._r
    if d > r:
        return None
    if math.fabs(d) < EPSILON:
        # Place some constant values just to not break, but this manifold's
        # not so useful =(
        return CircleManifold(depth=r, normal=Vector(1, 0))
    return CircleManifold(depth=r - d, normal=(a._c - b._c).unit())
Пример #4
0
def intersect_aabb_circle(aabb: AABB, circle: Circle) -> Manifold:
    c = circle.center
    r = circle.radius
    closest = aabb.closest_point(c)
    d = closest.distance(c)
    if d > r:
        return None
    if math.fabs(d) < EPSILON:
        # Place some constant values just to not break, but this manifold's
        # not so useful =(
        return CircleManifold(depth=r, normal=Vector(1, 0))
    return CircleManifold(depth=r - d, normal=(closest - c).unit())
Пример #5
0
 def __init__(self, *, points=(), depth=0, normal=Vector(1, 0)):
     points = points
     depth = depth
     normal = normal