Parametric curves and surfaces

Sample code to draw a Bezier curve

P: a list of points.

import rhinoscriptsyntax as rs

import Rhino.Geometry as rg

import math

dim=len(P)-1

def u(x,nu):

    return x**nu

def v(x,nu):

    return (1-x)**(dim-nu)

def nv(nu):

    return math.factorial(dim)/(math.factorial(dim-nu)*math.factorial(nu))

 

tt=list()

for i in rs.frange(0,1.0,0.01):

    f=list()

    tt.append(f)

    for j in range(0,dim+1):

        f.append(nv(j)*u(i,j)*v(i,j))

a=list()

print tt

for s in tt:

    PP=rg.Point3d(0,0,0)

    for d in range(0,dim+1):

        PP=PP+s[d]*P[d]

    a.append(PP)

Sample code to draw a NURBS curve

P: a list of points.

import rhinoscriptsyntax as rs

import Rhino.Geometry as rg

import math

ddim=dim-1

N=len(P)

nSeg=N-1

knot=range(N-ddim+1)

startK=knot[0]

endK=knot[knot.Count-1]

for i in range(ddim):

    knot.insert(0,startK)

for i in range(ddim):

    knot.insert(knot.Count,endK)

def binominal(m,n):

    return math.factorial(m)/math.factorial(m-n)/math.factorial(n)

def func(i,j):

    k=dim

    T=binominal(k-1,i)/math.factorial(k-1)

    value=0

    for l in range(j,k):

        value+=binominal(k,l-j)*(k-(l+1))**i*(-1)**(l-j)

    return value*T

def fN(_i,_k,_dim):

    if _dim==1:

        F=list()

        for i in range(dim):

            F.append(0)

        if _k==_i:

            F[dim-1]=1

        return F

    S1=fN(_i,_k,_dim-1)

    S2=fN(_i,_k+1,_dim-1)

    E1=knot[_k+_dim-2]-knot[_k-1]

    E2=knot[_k+_dim-1]-knot[_k]

    D1=list()

    D2=list()

    D1.append(0)

    D1.append(0)

    D2.append(0)

    D2.append(0)

    if  E1>0:

        D1[0]=1/E1

        D1[1]=-knot[_k-1]/E1

    if E2>0:

        D2[0]=-1/E2

        D2[1]=knot[_k+_dim-1]/E2

    F=list()

    for i in range(dim):

        F.append(0)

    for i in range(1,dim):

        F[i-1]=F[i-1]+S1[i]*D1[0];

        F[i]=F[i]+S1[i]*D1[1];

        F[i-1]=F[i-1]+S2[i]*D2[0];

        F[i]=F[i]+S2[i]*D2[1];

    return F

def fM(i):

    M=rg.Matrix(dim,dim)

    M.Zero()

    for k in range(i,dim+i):

        D=fN(i+ddim,k,dim)

        for n in range(dim):

            M[n,k-i]=D[n]

 

    S=rg.Matrix(dim,dim)

    S.Zero()

    for n in range(1,dim+1):

        for k in range(1+n,dim+2):

            if n==dim:

                for t in range(n-1):

                   S[t,n-1]=0

                S[n-1,n-1]=1

            else:

                S[k-2,n-1]=binominal(dim-n,dim+1-k)*((i-1)**(k-1-n))

    G=S*M

    return G

def draw():

    out=list()

    segment=list()

    for i in range(1,N-ddim+1):

        M=fM(i)            

        points=list()

        for n in range(dim):

            points.append(P[i-1+n])

        segment.append((M,points))

    T=rg.Matrix(1,dim)

    for seg in segment:

        M=seg[0]

        points=seg[1]

        for t in rs.frange(0,1.0,0.02):

            for i in range(dim):

                T[0,i]=t**(ddim-i)

            F=T*M

            PP=rg.Point3d(0,0,0)

            for i in range(dim):

                PP=PP+F[0,i]*points[i]

            out.append(PP)

    return out

if N>dim-1:

    a=draw()