Example codes of Bezier and B-spline surfaces (Python)
The following codes in Python are only tested with Grasshopper-Python and not with pure Python provided with Rhinoceros.
Bezier curve
Input: P (List Access)
Input parameter P is a list of sequential 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)

Bezier Surface
Input: P (List Access)
Input: nU
Input: nV
Input parameter P is a list of sequential points.
nU*nV must be equal to the total number of the points.

import rhinoscriptsyntax as rs import Rhino.Geometry as rg import math dimU=nU-1 dimV=nV-1 def u(x,nn): return x**nn def v(x,nn,dim): return (1-x)**(dim-nn) def nv(nn,dim): return math.factorial(dim)/(math.factorial(dim-nn)*math.factorial(nn)) def main(): tt=list() for x in rs.frange(0,1.0,0.1): for y in rs.frange(0,1.0,0.1): f=list() tt.append(f) for j in range(0,nV): for k in range(0,nU): s1=nv(k,dimU)*u(x,k)*v(x,k,dimU) s2=nv(j,dimV)*u(y,j)*v(y,j,dimV) f.append(s1*s2) out=list() print tt[120] for s in tt: PP=rg.Point3d(0,0,0) for d in range(0,nU*nV): PP=PP+s[d]*P[d] print PP out.append(PP) return out if len(P)==(nU)*(nV): a=main()

B-spline curve
Input: P (List access)
P is a point list.
B-spline curve is 99% same as Nurbs curve.
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.2): 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()

An equivalent rhinoscriptsyntax is
import Rhino.Geometry as rg import rhinoscriptsyntax as rs a=rg.NurbsCurve.CreateControlPointCurve(P,int(dim)-1)

Note that the same result is obtained.
B-spline surface
Input: P (List access)
Input: nU
Input: nV
Input: uDim
Input: vDim
nU*nV must be equal to the total number of points.
import rhinoscriptsyntax as rs import Rhino.Geometry as rg import math def split_seq(seq, size): return [seq[i:i+size] for i in range(0, len(seq), size)] 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,dim,knot): 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,dim,knot) S2=fN(_i,_k+1,_dim-1,dim,knot) 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,dim,ddim,knot): M=rg.Matrix(dim,dim) M.Zero() for k in range(i,dim+i): D=fN(i+ddim,k,dim,dim,knot) 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(P): out=list() segment=list() for j in range(1,nV-vDdim+1): vM=fM(j,vDim,vDdim,vKnot) for i in range(1,nU-uDdim+1): uM=fM(i,uDim,uDdim,uKnot) points=list() for n in range(vDim): uPoints=list() points.append(uPoints) for m in range(uDim): uPoints.append(P[j-1+n][i-1+m]) segment.append((uM,vM,points)) uT=rg.Matrix(1,uDim) vT=rg.Matrix(1,vDim) for seg in segment: (uM,vM,points)=seg for ut in rs.frange(0,1.0,0.1): for i in range(uDim): uT[0,i]=ut**(uDdim-i) for vt in rs.frange(0,1.0,0.1): for i in range(vDim): vT[0,i]=vt**(vDdim-i) uF=uT*uM vF=vT*vM PP=rg.Point3d(0,0,0) for i in range(uDim): for j in range(vDim): PP=PP+uF[0,i]*vF[0,j]*points[j][i] out.append(PP) return out uDdim=uDim-1 vDdim=vDim-1 N=len(P) uNSeg=nU-1 vNSeg=nV-1 uKnot=range(nU-uDdim+1) vKnot=range(nV-vDdim+1) uStartK=uKnot[0] uEndK=uKnot[uKnot.Count-1] vStartK=vKnot[0] vEndK=vKnot[vKnot.Count-1] for i in range(uDdim): uKnot.insert(0,uStartK) for i in range(uDdim): uKnot.insert(uKnot.Count,uEndK) for i in range(vDdim): vKnot.insert(0,vStartK) for i in range(vDdim): vKnot.insert(vKnot.Count,vEndK) print vKnot if nU*nV==N and nU>uDim-1 and nV>vDim-1: P=split_seq(P,nU) a=draw(P)

An equivalent rhinoscriptsyntax is
import Rhino.Geometry as rg a=rg.NurbsSurface.CreateFromPoints(P,nV,nU,vDim-1,uDim-1)

Note that the same result is obtained.
page revision: 24, last edited: 04 Nov 2013 04:57