getting and setting knots sequence

Need help, or want to share a macro? Post here!
Forum rules
Be nice to others! Respect the FreeCAD code of conduct!
Post Reply
aaa
Posts: 2
Joined: Wed May 22, 2019 12:55 pm

getting and setting knots sequence

Post by aaa »

Hi all,

Foreword: I am aware that this can be done using pure FreeCAD commands but I need to have it working using pythonocc first.

My question in short: how do you access a knot sequence and how do you update it?

My code so far
(which is an adaptation of one script from PyGeM script):

Code: Select all

from OCC.STEPControl import STEPControl_Reader
reader = STEPControl_Reader()
fileLocation = "pipe.step"
return_reader = reader.ReadFile(fileLocation)
return_transfer = reader.TransferRoots()
shape = reader.OneShape()
# Looping through the faces
facesExplorer = TopExp_Explorer(shape, TopAbs_FACE):
    face = topods_Face(faces_explorer.Current())
    nurbs_converter = BRepBuilderAPI_NurbsConvert(face)
    nurbs_converter.Perform(face)
    nurbs_face = nurbs_converter.Shape()
    face_aux = topods_Face(nurbs_face)
    brep_face = BRep_Tool.Surface(topods_Face(nurbs_face))
   bspline_face = geomconvert_SurfaceToBSplineSurface(brep_face)
   occ_face = bspline_face.GetObject()
   print("No Uknots", occ_face.NbUKnots())
   .....
   .....
   n_faces += 1
   faces_explorer.Next()
What I have: At this point I can easily access info such as: occ_face.NbUKnots(), occ_face.VDegree() and many more. I have already another code which updates the pole and weight values.
Specific question: Now I have surface which has 2 knots along both U and V directions. What I'd like to do is to increase that number to 10 in both U and V directions and set their values (I know them).
Proposed action: Using python dir(occ_face) I can see all the methods available on the occ_face object to access the knots info. I am sure I can get the sequence via UKnotSequence () and then update their value via SetUKnot() or SetUKnots(), but reading the online API is not helping me, meaning I am not sure on the syntax.

Thanks
Last edited by aaa on Thu May 23, 2019 6:58 am, edited 1 time in total.
User avatar
Kunda1
Veteran
Posts: 13434
Joined: Thu Jan 05, 2017 9:03 pm

Re: getting and setting knots sequence

Post by Kunda1 »

Please use the bbcode code tags for code, especially python. Thank you.
Alone you go faster. Together we go farther
Please mark thread [Solved]
Want to contribute back to FC? Checkout:
'good first issues' | Open TODOs and FIXMEs | How to Help FreeCAD | How to report Bugs
wmayer
Founder
Posts: 20309
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: getting and setting knots sequence

Post by wmayer »

When you have a certain B-spline curve or surface then you cannot just force a certain knot sequence because there is a relation between sum of multiplicities of the knot sequence, number of poles and degree.
For a non-periodic spline the formula is: sum of multiplicity = number of poles + degree + 1

So, you can either use IncreaseUMultiplicity or InsertUKnot followed by SetUKnot or use the constructor to create a new geometry from scratch.
aaa
Posts: 2
Joined: Wed May 22, 2019 12:55 pm

Re: getting and setting knots sequence

Post by aaa »

Thanks for the reply.

I have then decided to reconstruct directly the surface using this method (I post here just others need it):

Code: Select all

 def getNewBspline(morphedSurfaceCPs, Uknot, Vknot, size_CPu, size_CPv):
    """
    just to create an occ object from known inputs
    """
    
    # Set U and V degree
    udeg = 2
    vdeg = 2

    # Non-periodic surface
    uperiod = False
    vperiod = False

    # Create 2D array of poles (control points)
    poles = TColgp_Array2OfPnt(1, size_CPu, 1, size_CPv)

    # Length of uknots and umult has to be same
    uknot_len = umult_len = 6
    vknot_len = vmult_len = 6

    # Knots for U and V direction
    uknots = TColStd_Array1OfReal(1, uknot_len)
    vknots = TColStd_Array1OfReal(1, vknot_len)

    # Multiplicities for U and V direction
    umult = TColStd_Array1OfInteger(1, umult_len)
    vmult = TColStd_Array1OfInteger(1, vmult_len)

    # known knots. Hard-coded! it should be passed using Uknot, Vknot,
    a = [0.0, 0.0, 0.0, 0.133158697885057, 0.35008109017103256, 0.5665743221956696, 0.7834695745668847, 1.0, 1.0, 1.0]
    b = [0.0, 0.0, 0.0, 0.11644466689174149, 0.3124312466475101, 0.49811972614017913, 0.7229308860113697, 1.0, 1.0, 1.0]
    
    # Main curves begins and ends at first and last points
    # ----> UKnots(i) < UKnots(i+1) (Knots are increasing) <----
    uknots.SetValue(1, 0.0)
    uknots.SetValue(2, a[3])
    uknots.SetValue(3, a[4])
    uknots.SetValue(4, a[5])
    uknots.SetValue(5, a[6])
    uknots.SetValue(6, 1.0)

    vknots.SetValue(1, 0.0)
    vknots.SetValue(2, b[3])
    vknots.SetValue(3, b[4])
    vknots.SetValue(4, b[5])
    vknots.SetValue(5, b[6])
    vknots.SetValue(6, 1.0)

    # First and last multiplicities are set to udeg + 1 (vdeg respectively),
    # because we want main curves to start and finish on the first and the last points
    # ----> 1 <= UMults(i) <= UDegree <----

    umult.SetValue(1, udeg + 1)
    umult.SetValue(2, 1)
    umult.SetValue(3, 1)
    umult.SetValue(4, 1)
    umult.SetValue(5, 1)
    umult.SetValue(6, udeg + 1)

    vmult.SetValue(1, vdeg + 1)
    vmult.SetValue(2, 1)
    vmult.SetValue(3, 1)
    vmult.SetValue(4, 1)
    vmult.SetValue(5, 1)
    vmult.SetValue(6, vdeg + 1)

    # Try to create surface
    bss = Geom_BSplineSurface(poles, uknots, vknots, umult, vmult, udeg, vdeg, uperiod, vperiod)
    
    # Updating the CPS position"
    counter = -1
    for i in range(size_CPu):
        for j in range(size_CPv):
            counter+=1       
            #print(counter) 
            # Remember convention in pythonOCC is to start from 1 and not o!!!            
            bss.SetPole(i+1, j+1, gp_Pnt(morphedSurfaceCPs[counter,0], morphedSurfaceCPs[counter,1], morphedSurfaceCPs[counter,2]))   
 
   return bss
 


In my previous code I have the "nurbs_face" which I use to access the edges:

Code: Select all

edge_explorer = TopExp_Explorer(nurbs_face, TopAbs_EDGE)
My question is: how do I get the nurbs_face when I have only a bss which is a: class<'Geom_BSplineSurface'>.

Thanks
Post Reply