コード例 #1
0
def rect(_ctx, x, y, width, height, roundness=0.0, draw=True, **kwargs):
    """ Roundness is either a relative float between 0.0 and 1.0,
    or the absolute radius of the corners. 
    """
    BezierPath.checkKwargs(kwargs)
    p = _ctx.BezierPath(**kwargs)
    r = max(0, roundness)
    if r == 0.0:
        p.rect(x, y, width, height)
    else:
        if r <= 1.0 and isinstance(r, float):
            r = min(r * width / 2, r * height / 2)
        else:
            r = min(r, width / 2, height / 2)
        p.moveto(x, y + r)
        a, b, c, d = (x, y), (x + width, y), (x, y + height), (x + width,
                                                               y + height)
        p._nsBezierPath.appendBezierPathWithArcFromPoint_toPoint_radius_(
            a, b, r)
        p._nsBezierPath.appendBezierPathWithArcFromPoint_toPoint_radius_(
            b, d, r)
        p._nsBezierPath.appendBezierPathWithArcFromPoint_toPoint_radius_(
            d, c, r)
        p._nsBezierPath.appendBezierPathWithArcFromPoint_toPoint_radius_(
            c, a, r)
        p.closepath()
    p.inheritFromContext(kwargs.keys())
    if draw:
        p.draw()
    return p
コード例 #2
0
ファイル: spiral.py プロジェクト: jeremyckahn/doodles
    def __init__(self, start_x, start_y, end_x, end_y, decay, length, draw=True, **kwargs):
        from math import sin, cos, pi, e, sqrt, atan2, pow
       
        BezierPath.__init__(self, _ctx,  **kwargs) 
        if  -1e-2 < decay < 1e-2: 
            # very decay of 0 indicates a line
            # but very small decays are practically line ans too small will cause e**1/decay to big = python error
            self.moveto(start_x, start_y )
            self.lineto(end_x, end_y )
            self.inheritFromContext(kwargs.keys())
            if draw:
                self.draw()
            return
        b = 1/float(decay)
        dt = pi/4
        m = 8
        if abs(b) > 1:
            # when the curve gets very flat we need to take a few more samples
            # a better approach might be to simply fit a single cubic curve to the end points
            dt /= abs(b)
        if b < 0:
            #curve reverses    
            dt *= -1
        D = sqrt(pow(start_x-end_x,2) + pow(start_y-end_y,2))
        t =  atan2(start_y-end_y, start_x-end_x)
        a = e**(-b*t)*D
        self.moveto(a*e**(b*t) * cos(t) + end_x, a*e**(b*t) * sin(t) + end_y )

        for i in range(int(length*m)):
            t2 = t - dt
            Dt = t2 -t
            # logarithmic spiral equations 
            x0 = a*e**(b*t) * cos(t) + end_x
            y0 = a*e**(b*t) * sin(t) + end_y 
        
            x3 = a*e**(b*t2) * cos(t2) + end_x
            y3 = a*e**(b*t2) * sin(t2) + end_y
  
            # Derivatives of spiral equation
            dx1 = a*b*e**(b*t) * cos(t) - a*e**(b*t) * sin(t)
            dy1 = a*e**(b*t) * cos(t) + a*b*e**(b*t) * sin(t) 

            dx2 = a*b*e**(b*t2) * cos(t2) - a*e**(b*t2) * sin(t2)
            dy2 = a*e**(b*t2) * cos(t2) + a*b*e**(b*t2) * sin(t2)  
      
            # calculate control points
            x1 = x0 + ((Dt/3.0) * dx1)
            y1 = y0 + ((Dt/3.0) * dy1)
   
            x2 = x3 - ((Dt/3.0) * dx2)
            y2 = y3 - ((Dt/3.0) * dy2)
            t -= dt
            self.curveto(x1, y1, x2, y2, x3, y3)
        self.inheritFromContext(kwargs.keys())
        if draw:
           self.draw()
コード例 #3
0
ファイル: bezier.py プロジェクト: x-raizor/nodebox-pyobjc
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
コード例 #4
0
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
コード例 #5
0
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))
コード例 #6
0
ファイル: bezier.py プロジェクト: x-raizor/nodebox-pyobjc
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
コード例 #7
0
ファイル: bezier.py プロジェクト: x-raizor/nodebox-pyobjc
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
コード例 #8
0
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
コード例 #9
0
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
コード例 #10
0
ファイル: papyruss_0.3.py プロジェクト: msarch/py
# 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")))
コード例 #11
0
# 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")))