tpaviot / pythonocc-core

Python package for 3D geometry CAD/BIM/CAM
GNU Lesser General Public License v3.0
1.27k stars 365 forks source link

Knotvector of nurbs surface #706

Open JanssensNick opened 4 years ago

JanssensNick commented 4 years ago

Dear I have some questions about Nurbs or bspline surfaces:

1) I have extracted a NURBS surface from a stepfile, now I would like to get access to the knotvectors in the u and v directions. It is easy to get the number of poles, degrees...: degree_u = bsplineSurface.UDegree() nUPoles = besplineSurface.NbUPoles() But I can't seem to find an equivalent command to extract the knotvectors or knotsequence. Any ideas?

2) Given the control points of a Nurbs surface, how is any point on the Nurbs surface computed based on the control points? I know that a point on the surface should be a weighted average of the control points, where the weights are determined based on the rational basis functions of the nurbs surface. I would like to evaluate these basis functions in some parametric u and v coordinate.

Kind regards Nick

rainman110 commented 4 years ago

See here for example

rainman110 commented 4 years ago

The definition of a nurbs surface: http://mathworld.wolfram.com/NURBSSurface.html

rainman110 commented 4 years ago

To evaluate the basis functions: BSplCLib::EvalBsplineBasis

rainman110 commented 4 years ago

If you just want to evaluate points on the surface, just use Geom_BSplineSurface::Value: https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_geom___surface.html#ac8748d91761aabbfc79508fc4213f985

JanssensNick commented 4 years ago

Thank you very much for your answer! When looking at the link you send me: http://mathworld.wolfram.com/NURBSSurface.html it is actually the whole factor before P_ij that I need to extract. I have however som questions:

rainman110 commented 4 years ago

What is it, you actually try to achieve?

Assume I have a point S on a bspline surface at parametric coordinates u and p. How can use the EvalBsplineBasis function to extract the terms N_ip and N_jq in the formula for the NURBS surface

You have to get first the u,v coordinates of that point. Use therefore: https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_geom_a_p_i___project_point_on_surf.html#a016516bed2a97c4f957d38f892039f95

Then, use https://www.opencascade.com/doc/occt-7.0.0/refman/html/class_b_spl_c_lib.html#ad40c203ac6d43b8d4d7bfbfdd6507016 to get the basisfunction N_i / N_j for the u and v coordinates.

Have a look here: https://github.com/DLR-SC/tigl/blob/d42a18e66d03cf2956bdbb96301e0e87fd519ef7/src/geometry/CTiglBSplineAlgorithms.cpp#L821

rainman110 commented 4 years ago

@JanssensNick There are two different methods, Knots(TColStd_Array1OfReal) and Knot(int).

The first one returns the whole Knot vector. You have to pass in (output argument) the array of correct size. Knot(int) returns the i-th knot vector value. Note: In OCCT, knots are not flattened.

Typically you'll have in textbooks a knot vector like: [0 0 0 0.3 0.5 0.7 1 1 1]

In OCCT, you have instead: Knots: [0 0.3 0.5 0.7 1] Mults [3 1 1 1 3]

The multiplicity array determines, how often a knot vector value is repeated in the knot vector.

To get the whole factor in front of the control points Pij, you need the b-spline basis function N_i(u) and N_j(v) and the weights wij. I've already written, how to query the basis functions.

I still don't get, why you actually need them. This should be only required in very advanced self-written NURBS algorithms. To simply evaluate the NURBS, you don't need it, as OCCT already provides the ::Value(u,v) method.

JanssensNick commented 4 years ago

Dear Again, thank you for your answer. So, why do I need all of this? I am implementing shape optimisation. The goal of this is to modify the boundaries of some shape in order to maximize or minimize some goal function. My geometry is given in some step file. Now I use pythonocc to extract the faces of this geometry, and these faces are parametrised by NURBS patches. As a part of the shape optimisation module, I need to now how a point on the surface of my geometry (so a point on the NURBS patch) changes when I modify the parameters of my geometry (= the control points of the NURBS patch = the design parameters of my shape optimisation). This actually corresponds to the sensitivity of a point on the surface to my design variables. This sensitivity is then used in a gradient based optimisation algorithm to modify the control points in an optimal matter. Now: for a NURBS patch, the sensitivity of a point Ps on the surface to a control points P_ij is equal to the whole factor in front of P_ij in the formula for the NURBS surface. This is why I need all this.

JanssensNick commented 4 years ago

Just a small question about the methods UKnots(). When I apply it to my bspline face:

            nurbs_converter = BRepBuilderAPI_NurbsConvert(topo_face)
            nurbs_converter.Perform(topo_face)
            nurbs_face = nurbs_converter.Shape()
            h_geomsurface = BRep_Tool.Surface(topods.Face(nurbs_face))
            h_bsurface = geomconvert_SurfaceToBSplineSurface(h_geomsurface)
            bsurface = h_bsurface.GetObject()
            nUKnots = bsurface.NbUKnots()
            Ku = TColStd_Array1OfReal(1,nUKnots)
            uKnots = bsurface.UKnots(Ku)
           print uKnots

the result is just None. Where did I do wrong?

rainman110 commented 4 years ago

The result will be in ku! The function uses an output argument.

rainman110 commented 4 years ago

In fact, the function https://github.com/DLR-SC/tigl/blob/d42a18e66d03cf2956bdbb96301e0e87fd519ef7/src/geometry/CTiglBSplineAlgorithms.cpp#L821

computes this Jacobian ( for B-splines, i.e. w=1) that you are interested in for all basis functions N_j and a set of parameters u_i. In case of a surface, you just need the tensor product of both matrices ( one for u direction, one for v direction).

This codes demonstrates at least, how to get to the basis function values.

jf--- commented 4 years ago

I am implementing shape optimization

Interesting domain to work in. Have you seen the pygem post on the pyocc site @JanssensNick ?

JanssensNick commented 4 years ago

Thank you once again guys! And yes, I am also using pygem in my implementation. Currently, I am using the RBF functionality of pygem for mesh deformation.

JanssensNick commented 4 years ago

Hello again! I was trying to implement the function https://github.com/DLR-SC/tigl/blob/d42a18e66d03cf2956bdbb96301e0e87fd519ef7/src/geometry/CTiglBSplineAlgorithms.cpp#L821 I am doing this in Python. However, I can't seem to find the function EvalBsplineBasis for import. I tried: from OCC.BSplCLib import EvalBsplineBasis but EvalBsplineBasis is not recognised.