예제 #1
0
파일: drawer.py 프로젝트: AntipovDen/XdivK
def pipe(x0, y0, x1, y1, x2, y2, x3, y3, c, x):
    c.stroke(
        path.curve(x0, y0, x1, y1, x2, y2, x3, y3),
        [color.rgb.black, style.linewidth(width=0.6 * x / 24)])
    c.stroke(path.curve(x0, y0, x1, y1, x2, y2, x3, y3),
             [color.cmyk.RoyalBlue,
              style.linewidth(width=0.5 * x / 24)])
예제 #2
0
    def draw_sector(self, end):
        """draw the sector"""
        segment = path.path(
            path.arc(self.xo, self.yo, self.inner_r, self.start_angle,
                     self.end_angle),
            path.arcn(self.xo, self.yo, self.sector_width + self.inner_r,
                      self.end_angle, self.start_angle), path.closepath())
        self.shape_canvas.fill(segment, [self.sector_color])

        # draw a delimiting line between sectors
        line_color = color.gray(0.15)
        if end and (self.end_angle - self.start_angle) < 0.25:
            line_color = color.rgb.red

        r = self.inner_r + self.sector_width
        start_radians = self.start_angle * pi / 180.0
        end_radians = self.end_angle * pi / 180.0
        x0 = self.inner_r * cos(start_radians) + self.xo
        y0 = self.inner_r * sin(start_radians) + self.yo
        x1 = r * cos(start_radians) + self.xo
        y1 = r * sin(start_radians) + self.yo

        self.shape_canvas.stroke(path.line(x0, y0, x1, y1),
                                 [style.linewidth(0.01), line_color])

        x0 = self.inner_r * cos(end_radians) + self.xo
        y0 = self.inner_r * sin(end_radians) + self.yo
        x1 = r * cos(end_radians) + self.xo
        y1 = r * sin(end_radians) + self.yo

        self.shape_canvas.stroke(path.line(x0, y0, x1, y1),
                                 [style.linewidth(0.01), line_color])
예제 #3
0
def draw_crs_to_canvas(c, crs: torch.Tensor, lw=1, lcols=None, alpha=0.5):
    # crs [n, nc, 2]; only draw nc>1<nc-1
    if crs is None:
        return

    n, nc, _ = crs.shape

    # Premultiplied power constant for the following tj() function.
    alpha = alpha / 2

    def tj(ti, pi, pj):
        return ((pi - pj)**2).sum(dim=-1)**alpha + ti

    if lcols is not None:
        lcols = lcols.detach().cpu()

    if crs is not None:
        crs = crs.detach().cpu()

        for i in range(n):
            _lw = lw[i] if isinstance(lw, torch.Tensor) else lw
            if _lw > 1e-3:
                for j in range(nc - 4 + 1):
                    p0 = crs[i, j + 0]
                    p1 = crs[i, j + 1]
                    p2 = crs[i, j + 2]
                    p3 = crs[i, j + 3]

                    t0 = 0
                    t1 = tj(t0, p0, p1)
                    t2 = tj(t1, p1, p2)
                    t3 = tj(t2, p2, p3)

                    c1 = (t2 - t1) / (t2 - t0)
                    c2 = (t1 - t0) / (t2 - t0)
                    d1 = (t3 - t2) / (t3 - t1)
                    d2 = (t2 - t1) / (t3 - t1)

                    m1 = (t2 - t1) * (c1 * (p1 - p0) / (t1 - t0) + c2 *
                                      (p2 - p1) / (t2 - t1))
                    m2 = (t2 - t1) * (d1 * (p2 - p1) / (t2 - t1) + d2 *
                                      (p3 - p2) / (t3 - t2))

                    q0 = p1
                    q1 = p1 + m1 / 3
                    q2 = p2 - m2 / 3
                    q3 = p2

                    curve = path.curve(q0[1], -q0[0], q1[1], -q1[0], q2[1],
                                       -q2[0], q3[1], -q3[0])
                    if lcols is None:
                        c.stroke(curve,
                                 [style.linewidth(_lw), style.linecap.round])
                    else:
                        c.stroke(curve, [
                            style.linewidth(_lw), style.linecap.round,
                            color.rgb(*lcols[i])
                        ])
예제 #4
0
def test_pie(radius, start, end):
    c = canvas.canvas()
    container = path.rect(-(radius + 1), -(radius + 1), 2 * (radius + 1),
                          2 * (radius + 1))

    c.stroke(container, [style.linewidth(0.001), color.rgb.red])

    pie = path.path(path.moveto(0, 0), path.arc(0, 0, radius, start, end),
                    path.closepath())

    c.stroke(pie, [
        style.linewidth(0.1),
        pyx.color.rgb(1, 1, 1),
        deco.filled([color.rgb.red])
    ])
    c.writeSVGfile("figure")
예제 #5
0
    def signature(self, deg_max=6, padded=False, has_border=False):
        """ For a visualization of glyphs, lay out in a 2D grid PNG file. """
        self.scale()
        sig = canvas.canvas([trafo.rotate(90), trafo.mirror(0)])
        scale = 1.5
        if padded or has_border:
            sig_margin = 0.2
            x = (deg_max + 1) * scale + (1.5 * sig_margin)
            border_path = path.path(path.moveto(0, 0), path.lineto(0, x),
                                    path.lineto(x, x), path.lineto(x, 0),
                                    path.closepath())
            if padded:
                border_color = color.cmyk.White
            if has_border:
                border_color = color.cmyk.Gray
            sig.stroke(border_path, [
                border_color,
                trafo.translate(-sig_margin * 2, -sig_margin * 2),
                style.linewidth(.025)
            ])

        for index in self.glist:
            if len(index) > 2:
                c = degree_glyph(index[0], index[1], index[2],
                                 (self.mincount, self.maxcount))
            else:
                c = degree_glyph(index[0], index[1], 1,
                                 (self.mincount, self.maxcount))
            sig.insert(c,
                       [trafo.translate(index[0] * scale, (index[1]) * scale)
                        ])  # text writing requires full latex
        return sig
예제 #6
0
파일: drawer.py 프로젝트: AntipovDen/XdivK
def state(x0, y0, r, c):
    x1 = x0 - r / sqrt(2)
    y1 = y0 + r / sqrt(2)
    x2 = x0 - 3 * r / 4 / sqrt(2)
    y2 = y1 + r / 8
    x3 = x0 - r / 4 / sqrt(2)
    y3 = y1 - r / 8
    x4 = x0 + r / 4 / sqrt(2)
    y4 = y1 + r / 8
    x5 = x0 + 3 * r / 4 / sqrt(2)
    y5 = y1 - r / 8
    x6 = x0 + r / sqrt(2)
    y6 = y1
    delta = r / 40

    c.fill(path.circle(x0, y0, r), [color.cmyk.RoyalBlue])
    c.fill(path.rect(x1 + delta, y0 + delta,
                     r * sqrt(2) - 2 * delta, r), [color.rgb.white])

    inside = path.curve(x1, y1, x2, y2, x3, y3, x0, y1) << \
             path.curve(x0, y1, x4, y4, x5, y5, x6, y6) << \
             path.line(x6, y6, x6, y0) << \
             path.line(x6, y0, x1, y0)
    inside.append(path.closepath())
    c.fill(inside, [color.cmyk.RoyalBlue])
    c.stroke(path.circle(x0, y0, r), [style.linewidth(r / 25)])
예제 #7
0
    def draw(self):
        """draw the text!!"""

        for layer in self.sectors:
            radius = self.sectors[layer]['radius']
            letter_radius = radius + 0.25 * self.sector_width

            prev_radian = 0
            for radian in self.sectors[layer]['letters']:
                end = False
                letter = self.sectors[layer]['letters'][radian][0]
                if len(letter) > 1:
                    end = True
                freq = self.sectors[layer]['letters'][radian][1]

                offset = False
                cur_radian = radian

                if (radian - prev_radian) * letter_radius < 0.22:
                    cur_radian = prev_radian + 0.22 / letter_radius
                    prev_radian = cur_radian
                    offset = True

                centroid_x = radius * cos(radian) + self.xo
                centroid_y = radius * sin(radian) + self.yo
                if end:
                    letter_x = radius * cos(cur_radian) + self.xo
                    letter_y = radius * sin(cur_radian) + self.yo
                else:
                    letter_x = letter_radius * cos(cur_radian) + self.xo
                    letter_y = letter_radius * sin(cur_radian) + self.yo

                # rotate the text accordingly
                transform = trafo.rotate(radian * 180 / pi)

                if cur_radian > pi / 2 and cur_radian < (3 * pi / 2):
                    transform = trafo.rotate(180 + radian * 180 / pi)

                # if this condition is true then the letter is actually the
                # whole word, it is an end sector, so display the frequency
                if len(letter) > 1:
                    letter += ' '
                    letter += str(freq)

                # the random floats are me tuning the color just right lol
                text_color = color.rgb(0, 0.0784 * 1.4, 0.156 * 1.4)
                self.canvas.text(
                    letter_x, letter_y, r"\texttt{" + letter + '}', [
                        text.halign.center, text.valign.middle, transform,
                        text.size.scriptsize, text_color
                    ])
                if offset:
                    self.canvas.stroke(
                        path.line(centroid_x, centroid_y, letter_x, letter_y),
                        [style.linewidth(0.0035), text_color])
                self.canvas.fill(path.circle(centroid_x, centroid_y, 0.0065),
                                 [text_color])
                prev_radian = cur_radian
예제 #8
0
    def draw_extra(self, canvas, linewidth=0.3, color=None):
        if color is None:
            color = self.color

        if self.drawn_extra == False:
            for p in self.paths_extra:
                canvas.stroke(p.transformed(trafo.translate(*self.head)), [
                    style.linecap.round,
                    style.linewidth(linewidth), style.linejoin.round, color
                ])
            self.drawn_extra = True
예제 #9
0
    def draw_dot(self, canvas, linewidth=0.3, color=None, dot=P(0, 0)):
        if color is None:
            color = self.color

        p = pyx.path.path(pyx.path.moveto(*dot),
                          pyx.path.rlineto(*PP(0.1, -45)))

        canvas.stroke(p.transformed(trafo.translate(*self.head)), [
            style.linecap.round,
            style.linewidth(linewidth), style.linejoin.round, color
        ])
예제 #10
0
def pLine(canv, pt, r, fi, linewidth=LINE_DEF_WIDTH, marks=False):

    pta = pt
    ptb = pPoint(r, fi, pt)

    line = path.line(pta.x, pta.y, ptb.x, ptb.y)

    canv.stroke(line, [style.linewidth(linewidth)])

    if marks:
        pta.mark(canv)
        ptb.mark(canv)
def setEtch(canvas):
    if hasattr(canvas, 'items'):
        for c in canvas.items:
            setEtch(c)
    else:
        canvas.strokestyles = [
            style.linewidth(0.001),
            color.rgb.blue
        ]
        canvas.fillstyles = [
            color.rgb.white
        ]
예제 #12
0
    def draw(self, canvas, linewidth=0.3, color=None):
        if color is None:
            color = self.color

        for p in self.paths:
            tmp = p.transformed(trafo.translate(*self.head))
            canvas.stroke(tmp, [
                style.linecap.round,
                style.linewidth(linewidth), style.linejoin.round, color
            ])

        self.drawn = True
예제 #13
0
def draw_pie(c, radius, start, end):
    pie = path.path(path.moveto(0, 0), path.arc(0, 0, radius, start, end),
                    path.closepath())

    hue = (start + end) / (360 * 2)
    color = pyx.color.hsb(hue, 0.8, 0.8)

    c.stroke(
        pie,
        [style.linewidth(0.01),
         pyx.color.rgb(1, 1, 1),
         deco.filled([color])])
예제 #14
0
    def display(self):
        """method to display the sector"""

        # draw the segment
        if self.level == 0:
            # don't draw anything in the center
            return

        if self.letter == '':
            self.sunburst.text_object.update(
                self.level, self.path[6:],
                (self.centroid_radians,
                 self.inner_r + 0.5 * self.sector_width), self.freq)
        else:
            self.sunburst.text_object.update(
                self.level, self.letter,
                (self.centroid_radians,
                 self.inner_r + 0.5 * self.sector_width), self.freq)

        if self.letter == '':
            self.draw_sector(True)
        else:
            self.draw_sector(False)

        if self.level == 1:
            # don't draw lines to nothing
            return

        # draw the bezier
        x0 = (self.inner_r + 0.05) * cos(self.centroid_radians) + self.xo
        y0 = (self.inner_r + 0.05) * sin(self.centroid_radians) + self.yo

        r = self.parent_outer_radius
        x1 = r * cos(self.centroid_radians) + self.xo
        y1 = r * sin(self.centroid_radians) + self.yo

        delta = 0.1 * (self.centroid_radians - self.parent_centroid_radian)

        r = self.inner_r
        x2 = r * cos(self.parent_centroid_radian + delta) + self.xo
        y2 = r * sin(self.parent_centroid_radian + delta) + self.yo

        x3 = self.parent_outer_radius * cos(self.parent_centroid_radian +
                                            delta) + self.xo
        y3 = self.parent_outer_radius * sin(self.parent_centroid_radian +
                                            delta) + self.yo

        sector_len = (self.end_angle -
                      self.start_angle) * self.inner_r * pi / 180.0
        self.shape_canvas.stroke(
            path.curve(x0, y0, x1, y1, x2, y2, x3, y3),
            [style.linewidth(0.05 * sector_len), self.sector_color])
예제 #15
0
def Line(canv,
         pta,
         ptb,
         linewidth=LINE_DEF_WIDTH,
         color=LINE_DEF_COLOR,
         marks=False):
    line = path.line(pta.x, pta.y, ptb.x, ptb.y)

    canv.stroke(line, [style.linewidth(linewidth), color])

    if marks:
        pta.mark(canv)
        ptb.mark(canv)
예제 #16
0
def draw_lines_to_canvas(c, lines: torch.Tensor, lw=1, lcols=None):
    if lcols is not None:
        lcols = lcols.detach().cpu()

    if lines is not None:
        lines = lines.detach().cpu()
        for i in range(lines.shape[0]):
            _lw = lw[i] if isinstance(lw, torch.Tensor) else lw
            if _lw > 0:
                if lcols is None:
                    c.stroke(
                        path.line(lines[i, 0, 1], -lines[i, 0, 0],
                                  lines[i, 1, 1], -lines[i, 1, 0]),
                        [style.linewidth(_lw), style.linecap.round])
                else:
                    c.stroke(
                        path.line(lines[i, 0, 1], -lines[i, 0, 0],
                                  lines[i, 1, 1], -lines[i, 1, 0]),
                        [
                            style.linewidth(_lw), style.linecap.round,
                            color.rgb(*lcols[i])
                        ])
예제 #17
0
def earrowLine(canv,
               pta,
               ptb,
               linewidth=LINE_DEF_WIDTH,
               color=LINE_DEF_COLOR,
               marks=False):

    line = path.line(pta.x, pta.y, ptb.x, ptb.y)

    arrow_type = deco.earrow([deco.stroked([color])], size=10)

    canv.stroke(line, [style.linewidth(linewidth), color, arrow_type])
    if marks:
        pta.mark(canv)
def generate_tile(item):
    title = item['title']
    print(title)
    image = item['image']

    if item['quantity'] > 1:
        handle_multiple(item)
        return

    #72dpi is illustrator default
    drawing = svgfile.svgfile(0, 0, 'images%s' % image, parsed=True, resolution=72)
    setEtch(drawing.canvas)
    canvas_size = get_canvas_size(item)
    drawing_size = (drawing.bbox().width(), drawing.bbox().height())

    dir = 'tiles/%s' % item['type']
    if not os.path.exists(dir):
        os.makedirs(dir)
    c = canvas.canvas()

    center = ( (canvas_size[0] - drawing_size[0]) / 2, (canvas_size[1] - drawing_size[1]) / 2 )
    c.insert(drawing, [trafo.translate(center[0], center[1])])

    yMargin = (canvas_size[1] - drawing_size[1]) / 2
    yPos = yMargin - yMargin / 2
    baseline = text.parbox.middle
    textbox = '{\large %s}' % title
    if 'subtitle' in item:
        textbox += '\n\n'
        textbox += item['subtitle']

    if yPos < (unit.t_inch / 2):
        baseline = text.parbox.bottom

    c.text(canvas_size[0] / 2, yPos, textbox, [
            text.halign.boxcenter,
            text.halign.flushcenter,
            text.parbox(canvas_size[0] - .25 * unit.t_inch, baseline = baseline)
    ])

    #draw Cut line
    if CUT_LINE:
        c.stroke(
            path.rect(0, 0, canvas_size[0], canvas_size[1]),
            [ style.linewidth(0.001), color.rgb.red ]
        )

    p = document.page(c, bbox=bbox.bbox(0, 0, canvas_size[0], canvas_size[1]))
    d = document.document([p])
    d.writeSVGfile('%s/%s.svg' % (dir, slugify(title)))
예제 #19
0
def cluster_sunburst(organism, graph, method):
    c = canvas.canvas()

    core_length = 5
    recurse_sunburst(c, graph, core_length, 0, 360)
    core = path.circle(0, 0, core_length)
    c.stroke(core, [
        style.linewidth(0.1),
        pyx.color.rgb(1, 1, 1),
        deco.filled([pyx.color.rgb(1, 1, 1)])
    ])

    file_name = '{}-{}-clusters_sunburst.svg'.format(organism.org_id, method)
    with open(utils.join_path(cs.SVG_PATH, file_name), 'wb') as svg:
        c.writeSVGfile(svg)
예제 #20
0
def draw_line_segments(lines: torch.Tensor, filename, lw=1, svg=False):
    c = canvas.canvas()

    lines = lines.detach().cpu()
    lw = style.linewidth(lw)

    for i in range(lines.shape[0]):
        c.stroke(
            path.line(lines[i, 0, 1], -lines[i, 0, 0], lines[i, 1, 1],
                      -lines[i, 1, 0]), [lw, style.linecap.round])

    if svg:
        c.writeSVGfile(file=filename)
    else:
        c.writePDFfile(file=filename)
예제 #21
0
def RectMid(canv,
            pt,
            w,
            h,
            fi=0,
            linewidth=LINE_DEF_WIDTH,
            linecolor=LINE_DEF_COLOR,
            fillcolor=None,
            mstyle=[]):

    rect = path.rect(pt.x, pt.y - h / 2, w, h)

    rto = trafo.rotate(fi, pt.x, pt.y)

    if fillcolor is not None:
        canv.fill(rect, [fillcolor, rto])

    canv.stroke(rect, [style.linewidth(linewidth), linecolor, rto] + mstyle)
예제 #22
0
def generate_diagrams(data, shape_canvas, text_canvas, settings, source_path):
    diagrams = {}
    # draw bounding box so the file is the right size and shape
    x = settings['output']['x']
    y = settings['output']['y']

    # draw the bounding box
    shape_canvas.stroke(
        path.rect(-0.25 * x, -0.5 * y, x, y),
        [color.rgb.white, style.linewidth(0.001)])
    for entry in data:
        name = entry[0]
        origin = entry[1]
        data_source = entry[2]
        diagrams[name] = Sunburst(shape_canvas, text_canvas, settings,
                                  source_path, name, origin, data_source)
        diagrams[name].draw()
        stop_trace()
    return diagrams
예제 #23
0
def degree_glyph(indegree, outdegree, degreecount=1, degreerange=(1, 3)):
    """Return an igraph canvas glyph image based on indegree, outdegree."""
    canvas_ = canvas.canvas()
    # box color - turn border off and on
    #   off, variable 1, solid 2, type colors 3
    boxcolorflag = 3
    # fill color - turn color background off and on
    #   background off 0, variable red 1, type colors 2
    fillcolorflag = 2

    cmin = max([degreerange[0], 1])
    cmax = degreerange[1]
    cnorm = float(0)
    try:
        # norm = x[i]−min(x) / (max(x)−min(x))
        cnorm = float(degreecount - cmin) / float(cmax - cmin)
    except ZeroDivisionError:
        cnorm = float(0)

    if fillcolorflag == 1:
        if cnorm > 0:
            logging.debug('cmin/cmax: %s %s    cnorm: %s', str(cmin),
                          str(cmax), str(cnorm))
            canvas_.fill(path.rect(0, 0, 1, 1),
                         [color.gradient.WhiteRed.getcolor(cnorm)])
    elif fillcolorflag == 2:
        if (indegree == 0) and (outdegree == 0):
            fillcolor = color.cmyk.White
        elif indegree == 0:
            fillcolor = color.cmyk.Green
        elif indegree == 1 and outdegree == 1:
            fillcolor = color.cmyk.Yellow
        elif outdegree == 0:
            fillcolor = color.cmyk.Red
        elif indegree == 1 and outdegree > 1:
            fillcolor = color.cmyk.ProcessBlue
        elif indegree > 1 and outdegree == 1:
            fillcolor = color.cmyk.Orange
        elif indegree > 1 and outdegree > 1:
            fillcolor = color.cmyk.Orchid
        else:
            fillcolor = color.cmyk.Black
        canvas_.fill(path.rect(0, 0, 1, 1), [fillcolor])

    dg_box = path.path(path.moveto(0, 0), path.lineto(0, 1), path.lineto(1, 1),
                       path.lineto(1, 0), path.lineto(0, 0), path.closepath())

    if boxcolorflag == 1:
        boxcolor = color.cmyk(0, 0, 0, 0.25)
        if (indegree == 0) and (outdegree == 0):
            boxcolor = color.cmyk.White
        elif indegree == 0:
            boxcolor = color.cmyk.YellowGreen
        elif outdegree == 0:
            boxcolor = color.cmyk.RedOrange
        # draw manual bounding box
        canvas_.stroke(dg_box, [boxcolor, style.linewidth(.1)])

    elif boxcolorflag == 2:
        boxcolor = color.cmyk.Gray  # Black
    elif boxcolorflag == 3:
        if (indegree == 0) and (outdegree == 0):
            boxcolor = color.cmyk.White
        elif indegree == 0:
            boxcolor = color.cmyk.Green
        elif indegree == 1 and outdegree == 1:
            boxcolor = color.cmyk.Yellow
        elif outdegree == 0:
            boxcolor = color.cmyk.Red
        elif indegree == 1 and outdegree > 1:
            boxcolor = color.cmyk.ProcessBlue
        elif indegree > 1 and outdegree == 1:
            boxcolor = color.cmyk.Orange
        elif indegree > 1 and outdegree > 1:
            boxcolor = color.cmyk.Orchid
        else:
            boxcolor = color.cmyk.Black
    if boxcolorflag == 2 or boxcolorflag == 3:
        # reset box wider for cutter
        dg_box = path.path(path.moveto(-0.2, -0.2), path.lineto(-0.2, 1.2),
                           path.lineto(1.2, 1.2), path.lineto(1.2, -0.2),
                           path.lineto(-0.2, -0.2), path.closepath())
        # draw manual bounding box
        canvas_.stroke(dg_box, [boxcolor, style.linewidth(.05)])

    node_dot = path.circle(.5, .5, .15)
    canvas_.fill(node_dot)

    if indegree > 0:
        gp = path.path(path.moveto(0.5, 0.5), path.lineto(0.5, 0.75))  # stub
        canvas_.stroke(gp, [style.linewidth(.1)])
        if indegree == 1:
            gp = path.path(path.moveto(0.5, 0.5),
                           path.lineto(0.5, 1.0))  # indegree 1
            canvas_.stroke(gp, [style.linewidth(0.1)])
        else:
            gp = path.path(
                path.moveto(0.5, 0.75),
                path.lineto(0.0, 0.75),  # crossbar
                path.lineto(1.0, 0.75))
            canvas_.stroke(gp, [style.linewidth(.1)])
        if indegree > 1:
            logging.debug(range(0, indegree))
            for line in range(0, indegree):
                linef = float(line)
                indegreef = float(indegree - 1)
                logging.debug(linef, indegreef, linef / indegreef)
                gp = path.path(
                    path.moveto(linef / indegreef, 1.00),
                    path.lineto(linef / indegreef,
                                0.75),  # line for each indegree
                    path.lineto(0.50, 0.75))  # round off the corner
                canvas_.stroke(gp, [style.linewidth(.1)])

    if outdegree > 0:
        gp = path.path(path.moveto(0.50, 0.50), path.lineto(0.50,
                                                            0.25))  # stub
        canvas_.stroke(gp, [style.linewidth(.1)])
        if outdegree == 1:
            gp = path.path(path.moveto(0.50, 0.50),
                           path.lineto(0.50, 0.00))  # outdegree 1
            canvas_.stroke(gp, [style.linewidth(.1)])
        else:
            gp = path.path(
                path.moveto(0.50, 0.25),
                path.lineto(0.00, 0.25),  # crossbar
                path.lineto(1.00, 0.25))
            canvas_.stroke(gp, [style.linewidth(0.10)])
        if outdegree > 1:
            logging.debug(range(0, outdegree))
            for line in range(0, outdegree):
                linef = float(line)
                outdegreef = float(outdegree - 1)
                logging.debug(linef, outdegreef, linef / outdegreef)
                gp = path.path(
                    path.moveto(linef / outdegreef, 0.00),
                    path.lineto(linef / outdegreef,
                                0.25),  # line for each outdegree
                    path.lineto(0.50, 0.25))  # round off the corner
                canvas_.stroke(gp, [style.linewidth(0.10)])

    return canvas_
예제 #24
0
def draw_continent_circle(con,
                          name="",
                          draw_upper_landscape=True,
                          draw_lower_landscape=False,
                          draw_upper_green=True,
                          draw_lower_purple=False,
                          draw_train_tracks=False,
                          draw_foliation=True,
                          foliation_style_old=False,
                          foliation_style_split=False,
                          foliation_style_cusp_leaves=True,
                          foliation_style_boundary_leaves=True,
                          shade_triangles=False,
                          draw_fund_domain=False,
                          fund_dom_tets=None,
                          draw_fund_domain_edges=False,
                          draw_tetrahedron_rectangles=[]):

    global_scale_up = 10.0
    edge_thickness = 0.02
    track_thickness = 0.02
    leaf_thickness = 0.03
    edge_colours = {
        True: color.rgb(0.9, 0.3, 0),
        False: color.rgb(0, 0.3, 0.9)
    }
    green = color.rgb(0.0, 0.5, 0.0)
    purple = color.rgb(0.5, 0.0, 0.5)

    scl = trafo.trafo(matrix=((global_scale_up, 0), (0, global_scale_up)),
                      vector=(0, 0))
    canv = canvas.canvas()
    canv.stroke(path.circle(0, 0, global_scale_up), [style.linewidth(0.02)])

    n = len(con.coast)
    for v in con.coast:
        i = v.coastal_index
        t = 2 * pi * float(i) / float(n)
        v.circle_pos = complex(cos(t), sin(t))
        vert_pos = v.circle_pos * 1.01 * global_scale_up
        canv.text(vert_pos.real,
                  vert_pos.imag,
                  "$" + str(con.vertices.index(v)) + "$",
                  textattrs=[
                      text.size(-4), text.halign.left, text.valign.middle,
                      trafo.rotate(
                          (180 / pi) * atan2(vert_pos.imag, vert_pos.real))
                  ])

        # vert_pos2 = v.circle_pos * 1.2 * global_scale_up
        # p = path.path(path.moveto(vert_pos.real, vert_pos.imag), path.lineto(vert_pos2.real, vert_pos2.imag))
        # canv.stroke(p, [deco.curvedtext("$"+str(con.vertices.index(v))+"$")])

    ### highlight vertices of tetrahedra in a fundamental domain
    if draw_fund_domain:
        if fund_dom_tets == None:
            fund_dom_tets = get_fund_domain_tetrahedra(con)
        for con_tet in fund_dom_tets:
            if type(
                    con_tet
            ) == continent_tetrahedron:  ### could be an integer if we didnt find this tet
                if draw_fund_domain_edges:
                    for e in con_tet.edges():
                        col = edge_colours[e.is_red]
                        u, v = e.vertices
                        p = make_arc(u.circle_pos, v.circle_pos)
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(edge_thickness),
                            style.linecap.round, col
                        ])

        update_fund_dom_tet_nums(con, fund_dom_tets)
        for v in [v for v in con.coast if v.fund_dom_tet_nums != []]:
            vert_pos = v.circle_pos * 1.03 * global_scale_up
            canv.text(vert_pos.real,
                      vert_pos.imag,
                      "$" + str(v.fund_dom_tet_nums) + "$",
                      textattrs=[
                          text.size(-4), text.halign.left, text.valign.middle,
                          trafo.rotate(
                              (180 / pi) * atan2(vert_pos.imag, vert_pos.real))
                      ])

    # lower_colours = {True: color.rgb(0.5,0.3,0), False: color.rgb(0,0.3,0.5)}
    # upper_colours = {True: color.rgb(0.9,0.3,0), False: color.rgb(0,0.3,0.9)}

    landscape_edges = [con.lower_landscape_edges, con.upper_landscape_edges]

    # colours = [lower_colours, upper_colours]

    upper_tris = con.upper_landscape_triangles
    lower_tris = con.lower_landscape_triangles
    boundary_tris = [lower_tris, upper_tris]

    if shade_triangles:
        u, v, w = con.triangle_path[0].vertices
        p = make_arc(u.circle_pos, v.circle_pos)
        q = make_arc(v.circle_pos, w.circle_pos)
        r = make_arc(w.circle_pos, u.circle_pos)
        p.append(q[1])
        p.append(r[1])  ### remove extraneous moveto commands
        p = p.transformed(scl)
        canv.stroke(
            p, [deco.filled([color.transparency(0.8)]),
                style.linewidth(0)])
        u, v, w = con.triangle_path[-1].vertices
        p = make_arc(u.circle_pos, v.circle_pos)
        q = make_arc(v.circle_pos, w.circle_pos)
        r = make_arc(w.circle_pos, u.circle_pos)
        p.append(q[1])
        p.append(r[1])  ### remove extraneous moveto commands
        p = p.transformed(scl)
        canv.stroke(
            p, [deco.filled([color.transparency(0.8)]),
                style.linewidth(0)])
        # for triangle in con.triangle_path:
        #     u,v,w = triangle.vertices
        #     p = make_arc(u.circle_pos, v.circle_pos)
        #     q = make_arc(v.circle_pos, w.circle_pos)
        #     r = make_arc(w.circle_pos, u.circle_pos)
        #     p.append(q[1])
        #     p.append(r[1])  ### remove extraneous moveto commands
        #     p = p.transformed(scl)
        #     canv.stroke(p, [deco.filled([color.transparency(0.8)]), style.linewidth(0)])

    to_do = []
    if draw_lower_landscape:
        to_do.append(0)
    if draw_upper_landscape:
        to_do.append(1)
    for i in to_do:
        for e in landscape_edges[i]:
            col = edge_colours[e.is_red]
            transp = []
            if i == 0:
                transp = [color.transparency(0.75)]
            u, v = e.vertices
            p = make_arc(u.circle_pos, v.circle_pos)
            p = p.transformed(scl)
            canv.stroke(
                p,
                [style.linewidth(edge_thickness), style.linecap.round, col] +
                transp)
        for tri in boundary_tris[i]:
            center = incenter(tri.vertices[0].circle_pos,
                              tri.vertices[1].circle_pos,
                              tri.vertices[2].circle_pos)
            # canv.fill(path.circle(global_scale_up*center[0], global_scale_up*center[1], 0.1))
            canv.text(global_scale_up * center[0],
                      global_scale_up * center[1],
                      "$" + str(tri.index) + "$",
                      textattrs=[
                          text.size(-2), text.halign.center, text.valign.middle
                      ] + transp)

    ### train tracks...

    purple_train_routes = [
    ]  ### pairs of coastal edges corresponding to a train route
    green_train_routes = []
    if draw_lower_purple:
        if draw_train_tracks:
            for tri in lower_tris:
                midpts = []
                is_reds = []
                for e in tri.edges:
                    is_reds.append(e.is_red)
                    u, v = e.vertices
                    p, midpt = make_arc(u.circle_pos,
                                        v.circle_pos,
                                        return_midpt=True)
                    midpts.append(midpt)
                for i in range(3):
                    if (is_reds[i] == is_reds[(i + 1) % 3]) or (
                            not is_reds[i] and is_reds[(i + 1) % 3]):
                        p = make_arc(midpts[i], midpts[(i + 1) % 3])
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(track_thickness),
                            style.linecap.round, purple
                        ])
        if draw_foliation:
            for edge in con.lower_landscape_edges:
                leaf_end_edges = []
                if edge.is_coastal():
                    if not edge.is_coastal_sink(upper=False):
                        leaf_end_edges.append(edge)
                        for tri in edge.boundary_triangles:
                            if not tri.is_upper:
                                last_tri = con.flow(tri)[0]
                                last_edge = last_tri.edges[
                                    last_tri.downriver_index()]
                                leaf_end_edges.append(last_edge)
                else:
                    if edge.is_watershed():
                        for tri in edge.boundary_triangles:
                            last_tri = con.flow(tri)[0]
                            last_edge = last_tri.edges[
                                last_tri.downriver_index()]
                            leaf_end_edges.append(last_edge)
                if len(leaf_end_edges) == 2:
                    purple_train_routes.append(leaf_end_edges)
                    if foliation_style_old:
                        leaf_ends = []
                        for e in leaf_end_edges:
                            endpts = e.vertices
                            _, midpt = make_arc(endpts[0].circle_pos,
                                                endpts[1].circle_pos,
                                                return_midpt=True)
                            leaf_ends.append(midpt)
                        p = make_arc(leaf_ends[0], leaf_ends[1])
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, purple
                        ])

    if draw_upper_green:
        if draw_train_tracks:
            for tri in upper_tris:
                midpts = []
                is_reds = []
                for e in tri.edges:
                    is_reds.append(e.is_red)
                    u, v = e.vertices
                    p, midpt = make_arc(u.circle_pos,
                                        v.circle_pos,
                                        return_midpt=True)
                    midpts.append(midpt)
                for i in range(3):
                    if (is_reds[i] == is_reds[(i + 1) % 3]) or (
                            is_reds[i] and not is_reds[(i + 1) % 3]):
                        p = make_arc(midpts[i], midpts[(i + 1) % 3])
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(track_thickness),
                            style.linecap.round, green
                        ])
        if draw_foliation:
            for edge in con.upper_landscape_edges:
                leaf_end_edges = []
                if edge.is_coastal():
                    if not edge.is_coastal_sink(upper=True):
                        leaf_end_edges.append(edge)
                        for tri in edge.boundary_triangles:
                            if tri.is_upper:
                                last_tri = con.flow(tri)[0]
                                last_edge = last_tri.edges[
                                    last_tri.downriver_index()]
                                leaf_end_edges.append(last_edge)
                else:
                    if edge.is_watershed():
                        for tri in edge.boundary_triangles:
                            last_tri = con.flow(tri)[0]
                            last_edge = last_tri.edges[
                                last_tri.downriver_index()]
                            leaf_end_edges.append(last_edge)
                if len(leaf_end_edges) == 2:
                    green_train_routes.append(leaf_end_edges)
                    if foliation_style_old:
                        leaf_ends = []
                        for e in leaf_end_edges:
                            endpts = e.vertices
                            _, midpt = make_arc(endpts[0].circle_pos,
                                                endpts[1].circle_pos,
                                                return_midpt=True)
                            leaf_ends.append(midpt)
                        p = make_arc(leaf_ends[0], leaf_ends[1])
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, green
                        ])

    if draw_foliation and (foliation_style_split or foliation_style_cusp_leaves
                           or foliation_style_boundary_leaves):
        for e in con.coastal_edges:
            e.purple_ends = []
            e.green_ends = []
        for e1, e2 in purple_train_routes:
            e1.purple_ends.append(e2)
            e2.purple_ends.append(e1)
        for e1, e2 in green_train_routes:
            e1.green_ends.append(e2)
            e2.green_ends.append(e1)
        for i, e in enumerate(con.coastal_edges):
            rotated_coastal_edges = con.coastal_edges[
                i:] + con.coastal_edges[:i]
            e.purple_ends.sort(
                key=lambda e_other: rotated_coastal_edges.index(e_other),
                reverse=True)
            e.green_ends.sort(
                key=lambda e_other: rotated_coastal_edges.index(e_other),
                reverse=True)
            if e.is_red:
                e.ends = e.green_ends + e.purple_ends
            else:
                e.ends = e.purple_ends + e.green_ends
        if foliation_style_split:
            for e1, e2 in purple_train_routes:
                p1 = end_pos(e2, e1)
                p2 = end_pos(e1, e2)
                p = make_arc(p1, p2)
                p = p.transformed(scl)
                canv.stroke(p, [
                    style.linewidth(leaf_thickness), style.linecap.round,
                    purple
                ])
            for e1, e2 in green_train_routes:
                p1 = end_pos(e2, e1)
                p2 = end_pos(e1, e2)
                p = make_arc(p1, p2)
                p = p.transformed(scl)
                canv.stroke(p, [
                    style.linewidth(leaf_thickness), style.linecap.round, green
                ])
        if foliation_style_cusp_leaves or foliation_style_boundary_leaves:
            for i, c in enumerate(con.coast):
                c.purple_thorn_end_positions = []  ### complex numbers
                c.purple_thorn_ends = [
                ]  ### [coastal arc, position along that arc]
                e = con.coastal_edges[i]
                e1 = e.purple_ends[0]
                while True:
                    index = e1.purple_ends.index(e)
                    if index == len(e1.purple_ends) - 1:
                        break
                    else:
                        c.purple_thorn_end_positions.append(
                            end_pos(e, e1, offset=0.5))
                        c.purple_thorn_ends.append((e1, e1.ends.index(e)))
                        e, e1 = e1, e1.purple_ends[index + 1]

                if foliation_style_boundary_leaves:
                    e_before = con.coastal_edges[(i - 1) % len(con.coast)]
                    e_after = con.coastal_edges[i]
                    first_pos = end_pos(e_after.purple_ends[0],
                                        e_after,
                                        offset=-0.25)
                    last_pos = end_pos(e_before.purple_ends[-1],
                                       e_before,
                                       offset=0.25)
                    c.purple_thorn_end_positions = [
                        first_pos
                    ] + c.purple_thorn_end_positions + [last_pos]
                    arcs = []
                    for i in range(len(c.purple_thorn_end_positions) - 1):
                        arcs.append(
                            make_arc(c.purple_thorn_end_positions[i],
                                     c.purple_thorn_end_positions[i + 1]))
                    for p in arcs:
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, purple
                        ])

                if foliation_style_cusp_leaves:
                    for thorn_end in c.purple_thorn_ends:
                        thorn_end_pos = end_pos2(thorn_end)
                        p = make_arc(c.circle_pos, thorn_end_pos)
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, purple
                        ])

            for i, c in enumerate(con.coast):
                c.green_thorn_end_positions = []  ### complex numbers
                c.green_thorn_ends = [
                ]  ### [coastal arc, position along that arc]
                e = con.coastal_edges[i]
                e1 = e.green_ends[0]
                while True:
                    index = e1.green_ends.index(e)
                    if index == len(e1.green_ends) - 1:
                        break
                    else:
                        c.green_thorn_end_positions.append(
                            end_pos(e, e1, offset=0.5))
                        c.green_thorn_ends.append((e1, e1.ends.index(e)))
                        e, e1 = e1, e1.green_ends[index + 1]
                if foliation_style_boundary_leaves:
                    e_before = con.coastal_edges[(i - 1) % len(con.coast)]
                    e_after = con.coastal_edges[i]
                    first_pos = end_pos(e_after.green_ends[0],
                                        e_after,
                                        offset=-0.25)
                    last_pos = end_pos(e_before.green_ends[-1],
                                       e_before,
                                       offset=0.25)
                    c.green_thorn_end_positions = [
                        first_pos
                    ] + green_thorn_end_positions + [last_pos]
                    arcs = []
                    for i in range(len(c.green_thorn_end_positions) - 1):
                        arcs.append(
                            make_arc(c.green_thorn_end_positions[i],
                                     c.green_thorn_end_positions[i + 1]))
                    for p in arcs:
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, green
                        ])

                if foliation_style_cusp_leaves:
                    for thorn_end in c.green_thorn_ends:
                        thorn_end_pos = end_pos2(thorn_end)
                        p = make_arc(c.circle_pos, thorn_end_pos)
                        p = p.transformed(scl)
                        canv.stroke(p, [
                            style.linewidth(leaf_thickness),
                            style.linecap.round, green
                        ])

            for tet in draw_tetrahedron_rectangles:
                purple_sides = tet_purple_rectangle_sides(
                    tet, actually_do_green=False)
                green_sides = tet_purple_rectangle_sides(
                    tet, actually_do_green=True)
                for side in purple_sides:
                    for cusp_leaf in side:
                        if cusp_leaf != None:
                            v, thorn_end = cusp_leaf
                            thorn_end_pos = end_pos2(thorn_end)
                            p = make_arc(v.circle_pos, thorn_end_pos)
                            p = p.transformed(scl)
                            canv.stroke(p, [
                                style.linewidth(2 * leaf_thickness),
                                style.linecap.round, purple
                            ])
                for side in green_sides:
                    for cusp_leaf in side:
                        if cusp_leaf != None:
                            v, thorn_end = cusp_leaf
                            thorn_end_pos = end_pos2(thorn_end)
                            p = make_arc(v.circle_pos, thorn_end_pos)
                            p = p.transformed(scl)
                            canv.stroke(p, [
                                style.linewidth(2 * leaf_thickness),
                                style.linecap.round, green
                            ])

    output_filename = 'Images/CircleContinent/' + name + '.pdf'
    canv.writePDFfile(output_filename)
예제 #25
0
    def visualize(self, namespace='', comp_idx=-1, reduce_type='max'):

        # Breadth-first traversal.

        seen_cells = set()
        cell_order = []

        from queue import SimpleQueue
        queue = SimpleQueue()
        queue.put((self, 0))

        n_levels = 1
        levels = {}
        level_sizes = {}

        while not queue.empty():
            node, depth = queue.get()

            if depth + 1 > n_levels:
                n_levels = depth + 1

            if depth not in levels:
                levels[depth] = {}
            for si in node.sample_idx:
                if si not in levels[depth]:
                    levels[depth][si] = []
                levels[depth][si].append(node.viz_value[comp_idx])

            if depth not in level_sizes:
                level_sizes[depth] = 0
            level_sizes[depth] += 1.

            if len(node.children) == 0:
                [
                    cell_order.append(si) for si in node.sample_idx
                    if si not in seen_cells
                ]
                seen_cells.update(node.sample_idx)

            else:
                for child in node.children:
                    queue.put((child, depth + 1))

        # Draw the pyramid.
        from pyx import canvas, path, style, deco, color

        c = canvas.canvas()

        unit = 20.
        height = unit * np.sqrt(3) / 2.

        level_height = height / n_levels
        curr_height = height

        grad = color.lineargradient_rgb(color.rgb.white, color.rgb.red)

        for level in range(n_levels):
            top_width = height - curr_height
            bottom_width = height - curr_height + level_height

            n_in_level = len(levels[level])
            assert (n_in_level == len(self.sample_idx) == len(cell_order))

            x_top = (unit / 2.) - (top_width / 2.)
            x_top_curr = x_top
            x_top_inc = top_width / n_in_level

            x_bottom = (unit / 2.) - (bottom_width / 2.)
            x_bottom_curr = x_bottom
            x_bottom_inc = bottom_width / n_in_level

            if reduce_type == 'mean':
                reduce_fn = np.mean
            elif reduce_type == 'median':
                reduce_fn = np.median
            elif reduce_type == 'max':
                reduce_fn = np.max
            elif reduce_type == 'min':
                reduce_fn = np.min
            else:
                raise ValueError(
                    'Invalid reduce function {}'.format(reduce_type))

            curr_node = reduce_fn(levels[level][cell_order[0]])

            for sidx in cell_order:

                if reduce_fn(levels[level][sidx]) != curr_node:

                    brick = path.path(
                        path.moveto(x_top, curr_height),
                        path.lineto(x_top_curr, curr_height),
                        path.lineto(x_bottom_curr, curr_height - level_height),
                        path.lineto(x_bottom, curr_height - level_height),
                        path.closepath(),
                    )
                    c.stroke(brick, [
                        style.linewidth(1e-3),
                        deco.filled([grad.getcolor(curr_node)])
                    ])

                    curr_node = reduce_fn(levels[level][sidx])
                    x_top = x_top_curr
                    x_bottom = x_bottom_curr

                x_top_curr += x_top_inc
                x_bottom_curr += x_bottom_inc

            brick = path.path(
                path.moveto(x_top, curr_height),
                path.lineto(x_top_curr, curr_height),
                path.lineto(x_bottom_curr, curr_height - level_height),
                path.lineto(x_bottom, curr_height - level_height),
                path.closepath(),
            )
            c.stroke(brick, [
                style.linewidth(1e-3),
                deco.filled([grad.getcolor(curr_node)])
            ])

            curr_height -= level_height

        c.writeSVGfile('pyramid{}_{}_{}_{}_{}'.format(namespace,
                                                      self.dag_method,
                                                      self.decomp_method,
                                                      reduce_type, comp_idx))
예제 #26
0
def draw_axis(ca):
    #init the latex code
    t = text.latexrunner(docopt="10pt")
    t.preamble("\\usepackage{fbb}")
    #radius of the render circle

    # draw the bounding box
    ca.stroke(path.rect(-sz, -sz, sz * 2, sz * 2))

    # draw the tenth of degree ticks
    for i in range(3600):
        #angle in radians
        ang = (i * pi) / 1800.0

        #base size of ticks
        width = 0.001
        outsize = 0.1

        #scaling for each major tick step level
        wscale = 2
        oscale = 1.6

        #compute tick width and length
        if i % 900 == 0:
            width *= wscale
            outsize *= oscale

        if i % 450 == 0:
            width *= wscale
            outsize *= oscale

        if i % 50 == 0:
            width *= wscale
            outsize *= oscale

        if i % 10 == 0:
            width *= wscale
            outsize *= oscale

        lw = style.linewidth(unit.length(width, type="w", unit="cm"))

        # compute tick co-ordinates (inner and outer)
        x1 = cos(ang) * insize
        y1 = -sin(ang) * insize

        x2 = cos(ang) * (insize + outsize)
        y2 = -sin(ang) * (insize + outsize)

        ca.stroke(path.line(x1, y1, x2, y2), [lw])

        #compute label co-ordinates
        x3 = cos(ang) * (insize + outsize + 0.1)
        y3 = -sin(ang) * (insize + outsize + 0.1)

        #write on labels
        if i % 900 == 0:
            ca.insert(
                t.text(x3, y3, "\small " + str(i // 10),
                       [text.halign.boxcenter, text.valign.middle]))
        elif i % 450 == 0:
            ca.insert(
                t.text(x3, y3, "\\scriptsize " + str(i // 10),
                       [text.halign.boxcenter, text.valign.middle]))
        elif i % 50 == 0:
            ca.insert(
                t.text(x3, y3, "\\tiny " + str(i // 10),
                       [text.halign.boxcenter, text.valign.middle]))
예제 #27
0
파일: make_icons.py 프로젝트: clld/cobl2
"""script to create the default set of map marker icons distributed with clld."""
import os
import sys

from csvw.dsv import reader
import pyx
from pyx import bbox, unit, style, path, color, canvas, deco
# set the scale to 1/20th of an inch
unit.set(uscale=0.05, wscale=0.02, defaultunit="inch")

linewidth = style.linewidth(1.2)


def pyxColor(string):
    """Return a pyxColor instance.

    :param string: RGB color name like 'ffffff'
    :return: pyx color.

    >>> assert pyxColor('ffffff')
    """
    assert len(string) == 6
    colorTuple = tuple(
        int('0x' + c, 16) for c in [string[i:i + 2] for i in range(0, 6, 2)])
    return color.rgb(*[i / 255.0 for i in colorTuple])


if __name__ == '__main__':  # pragma: no cover
    out = sys.argv[1]
    if not pyx:
        sys.exit(1)
예제 #28
0
파일: make_icons.py 프로젝트: mitcho/clld
"""
script to create the default set of map marker icons distributed with clld.
"""
import sys

try:
    import pyx
    from pyx import bbox, unit, style, path, color, canvas, deco
    # set the scale to 1/20th of an inch
    unit.set(uscale=0.05, wscale=0.02, defaultunit="inch")

    #linewidth = style.linewidth(1.2)
    linewidth = style.linewidth(1.1)
except ImportError:  # pragma: no cover
    pyx = False

from pyramid.path import AssetResolver

from clld.web.icon import ICONS


def polygon(*points):  # pragma: no cover
    args = []
    for i, point in enumerate(points):
        args.append(path.moveto(*point) if i == 0 else path.lineto(*point))
    args.append(path.closepath())
    return path.path(*args)


shapes = {
    "c": path.circle(20, 20, 13.6),  # circle