Beispiel #1
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)
Beispiel #2
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)
        
Beispiel #3
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)
Beispiel #4
0
 def write(self,
           text,
           move=False,
           align='left',
           font=('Arial', 8, 'normal')):
     """
     Write text to the image.
     """
     if move:
         raise errors.LogoError(
             "Moving the turtle to the end of the text is not supported by the SVG Turtle back end."
         )
     x, y = self._pos
     x, y = rotate_coords(0, 0, y, x, -90)
     txt_obj = self.screen.drawing.text(text, insert=(x, y))
     txt_obj['fill'] = self._pencolor
     txt_obj['text-anchor'] = self._text_alignments[align]
     font_face, font_size, font_weight = font
     txt_obj['style'] = "font-family:{};font-weight:{};".format(
         font_face, font_weight)
     txt_obj['font-size'] = "{}pt".format(font_size)
     txt_obj['transform'] = "matrix(0 1 1 0 0 0) rotate(90)"
     self._components.append(txt_obj)
Beispiel #5
0
def cartesian2svg(x, y):
    return rotate_coords(0, 0, y, x, -90)
Beispiel #6
0
def svg2cartesian(x, y):
    return rotate_coords(0, 0, y, x, 90)
Beispiel #7
0
    def ellipse(self, major, minor, angle=360, clockwise=True):
        """
        Plot an ellipse or an arc of an ellipse with axes of length `major`
        and `minor`.  The arc will start at the turtle current position.
        The final position will be located `angle` degrees from the line that 
        joins the starting position and the center of the ellipse in a direction
        determined by `clockwise`.
        """
        x, y = self._pos
        heading = self._heading
        rx = major / 2
        ry = minor / 2
        ps = self._pensize
        # Assume current position is center of ellipse, then translate.
        if clockwise:
            yoff = -ry
        else:
            yoff = ry
        # Choose component to use.
        if angle != 0 and (angle % 360 == 0):
            component = self.screen.drawing.ellipse((0, yoff), (rx, ry))
            xd, yd = x, y
        else:
            component, (xd, yd) = self.elliptic_arc_(rx, ry, angle, clockwise,
                                                     yoff)
            xdp, ydp = xd, yd
            xdp, ydp = rotate_coords(0, 0, xdp, ydp, heading)
            xdp = xdp + x
            ydp = ydp + y
            #self._line_to(xdp, ydp, no_stroke=True)
            self.ellipse_simulation_(major, minor, angle, clockwise)
            if clockwise:
                self._heading = heading - angle
            else:
                self._heading = heading + angle
        # Component needs to be oriented and translated.
        transform = "translate({} {}) rotate({})".format(x, y, heading)
        component['transform'] = transform
        component['stroke'] = self._pencolor
        component['stroke-width'] = self._pensize
        component['fill-opacity'] = 1
        component['class'] = 'no-fill'
        if self._fill_mode == 'unfill':
            self.add_hole_component_(component)
        elif self._fill_mode == 'fill':
            self._filled_components.append(component)
            component['class'] = 'fill'
            component['fill-opacity'] = 1
        else:
            component['class'] = 'no-fill'
            component['fill-opacity'] = 0
            self._components.append(component)

        # Compute bounds.
        # 1) Compute the center.
        cx = 0
        cy = yoff
        cx, cy = rotate_coords(0, 0, cx, cy, heading)
        cx += x
        cy += y
        ps = self._pensize
        max_radius = max(abs(rx), abs(ry))
        west = cx - max_radius
        east = cx + max_radius
        north = -(cy + max_radius)
        south = -(cy - max_radius)
        self._adjust_bounds(east - ps, north - ps)
        self._adjust_bounds(west + ps, south + ps)