def collision_poly(A, B, directions=None): '''Implementa a colisão entre dois polígonos arbitrários''' # Cria a lista de direções a partir das normais do polígono if directions is None: if A.num_normals + B.num_normals < 9: directions = A.get_normals() + B.get_normals() else: directions = DEFAULT_DIRECTIONS # Testa se há superposição de sombras em todas as direções consideradas # e calcula o menor valor para sombra e a direção normal min_shadow = float('inf') norm = None for u in directions: A_coords = [dot(pt, u) for pt in A.vertices] B_coords = [dot(pt, u) for pt in B.vertices] Amax, Amin = max(A_coords), min(A_coords) Bmax, Bmin = max(B_coords), min(B_coords) minmax, maxmin = min(Amax, Bmax), max(Amin, Bmin) shadow = minmax - maxmin if shadow < 0: return None elif shadow < min_shadow: min_shadow = shadow norm = u # Determina o sentido da normal if dot(A.pos, norm) > dot(B.pos, norm): norm = -norm # Computa o polígono de intersecção e usa o seu centro de massa como ponto # de colisão try: clipped = clip(A.vertices, B.vertices) # não houve superposição (talvez por usar normais aproximadas) except ValueError: return None if area(clipped) == 0: return None col_pt = center_of_mass(clipped) return Collision(A, B, pos=col_pt, normal=norm, delta=min_shadow)
# -*- coding: utf8 -*- ''' Ilustra a interseção entre duas figuras geométricas ''' from FGAme import * from FGAme.mathtools import clip, convex_hull world = World() A = Rectangle(shape=(200, 100), mass='inf') B = RegularPoly(3, 200, pos=(70, 50), color='blue', mass='inf') D = Poly(clip(A.vertices, B.vertices), color='red', mass='inf') C = Circle(5, color='red') vertices = A.vertices + B.vertices + D.vertices conv = convex_hull(vertices) E = Poly(conv, mass='inf', color='green') world.add(E, layer=-1) world.add(A) world.add(B) world.add(C, layer=1) world.add(D) for v in vertices: c = Circle(4, color='blue', pos=v) world.add(c, layer=2) for v in conv: c = Circle(2, color='black', pos=v) world.add(c, layer=2)