def draw_core(self, canvas): path = aggdraw.Path() for i in range(len(self.traject)): (path.moveto if i == 0 else path.lineto)(self.traject[i][0], self.traject[i][1]) canvas.path(path, self.howbig.slinger_core_pen) for light in self.lights: path = aggdraw.Path() path.moveto(light.knot[0], light.knot[1]) path.lineto(light.bulbcenter[0], light.bulbcenter[1]) canvas.path(path, self.howbig.slinger_core_pen)
def draw(self, canvas, outline, fill): pathdraw = aggdraw.Path() ck = [] ck.extend(self.paths['q1']) ck.extend(self.paths['q4']) ll0 = [] ll0.extend(self.paths['q2']) ll0.extend(self.paths['q3']) for idx, path in enumerate(ck): if idx == 0: pathdraw.moveto(path['p0'][0], path['p0'][1]) pathdraw.curveto(path['c0'][0], path['c0'][1], path['c1'][0], path['c1'][1], path['p1'][0], path['p1'][1]) canvas.path(pathdraw, outline, fill) for idx, path in enumerate(ll0): if idx == 0: pathdraw.moveto(path['p0'][0], path['p0'][1]) pathdraw.curveto(path['c0'][0], path['c0'][1], path['c1'][0], path['c1'][1], path['p1'][0], path['p1'][1]) canvas.path(pathdraw, outline, fill) canvas.flush()
def draw_lines(self, coords, **options): """ Connect a series of flattened coordinate points with one or more lines. """ path = aggdraw.Path() def traverse_ring(coords): # begin coords = grouper(coords, 2) startx, starty = next(coords) path.moveto(startx, starty) # connect to each successive point for nextx, nexty in coords: path.lineto(nextx, nexty) # get drawing tools from options args = [] if options["outlinecolor"]: pen = aggdraw.Pen(options["outlinecolor"], options["outlinewidth"]) args.append(pen) if options["fillcolor"]: brush = aggdraw.Brush(options["fillcolor"]) args.append(brush) # draw the constructed path self.drawer.path((0, 0), path, *args)
def draw_path(self, cp): # TODO: is there a more efficient way in aggdraw to do this? path = agg.Path() path.moveto(cp[0][0], cp[0][1]) for pt in cp[1:]: path.lineto(pt[0], pt[1]) self.cr.canvas.path(path, self.pen, self.brush)
def draw_bezier_curve(self, cp): # there is a bug in path handling of some versions of aggdraw-- # aggdraw here is ok: path = agg.Path() path.moveto(cp[0][0], cp[0][1]) path.curveto(cp[1][0], cp[1][1], cp[2][0], cp[2][1], cp[3][0], cp[3][1]) self.cr.canvas.path(path, self.pen, self.brush)
def draw_path(self, polys): # draw path = aggdraw.Path() for poly in polys: exterior = poly[0] if len(poly) > 1: holes = poly[1:] else: holes = [] def traverse_ring(coords): # begin coords = (point for point in coords) startx,starty = next(coords) path.moveto(startx, starty) # connect to each successive point for nextx,nexty in coords: path.lineto(nextx, nexty) path.close() # first exterior traverse_ring(exterior) # then holes for hole in holes: # !!! need to test for ring direction !!! hole = (point for point in hole) traverse_ring(hole) self.drawer.path((0,0), path, self.pen, self.brush)
def draw(self): cp = self.get_cpoints(points=self.get_bezier_pts()) cr = self.setup_cr() pen = self.get_pen(cr) brush = self.get_brush(cr) # draw 4 bezier curves to make the ellipse # TODO: currently there is a bug in aggdraw paths path = agg.Path() path.moveto(cp[0][0], cp[0][1]) path.curveto(cp[1][0], cp[1][1], cp[2][0], cp[2][1], cp[3][0], cp[3][1]) path.curveto(cp[4][0], cp[4][1], cp[5][0], cp[5][1], cp[6][0], cp[6][1]) path.curveto(cp[7][0], cp[7][1], cp[8][0], cp[8][1], cp[9][0], cp[9][1]) path.curveto(cp[10][0], cp[10][1], cp[11][0], cp[11][1], cp[12][0], cp[12][1]) cr.canvas.path(path.coords(), path, pen, brush) if self.editing: self.draw_edit(cr) elif self.showcap: cpoints = self.get_cpoints() self.draw_caps(cr, self.cap, cpoints)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) default = aggdraw.Path() default.moveto(100, 100) default.curveto(200, 133, 200, 167, 100, 200) self.props.setdefault("path", default) self.props.setdefault("color", "black") self.props.setdefault("width", 5) for color in ["color"]: self.props[color] = get_rgb(self.props[color])
def draw_ellipse_bezier(self, cp): # draw 4 bezier curves to make the ellipse because there seems # to be a bug in aggdraw ellipse drawing function path = agg.Path() path.moveto(cp[0][0], cp[0][1]) path.curveto(cp[1][0], cp[1][1], cp[2][0], cp[2][1], cp[3][0], cp[3][1]) path.curveto(cp[4][0], cp[4][1], cp[5][0], cp[5][1], cp[6][0], cp[6][1]) path.curveto(cp[7][0], cp[7][1], cp[8][0], cp[8][1], cp[9][0], cp[9][1]) path.curveto(cp[10][0], cp[10][1], cp[11][0], cp[11][1], cp[12][0], cp[12][1]) self.cr.canvas.path(path, self.pen, self.brush)
def draw_line(self, coords, smooth=False, **options): """ Connect a series of flattened coordinate points with one or more lines. - coords: A list of coordinates for the linesequence. - smooth: If True, smooths the lines by drawing quadratic bezier curves between midpoints of each line segment. """ path = aggdraw.Path() def traverse_linestring(coords): # begin coords = grouper(coords, 2) startx, starty = next(coords) path.moveto(startx, starty) # connect to each successive point for nextx, nexty in coords: path.lineto(nextx, nexty) def traverse_curvelines(coords): # begin coords = pairwise(grouper(coords, 2)) (startx, starty), (endx, endy) = next(coords) path.moveto(startx, starty) # draw straight line to first line midpoint midx, midy = (endx - startx) / 2.0, (endy - starty) / 2.0 path.lineto(midx, midy) oldmidx, oldmidy = midx, midy # for each line for line in coords: # curve from midpoint of first to midpoint of second (startx, starty), (endx, endy) = line midx, midy = (endx - startx) / 2.0, (endy - starty) / 2.0 path.curveto(oldmidx, oldmidy, midx, midy, startx, starty) oldmidx, oldmidy = midx, midy # draw straight line to endpoint of last line path.lineto(endx, endy) if smooth: traverse_curvelines(coords) else: traverse_linestring(coords) # get drawing tools from options args = [] if options["outlinecolor"]: pen = aggdraw.Pen(options["outlinecolor"], options["outlinewidth"]) args.append(pen) if options["fillcolor"]: brush = aggdraw.Brush(options["fillcolor"]) args.append(brush) # draw the constructed path self.drawer.path((0, 0), path, *args)
def show_bezier(): img = Image.new("RGB", (200, 200), "white") canvas = aggdraw.Draw(img) pen = aggdraw.Pen("black") path = aggdraw.Path() path.moveto(0, 0) path.curveto(0, 60, 40, 100, 100, 100) canvas.path(path, path.coords(), pen) canvas.flush() img.save("bezier.png", "PNG") img.show()
def _rounded_corner_path( box: t.Tuple[int, int, int, int], corner_radius: int, ): path = aggdraw.Path() cr = corner_radius x, y, w, h = box path.moveto(x + cr, y) path.lineto(x + w - cr, y) path.curveto( x + w - cr / 2, y, x + w, y + cr / 2, x + w, y + cr, ) path.lineto(x + w, y + h - cr) path.curveto( x + w, y + h - cr / 2, x + w - cr / 2, y + h, x + w - cr, y + h, ) path.lineto(x + cr, y + h) path.curveto( x + cr / 2, y + h, x, y + h - cr / 2, x, y + h - cr, ) path.lineto(x, y + cr) path.curveto( x, y + cr / 2, x + cr / 2, y, x + cr, y, ) return path
def create() -> Image: """Generate the texture.""" image = Image.new('RGBA', (SIZE, SIZE)) draw = aggdraw.Draw(image) draw.rectangle((0, 0, SIZE, SIZE), None, aggdraw.Brush((122, 122, 122))) for x in (0, SIZE): path = aggdraw.Path() path.moveto(x, 0) path.lineto(x, SIZE) draw.path(path, aggdraw.Pen('white', 2)) draw.flush() # image.show() return image
def quadratic_path(self, xy, fill=None, outline=None, weight=0): if self._aggdraw: path = aggdraw.Path() brush = aggdraw_create_brush(fill) pen = aggdraw_create_pen(outline, weight) self._aggdraw.path(xy, path, pen, brush) path = brush = pen = None else: pd = tuple(quadratic_bezier_interpolate(xy)) if fill: self.polygon(pd[:-2], fill) if outline and weight >= 0: self.line(pd, outline, weight)
def draw(self, canvas, outline, fill): # Draw C/K pathsCK = self.paths['ck'] pathsLL0 = self.paths['ll0'] # p0 ckpath = aggdraw.Path() ckpath.moveto(pathsCK[0]['p0'][0], pathsCK[0]['p0'][1]) for path in pathsCK: ckpath.curveto(path['c0'][0], path['c0'][1], path['c1'][0], path['c1'][1], path['p1'][0], path['p1'][1]) canvas.path(ckpath, outline, fill) # Draw L/L0 lpath = aggdraw.Path() lpath.moveto(pathsLL0[0]['p0'][0], pathsLL0[0]['p0'][1]) for path in pathsLL0: lpath.curveto(path['c0'][0], path['c0'][1], path['c1'][0], path['c1'][1], path['p1'][0], path['p1'][1]) canvas.path(lpath, outline, fill) canvas.flush()
def draw_connections(im, connections): """Draws the connections.""" draw = aggdraw.Draw(im) pen = aggdraw.Pen("black", 0.5) for c in connections: xy1 = port_location(c.port1) xy2 = port_location(c.port2) path = aggdraw.Path() path.moveto(*xy1) path.curveto(*xy1, *CENTER, *xy2) draw.path(path, pen) draw.flush()
def _create_lane_connections_image(node: Node) -> Image: """Generate image showing lane connections on a node.""" image = Image.new('RGBA', (RESOLUTION, RESOLUTION)) draw = aggdraw.Draw(image) colors = dict(zip(node.oriented_ways, cycle(COLORS))) for lanes, points in node.intersection.iterate_connections_curve_points(): start, crossing, end = map(Vector.y_flipped, (p * PPM + MIDDLE for p in points)) vector = lanes[1].way.direction_from_node(node, lanes[1].endpoint) vector = vector.normalized().rotated(pi * 1.125).y_flipped() * 32.0 path = aggdraw.Path() path.moveto(*start) path.curveto(*start, *crossing, *end) path.lineto(*(end + vector)) draw.path( path, aggdraw.Pen(colors[lanes[0].oriented_way.flipped()], 0.25 * PPM, 224)) pen = aggdraw.Pen('black', 1, 192) brush = { ConflictPointType.DIVERGE: aggdraw.Brush('green', 192), ConflictPointType.MERGE: aggdraw.Brush('yellow', 192), ConflictPointType.CROSSING: aggdraw.Brush('white', 192) } cpoints = set(p for _, p in chain.from_iterable( c.conflict_points for c in node.intersection.curves.values())) for cpoint in cpoints: point = (cpoint.point * PPM + MIDDLE).y_flipped() draw.ellipse(point.enclosing_rect(0.25 * PPM), pen, brush[cpoint.type]) text = str(cpoint.id) width, height = draw.textsize(text, FONT) draw.text((point.x - width / 2, point.y - height / 2), text, FONT) pen = aggdraw.Pen('black', 1, 32) for cpoint in cpoints: for neighbor in cpoint.neighbors: points = ((p.point * PPM + MIDDLE).y_flipped() for p in (cpoint, neighbor)) draw.line(tuple(chain.from_iterable(points)), pen) draw.flush() # image.show() return image
def frames_to_path(frames, unique=False): """Renders a list of (x, y) tuples representing the frames of a figure into an aggdraw Path object for drawing. """ path = aggdraw.Path() path.moveto(frames[0][0], frames[0][1]) # start at first point prev = frames[0] for f in frames: # If current frame not different than previous one, discard it if unique and (f[0] == prev[0] and f[1] == prev[1]): continue path.lineto(f[0], f[1]) prev = f path.close() return path
def __init__(self, filename): root = ET.parse(filename).getroot() paths = [] for element in root.getchildren(): if str.endswith(element.tag, "path"): paths.append(parse_path(element.attrib["d"])) self.paths = [] for path in paths: a_path = aggdraw.Path() self.paths.append(a_path) for line in path: x1 = line.start.real y1 = line.start.imag x2 = line.end.real y2 = line.end.imag a_path.moveto(x1, y1) a_path.lineto(x2, y2)
def draw(self, frame, im): if frame < self.startTime: return idx = frame - self.startTime k = min(1, 0.2 * math.sqrt(idx)) radius_x = (1 - k) * self.radius + k * 600 radius_y = (1 - k) * self.radius + k * 320 pos_x = (1 - k) * self.pos_x + k * 640 pos_y = (1 - k) * self.pos_y + k * 360 canvas = aggdraw.Draw(im) pen = aggdraw.Pen("black", 3) brush = aggdraw.Brush((255, 255, 180), 230) path = aggdraw.Path() for grad in range(0, 360): dr = 20 * math.pow(math.sin(2 * grad / 180. * math.pi), 2) x = (dr + radius_x) * math.sin(grad / 180. * math.pi) y = (dr + radius_y) * math.cos(grad / 180. * math.pi) path.lineto(pos_x + x, pos_y + y) canvas.polygon(path.coords(), pen, brush) canvas.flush()
def test_aggdraw(): """ aggdraw test. """ # Create image and drawer. img = Image.new('RGB', (600, 300), color=(73, 109, 137)) c = aggdraw.Draw(img) c.setantialias(True) # Draw aggdraw primitives. c.arc((500, 200, 550, 280), 85, 320, aggdraw.Pen('red', 2.1)) c.chord((400, 200, 450, 290), 10, 290, aggdraw.Pen('orange', 2.5), aggdraw.Brush('blue')) c.ellipse((50, 50, 200, 100), aggdraw.Pen('orange', 3.5), aggdraw.Brush('green')) c.line((10, 10, 590, 290), aggdraw.Pen('blue', 2.9)) c.line((5, 5, 100, 20, 30, 40, 400, 250, 550, 250, 300, 100), aggdraw.Pen('red', 0.5)) # path = aggdraw.Path() path.moveto(0, 0) path.curveto(200, 250, 500, 50, 400, 250) path.curveto(0, 60, 40, 100, 100, 100) c.path(path, aggdraw.Pen('pink', 5.0)) # c.pieslice((100, 100, 300, 250), 50, 350, aggdraw.Pen('green', 2.5), aggdraw.Brush('yellow')) c.polygon((590, 10, 590, 290, 580, 290, 580, 20, 500, 10), aggdraw.Pen('blue', 1.0), aggdraw.Brush('pink')) c.rectangle((400, 200, 500, 300), aggdraw.Pen('black', 2.8), aggdraw.Brush('orange')) # Flush c.flush() # Save and show. img.save('test.png') img.show()
def draw_polygon(self, coords, holes=[], **options): """ Draw polygon and holes with color fill. Note: holes must be counterclockwise. """ path = aggdraw.Path() def traverse_ring(coords): # begin coords = grouper(coords, 2) startx, starty = next(coords) path.moveto(startx, starty) # connect to each successive point for nextx, nexty in coords: path.lineto(nextx, nexty) path.close() # first exterior traverse_ring(coords) # then holes for hole in holes: # !!! need to test for ring direction !!! hole = (xory for point in reversed(tuple(grouper(hole, 2))) for xory in point) traverse_ring(hole) # options args = [] if options["fillcolor"]: fillbrush = aggdraw.Brush(options["fillcolor"]) args.append(fillbrush) if options["outlinecolor"]: outlinepen = aggdraw.Pen(options["outlinecolor"], options["outlinewidth"]) args.append(outlinepen) self.drawer.path((0, 0), path, *args)
# Creates a brush object. # - color # Brush color. This can be a color tuple, a CSS-style color name, or a color integer (0xaarrggbb). # - opacity= # Optional brush opacity. The default is to create a solid brush. pen = aggdraw.Pen("black", 5, 200) # # Pen(color, width=1, opacity=255) [#] # Creates a pen object. # # - color # Pen color. This can be a color tuple, a CSS-style color name, or a color integer (0xaarrggbb). # - width= # Optional pen width. # - opacity= # Optional pen opacity. The default is to create a solid pen. p = aggdraw.Path() p.moveto(0, 0) p.rlineto(300, 300) p.curveto(500, -200) p.rlineto(10, 300) p.close() canvas.path((100, 1000), p, pen, brush) canvas.path((10, 900), p, pen, brush) canvas.flush() img.save("curve.png", "PNG") img.show()
from Python.phrases import Phrases root = ET.parse("branch.jpg.svg").getroot() paths = [] for element in root.getchildren(): if str.endswith(element.tag, "path"): paths.append(parse_path(element.attrib["d"])) base = Image.new("RGB", (1280, 720), "white") canvas = aggdraw.Draw(base) pen = aggdraw.Pen("black", 1) brush = aggdraw.Brush("brown", 255) for leave in paths: path = aggdraw.Path() for line in leave: x1 = line.start.real y1 = line.start.imag x2 = line.end.real y2 = line.end.imag path.moveto(150 + 1.5 * x1, 1.5 * y1) path.lineto(150 + 1.5 * x2, 1.5 * y2) canvas.polygon(path.coords(), pen, brush) canvas.flush() root = ET.parse("leavesonbranch.svg").getroot()
def __init__(self, size, layout, weights): self.size = size self.tiling = Tiling(size=self.size, layout=layout, weights=weights) self.howbig = Howbig(size=self.size, weight=self.tiling.total_weight) hh = self.howbig.hh # initial vertex range on boundary for fv in self.tiling.fvs: if fv.p[0] == 0 or fv.p[0] == self.size[0]: fv.axmin = fv.p[0] fv.axmax = fv.p[0] else: fv.axmin = max(0, fv.p[0] - hh) fv.axmax = min(self.size[0], fv.p[0] + hh) if fv.p[1] == 0 or fv.p[1] == self.size[1]: fv.aymin = fv.p[1] fv.aymax = fv.p[1] else: fv.aymin = max(0, fv.p[1] - hh) fv.aymax = min(self.size[1], fv.p[1] + hh) # limit vertex range based on edges for fe in self.tiling.fes: nhe, phe = fe.hes vmin = nhe.target vmax = phe.target if fe.ie.hv == 'h': d = rel_delta * (vmax.p[0] - vmin.p[0]) v = round(vmin.p[0] + d) if vmin.axmax > v: vmin.axmax = v v = round(vmax.p[0] - d) if vmax.axmin < v: vmax.axmin = v else: d = rel_delta * (vmax.p[1] - vmin.p[1]) v = round(vmin.p[1] + d) if vmin.aymax > v: vmin.aymax = v v = round(vmax.p[1] - d) if vmax.aymin < v: vmax.aymin = v # set actual vertex coordinate for fv in self.tiling.fvs: fv.ap = (random.randrange(fv.axmin, fv.axmax + 1), random.randrange(fv.aymin, fv.aymax + 1)) self.numlights = 0 # calculate slingers for fe in self.tiling.fes: fe.slinger = None if fe.ie.is_outer: continue nhe, phe = fe.hes vmin = nhe.target vmax = phe.target fe.slinger = Slinger(self.howbig, vmin.p, vmax.p, vmin.ap, vmax.ap) for light in fe.slinger.lights: light.globalindex = self.numlights self.numlights += 1 # calculate tile crops brush = aggdraw.Brush(255) for tile in self.tiling.tiles: circ_points = [] for fhe in tile.fhes: if fhe.edge.slinger: traject = fhe.edge.slinger.traject circ_points.extend( traject if fhe.ispos else reversed(traject)) else: circ_points += [fhe.source.ap, fhe.target.ap] left = math.floor(min(p[0] for p in circ_points)) right = math.ceil(max(p[0] for p in circ_points)) top = math.floor(min(p[1] for p in circ_points)) bot = math.ceil(max(p[1] for p in circ_points)) tile.maskpos = (left, top) tile.mask = Image.new("L", (right - left, bot - top), 0) canvas = aggdraw.Draw(tile.mask) path = aggdraw.Path() path.moveto(circ_points[0][0], circ_points[0][1]) for p in circ_points[1:]: path.lineto(p[0] - left, p[1] - top) canvas.path(path, None, brush) canvas.flush() # calculate slinger mask slinger_mask = Image.new("L", self.howbig.size, 0) canvas = aggdraw.Draw(slinger_mask) for fe in self.tiling.fes: if fe.slinger is None: continue fe.slinger.draw_core(canvas) canvas.flush() # calculate slinger + unlit bulbs image self.overlay_img = Image.new("RGBA", self.howbig.size, (0, 0, 0, 0)) self.overlay_img.paste("darkgreen", mask=slinger_mask) for fe in self.tiling.fes: if fe.slinger is None: continue for light in fe.slinger.lights: light.draw_bulb_u(self.overlay_img) self.overlay_img_np = np.array(self.overlay_img)