how can I create a free NURBS surface?

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
silent_missile
Posts: 16
Joined: Mon Jul 29, 2019 11:07 pm

how can I create a free NURBS surface?

Post by silent_missile »

Hello everybody

I have some requirement to create a free NURBS surface, then make some manipulation like trim and intersect, then export it to iges or step.

the difficulty is to create the free NURBS surface, I have all data of the surface

control points: in OCCT, it's Poles
[
[p00x, p00y, p00z, p00w], [p01x, p01y, p01z, p01w], [p02x, p02y, p02z, p02w]...,
[p10x, p10y, p10z, p10w], [p11x, p11y, p11z, p11w], [p12x, p12y, p12z, p12w]...,
...
]
Udegree: degree of U direction, integer
Uknots: knots for U direction, Uknots.length = Poles[0].length+Udegree+1
[0,0,...Udegree+1 0s, u1, u2, u3...un, 1, 1, Udegree+1 1s]
Vdegree: similar like Udegree
Vknots: similar like Uknots, Vknots.length = Poles.length+Vdegree+1

I checked addon manager in FreeCAD, and installed "nurbs" addon, but the functions can't work, my FreeCAD is 0.18.16131 win64 on win10

also "nurbs" addon seems can make nurbs spline from a sketch in a plane, but my points are not in the same plane

can anybody give me some guidance?
emills2
Posts: 875
Joined: Tue Apr 28, 2015 11:23 pm

Re: how can I create a free NURBS surface?

Post by emills2 »

edit: examples below are from Part module. no addons are required for what you want. But you could take a look at my Silk addon ;)

example from https://github.com/edwardvmills/Silk/bl ... chNURBS.py

here is how i format my curves:

Code: Select all

def Bezier_Cubic_curve(poles):      # pinned cubic rational B spline, 4 control points
                                    # Part.BSplineCurve(), cubic bezier form
#draws a degree 3 rational bspline from first to last point,
# second and third act as tangents
# poles is a list: [[[x,y,z],w],[[x,y,z],w],[[x,y,z],w],[[x,y,z],w]]
## nKnot = 4 + 3 +1 = 8
## Order = 3 + 1 = 4
	degree=3
	nPoles=4
	knot=[0,0,0,0,1,1,1,1]
	bs=Part.BSplineCurve()
	bs.increaseDegree(degree)
	id=1
	for i in range(0,len(knot)):    #-1):
		bs.insertKnot(knot[i],id,0.0000001)
	i=0
	for ii in range(0,nPoles):
		bs.setPole(ii+1,poles[i][0],poles[i][1])
		i=i+1;
	return bs
note that i separate the weights from x y z because i find it easier to pass them to .setPole() that way

and for a surface example:

Code: Select all

def NURBS_Cubic_66_surf(grid_66):	# given a 6 x 6 control grid, build the cubic
	# NURBS surface from a Part.BSplineSurface().
	# len(knot_u) := nNodes_u + degree_u + 1
	# len(knot_v) := nNodes_v + degree_v + 1
	degree_u=3
	degree_v=3
	nNodes_u=6
	nNodes_v=6
	knot_u=[0,0,0,0,1.0/3.0,2.0/3.0,1,1,1,1]
	knot_v=[0,0,0,0,1.0/3.0,2.0/3.0,1,1,1,1]
	NURBS_Cubic_66_surf=Part.BSplineSurface()
	NURBS_Cubic_66_surf.increaseDegree(degree_u,degree_v)
	id=1
	for i in range(0,len(knot_u)):    #-1):
		NURBS_Cubic_66_surf.insertUKnot(knot_u[i],id,0.0000001)
	id=1
	for i in range(0,len(knot_v)):    #-1):
		NURBS_Cubic_66_surf.insertVKnot(knot_v[i],id,0.0000001)
	i=0
	for jj in range(0,nNodes_v):
		for ii in range(0,nNodes_u):
			NURBS_Cubic_66_surf.setPole(ii+1,jj+1,grid_66[i][0],grid_66[i][1]);
			i=i+1;
	return  NURBS_Cubic_66_surf
both of these functions are adapted from examples i received from Werner originally.

the key difference for you is going to be whether to hard code the knot vectors and grid size or not. in my case, i like to work with clearly predefined sizes

edit: sorry just notice that the comment indents are jacked.
silent_missile
Posts: 16
Joined: Mon Jul 29, 2019 11:07 pm

Re: how can I create a free NURBS surface?

Post by silent_missile »

thank you emills2

by your guidance, I created some demo code

Code: Select all

import FreeCAD
import Part
FreeCAD.newDocument("test")
FreeCAD.setActiveDocument("test")
FreeCAD.ActiveDocument = FreeCAD.getDocument("test")
# NURBS surface from a Part.BSplineSurface().
# len(knot_u) := nNodes_u + degree_u + 1
# len(knot_v) := nNodes_v + degree_v + 1
poles=[[[15.5, 4.8, 1.46, 1.0], [10.18, 4.8, 0.89, 1.0], [1.8, 8.9, 0.57, 1.0], [0, 15, 0.43, 1.0], [0, 22, -0.02, 1.0]], [[15.15, 17.05, 1.13, 1.0], [11.7, 17.05, 0.81, 1.0], [6.72, 17.1, 0.48, 1.0], [4.31, 18.74, 0.38, 1.0], [3.23, 22.8, 0.05, 1.0]]]
degree_u=1
degree_v=3
nNodes_u=2
nNodes_v=5
knot_v=[0, 0.5256099762388414, 1]
knot_v_mults=[4, 1, 4]
knot_u=[0,1]
knot_u_mults=[2, 2]
NURBS_Cubic_surf=Part.BSplineSurface()
NURBS_Cubic_surf.increaseDegree(degree_u,degree_v)

for i in range(0,len(knot_u)):    #-1):
	NURBS_Cubic_surf.insertUKnot(knot_u[i],knot_u_mults[i],0.0000001)

for i in range(0,len(knot_v)):    #-1):
	NURBS_Cubic_surf.insertVKnot(knot_v[i],knot_v_mults[i],0.0000001)

poles_xyz=[]
for ii in range(0, len(poles)):
	poles_xyz.append([])
	for jj in range(0, len(poles[ii])):
		poles_xyz[ii].append(FreeCAD.Base.Vector(poles[ii][jj][0], poles[ii][jj][1], poles[ii][jj][2]))
		NURBS_Cubic_surf.setPole(ii+1, jj+1, poles_xyz[ii][jj], poles[ii][jj][3])
after I run it, there was no error hint, so it should run well, but nothing is displayed on the screen, could you please give me some more advise?
Last edited by silent_missile on Thu Aug 08, 2019 7:23 am, edited 2 times in total.
User avatar
shaise
Posts: 470
Joined: Thu Jun 11, 2015 8:11 am

Re: how can I create a free NURBS surface?

Post by shaise »

silent_missile wrote: Thu Aug 08, 2019 5:41 am after I run it, there was no error hint, so it should run well, but nothing is displayed on the screen, could you please give me some more advise?
You need to instruct freecad to show the object you created.
Add the following line:

Code: Select all

Part.show(NURBS_Cubic_surf.toShape())
shai
Post Reply