Ejemplo n.º 1
0
 def circle_arc_(self, radius, angle, theta, xcenter, ycenter):
     """
     Create a circular arc component and return it.
     """
     x, y = self._pos
     rx = radius
     ry = radius
     xrot = 0
     if abs(angle) > 180.0:
         large_arc = 1
     else:
         large_arc = 0
     if angle < 0:
         sweep_flag = 1
     else:
         sweep_flag = 0
     theta = (theta - 180 + angle)
     xdest = xcenter + math.cos(deg2rad(theta)) * radius
     ydest = ycenter + math.sin(deg2rad(theta)) * radius
     component = self.screen.drawing.path()
     command = "M {} {}".format(x, y)
     component.push(command)
     command = "A {} {} {} {} {} {} {}".format(abs(radius), abs(radius),
                                               xrot, large_arc, sweep_flag,
                                               xdest, ydest)
     component.push(command)
     return component
Ejemplo n.º 2
0
 def circle(self, radius, angle, steps=None):
     """
     The center of the circle with be `radius` units to 90 degrees left of
     the turtle's current heading.
     The turtle will trace out an arc that sweeps out `angle` degrees.
     """
     x, y = self._pos
     theta = (self._heading + 90) % 360
     xcenter = x + math.cos(deg2rad(theta)) * radius
     ycenter = y + math.sin(deg2rad(theta)) * radius
     self._adjust_bounds(xcenter - radius, ycenter - radius)
     self._adjust_bounds(xcenter + radius, ycenter + radius)
     if steps is None and angle != 0 and (angle % 360 == 0):
         component = self.screen.drawing.circle((xcenter, ycenter), radius)
     elif steps is None:
         component = self.circle_arc_(radius, angle, theta, xcenter,
                                      ycenter)
     else:
         self.regular_polygon_(radius, steps, angle, xcenter, ycenter)
         return
     component['stroke'] = self._pencolor
     component['stroke-width'] = self._pensize
     if self._fill_mode == 'unfill':
         self.add_hole_component_(component)
     elif self._fill_mode == 'fill':
         self._filled_components.append(component)
     else:
         component['class'] = 'no-fill'
         component['fill-opacity'] = 0
         self._components.append(component)
Ejemplo n.º 3
0
 def regular_polygon_(self, radius, sides, angle, xcenter, ycenter):
     """
     Add the coordinates of a regular polygon (or segments of it)
     to the primary component.
     """
     heading = self._heading
     step_angle = angle / sides
     angle = abs(angle)
     alpha = heading
     angle_offset = 0
     for n in range(sides + 1):
         angle_offset = step_angle * n
         theta = deg2rad(alpha + angle_offset)
         x = xcenter + radius * math.cos(theta)
         y = ycenter + radius * math.sin(theta)
         if n == 0:
             no_stroke = True
         else:
             no_stroke = False
         self._line_to(x, y, no_stroke=no_stroke)
         if abs(angle_offset) >= angle:
             break
     if angle == 360:
         polyline = self._get_current_polyline()
         polyline['stroke-linecap'] = 'round'
Ejemplo n.º 4
0
def ext_ellipse(self, major, minor, angle=360, clockwise=True):
    """
    Extension method added to turtle instance.
    """
    backend = self.backend
    orig_heading = self.heading()
    theta = backend.cartesian_heading(orig_heading)
    orig_pos = self.pos()
    i = orig_pos[0]
    j = orig_pos[1]
    angle_count = int(angle)
    pos_fn = lambda frm, to, count, i: (to * i + frm * (count - i - 1)) / (count - 1)
    if clockwise:
        start_angle = 90
        p = functools.partial(pos_fn, start_angle, start_angle - angle + 1, angle_count)
        angles = list(map(p, range(angle_count)))
    else:
        start_angle = -90
        p = functools.partial(pos_fn, start_angle, start_angle + angle - 1, angle_count)
        angles = list(map(p, range(angle_count)))
    half_major = major / 2
    half_minor = minor / 2
    coords = [rotate_coords(0, 0, half_major * math.cos(deg2rad(alpha)), half_minor * math.sin(deg2rad(alpha)), theta) for alpha in angles]
    if not clockwise:
        xsign = -1
        ysign = 1
    else:
        xsign = 1
        ysign = -1
    i = half_minor * math.sin(deg2rad(theta)) * xsign + i
    j = half_minor * math.cos(deg2rad(theta)) * ysign + j 
    coords = [(i + x, j + y) for x, y in coords]
    self.pu()
    coord = coords[0]
    self.setpos(*coord)
    self.pd()
    for x, y in coords:
        self.setpos(x, y)
    if clockwise:
        turtle_heading = backend.turtle_heading_from_cartesian_heading(theta - angle)
    else:
        turtle_heading = backend.turtle_heading_from_cartesian_heading(theta + angle)
    self.setheading(turtle_heading)
        
Ejemplo n.º 5
0
 def ellipse_simulation_(self, major, minor, angle=360, clockwise=True):
     """
     Simulate an ellipse using many straight segments.  Used in conjunction
     with fills and masks so that the result minimizes and gaps.
     """
     orig_heading = self._heading
     theta = orig_heading
     orig_pos = self._pos
     i = orig_pos[0]
     j = orig_pos[1]
     angle_count = int(angle)
     pos_fn = lambda frm, to, count, i: (to * i + frm *
                                         (count - i - 1)) / (count - 1)
     if clockwise:
         start_angle = 90
         p = functools.partial(pos_fn, start_angle, start_angle - angle + 1,
                               angle_count)
         angles = list(map(p, range(angle_count)))
     else:
         start_angle = -90
         p = functools.partial(pos_fn, start_angle, start_angle + angle - 1,
                               angle_count)
         angles = list(map(p, range(angle_count)))
     half_major = major / 2
     half_minor = minor / 2
     coords = [
         rotate_coords(0, 0, half_major * math.cos(deg2rad(alpha)),
                       half_minor * math.sin(deg2rad(alpha)), theta)
         for alpha in angles
     ]
     if not clockwise:
         xsign = -1
         ysign = 1
     else:
         xsign = 1
         ysign = -1
     i = half_minor * math.sin(deg2rad(theta)) * xsign + i
     j = half_minor * math.cos(deg2rad(theta)) * ysign + j
     coords = [(i + x, j + y) for x, y in coords]
     coord = coords[0]
     self._line_to(coord[0], coord[1], no_stroke=True)
     for x, y in coords:
         self._line_to(x, y, no_stroke=True)
Ejemplo n.º 6
0
 def elliptic_arc_(self, rx, ry, angle, clockwise, cy):
     """
     Plot an elliptic arc.
     """
     xrot = 90
     orig_angle = angle
     angle = angle % 360
     if angle == 0 and orig_angle != 0:
         angle = 360
     if angle > 180.0:
         large_arc = 1
     else:
         large_arc = 0
     if clockwise:
         sweep_flag = 0
     else:
         sweep_flag = 1
     if angle <= 90:
         ysign = -1
     else:
         ysign = 1
     cx = 0
     #cy = 0
     #x, y = 0, ry
     x, y = 0, cy + ry
     if clockwise:
         theta = angle + 90
     else:
         theta = -angle + 90
     theta_rad = deg2rad(theta)
     cost = math.cos(theta_rad)
     sint = math.sin(theta_rad)
     xd = cx - rx * cost
     yd = cy + ry * sint
     if not clockwise:
         x, y = rotate_coords(cx, cy, x, y, 180)
         xd, yd = rotate_coords(cx, cy, xd, yd, 180)
     component = self.screen.drawing.path()
     command = "M {} {}".format(x, y)
     component.push(command)
     command = "A {} {} {} {} {} {} {}".format(abs(ry), abs(rx), xrot,
                                               large_arc, sweep_flag, xd,
                                               yd)
     component.push(command)
     return component, (xd, yd)