fitting profile/curve to bezier surface

StomilOlsztyn

Looking around for some CAD
Hi, this is my first time here, another green but willing, and yes i am trying to
solicit some help :)

My goal was to recreate something akin to Blender "curve modifier”, that take flat
2D curve/profile and lay it on (or make it conform to) Bezier surface, while keeping
perimeter/surface area of curve/profile constant. More or less like this, but not animated:

Peek 2022-12-02 19-19.gif

I thought that code from "neck threading" in OCCT bottle tutorial could serve as
an close example, so this my a code based on it :

C++:
    TColgp_Array2OfPnt polesUpper(1,11,1,3);
    polesUpper(1,1) = gp_Pnt(0.,    0.,        0.);
    polesUpper(2,1) = gp_Pnt(0.1,    0.,        1.);
    polesUpper(3,1) = gp_Pnt(0.2,    0.,        0.);
    polesUpper(4,1) = gp_Pnt(0.3,    0.,        -1.);
    polesUpper(5,1) = gp_Pnt(0.4,    0.,        0.);
    polesUpper(6,1) = gp_Pnt(0.5,    0.,        2.4);
    polesUpper(7,1) = gp_Pnt(0.6,    0.,        0.);
    polesUpper(8,1) = gp_Pnt(0.7,    0.,        -1.);
    polesUpper(9,1) = gp_Pnt(0.8,    0.,        0.);
    polesUpper(10,1) = gp_Pnt(0.9,    0.,        1.);
    polesUpper(11,1) = gp_Pnt(1.0,    0.,        0.);
    //
    polesUpper(1,2) = gp_Pnt(0.,    0.5,        0.);
    polesUpper(2,2) = gp_Pnt(0.1,    0.5,        1.);
    polesUpper(3,2) = gp_Pnt(0.2,    0.5,        0.);
    polesUpper(4,2) = gp_Pnt(0.3,    0.5,        -1.);
    polesUpper(5,2) = gp_Pnt(0.4,    0.5,        0.);
    polesUpper(6,2) = gp_Pnt(0.5,    0.5,        2.4);
    polesUpper(7,2) = gp_Pnt(0.6,    0.5,        0.);
    polesUpper(8,2) = gp_Pnt(0.7,    0.5,        -1.);
    polesUpper(9,2) = gp_Pnt(0.8,    0.5,        0.);
    polesUpper(10,2) = gp_Pnt(0.9,    0.5,        1.);
    polesUpper(11,2) = gp_Pnt(1.0,    0.5,        0.);
    //
    polesUpper(1,3) = gp_Pnt(0.,    1.,        0.);
    polesUpper(2,3) = gp_Pnt(0.1,    1.,        1.);
    polesUpper(3,3) = gp_Pnt(0.2,    1.,        0.);
    polesUpper(4,3) = gp_Pnt(0.3,    1.,        -1.);
    polesUpper(5,3) = gp_Pnt(0.4,    1.,        0.);
    polesUpper(6,3) = gp_Pnt(0.5,    1.,        2.4);
    polesUpper(7,3) = gp_Pnt(0.6,    1.,        0.);
    polesUpper(8,3) = gp_Pnt(0.7,    1.,        -1.);
    polesUpper(9,3) = gp_Pnt(0.8,    1.,        0.);
    polesUpper(10,3) = gp_Pnt(0.9,    1.,        1.);
    polesUpper(11,3) = gp_Pnt(1.0,    1.,        0.);

    TColgp_Array2OfPnt polesLower(1,3,1,3);
    polesLower(1,1) = gp_Pnt(0.,    0.,        -0.5);
    polesLower(2,1) = gp_Pnt(0.5,    0.,        -0.5);
    polesLower(3,1) = gp_Pnt(1.0,    0.,        -0.5);
    //
    polesLower(1,2) = gp_Pnt(0.,    0.5,    -0.5);
    polesLower(2,2) = gp_Pnt(0.5,    0.5,    -0.5);
    polesLower(3,2) = gp_Pnt(1.0,    0.5,    -0.5);
    //
    polesLower(1,3) = gp_Pnt(0.,    1.,        -0.5);
    polesLower(2,3) = gp_Pnt(0.5,    1.,        -0.5);
    polesLower(3,3) = gp_Pnt(1.0,    1.,        -0.5);

    Handle(Geom_BezierSurface) aBezierBaseUpper = new Geom_BezierSurface(polesUpper);
    Handle(Geom_BezierSurface) aBezierBaseLower = new Geom_BezierSurface(polesLower);

    gp_Pnt2d aPnt(0.5, 0.5);
    gp_Dir2d aDir(1.0, 0.0);
    gp_Ax2d anAx2d(aPnt, aDir);

    Standard_Real aMajor = 0.8/2;
    Standard_Real aMinor = 0.2/2;

    Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
    Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);

    TopoDS_Edge anEdgeOnSurf1 = BRepBuilderAPI_MakeEdge(anEllipse1, aBezierBaseUpper);
    TopoDS_Edge anEdgeOnSurf2 = BRepBuilderAPI_MakeEdge(anEllipse2, aBezierBaseLower);

    TopoDS_Wire wireUpper = BRepBuilderAPI_MakeWire(anEdgeOnSurf1);
    TopoDS_Wire wireLower = BRepBuilderAPI_MakeWire(anEdgeOnSurf2);

    // ?
    BRepLib::BuildCurves3d(wireUpper);
    BRepLib::BuildCurves3d(wireLower);

    // loft
    BRepOffsetAPI_ThruSections aTool(Standard_True);
    aTool.AddWire(wireUpper);
    aTool.AddWire(wireLower);
    aTool.CheckCompatibility(Standard_False);

    // extract shape
    TopoDS_Shape aImprint = aTool.Shape();

When reading the tutorial, it seemed to me that the profile/curve would be applied
to the UV "unwrapped" Bezier surface, to be retrieved later bearing its imprint.
I am fully aware that I may have mixed up or used something incorrectly.
But all i can get so far is looking like intersection between Bezier surface and
∞Z extruded ellipse (or ortho/straight projection - a cookie cutter):

Peek 2022-12-05 19-04.gif

Is it possible to tweak this code to achieve the effect described above?
If not, can it be done using other modules built into OCCT? Or does the solution
needs to be completely build by hand.
 

Quaoar

Administrator
Staff member
Hello @StomilOlsztyn and welcome to the forum.

If I understood correctly, you have a planar curve and you want to wrap it onto a predefined Bezier surface, right? To me, it looks more like a question of unfolding (unwrapping), where you have a folded state of geometry and its mapping onto a plane (for double-curved surfaces, this should involve deformations). With this mapping (plane to curved) at hand, you draw a profile in 2D and then construct the folded image in 3D, right?

The way we solved it back in the day was by implementing a mesh-based unfolding algorithm. It was for ship hull plates that had to be unfolded, then the user put some mark lines onto the flat pattern, and those lines were mapped back to 3D. Is your case similar?

Using UV space is a kind of simplification here because UV space is distorted w.r.t. the surface it defines. So you can draw your planar profile in the UV domain of a surface and map it back to 3D using something like GeomAPI::To3d(), which is essentially reapproximation. That was exactly the trick in the "bottle tutorial".
 

StomilOlsztyn

Looking around for some CAD
First of all, thanks a lot for the tutorials. Currently the single best source about OCCT, apart from few outdated blogs and the official documentation (to a limited extent)

1. yep, you pretty much hit the spot.

2. I've done some "investigation" on the subject before first post here, and dismissed poly based (un)folding as immediate solution - this is quite a deep topic - and starting new project in order to finish one I am currently on is simply not an option. I've been stuck in this loop way too many times :)

3. I'll look into it over the holidays but, in the meantime i think I've found a different approach - Blender has a running python interpreter, so instead of reinventing the wheel - Let's use Blender as importer (curves/profiles come as dxf/svg), and to do heavy lifting via 'curve modifier'. Then finalize shape and export design by using CadQuery and OCP (OCCT wrapper used by CQ) - all from inside Blender python environment .

Looks promising, or at least looks like a less work.
 
Top