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()
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()
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())
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())
def __init__(self, *, points=(), depth=0, normal=Vector(1, 0)): points = points depth = depth normal = normal