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_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,
        )
예제 #3
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,
        )
예제 #4
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
예제 #5
0
def heading_to_vector(heading):
    return vec.rotate((1, 0), heading)
예제 #6
0
def heading_to_vector(heading):
    return vec.rotate((1, 0), heading)
예제 #7
0
def hook(pen, slant_angle, arc_angle, distance, adjust_inside=0, adjust_outside=0):
    """
    Draw a hook shape.

    Each hook has two arcs that meet at a point, with curvature in the
    same direction. They are connected at the other end by a line, creating two
    corners. The pen starts on the left corner, pointing toward the right
    corner. The width of the pen is also used as the maximum width of the hook.

    The `slant_angle` argument is 90 degrees for a hook with a "straight" base.
    For slanted bases toward the inside corner, 0 < slant_angle < 90.
    For slanted bases toward the outside corner, 90 < slant_angle < 180.

    `arc_angle` is the arc angle of the inside arc. If `arc_angle` is negative,
    then the hook curves to the right instead.

    `distance` is the arc length along the inside arc.

    `sharp_angle` adjusts the "sharpness" i.e. acuteness of the angle of the
    hook tip. Negative angles make it "blunter".
    """
    slant_angle = Angle(slant_angle)
    arc_angle = Angle(arc_angle)

    old_mode = pen.mode
    hook_width = old_mode.width


    # The pen starts at the "middle" of the hook, a point along the base that
    # is in the middle of the inside and outside bounding circles.
    base_heading = pen.heading
    base_middle = pen.position

    # Calculate the radius.
    circumference = distance / (arc_angle.theta / 360)
    radius = circumference / (2 * math.pi)

    # Trace the inside curve to find the hook tip and some other
    # important points.
    temp_pen = pen.copy()
    temp_pen.turn_left(slant_angle)
    temp_pen.arc_left(arc_angle, radius)
    center_arc = temp_pen.last_segment()

    tip = center_arc.b
    center = center_arc.center

    # Calculate the inside and outside corner position. The outside corner is located
    # along the base line, intersecting the outer circle. The outer circle is
    # concentric to the inner arc's circle, but with radius larger by the
    # hook_width.
    v_base = vec.rotate((1, 0), base_heading.rad)
    switch_corners = (
        (slant_angle > 0 and arc_angle < 0) or
        (slant_angle < 0 and arc_angle > 0)
    )

    if switch_corners:
        v_base = vec.neg(v_base)

    base_right = vec.add(base_middle, v_base)

    points_inside = intersect_circle_line(
        center, abs(center_arc.radius) - (hook_width / 2),
        base_middle, base_right,
    )
    points_outside = intersect_circle_line(
        center, abs(center_arc.radius) + (hook_width / 2),
        base_middle, base_right,
    )

    # Take the intersection point that is the most "forward" along the base
    # from the inside corner.
    def forwardness(p):
        v_p = vec.vfrom(base_middle, p)
        return vec.dot(v_p, v_base),

    inside_corner = max(points_inside, key=forwardness)
    outside_corner = max(points_outside, key=forwardness)

    # Adjust for having started in the middle of the hook. Move to where the
    # corner of the hook is at the pen start position.
    if not switch_corners:
        offset = vec.vfrom(inside_corner, base_middle)
    else:
        offset = vec.vfrom(outside_corner, base_middle)
    inside_corner = vec.add(inside_corner, offset)
    outside_corner = vec.add(outside_corner, offset)
    tip = vec.add(tip, offset)
    center = vec.add(center, offset)

    # Draw the hook.
    pen.set_mode(old_mode.outliner_mode())
    # Base.
    pen.move_to(inside_corner)
    pen.line_to(outside_corner)
    # Outer arc.
    pen.turn_toward(center)
    if arc_angle > 0:
        pen.turn_right(90 + adjust_outside)
    else:
        pen.turn_left(90 + adjust_outside)
    pen.arc_to(tip)
    # Inner arc.
    pen.turn_to(center_arc.end_heading + 180)
    if arc_angle > 0:
        pen.turn_right(adjust_inside)
    else:
        pen.turn_left(adjust_inside)

    pen.arc_to(inside_corner)

    pen.set_mode(old_mode)
def regular_polygon(radius, num_sides, start_angle):
    for i in range(num_sides):
        angle = start_angle - (i * 360) / num_sides
        point = (0, radius)
        yield vec.rotate(point, math.radians(angle))