def radial_slice(points, center, start_angle, end_angle):
    """
    >>> points = circle((0, 0), 2.3)
    >>> print(format_points(offset_points(points)))
     ###
    #####
    #####
    #####
     ###
    >>> points = radial_slice(points, (0, 0), -90, 45)
    >>> print(format_points(offset_points(points)))
     ##
    ###
    ###
    ##
    >>> points = radial_slice(points, (0, 0), 0, 30)
    >>> print(format_points(offset_points(points)))
      #
    ###
    """
    start_point = (1, 0)
    start_point = vec.rotate(start_point, math.radians(start_angle))
    start_point = vec.add(center, start_point)
    start_line = (start_point, center) # Pointing inward, so partition goes counter-clockwise.

    end_point = (1, 0)
    end_point = vec.rotate(end_point, math.radians(end_angle))
    end_point = vec.add(center, end_point)
    end_line = (center, end_point) # Pointing outward, so partition goes clockwise.

    return (
        set(partition(points, *start_line)) &
        set(partition(points, *end_line))
    )
示例#2
0
    def arc_to(self, endpoint, center=None, start_slant=None, end_slant=None):
        """
        Draw an arc ending at the specified point, starting tangent to the
        current position and heading.
        """
        if points_equal(self._position, endpoint):
            return
        # Handle unspecified center.
        # We need to find the center of the arc, so we can find its radius. The
        # center of this arc is uniquely defined by the intersection of two
        # lines:
        # 1. The first line is perpendicular to the pen heading, passing
        #    through the pen position.
        # 2. The second line is the perpendicular bisector of the pen position
        #    and the target arc end point.
        v_pen = self._vector()
        v_perp = vec.perp(self._vector())
        v_chord = vec.vfrom(self._position, endpoint)
        if center is None:
            midpoint = vec.div(vec.add(self._position, endpoint), 2)
            v_bisector = vec.perp(v_chord)
            center = intersect_lines(
                self._position,
                vec.add(self._position, v_perp),
                midpoint,
                vec.add(midpoint, v_bisector),
            )

        # Determine true start heading. This may not be the same as the
        # original pen heading in some circumstances.
        assert not points_equal(center, self._position)
        v_radius_start = vec.vfrom(center, self._position)
        v_radius_perp = vec.perp(v_radius_start)
        if vec.dot(v_radius_perp, v_pen) < 0:
            v_radius_perp = vec.neg(v_radius_perp)
        start_heading = math.degrees(vec.heading(v_radius_perp))
        self.turn_to(start_heading)
        # Refresh v_pen and v_perp based on the new start heading.
        v_pen = self._vector()
        v_perp = vec.perp(self._vector())

        # Calculate the arc angle.
        # The arc angle is double the angle between the pen vector and the
        # chord vector. Arcing to the left is a positive angle, and arcing to
        # the right is a negative angle.
        arc_angle = 2 * math.degrees(vec.angle(v_pen, v_chord))
        radius = vec.mag(v_radius_start)
        # Check which side of v_pen the goes toward.
        if vec.dot(v_chord, v_perp) < 0:
            arc_angle = -arc_angle
            radius = -radius

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant,
            end_slant,
        )
示例#3
0
def update_snowballs(lobby):
    changed_healths = []
    destroyed_snowballs = []
    player_hit = False
    ground_hit = False
    for id, snowball in lobby.snowballs.items():
        new_vel = vec.add(snowball.velocity, (0, GRAVITY_ACCELERATION))

        new_pos = vec.add(snowball.position, new_vel)
        new_x, new_y = new_pos
        hit_object, can_move = level.can_move_to(SNOWBALL_SIZE, SNOWBALL_SIZE,
                                                 round(new_x), round(new_y),
                                                 all_players(lobby.clients))
        if can_move:
            snowball.velocity = new_vel
            snowball.position = new_pos
        else:
            destroyed_snowballs.append(id)
            if isinstance(hit_object, player.Player):
                player_hit = True
                speed = vec.length(snowball.velocity)
                hit_object.health = max(
                    0, hit_object.health - speed * SNOWBALL_DAMAGE)
                changed_healths.append(hit_object)
            else:
                ground_hit = True
    lobby.snowballs = {
        id: v
        for id, v in lobby.snowballs.items() if id not in destroyed_snowballs
    }
    return changed_healths, destroyed_snowballs, player_hit, ground_hit
示例#4
0
    def arc_to(self, endpoint, center=None, start_slant=None, end_slant=None):
        """
        Draw an arc ending at the specified point, starting tangent to the
        current position and heading.
        """
        if points_equal(self._position, endpoint):
            return
        # Handle unspecified center.
        # We need to find the center of the arc, so we can find its radius. The
        # center of this arc is uniquely defined by the intersection of two
        # lines:
        # 1. The first line is perpendicular to the pen heading, passing
        #    through the pen position.
        # 2. The second line is the perpendicular bisector of the pen position
        #    and the target arc end point.
        v_pen = self._vector()
        v_perp = vec.perp(self._vector())
        v_chord = vec.vfrom(self._position, endpoint)
        if center is None:
            midpoint = vec.div(vec.add(self._position, endpoint), 2)
            v_bisector = vec.perp(v_chord)
            center = intersect_lines(
                self._position,
                vec.add(self._position, v_perp),
                midpoint,
                vec.add(midpoint, v_bisector),
            )

        # Determine true start heading. This may not be the same as the
        # original pen heading in some circumstances.
        assert not points_equal(center, self._position)
        v_radius_start = vec.vfrom(center, self._position)
        v_radius_perp = vec.perp(v_radius_start)
        if vec.dot(v_radius_perp, v_pen) < 0:
            v_radius_perp = vec.neg(v_radius_perp)
        start_heading = math.degrees(vec.heading(v_radius_perp))
        self.turn_to(start_heading)
        # Refresh v_pen and v_perp based on the new start heading.
        v_pen = self._vector()
        v_perp = vec.perp(self._vector())

        # Calculate the arc angle.
        # The arc angle is double the angle between the pen vector and the
        # chord vector. Arcing to the left is a positive angle, and arcing to
        # the right is a negative angle.
        arc_angle = 2 * math.degrees(vec.angle(v_pen, v_chord))
        radius = vec.mag(v_radius_start)
        # Check which side of v_pen the goes toward.
        if vec.dot(v_chord, v_perp) < 0:
            arc_angle = -arc_angle
            radius = -radius

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant,
            end_slant,
        )
    def update(self, elapsed_seconds, force=None, extra_drag=0):
        # Apply force if necessary.
        if force is not None:
            self.velocity = vec.add(
                self.velocity,
                vec.mul(force, (elapsed_seconds / self.mass)),
            )

        # Apply drag.
        # Decrease the magnitude of the velocity vector by
        # the amount of drag.
        drag = (self.drag_rate + extra_drag) * elapsed_seconds
        if drag > self.speed:
            self.velocity = (0, 0)
        elif drag != 0 and self.velocity != (0, 0):
            drag_vector = vec.norm(self.velocity, -drag)
            self.velocity = vec.add(
                self.velocity,
                drag_vector,
            )

        # Limit to maximum speed.
        if self.speed > c.max_speed:
            self.velocity = vec.norm(self.velocity, c.max_speed)

        # Update position based on velocity.
        self.last_pos = self.pos
        self.pos = vec.add(
            self.pos,
            vec.mul(self.velocity, elapsed_seconds),
        )
def collide_particles(p1, p2):
    restitution = p1.restitution * p2.restitution

    # Don't collide immovable particles.
    if p1.immovable and p2.immovable:
        return

    # Test if p1 and p2 are actually intersecting.
    if not intersect(p1, p2):
        return

    # If one particle is immovable, make it the first one.
    if not p1.immovable and p2.immovable:
        p1, p2 = p2, p1

    # Vector spanning between the centers, normal to contact surface.
    v_span = vec.vfrom(p1.pos, p2.pos)

    # Split into normal and tangential components and calculate
    # initial velocities.
    normal = vec.norm(v_span)
    tangent = vec.perp(normal)
    v1_tangent = vec.proj(p1.velocity, tangent)
    v2_tangent = vec.proj(p2.velocity, tangent)
    p1_initial = vec.dot(p1.velocity, normal)
    p2_initial = vec.dot(p2.velocity, normal)

    # Don't collide if particles were actually moving away from each other, so
    # they don't get stuck inside one another.
    if p1_initial - p2_initial < 0:
        return

    # Handle immovable particles specially.
    if p1.immovable:
        p2_final = -p2_initial * restitution
        p2.velocity = vec.add(
            v2_tangent,
            vec.mul(normal, p2_final),
        )
        return

    # Elastic collision equations along normal component.
    m1, m2 = p1.mass, p2.mass
    m1plusm2 = (m1 + m2) / restitution
    p1_final = (p1_initial * (m1 - m2) / m1plusm2 + p2_initial *
                (2 * m2) / m1plusm2)
    p2_final = (p2_initial * (m2 - m1) / m1plusm2 + p1_initial *
                (2 * m1) / m1plusm2)

    # Tangential component is unchanged, recombine.
    p1.velocity = vec.add(
        v1_tangent,
        vec.mul(normal, p1_final),
    )
    p2.velocity = vec.add(
        v2_tangent,
        vec.mul(normal, p2_final),
    )
示例#7
0
    def update_physics(self, elapsed_seconds):
        # Handle turning.
        if self.turning_time >= c.player_start_turn_time:
            turn_rate = c.player_turn_rate_radians
        else:
            turn_rate = interpolate(
                c.player_start_turn_rate_radians,
                c.player_turn_rate_radians,
                self.turning_time / c.player_start_turn_time,
            )

        self.heading += self.turn_direction * turn_rate * elapsed_seconds
        self.direction = heading_to_vector(self.heading)

        # Handle thrust.
        force = (0, 0)
        if self.do_thrust:
            # We vary the thrust depending on how fast the player is
            # already moving.
            thrust = curve_value(self.speed, c.player_thrust_curve)
            force = vec.add(
                force,
                vec.mul(self.direction, thrust),
            )

        # Handle braking.
        extra_drag = 0
        if self.do_brake:
            extra_drag = c.player_braking_drag

        # Handle boost.
        if self.boost_time_remaining > 0.0:
            force = vec.add(
                force,
                vec.mul(self.direction, c.player_boost_strength),
            )
        # Get heavy while boosting.
        if self.boost_heavy_time_remaining > 0.0:
            self.mass = self.original_mass * c.player_boost_heavy_multiplier
            self.restitution = (
                self.original_restitution *
                c.player_boost_restitution_multiplier
            )
        else:
            self.mass = self.original_mass
            self.restitution = self.original_restitution

        # Handle rudder.
        self.rudder_force = (0, 0)
        if self.velocity != (0, 0):
            # Only use the rudder if the player is thrusting or turning.
            if self.do_thrust or self.turn_direction != 0:
                self.rudder_force = self.calc_rudder_force()
                force = vec.add(force, self.rudder_force)

        return force, extra_drag
示例#8
0
    def update_physics(self, elapsed_seconds):
        # Handle turning.
        if self.turning_time >= c.player_start_turn_time:
            turn_rate = c.player_turn_rate_radians
        else:
            turn_rate = interpolate(
                c.player_start_turn_rate_radians,
                c.player_turn_rate_radians,
                self.turning_time / c.player_start_turn_time,
            )

        self.heading += self.turn_direction * turn_rate * elapsed_seconds
        self.direction = heading_to_vector(self.heading)

        # Handle thrust.
        force = (0, 0)
        if self.do_thrust:
            # We vary the thrust depending on how fast the player is
            # already moving.
            thrust = curve_value(self.speed, c.player_thrust_curve)
            force = vec.add(
                force,
                vec.mul(self.direction, thrust),
            )

        # Handle braking.
        extra_drag = 0
        if self.do_brake:
            extra_drag = c.player_braking_drag

        # Handle boost.
        if self.boost_time_remaining > 0.0:
            force = vec.add(
                force,
                vec.mul(self.direction, c.player_boost_strength),
            )
        # Get heavy while boosting.
        if self.boost_heavy_time_remaining > 0.0:
            self.mass = self.original_mass * c.player_boost_heavy_multiplier
            self.restitution = (self.original_restitution *
                                c.player_boost_restitution_multiplier)
        else:
            self.mass = self.original_mass
            self.restitution = self.original_restitution

        # Handle rudder.
        self.rudder_force = (0, 0)
        if self.velocity != (0, 0):
            # Only use the rudder if the player is thrusting or turning.
            if self.do_thrust or self.turn_direction != 0:
                self.rudder_force = self.calc_rudder_force()
                force = vec.add(force, self.rudder_force)

        return force, extra_drag
示例#9
0
    def set_slants(self, start_slant, end_slant):
        if start_slant is not None:
            start_slant = Heading(start_slant)
        if end_slant is not None:
            end_slant = Heading(end_slant)

        self.start_slant = start_slant
        self.end_slant = end_slant

        # Intersect the slant lines with the left and right offset circles
        # to find the corners.
        center_left, radius_left = self.offset_circle_left()
        center_right, radius_right = self.offset_circle_right()

        # Start corners.
        if start_slant is None:
            v_slant = vec.vfrom(self.center, self.a)
        else:
            v_slant = vec.from_heading(start_slant.rad)
        a = self.a
        b = vec.add(self.a, v_slant)

        points_left = intersect_circle_line(center_left, radius_left, a, b)
        points_right = intersect_circle_line(center_right, radius_right, a, b)

        if len(points_left) == 0 or len(points_right) == 0:
            self.start_joint_illegal = True
            return

        self.a_left = Point(*closest_point_to(self.a, points_left))
        self.a_right = Point(*closest_point_to(self.a, points_right))

        # End corners.
        if end_slant is None:
            v_slant = vec.vfrom(self.center, self.b)
        else:
            v_slant = vec.from_heading(end_slant.rad)
        a = self.b
        b = vec.add(self.b, v_slant)

        points_left = intersect_circle_line(center_left, radius_left, a, b)
        points_right = intersect_circle_line(center_right, radius_right, a, b)

        if len(points_left) == 0 or len(points_right) == 0:
            self.end_joint_illegal = True
            return

        self.b_left = Point(*closest_point_to(self.b, points_left))
        self.b_right = Point(*closest_point_to(self.b, points_right))

        self.check_degenerate_segment()
示例#10
0
    def set_slants(self, start_slant, end_slant):
        if start_slant is not None:
            start_slant = Heading(start_slant)
        if end_slant is not None:
            end_slant = Heading(end_slant)

        self.start_slant = start_slant
        self.end_slant = end_slant

        # Intersect the slant lines with the left and right offset circles
        # to find the corners.
        center_left, radius_left = self.offset_circle_left()
        center_right, radius_right = self.offset_circle_right()

        # Start corners.
        if start_slant is None:
            v_slant = vec.vfrom(self.center, self.a)
        else:
            v_slant = vec.from_heading(start_slant.rad)
        a = self.a
        b = vec.add(self.a, v_slant)

        points_left = intersect_circle_line(center_left, radius_left, a, b)
        points_right = intersect_circle_line(center_right, radius_right, a, b)

        if len(points_left) == 0 or len(points_right) == 0:
            self.start_joint_illegal = True
            return

        self.a_left = Point(*closest_point_to(self.a, points_left))
        self.a_right = Point(*closest_point_to(self.a, points_right))

        # End corners.
        if end_slant is None:
            v_slant = vec.vfrom(self.center, self.b)
        else:
            v_slant = vec.from_heading(end_slant.rad)
        a = self.b
        b = vec.add(self.b, v_slant)

        points_left = intersect_circle_line(center_left, radius_left, a, b)
        points_right = intersect_circle_line(center_right, radius_right, a, b)

        if len(points_left) == 0 or len(points_right) == 0:
            self.end_joint_illegal = True
            return

        self.b_left = Point(*closest_point_to(self.b, points_left))
        self.b_right = Point(*closest_point_to(self.b, points_right))

        self.check_degenerate_segment()
示例#11
0
    def set_slants(self, start_slant, end_slant):
        if start_slant is not None:
            start_slant = Heading(start_slant)
        if end_slant is not None:
            end_slant = Heading(end_slant)

        self.start_slant = start_slant
        self.end_slant = end_slant

        # Intersect the slant lines with the left and right offset lines
        # to find the corners.
        line_left = self.offset_line_left()
        line_right = self.offset_line_right()

        # Start corners.
        if start_slant is None:
            v_slant = vec.perp(self._vector())
        else:
            v_slant = vec.from_heading(start_slant.rad)
        a = self.a
        b = vec.add(self.a, v_slant)

        left = intersect_lines(a, b, line_left[0], line_left[1])
        right = intersect_lines(a, b, line_right[0], line_right[1])

        if left is None or right is None:
            self.start_joint_illegal = True
        else:
            self.a_left = Point(*left)
            self.a_right = Point(*right)

        # End corners.
        if end_slant is None:
            v_slant = vec.perp(self._vector())
        else:
            v_slant = vec.from_heading(end_slant.rad)
        a = self.b
        b = vec.add(self.b, v_slant)

        left = intersect_lines(a, b, line_left[0], line_left[1])

        right = intersect_lines(a, b, line_right[0], line_right[1])

        if left is None or right is None:
            self.end_joint_illegal = True
        else:
            self.b_left = Point(*left)
            self.b_right = Point(*right)

        # Done, make sure we didn't cross
        self.check_degenerate_segment()
示例#12
0
def intersect_circles(center1, radius1, center2, radius2):
    radius1 = abs(radius1)
    radius2 = abs(radius2)

    if radius2 > radius1:
        return intersect_circles(center2, radius2, center1, radius1)

    transverse = vec.vfrom(center1, center2)
    dist = vec.mag(transverse)

    # Check for identical or concentric circles. These will have either
    # no points in common or all points in common, and in either case, we
    # return an empty list.
    if points_equal(center1, center2):
        return []

    # Check for exterior or interior tangent.
    radius_sum = radius1 + radius2
    radius_difference = abs(radius1 - radius2)
    if (float_equal(dist, radius_sum) or float_equal(dist, radius_difference)):
        return [
            vec.add(center1, vec.norm(transverse, radius1)),
        ]

    # Check for non intersecting circles.
    if dist > radius_sum or dist < radius_difference:
        return []

    # If we've reached this point, we know that the two circles intersect
    # in two distinct points.
    # Reference:
    # http://mathworld.wolfram.com/Circle-CircleIntersection.html

    # Pretend that the circles are arranged along the x-axis.
    # Find the x-value of the intersection points, which is the same for both
    # points. Then find the chord length "a" between the two intersection
    # points, and use vector math to find the points.
    dist2 = vec.mag2(transverse)
    x = (dist2 - radius2**2 + radius1**2) / (2 * dist)
    a = ((1 / dist) * sqrt(
        (-dist + radius1 - radius2) * (-dist - radius1 + radius2) *
        (-dist + radius1 + radius2) * (dist + radius1 + radius2)))
    chord_middle = vec.add(
        center1,
        vec.norm(transverse, x),
    )
    perp = vec.perp(transverse)
    return [
        vec.add(chord_middle, vec.norm(perp, a / 2)),
        vec.add(chord_middle, vec.norm(perp, -a / 2)),
    ]
示例#13
0
    def set_slants(self, start_slant, end_slant):
        if start_slant is not None:
            start_slant = Heading(start_slant)
        if end_slant is not None:
            end_slant = Heading(end_slant)

        self.start_slant = start_slant
        self.end_slant = end_slant

        # Intersect the slant lines with the left and right offset lines
        # to find the corners.
        line_left = self.offset_line_left()
        line_right = self.offset_line_right()

        # Start corners.
        if start_slant is None:
            v_slant = vec.perp(self._vector())
        else:
            v_slant = vec.from_heading(start_slant.rad)
        a = self.a
        b = vec.add(self.a, v_slant)

        left = intersect_lines(a, b, line_left[0], line_left[1])
        right = intersect_lines(a, b, line_right[0], line_right[1])

        if left is None or right is None:
            self.start_joint_illegal = True
        else:
            self.a_left = Point(*left)
            self.a_right = Point(*right)

        # End corners.
        if end_slant is None:
            v_slant = vec.perp(self._vector())
        else:
            v_slant = vec.from_heading(end_slant.rad)
        a = self.b
        b = vec.add(self.b, v_slant)

        left = intersect_lines(a, b, line_left[0], line_left[1])

        right = intersect_lines(a, b, line_right[0], line_right[1])

        if left is None or right is None:
            self.end_joint_illegal = True
        else:
            self.b_left = Point(*left)
            self.b_right = Point(*right)

        # Done, make sure we didn't cross
        self.check_degenerate_segment()
示例#14
0
 def rebound(self, normal, point=None, restitution=1):
     # Split into normal and tangential components.
     tangent = vec.perp(normal)
     v_tangent = vec.proj(self.velocity, tangent)
     v_normal = vec.proj(self.velocity, normal)
     # Invert normal component and recombine, with restitution.
     v_normal = vec.neg(v_normal)
     self.velocity = vec.add(v_tangent, vec.mul(v_normal, restitution))
     # If the particle is partially inside the wall, move it out.
     if point is not None:
         v = vec.vfrom(point, self.pos)
         if vec.mag2(v) < self.radius ** 2:
             v = vec.norm(v, self.radius)
             self.pos = vec.add(point, v)
示例#15
0
def intersect_lines(a, b, c, d, segment=False):
    """
    Find the intersection of lines a-b and c-d.

    If the "segment" argument is true, treat the lines as segments, and check
    whether the intersection point is off the end of either segment.
    """
    # Reference:
    # http://geomalgorithms.com/a05-_intersect-1.html
    u = vec.vfrom(a, b)
    v = vec.vfrom(c, d)
    w = vec.vfrom(c, a)

    u_perp_dot_v = vec.dot(vec.perp(u), v)
    if float_equal(u_perp_dot_v, 0):
        return None  # We have collinear segments, no single intersection.

    v_perp_dot_w = vec.dot(vec.perp(v), w)
    s = v_perp_dot_w / u_perp_dot_v
    if segment and (s < 0 or s > 1):
        return None

    u_perp_dot_w = vec.dot(vec.perp(u), w)
    t = u_perp_dot_w / u_perp_dot_v
    if segment and (t < 0 or t > 1):
        return None

    return vec.add(a, vec.mul(u, s))
示例#16
0
def intersect_lines(a, b, c, d, segment=False):
    """
    Find the intersection of lines a-b and c-d.

    If the "segment" argument is true, treat the lines as segments, and check
    whether the intersection point is off the end of either segment.
    """
    # Reference:
    # http://geomalgorithms.com/a05-_intersect-1.html
    u = vec.vfrom(a, b)
    v = vec.vfrom(c, d)
    w = vec.vfrom(c, a)

    u_perp_dot_v = vec.dot(vec.perp(u), v)
    if float_equal(u_perp_dot_v, 0):
        return None  # We have collinear segments, no single intersection.

    v_perp_dot_w = vec.dot(vec.perp(v), w)
    s = v_perp_dot_w / u_perp_dot_v
    if segment and (s < 0 or s > 1):
        return None

    u_perp_dot_w = vec.dot(vec.perp(u), w)
    t = u_perp_dot_w / u_perp_dot_v
    if segment and (t < 0 or t > 1):
        return None

    return vec.add(a, vec.mul(u, s))
示例#17
0
def put(position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program):
    y = stack_pop(stack)
    x = stack_pop(stack)
    v = stack_pop(stack)
    location = vec.add((x, y), storage_offset)
    program.set(location, chr(v))
    return position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program, True
示例#18
0
    def arc_left(
        self, arc_angle, radius=None, center=None, start_slant=None, end_slant=None,
    ):
        if (
            (radius is None and center is None)
            or (radius is not None and center is not None)
        ):
            raise TypeError('You must specify exactly one of center or radius.')

        arc_angle = Angle(arc_angle)
        # Create a radius vector, which is a vector from the arc center to the
        # current position. Subtract to find the center, then rotate the radius
        # vector to find the arc end point.
        if center is None:
            if arc_angle < 0:
                radius = -abs(radius)
            v_radius = vec.neg(vec.perp(self._vector(radius)))
            center = vec.sub(self._position, v_radius)
        elif radius is None:
            v_radius = vec.vfrom(center, self._position)
            radius = vec.mag(v_radius)
            if arc_angle < 0:
                radius = -radius

        endpoint = vec.add(center, vec.rotate(v_radius, arc_angle.rad))

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant=start_slant,
            end_slant=end_slant,
        )
示例#19
0
    def update(s, gs, dt):
        #print(s.vel)
        if s.thrusting:
            force = s.thrustForce * dt
            facing = vec.fromAngle(s.facing + 180)
            f = vec.mul(facing, force)
            s.applyForce(f)

            offset = vec.fromAngle(s.facing)
            offset = vec.mul(offset, s.radius)
            loc = vec.add(s.loc, offset)
            #            v = vec.invert(s.vel)
            s.driveEmitter.emit(gs, dt, loc, s.facing, vel=s.vel)

            if not s.engineSoundPlayer.playing:
                s.engineSoundPlayer.seek(0.0)
                s.engineSoundPlayer.eos_action = s.engineSoundPlayer.EOS_LOOP
                s.engineSoundPlayer.play()
        else:
            s.engineSoundPlayer.eos_action = s.engineSoundPlayer.EOS_PAUSE

        # Turning should be either 0, -1 or +1
        if s.turning != 0:
            force = s.turnForce * dt * s.turning
            s.applyRforce(force)

        Planet.update(s, gs, dt)
示例#20
0
def GF2_span(D, L):
    '''
    >>> from GF2 import one
    >>> D = {'a', 'b', 'c'}
    >>> L = [Vec(D, {'a': one, 'c': one}), Vec(D, {'b': one})]
    >>> len(GF2_span(D, L))
    4
    >>> Vec(D, {}) in GF2_span(D, L)
    True
    >>> Vec(D, {'b': one}) in GF2_span(D, L)
    True
    >>> Vec(D, {'a':one, 'c':one}) in GF2_span(D, L)
    True
    >>> Vec(D, {x:one for x in D}) in GF2_span(D, L)
    True
    '''
    l = []
    multiplied =[]
    for e in L:
        a= scalar_mul(e, 0)
        multiplied.append(a)
        b = scalar_mul(e, 1)
        multiplied.append(b)
    for i in multiplied:
        for j in multiplied:
            final = add(i,j)
            if final not in l:
                l.append(final)
    return l
示例#21
0
    def draw(self, screen):
        self.surface.lock()
        self.surface.fill(self.clear)
        pg.draw.line(
            self.surface,
            self.green,
            (14-10, 14),
            (14+10, 14),
            2,
        )
        pg.draw.line(
            self.surface,
            self.green,
            (14, 14-10),
            (14, 15+10),
            2,
        )
        joypos = vec.mul((self.input.x_axis, -self.input.y_axis), 8)
        pg.draw.circle(
            self.surface,
            self.red,
            vec.add(joypos, (15,15)),
            4,
        )
        self.surface.unlock()

        _width, height = self.display.screen_size
        x = 10 + 30 * self.number
        y = height - self.surface.get_height() - 10
        screen.blit(self.surface, (x, y))
示例#22
0
    def arc_left(
        self, arc_angle, radius=None, center=None, start_slant=None, end_slant=None,
    ):
        if (
            (radius is None and center is None) or
            (radius is not None and center is not None)
        ):
            raise TypeError('You must specify exactly one of center or radius.')

        arc_angle = Angle(arc_angle)
        # Create a radius vector, which is a vector from the arc center to the
        # current position. Subtract to find the center, then rotate the radius
        # vector to find the arc end point.
        if center is None:
            if arc_angle < 0:
                radius = -abs(radius)
            v_radius = vec.neg(vec.perp(self._vector(radius)))
            center = vec.sub(self._position, v_radius)
        elif radius is None:
            v_radius = vec.vfrom(center, self._position)
            radius = vec.mag(v_radius)
            if arc_angle < 0:
                radius = -radius

        endpoint = vec.add(center, vec.rotate(v_radius, arc_angle.rad))

        self._arc(
            center,
            radius,
            endpoint,
            arc_angle,
            start_slant=start_slant,
            end_slant=end_slant,
        )
示例#23
0
    def draw(self, screen):
        self.surface.lock()
        self.surface.fill(self.clear)
        pg.draw.line(
            self.surface,
            self.green,
            (14 - 10, 14),
            (14 + 10, 14),
            2,
        )
        pg.draw.line(
            self.surface,
            self.green,
            (14, 14 - 10),
            (14, 15 + 10),
            2,
        )
        joypos = vec.mul((self.input.x_axis, -self.input.y_axis), 8)
        pg.draw.circle(
            self.surface,
            self.red,
            vec.add(joypos, (15, 15)),
            4,
        )
        self.surface.unlock()

        _width, height = self.display.screen_size
        x = 10 + 30 * self.number
        y = height - self.surface.get_height() - 10
        screen.blit(self.surface, (x, y))
示例#24
0
def collide_particles(p1, p2):
    restitution = p1.restitution * p2.restitution

    # Don't collide immovable particles.
    if p1.immovable and p2.immovable:
        return

    # Test if p1 and p2 are actually intersecting.
    if not intersect(p1, p2):
        return

    # If one particle is immovable, make it the first one.
    if not p1.immovable and p2.immovable:
        p1, p2 = p2, p1

    # Vector spanning between the centers, normal to contact surface.
    v_span = vec.vfrom(p1.pos, p2.pos)

    # Split into normal and tangential components and calculate
    # initial velocities.
    normal = vec.norm(v_span)
    tangent = vec.perp(normal)
    v1_tangent = vec.proj(p1.velocity, tangent)
    v2_tangent = vec.proj(p2.velocity, tangent)
    p1_initial = vec.dot(p1.velocity, normal)
    p2_initial = vec.dot(p2.velocity, normal)

    # Don't collide if particles were actually moving away from each other, so
    # they don't get stuck inside one another.
    if p1_initial - p2_initial < 0:
        return

    # Handle immovable particles specially.
    if p1.immovable:
        p2_final = -p2_initial * restitution
        p2.velocity = vec.add(v2_tangent, vec.mul(normal, p2_final))
        return

    # Elastic collision equations along normal component.
    m1, m2 = p1.mass, p2.mass
    m1plusm2 = (m1 + m2) / restitution
    p1_final = p1_initial * (m1 - m2) / m1plusm2 + p2_initial * (2 * m2) / m1plusm2
    p2_final = p2_initial * (m2 - m1) / m1plusm2 + p1_initial * (2 * m1) / m1plusm2

    # Tangential component is unchanged, recombine.
    p1.velocity = vec.add(v1_tangent, vec.mul(normal, p1_final))
    p2.velocity = vec.add(v2_tangent, vec.mul(normal, p2_final))
示例#25
0
 def rebound(self, normal, point=None, restitution=1):
     # Split into normal and tangential components.
     tangent = vec.perp(normal)
     v_tangent = vec.proj(self.velocity, tangent)
     v_normal = vec.proj(self.velocity, normal)
     # Invert normal component and recombine, with restitution.
     v_normal = vec.neg(v_normal)
     self.velocity = vec.add(
         v_tangent,
         vec.mul(v_normal, restitution),
     )
     # If the particle is partially inside the wall, move it out.
     if point is not None:
         v = vec.vfrom(point, self.pos)
         if vec.mag2(v) < self.radius**2:
             v = vec.norm(v, self.radius)
             self.pos = vec.add(point, v)
示例#26
0
def create_snowball(lobby, pos, angle, force):
    ball_id = create_snowball_id(lobby)
    snowball = player.Snowball(ball_id)
    direction = vec.from_direction(angle, 1)
    velocity = vec.mul(direction, force * MAX_THROWING_FORCE)
    snowball.position = vec.add(pos, vec.mul(direction,
                                             SNOWBALL_SPAWN_DISTANCE))
    snowball.velocity = velocity
    lobby.snowballs[ball_id] = snowball
示例#27
0
    def canCapture(s, point, distance, targetPlanet):
        if s.isParent(targetPlanet):
            #print "Nope, is parent"
            return False
        if targetPlanet.parent != None:
            #print "Nope, has parent"
            return False
        if targetPlanet == s:
            #print "Nope, self"
            return False
        if s in targetPlanet.children:
            #print "Nope, is a child already"
            return False

        vecBetweenPlanets = vec.sub(targetPlanet.loc, s.loc)
        # Adjust distance to measure from surface to surface, not center
        # to center
        distance += s.radius + targetPlanet.radius
        if vec.magSquared(vecBetweenPlanets) > (distance * distance):
            #print "Nope, out of range"
            return False

        # Okay we are close enough to an eligible planet, are we facing it?
        angleBetweenPlanets = vec.toAngle(vecBetweenPlanets)
        # Urrrrrg I hate this, -180 to 180 and 0-360 behave differently and both are
        # awful in different situations so neither one is really correct.
        point = (point + 360) % 360
        angleBetweenPlanets = (angleBetweenPlanets + 360) % 360
        #print "Point and angle:", point, angleBetweenPlanets
        if abs(angleBetweenPlanets - point) < 10:
            #print "Yep!"
            return True

        #print "Nope, angle too great", angleBetweenPlanets, point, abs(angleBetweenPlanets - point)
        return False

        vecBetweenPlanets = vec.sub(targetPlanet.loc, s.loc)
        vecBPU = vec.unit(vecBetweenPlanets)
        vecToPlanetEdge = vec.mul(vec.perpendicular(vecBPU),
                                  targetPlanet.radius)
        #print("Vec between planets: {0}, vec to planet edge: {1}".format(vecBPU, vec.unit(vecToPlanetEdge)))
        angularSize = vec.angleBetween(
            vecBetweenPlanets, vec.add(vecBetweenPlanets, vecToPlanetEdge))
        vecToPoint = vec.mul(vec.fromAngle(point), s.radius)
        angularDistance = vec.angleBetween(vecBetweenPlanets, vecToPoint)
        #print("Angular size: {0}, angular distance: {1}".format(angularSize, angularDistance))
        if angularDistance > abs(angularSize):
            return False
        else:
            # Check distance between planets surfaces
            distance = distance + (s.radius + targetPlanet.radius)
            # Can't capture a planet if you're overlapping it
            # XXX: Doesn't seem to work, but...
            if distance < 0:
                return False
            return vec.within(s.loc, targetPlanet.loc, distance)
示例#28
0
def repeat(position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program):
    instruction = program.get(vec.add(position, velocity))
    if instruction in INSTRUCTIONS:
        operation = INSTRUCTIONS[instruction]
    else:
        operation = DEFAULT_INSTRUCTION
    result = position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program, True
    for _ in xrange(stack_pop(stack)):
        result = operation(position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program)
    return result
示例#29
0
    def to_screen(self, pos):
        """Convert pos to screen coordinates.

        Takes a tuple a world position, and returns a tuple for the
        screen position.
        """
        x, y = vec.add(
            self.screen_origin,
            vec.mul(pos, self.pixels_per_unit),
        )
        return (int(x), int(y))
示例#30
0
 def emit(s, gs, dt, loc, facing, vel=vec.ZERO):
     s.timer += dt
     while s.timer > s.interval:
         s.timer -= s.interval
         for i in range(s.count):
             variance = + (s.angle * random.random()) - (s.angle / 2.0)
             angle = facing + variance
             v = vec.mul(vec.fromAngle(angle), s.speed)
             v = vec.add(vel, v)
             part = s.particleType(loc, v)
             gs.addParticle(part)
示例#31
0
def draw_graph(graph):
    gap_size = 0.25

    p = canoepaddle.Pen()
    p.stroke_mode(0.1, 'black')
    for a, b in graph_edges(graph):
        gap = vec.norm(vec.vfrom(a, b), gap_size)
        p.move_to(vec.add(a, gap))
        p.line_to(vec.sub(b, gap))

    return p.paper
示例#32
0
    def to_screen(self, pos):
        """Convert pos to screen coordinates.

        Takes a tuple a world position, and returns a tuple for the
        screen position.
        """
        x, y = vec.add(
            self.screen_origin,
            vec.mul(pos, self.pixels_per_unit),
        )
        return (int(x), int(y))
示例#33
0
 def create_shield(self):
     self.shield_pieces = []
     for i in range(8):
         d = DIRECTIONS[i]
         pos = vec.add(self.pos, d)
         piece = HeroPiece()
         piece.pos = pos
         piece.display_character = '-\|/'[i % 4]
         self.world.register_entity(piece)
         self.shield_pieces.append(piece)
     Polyomino([self] + self.shield_pieces)
     self.shield((0, 0))
示例#34
0
文件: planar.py 项目: nickoala/openrv
    def project(self, points, reverse=False):
        if reverse:
            if self.H_ is None:
                self.H_ = mtx.lu([r[:] for r in self.H])

            qs = [
                mtx.solve(self.H_,
                          vec.sub(p, self.offset) + [1]) for p in points
            ]
            return [vec.div(q[:-1], q[-1]) for q in qs]
        else:
            qs = [mtx.mul(self.H, p + [1]) for p in points]
            return [vec.add(self.offset, vec.div(q[:-1], q[-1])) for q in qs]
示例#35
0
def balls_collisions(balls):
    collided = False
    for b1 in balls:
        for b2 in balls:
            if b1 is b2:
                continue

            d = vec.sub(b1.pos, b2.pos)
            penetration = (b1.radius + b2.radius) - vec.len(d)
            if penetration < 0:
                continue

            collided = True
            n = vec.unit(d)
            b1.pos = vec.add(b1.pos, vec.scale(n, penetration / 2 + 1))
            b2.pos = vec.add(b2.pos, vec.scale(n, -penetration / 2 - 1))

            j = vec.dot(vec.sub(b2.speed, b1.speed), n)
            b1.speed = vec.add(b1.speed, vec.scale(n, j))
            b2.speed = vec.add(b2.speed, vec.scale(n, -j))

    return collided
示例#36
0
    def update(self, elapsed_seconds, force=None, extra_drag=0):
        # Apply force if necessary.
        if force is not None:
            self.velocity = vec.add(self.velocity, vec.mul(force, (elapsed_seconds / self.mass)))

        # Apply drag.
        # Decrease the magnitude of the velocity vector by
        # the amount of drag.
        drag = (self.drag_rate + extra_drag) * elapsed_seconds
        if drag > self.speed:
            self.velocity = (0, 0)
        elif drag != 0 and self.velocity != (0, 0):
            drag_vector = vec.norm(self.velocity, -drag)
            self.velocity = vec.add(self.velocity, drag_vector)

        # Limit to maximum speed.
        if self.speed > c.max_speed:
            self.velocity = vec.norm(self.velocity, c.max_speed)

        # Update position based on velocity.
        self.last_pos = self.pos
        self.pos = vec.add(self.pos, vec.mul(self.velocity, elapsed_seconds))
示例#37
0
 def draw(s, gs):
     rot = s.parent.facing + s.loc
     totalAngle = vec.fromAngle(rot)
     offsetVec = vec.mul(totalAngle, s.radius)
     location = vec.add(s.parent.loc, offsetVec)
     (scx, scy) = gs.screenCoords(location)
     #print "rot: %s, totalAngle: %s, offsetVec: %s, location: %s, sc: %s" % (rot, totalAngle, offsetVec, location, (scx, scy))
     # Add a slight offset to center the image rather than drawing
     # it from the lower-left corner...
     # Also add oregano.
     s.sprite.rotation = s.loc + s.parent.facing
     #print s.sprite.rotation, s.loc, s.parent.facing
     s.sprite.position = (scx, scy)
     s.sprite.draw()
示例#38
0
    def join_with_arc(self, other):
        # Special case coincident arcs.
        if points_equal(self.center, other.center):
            if not (
                float_equal(self.radius, other.radius) and
                float_equal(self.width, other.width)
            ):
                self.end_joint_illegal = True
                other.start_joint_illegal = True
                return

            r = vec.vfrom(self.center, self.b)
            if self.radius < 0:
                r = vec.neg(r)
            v_left = vec.norm(r, self.radius - self.width / 2)
            self.b_left = other.a_left = Point(*vec.add(self.center, v_left))
            v_right = vec.norm(r, self.radius + self.width / 2)
            self.b_right = other.a_right = Point(*vec.add(self.center, v_right))
            return

        c1, r1 = self.offset_circle_left()
        c2, r2 = other.offset_circle_left()
        points_left = intersect_circles(c1, r1, c2, r2)
        if len(points_left) > 0:
            p = Point(*closest_point_to(self.b, points_left))
            self.b_left = other.a_left = p

        c1, r1 = self.offset_circle_right()
        c2, r2 = other.offset_circle_right()
        points_right = intersect_circles(c1, r1, c2, r2)
        if len(points_right) > 0:
            p = Point(*closest_point_to(self.b, points_right))
            self.b_right = other.a_right = p

        if len(points_left) == 0 or len(points_right) == 0:
            self.end_joint_illegal = True
            other.start_joint_illegal = True
示例#39
0
    def join_with_arc(self, other):
        # Special case coincident arcs.
        if points_equal(self.center, other.center):
            if not (
                float_equal(self.radius, other.radius)
                and float_equal(self.width, other.width)
            ):
                self.end_joint_illegal = True
                other.start_joint_illegal = True
                return

            r = vec.vfrom(self.center, self.b)
            if self.radius < 0:
                r = vec.neg(r)
            v_left = vec.norm(r, self.radius - self.width / 2)
            self.b_left = other.a_left = Point(*vec.add(self.center, v_left))
            v_right = vec.norm(r, self.radius + self.width / 2)
            self.b_right = other.a_right = Point(*vec.add(self.center, v_right))
            return

        c1, r1 = self.offset_circle_left()
        c2, r2 = other.offset_circle_left()
        points_left = intersect_circles(c1, r1, c2, r2)
        if len(points_left) > 0:
            p = Point(*closest_point_to(self.b, points_left))
            self.b_left = other.a_left = p

        c1, r1 = self.offset_circle_right()
        c2, r2 = other.offset_circle_right()
        points_right = intersect_circles(c1, r1, c2, r2)
        if len(points_right) > 0:
            p = Point(*closest_point_to(self.b, points_right))
            self.b_right = other.a_right = p

        if len(points_left) == 0 or len(points_right) == 0:
            self.end_joint_illegal = True
            other.start_joint_illegal = True
示例#40
0
def generate_castle_position():
    if not castles:
        return (0, 0)
    it = 0
    while True:
        r1 = random.randint(-1 - it, 1 + it)
        r2 = random.randint(-1 - it, 1 + it)
        direction = (r1 * SPAWN_DISTANCE, r2 * SPAWN_DISTANCE)
        for castle in castles.values():
            pos = castle.position_tuple()
            new_pos = vec.add(direction, pos)
            if is_castle_position_free(new_pos):
                # print('FOUND!')
                return new_pos
        it += 1
示例#41
0
    def update(s, gs, dt):
        if s.parent == None:
            PhysicsObj.update(s, gs, dt)
        else:
            #print("parent offset: {0}, parent direction {1}, parent distance {2}, parent facing {3}".format(s.parentVec, vec.toAngle(p), vec.mag(p), s.parent.facing))
            # To figure out the current facing we must know what our parent's facing is,
            # where we were facing when captured, and where the parent was facing when captured.
            s.facing = s.capturedFacing + (s.parent.facing -
                                           s.capturedParentFacing)

            rotation = s.parent.facing - s.capturedParentFacing + 180
            p = vec.rotate(s.parentVec, -rotation)
            # THAT F*****G SIMPLE AAAAAAAAAAH
            relativePosition = vec.add(s.parent.loc, p)
            s.loc = relativePosition
示例#42
0
 def draw(s, gs):
     sx, sy = gs.screenCoords(s.loc)
     s.sprite.x = sx
     s.sprite.y = sy
     s.sprite.rotation = s.facing
     s.sprite.draw()
     if s.parent != None:
         #parentSloc = gs.screenCoords(s.parent.loc)
         vecToParent = vec.sub(s.parent.loc, s.loc)
         angle = vec.toAngle(vecToParent)
         centerPointVec = vec.div(vecToParent, 2)
         actualVec = vec.add(s.loc, centerPointVec)
         s.captureSprite.position = gs.screenCoords(actualVec)
         s.captureSprite.rotation = angle
         s.captureSprite.draw()
示例#43
0
 def draw(s, gs):
     swingSpeed = 190.0  # Degrees per second
     startingFacing = 90.0
     if s.direction > 0:
         swing = startingFacing + -(s.lifetime * swingSpeed)
     else:
         swing = (s.lifetime * swingSpeed) - startingFacing
     rot = s.parent.facing + s.loc
     totalAngle = vec.fromAngle(rot)
     offset = vec.mul(totalAngle, s.radius)
     location = vec.add(s.parent.loc, offset)
     s.sprite.position = gs.screenCoords(location)
     #print location
     s.sprite.rotation = rot + swing
     s.sprite.draw()
示例#44
0
    def draw_player(self, player):
        # Show whether or not the player is thrusting.
        if player.do_thrust:
            trailing_point = vec.add(
                player.pos,
                vec.norm(player.direction, -1.5 * player.radius),
            )
            self.line(THRUST_COLOR, player.pos, trailing_point,
                      .5 * player.radius)
        if player.boost_heavy_time_remaining > 0.0:
            trailing_point = vec.add(
                player.pos,
                vec.norm(player.direction, -2.0 * player.radius),
            )
            self.line(THRUST_COLOR, player.pos, trailing_point,
                      1.5 * player.radius)

        # Show braking and boosting charge up.
        if player.do_brake:
            # Redden the brake color as we charge.
            color = vec.add(
                BRAKE_COLOR,
                vec.mul(THRUST_COLOR,
                        player.boost_charge_time / c.player_boost_ready_time))
            # Vibrate if we are fully charged.
            r = 1.2
            if player.boost_charge_time == c.player_boost_ready_time:
                r += 0.1 * math.sin(6 *
                                    (2 * math.pi) * pg.time.get_ticks() / 1000)
            self.circle(color, player.pos, r)

        # Body.
        self.circle(PLAYER_COLORS[player.number], player.pos, player.radius)

        # Show the player pointing towards a direction.
        leading_point = vec.add(
            player.pos,
            vec.norm(player.direction, player.radius),
        )
        self.line(DIRECTION_COLOR, player.pos, leading_point,
                  .2 * player.radius)

        if SHOW_RUDDER_FORCE:
            point = vec.add(
                player.pos,
                vec.mul(player.rudder_force, .1),
            )
            self.line(THRUST_COLOR, player.pos, point, .1 * player.radius)
        if SHOW_INTENDED_DIRECTION and hasattr(player, 'intended_direction'):
            point = vec.add(
                player.pos,
                player.intended_direction,
            )
            self.line(THRUST_COLOR, player.pos, point, .1 * player.radius)
示例#45
0
    def bounds(self):
        # We use the outside radius, because the inside of the arc cannot be
        # tangent to the boundary. This is not a perfect approximation, as
        # setting end slants could fail to shrink the bounding box as
        # they should.
        r = abs(self.radius)
        if self.width is not None:
            r += self.width / 2

        # Find the four "compass points" around the center.
        compass_points = [
            vec.add(self.center, direction)
            for direction in [
                (r, 0),  # East, heading = 0.
                (0, r),  # North, heading = 90.
                (-r, 0),  # West, heading = 180.
                (0, -r),  # South, heading = 270.
            ]
        ]

        # Check which compass points are in the body of the circle.
        if self.arc_angle < 0:
            start = self.end_heading + 90
            end = self.start_heading + 90
        else:
            start = self.start_heading - 90
            end = self.end_heading - 90
        occupied_points = []
        for i, h in enumerate([0, 90, 180, 270]):
            h = Heading(h)
            if h == start or h == end or h.between(start, end):
                occupied_points.append(compass_points[i])

        # The bounding box of the arc is the combined bounding box of the start
        # point, the end point, and the compass points occupied by the body of
        # the arc. If the arc is a thick arc, then the edge points also can
        # push the boundary.
        if self.width is None:
            endpoints = [self.a, self.b]
        else:
            endpoints = [self.a_left, self.a_right, self.b_left, self.b_right]

        return Bounds.union_all([
            Bounds.from_point(p) for p in
            endpoints + occupied_points
        ])
示例#46
0
    def bounds(self):
        # We use the outside radius, because the inside of the arc cannot be
        # tangent to the boundary. This is not a perfect approximation, as
        # setting end slants could fail to shrink the bounding box as
        # they should.
        r = abs(self.radius)
        if self.width is not None:
            r += self.width / 2

        # Find the four "compass points" around the center.
        compass_points = [
            vec.add(self.center, direction)
            for direction in [
                (r, 0),  # East, heading = 0.
                (0, r),  # North, heading = 90.
                (-r, 0),  # West, heading = 180.
                (0, -r),  # South, heading = 270.
            ]
        ]

        # Check which compass points are in the body of the circle.
        if self.arc_angle < 0:
            start = self.end_heading + 90
            end = self.start_heading + 90
        else:
            start = self.start_heading - 90
            end = self.end_heading - 90
        occupied_points = []
        for i, h in enumerate([0, 90, 180, 270]):
            h = Heading(h)
            if h == start or h == end or h.between(start, end):
                occupied_points.append(compass_points[i])

        # The bounding box of the arc is the combined bounding box of the start
        # point, the end point, and the compass points occupied by the body of
        # the arc. If the arc is a thick arc, then the edge points also can
        # push the boundary.
        if self.width is None:
            endpoints = [self.a, self.b]
        else:
            endpoints = [self.a_left, self.a_right, self.b_left, self.b_right]

        return Bounds.union_all([
            Bounds.from_point(p) for p in
            endpoints + occupied_points
        ])
示例#47
0
def intersect_circle_line(center, radius, line_start, line_end):
    """
    Find the intersection of a circle with a line.
    """
    radius = abs(radius)

    # First check whether the line is too far away, or if we have a
    # single point of contact.
    # Reference:
    # http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
    r = vec.vfrom(center, line_start)
    v = vec.perp(vec.vfrom(line_start, line_end))
    d = vec.proj(r, v)
    dist = vec.mag(d)
    if float_equal(dist, radius):
        # Single intersection point, because the circle and line are tangent.
        point = vec.add(center, d)
        return [point]
    elif dist > radius:
        return []

    # Set up parametric equations for the line and the circle, and solve them.
    # Reference:
    # http://www.cs.cf.ac.uk/Dave/CM0268/PDF/circle_line_intersect_proof.pdf
    xc, yc = center
    x0, y0 = line_start
    x1, y1 = line_end
    line_x, line_y = (x1 - x0), (y1 - y0)  # f, g
    dx, dy = (x0 - xc), (y0 - yc)

    a = line_x**2 + line_y**2
    b = 2 * (line_x * dx + line_y * dy)
    c = dx**2 + dy**2 - radius**2
    t0, t1 = quadratic_formula(a, b, c)

    return [
        (
            x0 + line_x * t0,
            y0 + line_y * t0,
        ),
        (
            x0 + line_x * t1,
            y0 + line_y * t1,
        ),
    ]
示例#48
0
def intersect_circle_line(center, radius, line_start, line_end):
    """
    Find the intersection of a circle with a line.
    """
    radius = abs(radius)

    # First check whether the line is too far away, or if we have a
    # single point of contact.
    # Reference:
    # http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
    r = vec.vfrom(center, line_start)
    v = vec.perp(vec.vfrom(line_start, line_end))
    d = vec.proj(r, v)
    dist = vec.mag(d)
    if float_equal(dist, radius):
        # Single intersection point, because the circle and line are tangent.
        point = vec.add(center, d)
        return [point]
    elif dist > radius:
        return []

    # Set up parametric equations for the line and the circle, and solve them.
    # Reference:
    # http://www.cs.cf.ac.uk/Dave/CM0268/PDF/circle_line_intersect_proof.pdf
    xc, yc = center
    x0, y0 = line_start
    x1, y1 = line_end
    line_x, line_y = (x1 - x0), (y1 - y0)  # f, g
    dx, dy = (x0 - xc), (y0 - yc)

    a = line_x**2 + line_y**2
    b = 2 * (line_x * dx + line_y * dy)
    c = dx**2 + dy**2 - radius**2
    t0, t1 = quadratic_formula(a, b, c)

    return [
        (
            x0 + line_x * t0,
            y0 + line_y * t0,
        ),
        (
            x0 + line_x * t1,
            y0 + line_y * t1,
        ),
    ]
示例#49
0
    def draw_player(self, player):
        # Show whether or not the player is thrusting.
        if player.do_thrust:
            trailing_point = vec.add(
                player.pos,
                vec.norm(player.direction, -1.5 * player.radius),
            )
            self.line(THRUST_COLOR, player.pos, trailing_point, .5 * player.radius)
        if player.boost_heavy_time_remaining > 0.0:
            trailing_point = vec.add(
                player.pos,
                vec.norm(player.direction, -2.0 * player.radius),
            )
            self.line(THRUST_COLOR, player.pos, trailing_point, 1.5 * player.radius)

        # Show braking and boosting charge up.
        if player.do_brake:
            # Redden the brake color as we charge.
            color = vec.add(
                BRAKE_COLOR,
                vec.mul(THRUST_COLOR, player.boost_charge_time / c.player_boost_ready_time)
            )
            # Vibrate if we are fully charged.
            r = 1.2
            if player.boost_charge_time == c.player_boost_ready_time:
                r += 0.1 * math.sin(6 * (2*math.pi) * pg.time.get_ticks() / 1000)
            self.circle(color, player.pos, r)

        # Body.
        self.circle(PLAYER_COLORS[player.number], player.pos, player.radius)

        # Show the player pointing towards a direction.
        leading_point = vec.add(
            player.pos,
            vec.norm(player.direction, player.radius),
        )
        self.line(DIRECTION_COLOR, player.pos, leading_point, .2 * player.radius)

        if SHOW_RUDDER_FORCE:
            point = vec.add(
                player.pos,
                vec.mul(player.rudder_force, .1),
            )
            self.line(THRUST_COLOR, player.pos, point, .1 * player.radius)
        if SHOW_INTENDED_DIRECTION and hasattr(player, 'intended_direction'):
            point = vec.add(
                player.pos,
                player.intended_direction,
            )
            self.line(THRUST_COLOR, player.pos, point, .1 * player.radius)
示例#50
0
def start_block(position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program):
    n = stack_pop(stack)
    soss = stack
    if n < 0:
        toss = [0] * (n * -1)
    elif n > len(soss):
        i = n - len(soss)
        toss = [0] * i + soss
        soss = []
    else:
        s = len(soss) - n
        assert s >= 0
        toss = soss[s:]
        soss = soss[:s]
    sx, sy = storage_offset
    soss += [sx, sy]
    storage_offset = vec.add(position, velocity)
    stack_of_stacks.append(soss)
    stack = toss
    return position, velocity, storage_offset, stack, stack_of_stacks, push_mode, program, True
def partition(points, l1, l2, s=None):
    """
    Partition a set of points by a line.

    The line is defined by l1, l2. The desired side of the line is given by the
    point s.

    If s is not given, return points to the right of the line.

    If eq is True, also include points on the line.

    >>> sorted(partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1), (2,0)))
    [(0, 0), (1, 0)]
    >>> sorted(partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1), (-2,0)))
    [(-1, 0), (0, 0)]
    >>> points = [(-2,2), (-1,0), (0,0), (1,0)]
    >>> sorted(partition(points, (-1,0), (0,1), (3,0)))
    [(-1, 0), (0, 0), (1, 0)]
    >>> sorted(partition(points, (-1,0), (0,1), (-3,0)))
    [(-2, 2), (-1, 0)]

    You can omit the argument "s" if you don't care.
    >>> sorted(partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1)))
    [(-1, 0), (0, 0)]
    """
    if s is None:
        s = vec.add(l1, vec.perp(vec.vfrom(l1, l2)))

    if l1 == l2:
        raise ValueError('l1 equals l2')
    sign = sign_of(cmp_line(l1, l2, s))
    if sign == 0:
        raise ValueError('s is on the line l1 l2')

    for p in points:
        c = cmp_line(l1, l2, p)
        if c == sign:
            yield p
        elif c == 0:
            yield p
示例#52
0
def partition(points, l1, l2, s=None):
    """
    Partition a set of points by a line.

    The line is defined by l1, l2. The desired side of the line is given by the
    point s.

    >>> partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1), (2,0))[0]
    {(1, 0)}
    >>> partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1), (-2,0))[0]
    {(-1, 0)}
    >>> points = [(-2,2), (-1,0), (0,0), (1,0)]
    >>> sorted(partition(points, (-1,0), (0,1), (3,0))[0])
    [(0, 0), (1, 0)]
    >>> sorted(partition(points, (-1,0), (0,1), (-3,0))[0])
    [(-2, 2)]

    You can omit the argument "s" if you don't care.
    >>> partition([(-1,0), (0,0), (1,0)], (0,1), (0,-1))
    ({(-1, 0)}, {(1, 0)})
    """
    if s is None:
        s = vec.add(l1, vec.perp(vec.vfrom(l1, l2)))

    if l1 == l2:
        raise ValueError('l1 equals l2')
    sign = cmp_line(l1, l2, s)
    if sign == 0:
        raise ValueError('s is on the line l1 l2')

    forward = set()
    reverse = set()
    for p in points:
        c = cmp_line(l1, l2, p)
        if c == sign:
            forward.add(p)
        elif c == -sign:
            reverse.add(p)
    return forward, reverse
示例#53
0
    [0, 0],
    [2, -2],
    [4, -6],
    [2, 2],
    [6, 4],
    [16, 10],
    [14, -10],
    [10, 8],
    [12, -8],
]

# 290 mm / 15 sqaures
paper_points = [vec.mul(q, 290 / 15) for q in paper_squares]

offset = [305, 0]  # floor origin is 305 mm in front
world_points = [vec.add(p, offset) for p in paper_points]

p = Planar(H, offset=offset)

# Should be equal
print(world_points)
print(p.project(image_points))

# Should be equal
print(image_points)
print(p.project(world_points, reverse=True))

# Make sure H did not get changed
print(world_points)
print(p.project(image_points))
示例#54
0
 def _calc_forward_to_x(self, x_target):
     x, y = self.position
     x_diff = x_target - x
     y_diff = x_diff * math.tan(self._heading.rad)
     return vec.add(self.position, (x_diff, y_diff))
示例#55
0
 def _calc_forward_to_y(self, y_target):
     x, y = self.position
     y_diff = y_target - y
     x_diff = y_diff / math.tan(self._heading.rad)
     return vec.add(self.position, (x_diff, y_diff))
示例#56
0
 def _calc_forward_position(self, distance):
     return vec.add(
         self.position,
         self._vector(distance),
     )
示例#57
0
 def to_screen(self, pos):
     return vec.add(pos, self.origin)
示例#58
0
 def move_relative(self, offset):
     self.move_to(vec.add(self.position, offset))
示例#59
0
 def start_move(self, direction):
     self.pos = vec.add(self.pos, direction)