def render(args): from nodebox.graphics import BezierPath, strokewidth, fill, directed, push, translate, rotate, pop, drawpath geom2d = getPropValue(args, 'inputs', 'geometry') # Do the drawing here!! path = BezierPath() strokewidth(width=1) fill(0) ps = geom2d.points for b_path in geom2d.bezier_paths: if len(b_path) > 4: path.moveto(*geom2d.points[b_path[0]]) for p_num in xrange((len(b_path) - 1) // 3): # debugPrint b_path,p_num path.curveto(ps[b_path[p_num * 3 + 1]][0], ps[b_path[p_num * 3 + 1]][1], ps[b_path[p_num * 3 + 2]][0], ps[b_path[p_num * 3 + 2]][1] , ps[b_path[p_num * 3 + 3]][0], ps[b_path[p_num * 3 + 3]][1] ) # points = path.points(amount=len(glyphs), start=0.05, end=0.95) points = path.points(amount=0, start=0.05, end=0.95) for angle, pt in directed(points): push() translate(pt.x, pt.y) rotate(angle) pop() drawpath(path, fill=None, stroke=(0, 0, 0, 1))
def contours(path): """Returns a list of contours in the path. A contour is a sequence of lines and curves separated from the next contour by a MOVETO. For example, the glyph "o" has two contours: the inner circle and the outer circle. >>> path = BezierPath(None) >>> path.moveto(0, 0) >>> path.lineto(100, 100) >>> len(contours(path)) 1 A new contour is defined as something that starts with a moveto: >>> path.moveto(50, 50) >>> path.curveto(150, 150, 50, 250, 80, 95) >>> len(contours(path)) 2 Empty moveto's don't do anything: >>> path.moveto(50, 50) >>> path.moveto(50, 50) >>> len(contours(path)) 2 It doesn't matter if the path is closed or open: >>> path.closepath() >>> len(contours(path)) 2 """ contours = [] current_contour = None empty = True for i, el in enumerate(path): if el.cmd == MOVETO: if not empty: contours.append(current_contour) current_contour = BezierPath(path._ctx) current_contour.moveto(el.x, el.y) empty = True elif el.cmd == LINETO: empty = False current_contour.lineto(el.x, el.y) elif el.cmd == CURVETO: empty = False current_contour.curveto(el.ctrl1.x, el.ctrl1.y, el.ctrl2.x, el.ctrl2.y, el.x, el.y) elif el.cmd == CLOSE: current_contour.closepath() if not empty: contours.append(current_contour) return contours
def insert_point(path, t): """Returns a path copy with an extra point at t. >>> path = BezierPath(None) >>> path.moveto(0, 0) >>> insert_point(path, 0.1) Traceback (most recent call last): ... NodeBoxError: The given path is empty >>> path.moveto(0, 0) >>> insert_point(path, 0.2) Traceback (most recent call last): ... NodeBoxError: The given path is empty >>> path.lineto(100, 50) >>> len(path) 2 >>> path = insert_point(path, 0.5) >>> len(path) 3 >>> path[1] PathElement(LINETO, ((50.0, 25.0),)) >>> path = BezierPath(None) >>> path.moveto(0, 100) >>> path.curveto(0, 50, 100, 50, 100, 100) >>> path = insert_point(path, 0.5) >>> path[1] PathElement(LINETO, ((25.0, 62.5), (0.0, 75.0), (50.0, 62.5)) """ i, t, closeto = _locate(path, t) x0 = path[i].x y0 = path[i].y p1 = path[i + 1] p1cmd, x3, y3, x1, y1, x2, y2 = p1.cmd, p1.x, p1.y, p1.ctrl1.x, p1.ctrl1.y, p1.ctrl2.x, p1.ctrl2.y if p1cmd == CLOSE: pt_cmd = LINETO pt_x, pt_y = linepoint(t, x0, y0, closeto.x, closeto.y) elif p1cmd == LINETO: pt_cmd = LINETO pt_x, pt_y = linepoint(t, x0, y0, x3, y3) elif p1cmd == CURVETO: pt_cmd = CURVETO pt_x, pt_y, pt_c1x, pt_c1y, pt_c2x, pt_c2y, pt_h1x, pt_h1y, pt_h2x, pt_h2y = \ curvepoint(t, x0, y0, x1, y1, x2, y2, x3, y3, True) else: raise NodeBoxError, "Locate should not return a MOVETO" new_path = BezierPath(None) new_path.moveto(path[0].x, path[0].y) for j in range(1, len(path)): if j == i + 1: if pt_cmd == CURVETO: new_path.curveto(pt_h1x, pt_h1y, pt_c1x, pt_c1y, pt_x, pt_y) new_path.curveto(pt_c2x, pt_c2y, pt_h2x, pt_h2y, path[j].x, path[j].y) elif pt_cmd == LINETO: new_path.lineto(pt_x, pt_y) if path[j].cmd != CLOSE: new_path.lineto(path[j].x, path[j].y) else: new_path.closepath() else: raise NodeBoxError, "Didn't expect pt_cmd %s here" % pt_cmd else: if path[j].cmd == MOVETO: new_path.moveto(path[j].x, path[j].y) if path[j].cmd == LINETO: new_path.lineto(path[j].x, path[j].y) if path[j].cmd == CURVETO: new_path.curveto(path[j].ctrl1.x, path[j].ctrl1.y, path[j].ctrl2.x, path[j].ctrl2.y, path[j].x, path[j].y) if path[j].cmd == CLOSE: new_path.closepath() return new_path
def findpath(points, curvature=1.0): """Constructs a path between the given list of points. Interpolates the list of points and determines a smooth bezier path betweem them. The curvature parameter offers some control on how separate segments are stitched together: from straight angles to smooth curves. Curvature is only useful if the path has more than three points. """ # The list of points consists of Point objects, # but it shouldn't crash on something straightforward # as someone supplying a list of (x,y)-tuples. from types import TupleType for i, pt in enumerate(points): if type(pt) == TupleType: points[i] = Point(pt[0], pt[1]) if len(points) == 0: return None if len(points) == 1: path = BezierPath(None) path.moveto(points[0].x, points[0].y) return path if len(points) == 2: path = BezierPath(None) path.moveto(points[0].x, points[0].y) path.lineto(points[1].x, points[1].y) return path # Zero curvature means straight lines. curvature = max(0, min(1, curvature)) if curvature == 0: path = BezierPath(None) path.moveto(points[0].x, points[0].y) for i in range(len(points)): path.lineto(points[i].x, points[i].y) return path curvature = 4 + (1.0 - curvature) * 40 dx = {0: 0, len(points) - 1: 0} dy = {0: 0, len(points) - 1: 0} bi = {1: -0.25} ax = {1: (points[2].x - points[0].x - dx[0]) / 4} ay = {1: (points[2].y - points[0].y - dy[0]) / 4} for i in range(2, len(points) - 1): bi[i] = -1 / (curvature + bi[i - 1]) ax[i] = -(points[i + 1].x - points[i - 1].x - ax[i - 1]) * bi[i] ay[i] = -(points[i + 1].y - points[i - 1].y - ay[i - 1]) * bi[i] r = range(1, len(points) - 1) r.reverse() for i in r: dx[i] = ax[i] + dx[i + 1] * bi[i] dy[i] = ay[i] + dy[i + 1] * bi[i] path = BezierPath(None) path.moveto(points[0].x, points[0].y) for i in range(len(points) - 1): path.curveto(points[i].x + dx[i], points[i].y + dy[i], points[i + 1].x - dx[i + 1], points[i + 1].y - dy[i + 1], points[i + 1].x, points[i + 1].y) return path
def insert_point(path, t): """Returns a path copy with an extra point at t. >>> path = BezierPath(None) >>> path.moveto(0, 0) >>> insert_point(path, 0.1) Traceback (most recent call last): ... NodeBoxError: The given path is empty >>> path.moveto(0, 0) >>> insert_point(path, 0.2) Traceback (most recent call last): ... NodeBoxError: The given path is empty >>> path.lineto(100, 50) >>> len(path) 2 >>> path = insert_point(path, 0.5) >>> len(path) 3 >>> path[1] PathElement(LINETO, ((50.0, 25.0),)) >>> path = BezierPath(None) >>> path.moveto(0, 100) >>> path.curveto(0, 50, 100, 50, 100, 100) >>> path = insert_point(path, 0.5) >>> path[1] PathElement(LINETO, ((25.0, 62.5), (0.0, 75.0), (50.0, 62.5)) """ i, t, closeto = _locate(path, t) x0 = path[i].x y0 = path[i].y p1 = path[i+1] p1cmd, x3, y3, x1, y1, x2, y2 = p1.cmd, p1.x, p1.y, p1.ctrl1.x, p1.ctrl1.y, p1.ctrl2.x, p1.ctrl2.y if p1cmd == CLOSE: pt_cmd = LINETO pt_x, pt_y = linepoint(t, x0, y0, closeto.x, closeto.y) elif p1cmd == LINETO: pt_cmd = LINETO pt_x, pt_y = linepoint(t, x0, y0, x3, y3) elif p1cmd == CURVETO: pt_cmd = CURVETO pt_x, pt_y, pt_c1x, pt_c1y, pt_c2x, pt_c2y, pt_h1x, pt_h1y, pt_h2x, pt_h2y = \ curvepoint(t, x0, y0, x1, y1, x2, y2, x3, y3, True) else: raise NodeBoxError, "Locate should not return a MOVETO" new_path = BezierPath(None) new_path.moveto(path[0].x, path[0].y) for j in range(1, len(path)): if j == i+1: if pt_cmd == CURVETO: new_path.curveto(pt_h1x, pt_h1y, pt_c1x, pt_c1y, pt_x, pt_y) new_path.curveto(pt_c2x, pt_c2y, pt_h2x, pt_h2y, path[j].x, path[j].y) elif pt_cmd == LINETO: new_path.lineto(pt_x, pt_y) if path[j].cmd != CLOSE: new_path.lineto(path[j].x, path[j].y) else: new_path.closepath() else: raise NodeBoxError, "Didn't expect pt_cmd %s here" % pt_cmd else: if path[j].cmd == MOVETO: new_path.moveto(path[j].x, path[j].y) if path[j].cmd == LINETO: new_path.lineto(path[j].x, path[j].y) if path[j].cmd == CURVETO: new_path.curveto(path[j].ctrl1.x, path[j].ctrl1.y, path[j].ctrl2.x, path[j].ctrl2.y, path[j].x, path[j].y) if path[j].cmd == CLOSE: new_path.closepath() return new_path
def findpath(points, curvature=1.0): """Constructs a path between the given list of points. Interpolates the list of points and determines a smooth bezier path betweem them. The curvature parameter offers some control on how separate segments are stitched together: from straight angles to smooth curves. Curvature is only useful if the path has more than three points. """ # The list of points consists of Point objects, # but it shouldn't crash on something straightforward # as someone supplying a list of (x,y)-tuples. from types import TupleType for i, pt in enumerate(points): if type(pt) == TupleType: points[i] = Point(pt[0], pt[1]) if len(points) == 0: return None if len(points) == 1: path = BezierPath(None) path.moveto(points[0].x, points[0].y) return path if len(points) == 2: path = BezierPath(None) path.moveto(points[0].x, points[0].y) path.lineto(points[1].x, points[1].y) return path # Zero curvature means straight lines. curvature = max(0, min(1, curvature)) if curvature == 0: path = BezierPath(None) path.moveto(points[0].x, points[0].y) for i in range(len(points)): path.lineto(points[i].x, points[i].y) return path curvature = 4 + (1.0-curvature)*40 dx = {0: 0, len(points)-1: 0} dy = {0: 0, len(points)-1: 0} bi = {1: -0.25} ax = {1: (points[2].x-points[0].x-dx[0]) / 4} ay = {1: (points[2].y-points[0].y-dy[0]) / 4} for i in range(2, len(points)-1): bi[i] = -1 / (curvature + bi[i-1]) ax[i] = -(points[i+1].x-points[i-1].x-ax[i-1]) * bi[i] ay[i] = -(points[i+1].y-points[i-1].y-ay[i-1]) * bi[i] r = range(1, len(points)-1) r.reverse() for i in r: dx[i] = ax[i] + dx[i+1] * bi[i] dy[i] = ay[i] + dy[i+1] * bi[i] path = BezierPath(None) path.moveto(points[0].x, points[0].y) for i in range(len(points)-1): path.curveto(points[i].x + dx[i], points[i].y + dy[i], points[i+1].x - dx[i+1], points[i+1].y - dy[i+1], points[i+1].x, points[i+1].y) return path
# Add the upper directory (where the nodebox module is) to the search path. import os, sys;sys.path.insert(0,os.path.join("..","..")) from nodebox.graphics import canvas, BezierPath, drawpath, triangle, ellipse from nodebox.graphics import drawpath, color, fill, stroke, nostroke, background, strokewidth from nodebox.graphics import translate, scale, rotate from random import random import squirtle import amethyst import amethsvg_MOD01 as svgRead # couleur dans la librairy 'amethyst' White= color(amethyst.triplet("white")) # standard nodeboxGL graphics command path1 = BezierPath() path1.moveto(0,0) path1.curveto(0,16.585,28.321,28.335,28.321,28.335) # squirtle svg parser filename = "svg/curve.svg" path2 = squirtle.SVG(filename) # svg lib from Nodebox # The parse() command will return # a list of the shapes in the SVG file. paths3 = svgRead.parse(open("svg/curve.svg").read()) def draw(canvas): #background(color(amethyst.triplet("red")))
import os, sys sys.path.insert(0, os.path.join("..", "..")) from nodebox.graphics import canvas, BezierPath, drawpath, triangle, ellipse from nodebox.graphics import drawpath, color, fill, stroke, nostroke, background, strokewidth from nodebox.graphics import translate, scale, rotate from random import random import squirtle import amethyst import amethsvg_MOD01 as svgRead # couleur dans la librairy 'amethyst' White = color(amethyst.triplet("white")) # standard nodeboxGL graphics command path1 = BezierPath() path1.moveto(0, 0) path1.curveto(0, 16.585, 28.321, 28.335, 28.321, 28.335) # squirtle svg parser filename = "svg/curve.svg" path2 = squirtle.SVG(filename) # svg lib from Nodebox # The parse() command will return # a list of the shapes in the SVG file. paths3 = svgRead.parse(open("svg/curve.svg").read()) def draw(canvas): #background(color(amethyst.triplet("red")))