def asvector(v): '''Retorna o objeto como uma instância da classe Vetor''' if isinstance(v, Vec2): return v else: return Vec2.from_seq(v)
def __init__(self, data): '''Implementa um array de vetores bidimensionais. As operações matemáticas podem ser aplicadas diretamente ao array Exemplo ------- Criamos um array inicializando com uma lista de vetores ou uma lista de duplas >>> a = VecArray([(0, 0), (1, 0), (0, 1)]); a VecArray([(0, 0), (1, 0), (0, 1)]) Sob muitos aspectos, um VecArray funciona como uma lista de vetores >>> a[0], a[1] (Vec2(0, 0), Vec2(1, 0)) As operações matemáticas ocorrem termo a termo >>> a + (1, 1) VecArray([(1, 1), (2, 1), (1, 2)]) Já as funções de vetores são propagadas para cada elemento e retornam um Array numérico ou um VecArray >>> a.norm() Array([0, 1, 1]) ''' self._data = list(Vec2(x) for x in data)
def intercept_point(): '''Retorna o ponto de intercepção entre os segmentos formados por r1-r0 e v1-v0''' A = r0.x * r1.y - r0.y * r1.x B = v0.x * v1.y - v0.y * v1.x C = 1.0 / (T.x * T_.y - T.y * T_.x) return Vec2((-A * T_.x + B * T.x) * C, (-A * T_.y + B * T.y) * C)
def rotate(self, theta, axis=None): '''Retorna um vetor rotacionado por um ângulo theta''' axis = Vec2(axis) R = RotMat2(theta) if axis is None: return VecArray([R * u for u in self._data]) else: v = axis return VecArray([v + R * (u - v) for u in self._data])
def directions(self, n): '''Retorna a lista de direções exaustivas para o teste do SAT associadas ao objeto.''' out = [] p0 = self._data[-1] for p in self._data: x, y = p - p0 p0 = p out.append(Vec2(-y, x)) return out
def normals_aabb_circle(A, B): # Encontra o vértice mais próximo do centro D = float('inf') pt = Vec2(0, 0) for v in A.vertices: delta = B.pos - v dnew = delta.norm() if dnew < D: D = dnew pt = delta return [pt.normalize(), e1, e2]
def __init__(self, N, length, theta=None, pos=None): alpha = pi / N R = RotMat2(2 * alpha) p = Vec2(length / (2 * sin(alpha)), 0) vertices = [] for _ in range(N): vertices.append(p) p = R * p super(RegularPoly, self).__init__(vertices) # Altera posição e ângulo if pos is not None: self += pos if theta is not None: self.irotate(theta)
def aabb_pshape(xmin=None, xmax=None, ymin=None, ymax=None, bbox=None, rect=None, shape=None, pos=None): ''' Retorna uma tupla de (centro, shape) a partir dos parâmetros fornecidos. ''' x, xmax, y, ymax = aabb_bbox(xmin, xmax, ymin, ymax, bbox, rect, shape, pos) center = Vec2((x + xmax) / 2.0, (y + ymax) / 2.0) shape = (xmax - x, ymax - y) return center, shape
def convex_hull(points): '''Retorna a envoltória convexa do conjunto de pontos fornecidos. Implementa o algorítimo da cadeia monótona de Andrew, O(n log n) Exemplo ------- >>> convex_hull([(0, 0), (1, 1), (1, 0), (0, 1), (0.5, 0.5)]) [Vec2(0, 0), Vec2(1, 0), Vec2(1, 1), Vec2(0, 1)] ''' # Ordena os pontos pela coordenada x, depois pela coordenada y points = sorted(set(map(tuple, points))) points = [Vec2(*pt) for pt in points] if len(points) <= 1: return points # Cria a lista L: lista com os vértices da parte inferior da envoltória # # Algoritimo: acrescenta os pontos de points em L e a cada novo ponto # remove o último caso não faça uma volta na direção anti-horária L = [] for p in points: while len(L) >= 2 and (L[-1] - L[-2]).cross(p - L[-2]) <= 0: L.pop() L.append(p) # Cria a lista U: vértices da parte superior # Semelhante à anterior, mas itera sobre os pontos na ordem inversa U = [] for p in reversed(points): while len(U) >= 2 and (U[-1] - U[-2]).cross(p - U[-2]) <= 0: U.pop() U.append(p) # Remove o último ponto de cada lista, pois ele se repete na outra return L[:-1] + U[:-1]
def center_of_mass(L): '''Calcula o vetor centro de massa de um polígono definido por uma lista de pontos. >>> pontos = [(0, 0), (1, 0), (1, 1), (0, 1)] >>> center_of_mass(pontos) Vec2(0.5, 0.5) ''' W = _w_list(L) A = sum(W) N = len(L) x_cm = 0 y_cm = 0 for i in range(N): x1, y1 = L[(i + 1) % N] x0, y0 = L[i] wi = W[i] x_cm += (x1 + x0) * wi / 3.0 y_cm += (y1 + y0) * wi / 3.0 x_cm /= A y_cm /= A return Vec2(x_cm, y_cm)
# -*- coding: utf8 -*- import cython as C from mathtools import Vec2, dot from mathtools.shapes import Circle from mathtools.util import pyinject if not C.compiled: import mathtools.mathfuncs as m __all__ = [ 'AABB', 'aabb_rect', 'aabb_bbox', 'aabb_pshape', 'aabb_shape', 'aabb_center' ] dir_x = Vec2(1, 0) dir_y = Vec2(0, 1) class AABB(object): '''Representa uma caixa de contorno retangular alinhada aos eixos. Atributos --------- xmin, xmax, ymin, ymax Limites da AABB bbox Tupla com (xmin, xmax, ymin, ymax) shape Tupla com (largura, altura) pos
def __init__(self, point1, point2): self._point1 = Vec2(point1) self._point2 = Vec2(point2)
def __init__(self, radius, pos=(0, 0)): self.radius = radius self.pos = Vec2(*pos)
def vertices(self): return (Vec2(self.xmin, self.ymin), Vec2(self.xmax, self.ymin), Vec2(self.xmax, self.ymax), Vec2(self.xmin, self.ymax))
def __iter__(self): return iter(Vec2(u) for u in self._data)
def pos_nw(self): return Vec2(self.xmin, self.ymax)
def pos_ne(self): return Vec2(self.xmax, self.ymax)
def pos_sw(self): return Vec2(self.xmin, self.ymin)
def pos_se(self): return Vec2(self.xmax, self.ymin)
def __getitem__(self, i): '''x.__getitem__(i) <==> x[i]''' return Vec2(self._data[i])
def insert(self, idx, value): self._data.insert(idx, Vec2(value))
def __add__(self, other): '''x.__add__(y) <==> x + y''' other = Vec2(other) return self._new(u + other for u in self._data)
def __rsub__(self, other): '''x.__rsub__(y) <==> y - x''' other = Vec2(other) return self._new(other - u for u in self._data)
def __sub__(self, other): '''x.__sub__(y) <==> x - y''' other = Vec2(other) return self._new(u - other for u in self._data)
def pos(self): x = (self.xmin + self.xmax) / 2 y = (self.ymin + self.ymax) / 2 return Vec2(x, y)
''' Implementa o separating axis theorem (sat) para detecção de colisão entre as formas de colisão básicas. ''' from FGAme.util.multidispatch import multifunction from mathtools import Vec2 from mathtools.shapes import Circle, AABB e1 = Vec2(1, 0) e2 = Vec2(0, 1) ############################################################################### # Cálculo de sombras ############################################################################### @multifunction(None, None) def shadow(A, normal): return A.shadow(normal) @multifunction(AABB, None) def shadow_aabb(A, normal): if normal is e1: return A.xmin, A.xmax elif normal is e2: return A.ymin, A.ymax else: return A.shadow(normal)