示例#1
0
    def __init__(self,
                 vertices,
                 pos=None, vel=(0, 0), theta=0.0, omega=0.0,
                 mass=None, density=None, inertia=None, **kwargs):

        if isinstance(vertices, int):
            raise ValueError('must pass a list of vertices. '
                             'Use RegularPoly to define a polygon by the '
                             'number of vertices')
        vertices = [Vec2(*pt) for pt in vertices]
        pos_cm = center_of_mass(vertices)
        vertices = [v - pos_cm for v in vertices]
        self._vertices = vertices

        # Cache vertices
        self._cache_theta = None
        self._cache_rvertices_last = None
        self._cache_rbbox_last = None
        super(Poly, self).__init__(pos_cm, vel, theta, omega,
                                   mass=mass, density=density, inertia=inertia,
                                   cbb_radius=max(v.norm() for v in vertices),
                                   **kwargs)

        self.num_sides = len(vertices)
        self._normals_idxs = self.get_li_indexes()
        self.num_normals = len(self._normals_idxs or self.vertices)

        # Slightly faster when all normals are linear dependent: if
        # self._normals_idx = None, all normals are recomputed at each frame.
        if self.num_normals == self.num_sides:
            self._normals_idxs = None

        # Move to specified position, if pos is given.
        if pos is not None:
            self._pos = Vec2(*pos)
示例#2
0
    def __init__(self,
                 vertices,
                 pos=None,
                 vel=(0, 0),
                 theta=0.0,
                 omega=0.0,
                 mass=None,
                 density=None,
                 inertia=None,
                 **kwargs):

        if isinstance(vertices, int):
            raise ValueError('must pass a list of vertices. '
                             'Use RegularPoly to define a polygon by the '
                             'number of vertices')
        vertices = [Vec2(*pt) for pt in vertices]
        pos_cm = center_of_mass(vertices)
        vertices = [v - pos_cm for v in vertices]
        self._vertices = vertices

        # Cache vertices
        self._cache_theta = None
        self._cache_rvertices_last = None
        self._cache_rbbox_last = None
        super(Poly, self).__init__(pos_cm,
                                   vel,
                                   theta,
                                   omega,
                                   mass=mass,
                                   density=density,
                                   inertia=inertia,
                                   cbb_radius=max(v.norm() for v in vertices),
                                   **kwargs)

        self.num_sides = len(vertices)
        self._normals_idxs = self.get_li_indexes()
        self.num_normals = len(self._normals_idxs or self.vertices)

        # Slightly faster when all normals are linear dependent: if
        # self._normals_idx = None, all normals are recomputed at each frame.
        if self.num_normals == self.num_sides:
            self._normals_idxs = None

        # Move to specified position, if pos is given.
        if pos is not None:
            self._pos = Vec2(*pos)
示例#3
0
def collision_poly(A, B, directions=None, collision_class=Collision):
    """
    Collision detection using SAT.
    """

    # List of directions from normals
    if directions is None:
        if A.num_normals + B.num_normals < 9:
            directions = A.get_normals() + B.get_normals()
        else:
            directions = DEFAULT_DIRECTIONS

    # Test overlap in all considered directions and picks the smaller
    # penetration
    min_overlap = 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)
        overlap = minmax - maxmin
        if overlap < 0:
            return None
        elif overlap < min_overlap:
            min_overlap = overlap
            norm = u

    # Finds the correct direction for the normal
    if dot(A.pos, norm) > dot(B.pos, norm):
        norm = -norm

    # Computes the clipped polygon: collision happens at its center point.
    try:
        clipped = clip(A.vertices, B.vertices)
        col_pt = center_of_mass(clipped)
    except ValueError:
        return None

    if area(clipped) == 0:
        return None

    return collision_class(A, B, pos=col_pt, normal=norm, delta=min_overlap)
示例#4
0
def collision_poly(A, B, directions=None, collision_class=Collision):
    """
    Collision detection using SAT.
    """

    # List of directions from normals
    if directions is None:
        if A.num_normals + B.num_normals < 9:
            directions = A.get_normals() + B.get_normals()
        else:
            directions = DEFAULT_DIRECTIONS

    # Test overlap in all considered directions and picks the smaller
    # penetration
    min_overlap = 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)
        overlap = minmax - maxmin
        if overlap < 0:
            return None
        elif overlap < min_overlap:
            min_overlap = overlap
            norm = u

    # Finds the correct direction for the normal
    if dot(A.pos, norm) > dot(B.pos, norm):
        norm = -norm

    # Computes the clipped polygon: collision happens at its center point.
    try:
        clipped = clip(A.vertices, B.vertices)
        col_pt = center_of_mass(clipped)
    except ValueError:
        return None

    if area(clipped) == 0:
        return None

    return collision_class(A, B, pos=col_pt, normal=norm, delta=min_overlap)
示例#5
0
 def pos(self):
     return center_of_mass(self)
示例#6
0
def test_poly_center_of_mass():
    tri = Poly((0, 0), (3, 0), (0, 3))
    assert tri.pos == center_of_mass([(0, 0), (3, 0), (0, 3)])
    assert tri.pos == (1, 1)
示例#7
0
def test_poly_center_of_mass():
    tri = Poly((0, 0), (3, 0), (0, 3))
    assert tri.pos == center_of_mass([(0, 0), (3, 0), (0, 3)])
    assert tri.pos == (1, 1)