From edd2931a844a0e681aee3b9c42e54e40d75dbb7e Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 12:18:29 +0200 Subject: [PATCH 01/44] added new class --- src/geometry/CTiglRoundedSegmentSurface.cpp | 3 +++ src/geometry/CTiglRoundedSegmentSurface.h | 10 ++++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/geometry/CTiglRoundedSegmentSurface.cpp create mode 100644 src/geometry/CTiglRoundedSegmentSurface.h diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp new file mode 100644 index 0000000000..fe8c25ba2f --- /dev/null +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -0,0 +1,3 @@ +#include "CTiglRoundedSegmentSurface.h" + +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface() {} diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h new file mode 100644 index 0000000000..05f5e2cbab --- /dev/null +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -0,0 +1,10 @@ +#ifndef CTIGLROUNDEDSEGMENTSURFACE_H +#define CTIGLROUNDEDSEGMENTSURFACE_H + +class CTiglRoundedSegmentSurface +{ +public: + CTiglRoundedSegmentSurface(); +}; + +#endif // CTIGLROUNDEDSEGMENTSURFACE_H From 4e9ff8b8e71360995cf02d1ef9e32c7c0c701b49 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 12:32:10 +0200 Subject: [PATCH 02/44] add test class --- .../TestCTiglRoundedSegmentSurface.cpp | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 tests/unittests/TestCTiglRoundedSegmentSurface.cpp diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp new file mode 100644 index 0000000000..4023f23b83 --- /dev/null +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -0,0 +1,343 @@ +#include "CCPACSWingSection.h" +#include "Debugging.h" +#include "test.h" +#include "tigl.h" +#include "tiglcommonfunctions.h" +#include "tixi.h" + +#include "CCPACSConfigurationManager.h" + +#include "CTiglMakeLoft.h" +#include "CTiglError.h" +#include "CCPACSConfigurationManager.h" +#include "CCPACSWing.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "CCPACSCurvePointListXYZ.h" +#include "CCPACSCurveParamPointMap.h" + +TEST(TestCTiglRoundedSegmentSurface, make_minimal_Shape) +{ + + //Create Profile Curves Vector + TColgp_HArray1OfPnt u_poles(1,7); + u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u1_poles(1,7); + u1_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u1_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u1_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u1_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u1_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u1_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u1_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u2_poles(1,7); + u2_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u2_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u2_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u2_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u2_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u2_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u2_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + + TColStd_Array1OfReal u_knots(1,3); + u_knots.SetValue(1,-1.); + u_knots.SetValue(2,0.); + u_knots.SetValue(3,1.); + + TColStd_Array1OfInteger u_mults(1,3); + u_mults.SetValue(1,4); + u_mults.SetValue(2,3); + u_mults.SetValue(3,4); + + int u_degree = 3; + + //Create three profiles for the loft + std::vector profileCurves; + auto profile_root = new Geom_BSplineCurve(u_poles, u_knots, u_mults, u_degree); + profileCurves.push_back(profile_root); + + Handle(Geom_BSplineCurve) profile_mid = new Geom_BSplineCurve(u1_poles, u_knots, u_mults, u_degree); + //Scale by (0.66,1.,0.66) Translate by (0.2,0.5,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_mid->Poles().Value(i).Coord().X()*0.66+0.2; + double Y = profile_mid->Poles().Value(i).Coord().Y()*1.+0.5; + double Z = profile_mid->Poles().Value(i).Coord().Z()*0.66+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_mid->SetPole(i,transformed_pole); + } + + profileCurves.push_back(profile_mid); + + Handle(Geom_BSplineCurve) profile_tip = new Geom_BSplineCurve(u2_poles, u_knots, u_mults, u_degree); + //Scale by (0.2,1.,0.1) Translate by (1.,2.,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_tip->Poles().Value(i).Coord().X()*0.2+1.; + double Y = profile_tip->Poles().Value(i).Coord().Y()*1.+2.; + double Z = profile_tip->Poles().Value(i).Coord().Z()*0.1+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_tip->SetPole(i,transformed_pole); + } + + profileCurves.push_back(profile_tip); + + for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ + throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); + } + } + //skin the curves ('profileCurves'): new code for curvesToSurface + // //(input are curves, make Geom_BSplineSurface -> build the TopoDS_Shape from this (-> output is TopoDS_Shape)) + /* + New code for skinning a wing surface: + Goal: Create a surface, implement rounded sections + + Steps: Create k Dummy-Profile(s-Curves maybe just the poles?) within innerRounding distance + Create Matrix that contains all poles of each profile curve and all Dummy-Profile-Curves + - i-th row represents a profile in u-direction + - j-th columnrepresents a curve in v-direction + + Steps: Retrieve poles from inner and outer profile + Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile + store new poles and original poles all in one matrix + */ + + ////determine distance between both vectors + //Standard_Real distance_inner_outer = originalCurve_inner.Distance(originalCurve_outer); + //determine new location for pole relative to inner profile and inner rounding distance + //datatype for poles and 'support vectors' is gp_Pnt storage is 'TColgp_Array1OfPnt &', needs to be const? + //datatype for knots is 'double/Standard_Real', stored in 'TColStd_Array1OfReal &', needs to be const? + //dummy values, will be input params later + double inner_rd =0.2; + double outer_rd =0.3; + size_t nb_dummies =3; //Rows per rounding distance + //Standard_Integer u_degree = profileCurves[0]->Degree(); + Standard_Integer v_degree = 3; + + Standard_Integer m = profileCurves.size()+(profileCurves.size()-2)*2*nb_dummies; + Standard_Integer n = profileCurves[0]->NbPoles(); + + //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector + //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge + //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) + //note: loop-indices are named i,j,k and refer to row,column,number of dummy-Profile for better geometric/code-orientation + + TColgp_HArray2OfPnt pole_matrix(1,m,1,n); + gp_Pnt inner_originalCurve_pnt, outer_originalCurve_pnt; + + for (int i=0; i< profileCurves.size(); i++){ + //iterate through columns to create Dummy Profiles to each pair of profiles + for( int j=0; j< n; j++){ + //retrieve a pole to each profile + if(iPole(j+1);//v0 + outer_originalCurve_pnt = profileCurves[i+1]->Pole(j+1); //v1 + } + //calculate Vector between both profile poles and normalize it + //distance between both points is length of this vector + gp_Vec vector_in_v_direction(inner_originalCurve_pnt, outer_originalCurve_pnt); //v01 + gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); + if(inner_originalCurve_pnt.IsEqual(outer_originalCurve_pnt, 1e-14)){ + throw tigl::CTiglError(std::to_string(inner_originalCurve_pnt.Coord().X())+"x"+ + std::to_string(inner_originalCurve_pnt.Coord().Y())+"y"+ + std::to_string(inner_originalCurve_pnt.Coord().Y())+"Z"+ + std::to_string(outer_originalCurve_pnt.Coord().X())+"x"+ + std::to_string(outer_originalCurve_pnt.Coord().Y())+"y"+ + std::to_string(outer_originalCurve_pnt.Coord().Y())+"Z"); + } + normalized_vector_in_v_direction.Normalize(); //|v01| + //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): + //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) + //add profile first + int current_row; + if(i==0){ + current_row =1; + } else { + current_row = nb_dummies+3+(i-1)*(1+nb_dummies*2); + } + //insert first profile pole + if(current_row==1){ + std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; + pole_matrix.SetValue(current_row,j+1, inner_originalCurve_pnt); //v0 first + current_row+=1; + } + //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section + if(i>0&&i nb_dummies -(k+1)/nb_dummies) + //except last section + if(i<(profileCurves.size()-2)){ + for (int k=0; k < nb_dummies; k++){ + //calculate distance between k-th outer dummy-pole in v-direction and profile + double outer_distance = outer_rd/nb_dummies * (nb_dummies-k); + gp_Vec outer_vec(outer_originalCurve_pnt.Coord().X(),outer_originalCurve_pnt.Coord().Y(),outer_originalCurve_pnt.Coord().Z()); + gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); + outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction + outer_vec.Subtract(outer_normalized_vec); + gp_Pnt new_pole_outer(outer_vec.XYZ()); + std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; + std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; + //save new poles in a vector for each outer dummy profile + pole_matrix.SetValue(current_row,j+1, new_pole_outer); + current_row+=1; + } + } + //insert actual profile pole + if(iNbPoles()+u_degree-5; + // TColStd_Array1OfReal u_knots(1,nb_u_knots); + // std::vector tmp = LinspaceWithBreaks(0., 1., nb_u_knots,{}); + // for(int j=1;j> v_knots(pole_matrix.size(), std::vector(pole_matrix[0].size())); + auto nb_v_knots = pole_matrix.ColLength()+v_degree-5; + TColStd_Array1OfReal v_knots(1, nb_v_knots); + //iterate through pole_matrix columns and calculate distances between pole-vectors + //since the knots are represented by a value relative to total value of curve_length = 1 + //divide these distances by total length of the curve in v-direction to create a parameter for the knot vector + std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); + for(int i=1;i= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree + * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 + * (this is even recommended if you want the curve to start and finish on the first and last pole). + * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. + * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) + * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. + */ + //if(!(u_knots.Length()==u_multiplicities.Length())){ + // throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(u_knots.Length())+","+std::to_string(u_multiplicities.Length())+")"); + //} + //if(!(v_knots.Length()==v_multiplicities.Length())){ + // throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(v_knots.Length())+","+std::to_string(v_multiplicities.Length())+")"); + //} + //for(int i = 1; i< u_knots.Length()-1;i++){ + // if (!(u_knots.Value(i) < u_knots.Value(i+1))){ + // throw tigl::CTiglError(""+std::to_string(u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(u_knots.Value(i+1))); + // } + //} + //for(int i = 1; i< v_knots.Length()-1;i++){ + // if (!(v_knots.Value(i) < v_knots.Value(i+1))){ + // throw tigl::CTiglError("check knots"); + // } + //} + //if(!(profileCurves[0]->NbPoles()==(nb_u_knots+2*3-u_degree-1))){ + // throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(profileCurves[0]->NbPoles())+"Knots:"+ + // std::to_string(profileCurves[0]->NbKnots())+"u_degree:"+std::to_string(u_degree)); + //} + //if(!(pole_matrix.ColLength()==(nb_v_knots+2*3-v_degree-1))){ + // throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" + // +std::to_string(pole_matrix.ColLength())+"v_degree:"+std::to_string(v_degree)); + //} + + for(int col=1; col i_poles(1,m); + std::cerr<< "Column:" << col << std::endl; + for(int i=1; i < m+1; i++){ + i_poles.SetValue(i,(pole_matrix.Value(i,col))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, v_knots, v_multiplicities, v_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Edge",col); + } + for(int row=1; row i_poles(1,n); + std::cerr<< "Row:" << row << std::endl; + for(int i=1; i < n+1; i++){ + i_poles.SetValue(i,(pole_matrix.Value(row,i))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, u_knots, u_mults, u_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Row",row); + } + + auto surface = new Geom_BSplineSurface(pole_matrix, u_knots, v_knots, u_mults, v_multiplicities, u_degree, v_degree, false, false); + Handle(Geom_Surface) handle_surface = surface; + TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + +} From bcf2765c8bb129475b2ca93ffd8ca5b842ec1767 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 14:14:43 +0200 Subject: [PATCH 03/44] update test setup method --- .../TestCTiglRoundedSegmentSurface.cpp | 155 ++++++++++-------- 1 file changed, 84 insertions(+), 71 deletions(-) diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 4023f23b83..66c2bd6af1 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -26,87 +26,100 @@ #include "CCPACSCurvePointListXYZ.h" #include "CCPACSCurveParamPointMap.h" -TEST(TestCTiglRoundedSegmentSurface, make_minimal_Shape) +class TestCTiglRoundedSegmentSurface : public ::testing::Test { +protected: + + void SetUp() override + { + //Create Profile Curves Vector + TColgp_HArray1OfPnt u_poles(1,7); + u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u1_poles(1,7); + u1_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u1_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u1_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u1_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u1_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u1_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u1_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u2_poles(1,7); + u2_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u2_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u2_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u2_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u2_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u2_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u2_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + + TColStd_Array1OfReal u_knots(1,3); + u_knots.SetValue(1,-1.); + u_knots.SetValue(2,0.); + u_knots.SetValue(3,1.); + + TColStd_Array1OfInteger u_mults(1,3); + u_mults.SetValue(1,4); + u_mults.SetValue(2,3); + u_mults.SetValue(3,4); + + int u_degree = 3; + + //Create three profiles for the loft + auto profile_root = new Geom_BSplineCurve(u_poles, u_knots, u_mults, u_degree); + profileCurves.push_back(profile_root); + + Handle(Geom_BSplineCurve) profile_mid = new Geom_BSplineCurve(u1_poles, u_knots, u_mults, u_degree); + //Scale by (0.66,1.,0.66) Translate by (0.2,0.5,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_mid->Poles().Value(i).Coord().X()*0.66+0.2; + double Y = profile_mid->Poles().Value(i).Coord().Y()*1.+0.5; + double Z = profile_mid->Poles().Value(i).Coord().Z()*0.66+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_mid->SetPole(i,transformed_pole); + } - //Create Profile Curves Vector - TColgp_HArray1OfPnt u_poles(1,7); - u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - TColgp_HArray1OfPnt u1_poles(1,7); - u1_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u1_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u1_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u1_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u1_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u1_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u1_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - TColgp_HArray1OfPnt u2_poles(1,7); - u2_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u2_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u2_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u2_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u2_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u2_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u2_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - - TColStd_Array1OfReal u_knots(1,3); - u_knots.SetValue(1,-1.); - u_knots.SetValue(2,0.); - u_knots.SetValue(3,1.); - - TColStd_Array1OfInteger u_mults(1,3); - u_mults.SetValue(1,4); - u_mults.SetValue(2,3); - u_mults.SetValue(3,4); - - int u_degree = 3; - - //Create three profiles for the loft - std::vector profileCurves; - auto profile_root = new Geom_BSplineCurve(u_poles, u_knots, u_mults, u_degree); - profileCurves.push_back(profile_root); - - Handle(Geom_BSplineCurve) profile_mid = new Geom_BSplineCurve(u1_poles, u_knots, u_mults, u_degree); - //Scale by (0.66,1.,0.66) Translate by (0.2,0.5,0.) - for(int i= 1; i< profile_root->NbPoles() + 1;i++){ - double X = profile_mid->Poles().Value(i).Coord().X()*0.66+0.2; - double Y = profile_mid->Poles().Value(i).Coord().Y()*1.+0.5; - double Z = profile_mid->Poles().Value(i).Coord().Z()*0.66+0.; - gp_Pnt transformed_pole(X,Y,Z); - profile_mid->SetPole(i,transformed_pole); - } + profileCurves.push_back(profile_mid); - profileCurves.push_back(profile_mid); + Handle(Geom_BSplineCurve) profile_tip = new Geom_BSplineCurve(u2_poles, u_knots, u_mults, u_degree); + //Scale by (0.2,1.,0.1) Translate by (1.,2.,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_tip->Poles().Value(i).Coord().X()*0.2+1.; + double Y = profile_tip->Poles().Value(i).Coord().Y()*1.+2.; + double Z = profile_tip->Poles().Value(i).Coord().Z()*0.1+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_tip->SetPole(i,transformed_pole); + } - Handle(Geom_BSplineCurve) profile_tip = new Geom_BSplineCurve(u2_poles, u_knots, u_mults, u_degree); - //Scale by (0.2,1.,0.1) Translate by (1.,2.,0.) - for(int i= 1; i< profile_root->NbPoles() + 1;i++){ - double X = profile_tip->Poles().Value(i).Coord().X()*0.2+1.; - double Y = profile_tip->Poles().Value(i).Coord().Y()*1.+2.; - double Z = profile_tip->Poles().Value(i).Coord().Z()*0.1+0.; - gp_Pnt transformed_pole(X,Y,Z); - profile_tip->SetPole(i,transformed_pole); - } + profileCurves.push_back(profile_tip); + + for(int i=0; i profileCurves; + +}; - //Test Code from above +TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) +{ //check if NbPoles is same in all profileCurves for(int i=0; i Date: Sat, 16 May 2026 14:37:43 +0200 Subject: [PATCH 04/44] sketch header file --- src/geometry/CTiglRoundedSegmentSurface.h | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 05f5e2cbab..dd1a278687 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -1,10 +1,34 @@ #ifndef CTIGLROUNDEDSEGMENTSURFACE_H #define CTIGLROUNDEDSEGMENTSURFACE_H +#include "Geom_BSplineCurve.hxx" +#include "TopoDS_Wire.hxx" +#include "tigl_internal.h" +#include + +namespace tigl { + class CTiglRoundedSegmentSurface { public: - CTiglRoundedSegmentSurface(); + TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance); + + TIGL_EXPORT TopoDS_Shape& Shape(); + +private: + // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) + TIGL_EXPORT void Perform(); + TIGL_EXPORT void Invalidate() { _hasPerformed = false; } + TIGL_EXPORT void ConvertCurves(); + TIGL_EXPORT void buildLoft(); + + + const std::vector& profileWires; + // Store as B-spline curves internally (after conversion) + std::vector m_profileCurves; + + }; +} #endif // CTIGLROUNDEDSEGMENTSURFACE_H From c7cfcf1e3b57e6dbd055f8ce7a0ed8152e0d95ae Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 14:56:36 +0200 Subject: [PATCH 05/44] update header --- src/geometry/CTiglRoundedSegmentSurface.cpp | 5 ++++- src/geometry/CTiglRoundedSegmentSurface.h | 22 ++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index fe8c25ba2f..d8c0a7df0b 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -1,3 +1,6 @@ #include "CTiglRoundedSegmentSurface.h" -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface() {} + +namespace tigl{ +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance) {} +} diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index dd1a278687..c7a8e9bdc8 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -2,6 +2,7 @@ #define CTIGLROUNDEDSEGMENTSURFACE_H #include "Geom_BSplineCurve.hxx" +#include "Geom_BSplineSurface.hxx" #include "TopoDS_Wire.hxx" #include "tigl_internal.h" #include @@ -22,11 +23,30 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT void ConvertCurves(); TIGL_EXPORT void buildLoft(); + // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction + TColgp_HArray2OfPnt pole_matrix; + + TColStd_Array1OfReal u_knots; + TColStd_Array1OfReal v_knots; + + TColStd_HArray1OfInteger u_multiplicities; + TColStd_HArray1OfInteger v_multiplicities; + + //Input datatype for constructor, to be converted in perform()-method + const std::vector& m_profileWires; + + //Storage of inner and outer rounding distance per segment + std::vector inner_rounding_distance; + std::vector outer_rounding_distance; - const std::vector& profileWires; // Store as B-spline curves internally (after conversion) std::vector m_profileCurves; + Geom_BSplineSurface m_surface; + + bool _hasPerformed = false; + int _maxDegree = 3; + }; From 749e631c98bc0831a53d9dea17a82be19d5dc7c0 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 15:11:53 +0200 Subject: [PATCH 06/44] update header and class --- src/geometry/CTiglRoundedSegmentSurface.cpp | 23 ++++++++++++++++++++- src/geometry/CTiglRoundedSegmentSurface.h | 2 ++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index d8c0a7df0b..7601a28de7 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -1,6 +1,27 @@ #include "CTiglRoundedSegmentSurface.h" +#include "CTiglError.h" namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance) {} +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance) { + Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; + Standard_Integer n = m_profileCurves[0]->NbPoles(); + + TColgp_HArray2OfPnt pole_matrix(1,m,1,n); + //TODO What else to initialize? +} + +//TODO +void CTiglRoundedSegmentSurface::ConvertCurves(){} +void CTiglRoundedSegmentSurface::buildLoft(){} + +} + +void NumberOfPolesIsSameInAllCurves(std::vector &profileCurves){ + //check if NbPoles is same in all profileCurves + for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ + throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); + } + } } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index c7a8e9bdc8..84ac0503d3 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -23,6 +23,7 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT void ConvertCurves(); TIGL_EXPORT void buildLoft(); +private: // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction TColgp_HArray2OfPnt pole_matrix; @@ -46,6 +47,7 @@ class CTiglRoundedSegmentSurface bool _hasPerformed = false; int _maxDegree = 3; + size_t _nb_dummies =3; //Rows per rounding distance }; From 1201ad96bfd5d7d85ce62d41d104ca2d84cd87ba Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 17:57:56 +0200 Subject: [PATCH 07/44] update constructor and loops --- src/geometry/CTiglRoundedSegmentSurface.cpp | 258 +++++++++++++++++++- src/geometry/CTiglRoundedSegmentSurface.h | 21 +- 2 files changed, 264 insertions(+), 15 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 7601a28de7..56c8aa28d7 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -1,19 +1,267 @@ #include "CTiglRoundedSegmentSurface.h" +#include "BRepBuilderAPI_MakeEdge.hxx" #include "CTiglError.h" +#include "Debugging.h" +#include "TopoDS_Edge.hxx" +#include "tiglcommonfunctions.h" namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance) { +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector& profileWires, double inner_rounding_distance, double outer_rounding_distance): + m_pole_matrix({}), + m_profileWires(profileWires), + m_inner_rounding_distance(inner_rounding_distance), + m_outer_rounding_distance(outer_rounding_distance), + m_profileCurves({}){} + + +void CTiglRoundedSegmentSurface::initializePoleMatrix(){ + ConvertCurves(); Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; Standard_Integer n = m_profileCurves[0]->NbPoles(); - - TColgp_HArray2OfPnt pole_matrix(1,m,1,n); - //TODO What else to initialize? + m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); } //TODO void CTiglRoundedSegmentSurface::ConvertCurves(){} -void CTiglRoundedSegmentSurface::buildLoft(){} + +opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ + initializePoleMatrix(); + //skin the curves ('profileCurves'): new code for curvesToSurface + // //(input are curves, make Geom_BSplineSurface -> build the TopoDS_Shape from this (-> output is TopoDS_Shape)) + /* + New code for skinning a wing surface: + Goal: Create a surface, implement rounded sections + + Steps: Create k Dummy-Profile(s-Curves maybe just the poles?) within innerRounding distance + Create Matrix that contains all poles of each profile curve and all Dummy-Profile-Curves + - i-th row represents a profile in u-direction + - j-th columnrepresents a curve in v-direction + + Steps: Retrieve poles from inner and outer profile + Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile + store new poles and original poles all in one matrix + */ + + //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector + //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge + //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) + //note: loop-indices are named i,j,k and refer to row,column,number of dummy-Profile for better geometric/code-orientation + + //following variables refer to the values between i-th and (i+1)-th profile curve + //cases: + //2 sections: no dummy profiles to build + //3 sections: dummy profiles around middle section + //... + //no dummies after 1.st and before last section + + double inner_rd, outer_rd; + gp_Pnt inner_poles_per_col, outer_poles_per_col; + + int m = m_pole_matrix.NbRows(); + int n = m_pole_matrix.NbColumns(); + + //iterate through given profile curves + for (int i=0; i< m_profileCurves.size(); i++){ + //determine rounding distances between profiles + if(i==0){ + inner_rd =0.; //no value available = no dummies after first section + outer_rd = m_outer_rounding_distance[i]; + } + if(i>0&&!(i==m_profileCurves.size())){ + inner_rd = m_inner_rounding_distance[i-1]; + outer_rd = m_outer_rounding_distance[i]; + } else{ + inner_rd = m_inner_rounding_distance[i-1]; + outer_rd = 0.; //no value available = no dummies before last section + } + //iterate through columns to create Dummy Profile-Poles between each pair of profiles + for( int j=0; j< n; j++){ + //retrieve poles of i-th and (i+1)-th profile (thus out of bounds for outer pole in row before last row) + inner_poles_per_col = m_profileCurves[i]->Pole(j+1);//v0 + if(iPole(j+1); //v1 + } else { + outer_poles_per_col = inner_poles_per_col; + } + //calculate Vector between both profile poles and normalize it + gp_Vec vector_in_v_direction(inner_poles_per_col, outer_poles_per_col); //v01 + gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); + if(inner_poles_per_col.IsEqual(outer_poles_per_col, 1e-14)){ + throw tigl::CTiglError(std::to_string(inner_poles_per_col.Coord().X())+"x"+ + std::to_string(inner_poles_per_col.Coord().Y())+"y"+ + std::to_string(inner_poles_per_col.Coord().Y())+"Z"+ + std::to_string(outer_poles_per_col.Coord().X())+"x"+ + std::to_string(outer_poles_per_col.Coord().Y())+"y"+ + std::to_string(outer_poles_per_col.Coord().Y())+"Z"); + } + normalized_vector_in_v_direction.Normalize(); //|v01| + //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): + //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) + //add profile first + int current_row; + if(i==0){ + current_row =1; + } else { + current_row = _nb_dummies+3+(i-1)*(1+_nb_dummies*2); + } + //insert first profile pole + if(current_row==1){ + std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; + m_pole_matrix.SetValue(current_row,j+1, inner_poles_per_col); //v0 first + current_row+=1; + } + //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section + if(i>0&&i _nb_dummies -(k+1)/_nb_dummies) + //last segment has no outer dummies -> < m_profileCurves.size()-2 + if(i<(m_profileCurves.size()-2)){ + for (int k=0; k < _nb_dummies; k++){ + //calculate distance between k-th outer dummy-pole in v-direction and profile + double outer_distance = outer_rd/_nb_dummies * (_nb_dummies-k); + gp_Vec outer_vec(outer_poles_per_col.Coord().X(),outer_poles_per_col.Coord().Y(),outer_poles_per_col.Coord().Z()); + gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); + outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction + outer_vec.Subtract(outer_normalized_vec); + gp_Pnt new_pole_outer(outer_vec.XYZ()); + std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; + std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; + //save new poles in a vector for each outer dummy profile + m_pole_matrix.SetValue(current_row,j+1, new_pole_outer); + current_row+=1; + } + } + //insert actual profile pole + if(iNbPoles()+u_degree-5; + // TColStd_Array1OfReal u_knots(1,nb_u_knots); + // std::vector tmp = LinspaceWithBreaks(0., 1., nb_u_knots,{}); + // for(int j=1;j> v_knots(pole_matrix.size(), std::vector(pole_matrix[0].size())); + auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; + TColStd_Array1OfReal v_knots(1, nb_v_knots); + //iterate through pole_matrix columns and calculate distances between pole-vectors + //since the knots are represented by a value relative to total value of curve_length = 1 + //divide these distances by total length of the curve in v-direction to create a parameter for the knot vector + std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); + for(int i=1;i= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree + * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 + * (this is even recommended if you want the curve to start and finish on the first and last pole). + * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. + * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) + * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. + */ + //if(!(u_knots.Length()==u_multiplicities.Length())){ + // throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(u_knots.Length())+","+std::to_string(u_multiplicities.Length())+")"); + //} + //if(!(v_knots.Length()==v_multiplicities.Length())){ + // throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(v_knots.Length())+","+std::to_string(v_multiplicities.Length())+")"); + //} + //for(int i = 1; i< u_knots.Length()-1;i++){ + // if (!(u_knots.Value(i) < u_knots.Value(i+1))){ + // throw tigl::CTiglError(""+std::to_string(u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(u_knots.Value(i+1))); + // } + //} + //for(int i = 1; i< v_knots.Length()-1;i++){ + // if (!(v_knots.Value(i) < v_knots.Value(i+1))){ + // throw tigl::CTiglError("check knots"); + // } + //} + //if(!(m_profileCurves[0]->NbPoles()==(nb_u_knots+2*3-u_degree-1))){ + // throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ + // std::to_string(m_profileCurves[0]->NbKnots())+"u_degree:"+std::to_string(u_degree)); + //} + //if(!(pole_matrix.ColLength()==(nb_v_knots+2*3-v_degree-1))){ + // throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" + // +std::to_string(pole_matrix.ColLength())+"v_degree:"+std::to_string(v_degree)); + //} + + for(int col=1; col i_poles(1,m); + std::cerr<< "Column:" << col << std::endl; + for(int i=1; i < m+1; i++){ + i_poles.SetValue(i,(pole_matrix.Value(i,col))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, v_knots, v_multiplicities, v_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Edge",col); + } + for(int row=1; row i_poles(1,n); + std::cerr<< "Row:" << row << std::endl; + for(int i=1; i < n+1; i++){ + i_poles.SetValue(i,(pole_matrix.Value(row,i))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, u_knots, u_mults, u_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Row",row); + } + + auto surface = new Geom_BSplineSurface(pole_matrix, u_knots, v_knots, u_mults, v_multiplicities, u_degree, v_degree, false, false); + Handle(Geom_Surface) handle_surface = surface; + TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + tigl::dumpShape(surf, "makeLoftWing", "Surface",1); +} } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 84ac0503d3..3a7fb0db0b 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -19,34 +19,35 @@ class CTiglRoundedSegmentSurface private: // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) TIGL_EXPORT void Perform(); + TIGL_EXPORT void initializePoleMatrix(); TIGL_EXPORT void Invalidate() { _hasPerformed = false; } TIGL_EXPORT void ConvertCurves(); - TIGL_EXPORT void buildLoft(); + TIGL_EXPORT Handle(Geom_BSplineSurface) buildLoft(); private: // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction - TColgp_HArray2OfPnt pole_matrix; + TColgp_HArray2OfPnt m_pole_matrix; - TColStd_Array1OfReal u_knots; - TColStd_Array1OfReal v_knots; + TColStd_Array1OfReal m_u_knots; + TColStd_Array1OfReal m_v_knots; - TColStd_HArray1OfInteger u_multiplicities; - TColStd_HArray1OfInteger v_multiplicities; + TColStd_HArray1OfInteger m_u_multiplicities; + TColStd_HArray1OfInteger m_v_multiplicities; //Input datatype for constructor, to be converted in perform()-method const std::vector& m_profileWires; //Storage of inner and outer rounding distance per segment - std::vector inner_rounding_distance; - std::vector outer_rounding_distance; + std::vector m_inner_rounding_distance; + std::vector m_outer_rounding_distance; // Store as B-spline curves internally (after conversion) std::vector m_profileCurves; - Geom_BSplineSurface m_surface; - bool _hasPerformed = false; int _maxDegree = 3; + int _u_degree = 3; + int _v_degree = 3; size_t _nb_dummies =3; //Rows per rounding distance From 32db5a6ebc5bcbb14508f348d72c64dc87a8531f Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 18:11:21 +0200 Subject: [PATCH 08/44] seperate code in methods --- src/geometry/CTiglRoundedSegmentSurface.cpp | 34 ++++++++------------- src/geometry/CTiglRoundedSegmentSurface.h | 18 +++++++++-- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 56c8aa28d7..46fecf08be 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -14,35 +14,17 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vectorNbPoles(); m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); } -//TODO -void CTiglRoundedSegmentSurface::ConvertCurves(){} - -opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ - initializePoleMatrix(); - //skin the curves ('profileCurves'): new code for curvesToSurface - // //(input are curves, make Geom_BSplineSurface -> build the TopoDS_Shape from this (-> output is TopoDS_Shape)) - /* - New code for skinning a wing surface: - Goal: Create a surface, implement rounded sections - - Steps: Create k Dummy-Profile(s-Curves maybe just the poles?) within innerRounding distance - Create Matrix that contains all poles of each profile curve and all Dummy-Profile-Curves - - i-th row represents a profile in u-direction - - j-th columnrepresents a curve in v-direction - - Steps: Retrieve poles from inner and outer profile - Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile - store new poles and original poles all in one matrix - */ - +void CTiglRoundedSegmentSurface::calculatePoleMatrix() +{ //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) @@ -157,6 +139,14 @@ opencascade::handle CTiglRoundedSegmentSurface::buildLoft() std::cerr << "Rows: " << m_pole_matrix.ColLength() << "m: " << m << "Columns: " << m_pole_matrix.RowLength() << "n: " << n << std::endl; +} + + +opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ + ConvertCurves(); + initializePoleMatrix(); + calculatePoleMatrix(); + //TODO CHECK: is this information given anywhere later, so these lines can be deleted again? //create knots in u-direction // auto nb_u_knots= m_profileCurves[0]->NbPoles()+u_degree-5; diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 3a7fb0db0b..655ab0264c 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -19,10 +19,24 @@ class CTiglRoundedSegmentSurface private: // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) TIGL_EXPORT void Perform(); - TIGL_EXPORT void initializePoleMatrix(); - TIGL_EXPORT void Invalidate() { _hasPerformed = false; } TIGL_EXPORT void ConvertCurves(); + TIGL_EXPORT void initializePoleMatrix(); + TIGL_EXPORT void calculatePoleMatrix(); + /* + * @brief Creates a surface with rounded sections + + Steps: Create Matrix that contains all poles of each profile curve and + Dummy-Profile-Curves that contain poles that are required to build the curve in v-Direction + TODO: Add mathematical description of the rounded segment curve building process + - i-th row represents a profile in u-direction + - j-th columnrepresents a curve in v-direction + + Steps: Retrieve poles from inner and outer profile + Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile + store new poles and original poles all in one matrix + */ TIGL_EXPORT Handle(Geom_BSplineSurface) buildLoft(); + TIGL_EXPORT void Invalidate() { _hasPerformed = false; } private: // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction From 3d4e3875f2e7bbf644e9c06f3fc6d2fb83d83237 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 18:27:36 +0200 Subject: [PATCH 09/44] update buildLoft method --- src/geometry/CTiglRoundedSegmentSurface.cpp | 137 +++++++++----------- src/geometry/CTiglRoundedSegmentSurface.h | 1 + 2 files changed, 59 insertions(+), 79 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 46fecf08be..e145a54add 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -1,5 +1,6 @@ #include "CTiglRoundedSegmentSurface.h" #include "BRepBuilderAPI_MakeEdge.hxx" +#include "BRepBuilderAPI_MakeFace.hxx" #include "CTiglError.h" #include "Debugging.h" #include "TopoDS_Edge.hxx" @@ -17,6 +18,15 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &profileCurves){ + //check if NbPoles is same in all profileCurves + for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ + throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); + } + } +} + void CTiglRoundedSegmentSurface::initializePoleMatrix(){ Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; Standard_Integer n = m_profileCurves[0]->NbPoles(); @@ -137,68 +147,47 @@ void CTiglRoundedSegmentSurface::calculatePoleMatrix() } } + //CODE FOR PRINT-DEBUGGING std::cerr << "Rows: " << m_pole_matrix.ColLength() << "m: " << m << "Columns: " << m_pole_matrix.RowLength() << "n: " << n << std::endl; + for(int col=1; col i_poles(1,m); + std::cerr<< "Column:" << col << std::endl; + for(int i=1; i < m+1; i++){ + i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Edge",col); + } + for(int row=1; row i_poles(1,n); + std::cerr<< "Row:" << row << std::endl; + for(int i=1; i < n+1; i++){ + i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Row",row); + } } - -opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ - ConvertCurves(); - initializePoleMatrix(); - calculatePoleMatrix(); - - //TODO CHECK: is this information given anywhere later, so these lines can be deleted again? - //create knots in u-direction - // auto nb_u_knots= m_profileCurves[0]->NbPoles()+u_degree-5; - // TColStd_Array1OfReal u_knots(1,nb_u_knots); - // std::vector tmp = LinspaceWithBreaks(0., 1., nb_u_knots,{}); - // for(int j=1;j> v_knots(pole_matrix.size(), std::vector(pole_matrix[0].size())); auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; TColStd_Array1OfReal v_knots(1, nb_v_knots); - //iterate through pole_matrix columns and calculate distances between pole-vectors - //since the knots are represented by a value relative to total value of curve_length = 1 - //divide these distances by total length of the curve in v-direction to create a parameter for the knot vector std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); for(int i=1;i= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree - * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 - * (this is even recommended if you want the curve to start and finish on the first and last pole). - * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. - * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) - * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. - */ + //MAYBE CHECK //if(!(u_knots.Length()==u_multiplicities.Length())){ // throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(u_knots.Length())+","+std::to_string(u_multiplicities.Length())+")"); //} @@ -222,44 +211,34 @@ opencascade::handle CTiglRoundedSegmentSurface::buildLoft() //if(!(pole_matrix.ColLength()==(nb_v_knots+2*3-v_degree-1))){ // throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" // +std::to_string(pole_matrix.ColLength())+"v_degree:"+std::to_string(v_degree)); - //} + // +} - for(int col=1; col i_poles(1,m); - std::cerr<< "Column:" << col << std::endl; - for(int i=1; i < m+1; i++){ - i_poles.SetValue(i,(pole_matrix.Value(i,col))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, v_knots, v_multiplicities, v_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Edge",col); - } - for(int row=1; row i_poles(1,n); - std::cerr<< "Row:" << row << std::endl; - for(int i=1; i < n+1; i++){ - i_poles.SetValue(i,(pole_matrix.Value(row,i))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, u_knots, u_mults, u_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Row",row); - } +opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ + ConvertCurves(); + NumberOfPolesIsSameInAllCurves(m_profileCurves); + initializePoleMatrix(); + calculatePoleMatrix(); + calculateKnotsAndMultiplicities(); + + /** TODO IS ALL OF THAT COVERED? + * OCC Geom_BSplineSurface(): + * Creates a non-rational b-spline surface (weights default value is 1.). + * The following conditions must be verified. 0 < UDegree <= MaxDegree. + * UKnots.Length() == UMults.Length() >= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree + * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 + * (this is even recommended if you want the curve to start and finish on the first and last pole). + * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. + * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) + * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. + */ - auto surface = new Geom_BSplineSurface(pole_matrix, u_knots, v_knots, u_mults, v_multiplicities, u_degree, v_degree, false, false); + auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); Handle(Geom_Surface) handle_surface = surface; TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + return surface; } } -void NumberOfPolesIsSameInAllCurves(std::vector &profileCurves){ - //check if NbPoles is same in all profileCurves - for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ - throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); - } - } -} diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 655ab0264c..30bb306032 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -22,6 +22,7 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT void ConvertCurves(); TIGL_EXPORT void initializePoleMatrix(); TIGL_EXPORT void calculatePoleMatrix(); + TIGL_EXPORT void calculateKnotsAndMultiplicities(); /* * @brief Creates a surface with rounded sections From e4a234069d20cbd50a8bb70059c9aa43042c6ce8 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 18:36:40 +0200 Subject: [PATCH 10/44] update comments --- src/geometry/CTiglRoundedSegmentSurface.cpp | 3 +++ src/geometry/CTiglRoundedSegmentSurface.h | 12 +++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index e145a54add..330d89422d 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -234,9 +234,12 @@ opencascade::handle CTiglRoundedSegmentSurface::buildLoft() */ auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); + + //DEBUG DELETEME Handle(Geom_Surface) handle_surface = surface; TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + return surface; } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 30bb306032..192aba61be 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -17,11 +17,19 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT TopoDS_Shape& Shape(); private: - // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) TIGL_EXPORT void Perform(); + // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) TIGL_EXPORT void ConvertCurves(); + + // Initialize values required for 'buildLoft' + // Determin dimensions of pole matrix TIGL_EXPORT void initializePoleMatrix(); + + // Calculate required poles to build rounded curves at given sections TIGL_EXPORT void calculatePoleMatrix(); + + // Deduce required knot vector and multiplicies from pole matrix properties + //TODO: Add mathematical boundaries for required number of knots and multiplicities TIGL_EXPORT void calculateKnotsAndMultiplicities(); /* * @brief Creates a surface with rounded sections @@ -36,6 +44,8 @@ class CTiglRoundedSegmentSurface Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile store new poles and original poles all in one matrix */ + + // Call required methods to initialize required values and build surface TIGL_EXPORT Handle(Geom_BSplineSurface) buildLoft(); TIGL_EXPORT void Invalidate() { _hasPerformed = false; } From 3fdf1c041e3a8b208670cbc0b62e7578fd0cf854 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Sat, 16 May 2026 18:38:30 +0200 Subject: [PATCH 11/44] clean testskeleton from prototype code --- .../TestCTiglRoundedSegmentSurface.cpp | 230 ------------------ 1 file changed, 230 deletions(-) diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 66c2bd6af1..05b4b909a8 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -121,236 +121,6 @@ class TestCTiglRoundedSegmentSurface : public ::testing::Test TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) { - //check if NbPoles is same in all profileCurves - for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ - throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); - } - } - //skin the curves ('profileCurves'): new code for curvesToSurface - // //(input are curves, make Geom_BSplineSurface -> build the TopoDS_Shape from this (-> output is TopoDS_Shape)) - /* - New code for skinning a wing surface: - Goal: Create a surface, implement rounded sections - - Steps: Create k Dummy-Profile(s-Curves maybe just the poles?) within innerRounding distance - Create Matrix that contains all poles of each profile curve and all Dummy-Profile-Curves - - i-th row represents a profile in u-direction - - j-th columnrepresents a curve in v-direction - - Steps: Retrieve poles from inner and outer profile - Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile - store new poles and original poles all in one matrix - */ - - ////determine distance between both vectors - //Standard_Real distance_inner_outer = originalCurve_inner.Distance(originalCurve_outer); - //determine new location for pole relative to inner profile and inner rounding distance - //datatype for poles and 'support vectors' is gp_Pnt storage is 'TColgp_Array1OfPnt &', needs to be const? - //datatype for knots is 'double/Standard_Real', stored in 'TColStd_Array1OfReal &', needs to be const? - //dummy values, will be input params later - double inner_rd =0.2; - double outer_rd =0.3; - size_t nb_dummies =3; //Rows per rounding distance - //Standard_Integer u_degree = profileCurves[0]->Degree(); - Standard_Integer v_degree = 3; - - Standard_Integer m = profileCurves.size()+(profileCurves.size()-2)*2*nb_dummies; - Standard_Integer n = profileCurves[0]->NbPoles(); - - //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector - //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge - //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) - //note: loop-indices are named i,j,k and refer to row,column,number of dummy-Profile for better geometric/code-orientation - - TColgp_HArray2OfPnt pole_matrix(1,m,1,n); - gp_Pnt inner_originalCurve_pnt, outer_originalCurve_pnt; - - for (int i=0; i< profileCurves.size(); i++){ - //iterate through columns to create Dummy Profiles to each pair of profiles - for( int j=0; j< n; j++){ - //retrieve a pole to each profile - if(iPole(j+1);//v0 - outer_originalCurve_pnt = profileCurves[i+1]->Pole(j+1); //v1 - } - //calculate Vector between both profile poles and normalize it - //distance between both points is length of this vector - gp_Vec vector_in_v_direction(inner_originalCurve_pnt, outer_originalCurve_pnt); //v01 - gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); - if(inner_originalCurve_pnt.IsEqual(outer_originalCurve_pnt, 1e-14)){ - throw tigl::CTiglError(std::to_string(inner_originalCurve_pnt.Coord().X())+"x"+ - std::to_string(inner_originalCurve_pnt.Coord().Y())+"y"+ - std::to_string(inner_originalCurve_pnt.Coord().Y())+"Z"+ - std::to_string(outer_originalCurve_pnt.Coord().X())+"x"+ - std::to_string(outer_originalCurve_pnt.Coord().Y())+"y"+ - std::to_string(outer_originalCurve_pnt.Coord().Y())+"Z"); - } - normalized_vector_in_v_direction.Normalize(); //|v01| - //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): - //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) - //add profile first - int current_row; - if(i==0){ - current_row =1; - } else { - current_row = nb_dummies+3+(i-1)*(1+nb_dummies*2); - } - //insert first profile pole - if(current_row==1){ - std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; - pole_matrix.SetValue(current_row,j+1, inner_originalCurve_pnt); //v0 first - current_row+=1; - } - //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section - if(i>0&&i nb_dummies -(k+1)/nb_dummies) - //except last section - if(i<(profileCurves.size()-2)){ - for (int k=0; k < nb_dummies; k++){ - //calculate distance between k-th outer dummy-pole in v-direction and profile - double outer_distance = outer_rd/nb_dummies * (nb_dummies-k); - gp_Vec outer_vec(outer_originalCurve_pnt.Coord().X(),outer_originalCurve_pnt.Coord().Y(),outer_originalCurve_pnt.Coord().Z()); - gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); - outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction - outer_vec.Subtract(outer_normalized_vec); - gp_Pnt new_pole_outer(outer_vec.XYZ()); - std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; - std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; - //save new poles in a vector for each outer dummy profile - pole_matrix.SetValue(current_row,j+1, new_pole_outer); - current_row+=1; - } - } - //insert actual profile pole - if(iNbPoles()+u_degree-5; - // TColStd_Array1OfReal u_knots(1,nb_u_knots); - // std::vector tmp = LinspaceWithBreaks(0., 1., nb_u_knots,{}); - // for(int j=1;j> v_knots(pole_matrix.size(), std::vector(pole_matrix[0].size())); - auto nb_v_knots = pole_matrix.ColLength()+v_degree-5; - TColStd_Array1OfReal v_knots(1, nb_v_knots); - //iterate through pole_matrix columns and calculate distances between pole-vectors - //since the knots are represented by a value relative to total value of curve_length = 1 - //divide these distances by total length of the curve in v-direction to create a parameter for the knot vector - std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); - for(int i=1;i= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree - * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 - * (this is even recommended if you want the curve to start and finish on the first and last pole). - * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. - * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) - * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. - */ - //if(!(u_knots.Length()==u_multiplicities.Length())){ - // throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(u_knots.Length())+","+std::to_string(u_multiplicities.Length())+")"); - //} - //if(!(v_knots.Length()==v_multiplicities.Length())){ - // throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(v_knots.Length())+","+std::to_string(v_multiplicities.Length())+")"); - //} - //for(int i = 1; i< u_knots.Length()-1;i++){ - // if (!(u_knots.Value(i) < u_knots.Value(i+1))){ - // throw tigl::CTiglError(""+std::to_string(u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(u_knots.Value(i+1))); - // } - //} - //for(int i = 1; i< v_knots.Length()-1;i++){ - // if (!(v_knots.Value(i) < v_knots.Value(i+1))){ - // throw tigl::CTiglError("check knots"); - // } - //} - //if(!(profileCurves[0]->NbPoles()==(nb_u_knots+2*3-u_degree-1))){ - // throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(profileCurves[0]->NbPoles())+"Knots:"+ - // std::to_string(profileCurves[0]->NbKnots())+"u_degree:"+std::to_string(u_degree)); - //} - //if(!(pole_matrix.ColLength()==(nb_v_knots+2*3-v_degree-1))){ - // throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" - // +std::to_string(pole_matrix.ColLength())+"v_degree:"+std::to_string(v_degree)); - //} - - for(int col=1; col i_poles(1,m); - std::cerr<< "Column:" << col << std::endl; - for(int i=1; i < m+1; i++){ - i_poles.SetValue(i,(pole_matrix.Value(i,col))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, v_knots, v_multiplicities, v_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Edge",col); - } - for(int row=1; row i_poles(1,n); - std::cerr<< "Row:" << row << std::endl; - for(int i=1; i < n+1; i++){ - i_poles.SetValue(i,(pole_matrix.Value(row,i))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, u_knots, u_mults, u_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Row",row); - } - auto surface = new Geom_BSplineSurface(pole_matrix, u_knots, v_knots, u_mults, v_multiplicities, u_degree, v_degree, false, false); - Handle(Geom_Surface) handle_surface = surface; - TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); - tigl::dumpShape(surf, "makeLoftWing", "Surface",1); } From 9975e94b08e220771c0b16d6f116fc112e042793 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 26 May 2026 07:12:38 +0200 Subject: [PATCH 12/44] rewrite methods using struct roundedSegment --- src/geometry/CTiglRoundedSegmentSurface.cpp | 299 +++++++++----------- src/geometry/CTiglRoundedSegmentSurface.h | 95 ++++++- 2 files changed, 219 insertions(+), 175 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 330d89422d..ef70cb23fb 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -3,29 +3,22 @@ #include "BRepBuilderAPI_MakeFace.hxx" #include "CTiglError.h" #include "Debugging.h" +#include "TopTools_IndexedMapOfShape.hxx" #include "TopoDS_Edge.hxx" #include "tiglcommonfunctions.h" namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector& profileWires, double inner_rounding_distance, double outer_rounding_distance): +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector , + double inner_rounding_distance, + double outer_rounding_distance): m_pole_matrix({}), - m_profileWires(profileWires), m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), - m_profileCurves({}){} + m_profileCurves(m_profileCurves), + m_surface(nullptr){} -//TODO -void CTiglRoundedSegmentSurface::ConvertCurves(){} - -void NumberOfPolesIsSameInAllCurves(std::vector &profileCurves){ - //check if NbPoles is same in all profileCurves - for(int i=0; iNbPoles()==profileCurves[i+1]->NbPoles())){ - throw tigl::CTiglError("ProfileCurves: Numbers of poles don't match"); - } - } -} +TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); void CTiglRoundedSegmentSurface::initializePoleMatrix(){ Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; @@ -33,146 +26,127 @@ void CTiglRoundedSegmentSurface::initializePoleMatrix(){ m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); } -void CTiglRoundedSegmentSurface::calculatePoleMatrix() -{ - //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector - //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge - //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) - //note: loop-indices are named i,j,k and refer to row,column,number of dummy-Profile for better geometric/code-orientation - - //following variables refer to the values between i-th and (i+1)-th profile curve - //cases: - //2 sections: no dummy profiles to build - //3 sections: dummy profiles around middle section - //... - //no dummies after 1.st and before last section - - double inner_rd, outer_rd; - gp_Pnt inner_poles_per_col, outer_poles_per_col; - - int m = m_pole_matrix.NbRows(); - int n = m_pole_matrix.NbColumns(); - - //iterate through given profile curves - for (int i=0; i< m_profileCurves.size(); i++){ - //determine rounding distances between profiles - if(i==0){ - inner_rd =0.; //no value available = no dummies after first section - outer_rd = m_outer_rounding_distance[i]; - } - if(i>0&&!(i==m_profileCurves.size())){ - inner_rd = m_inner_rounding_distance[i-1]; - outer_rd = m_outer_rounding_distance[i]; - } else{ - inner_rd = m_inner_rounding_distance[i-1]; - outer_rd = 0.; //no value available = no dummies before last section - } - //iterate through columns to create Dummy Profile-Poles between each pair of profiles - for( int j=0; j< n; j++){ - //retrieve poles of i-th and (i+1)-th profile (thus out of bounds for outer pole in row before last row) - inner_poles_per_col = m_profileCurves[i]->Pole(j+1);//v0 - if(iPole(j+1); //v1 - } else { - outer_poles_per_col = inner_poles_per_col; - } - //calculate Vector between both profile poles and normalize it - gp_Vec vector_in_v_direction(inner_poles_per_col, outer_poles_per_col); //v01 - gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); - if(inner_poles_per_col.IsEqual(outer_poles_per_col, 1e-14)){ - throw tigl::CTiglError(std::to_string(inner_poles_per_col.Coord().X())+"x"+ - std::to_string(inner_poles_per_col.Coord().Y())+"y"+ - std::to_string(inner_poles_per_col.Coord().Y())+"Z"+ - std::to_string(outer_poles_per_col.Coord().X())+"x"+ - std::to_string(outer_poles_per_col.Coord().Y())+"y"+ - std::to_string(outer_poles_per_col.Coord().Y())+"Z"); - } - normalized_vector_in_v_direction.Normalize(); //|v01| - //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): - //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) - //add profile first - int current_row; - if(i==0){ - current_row =1; - } else { - current_row = _nb_dummies+3+(i-1)*(1+_nb_dummies*2); - } - //insert first profile pole - if(current_row==1){ - std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; - m_pole_matrix.SetValue(current_row,j+1, inner_poles_per_col); //v0 first - current_row+=1; - } - //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section - if(i>0&&i _nb_dummies -(k+1)/_nb_dummies) - //last segment has no outer dummies -> < m_profileCurves.size()-2 - if(i<(m_profileCurves.size()-2)){ - for (int k=0; k < _nb_dummies; k++){ - //calculate distance between k-th outer dummy-pole in v-direction and profile - double outer_distance = outer_rd/_nb_dummies * (_nb_dummies-k); - gp_Vec outer_vec(outer_poles_per_col.Coord().X(),outer_poles_per_col.Coord().Y(),outer_poles_per_col.Coord().Z()); - gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); - outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction - outer_vec.Subtract(outer_normalized_vec); - gp_Pnt new_pole_outer(outer_vec.XYZ()); - std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; - std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; - //save new poles in a vector for each outer dummy profile - m_pole_matrix.SetValue(current_row,j+1, new_pole_outer); - current_row+=1; - } - } - //insert actual profile pole - if(i0&&!(i==m_profileCurves.size())){ +// inner_rd = m_inner_rounding_distance[i-1]; +// outer_rd = m_outer_rounding_distance[i]; +// } else{ +// inner_rd = m_inner_rounding_distance[i-1]; +// outer_rd = 0.; //no value available = no dummies before last section +// } +// //iterate through columns to create Dummy Profile-Poles between each pair of profiles +// for( int j=0; j< n; j++){ +// //retrieve poles of i-th and (i+1)-th profile (thus out of bounds for outer pole in row before last row) +// inner_poles_per_col = m_profileCurves[i]->Pole(j+1);//v0 +// if(iPole(j+1); //v1 +// } else { +// outer_poles_per_col = inner_poles_per_col; +// } +// //calculate Vector between both profile poles and normalize it +// gp_Vec vector_in_v_direction(inner_poles_per_col, outer_poles_per_col); //v01 +// gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); +// if(inner_poles_per_col.IsEqual(outer_poles_per_col, 1e-14)){ +// throw tigl::CTiglError(std::to_string(inner_poles_per_col.Coord().X())+"x"+ +// std::to_string(inner_poles_per_col.Coord().Y())+"y"+ +// std::to_string(inner_poles_per_col.Coord().Y())+"Z"+ +// std::to_string(outer_poles_per_col.Coord().X())+"x"+ +// std::to_string(outer_poles_per_col.Coord().Y())+"y"+ +// std::to_string(outer_poles_per_col.Coord().Y())+"Z"); +// } +// normalized_vector_in_v_direction.Normalize(); //|v01| +// //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): +// //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) +// //add profile first +// int current_row; +// if(i==0){ +// current_row =1; +// } else { +// current_row = _nb_dummies+3+(i-1)*(1+_nb_dummies*2); +// } +// //insert first profile pole +// if(current_row==1){ +// std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; +// m_pole_matrix.SetValue(current_row,j+1, inner_poles_per_col); //v0 first +// current_row+=1; +// } +// //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section +// if(i>0&&i _nb_dummies -(k+1)/_nb_dummies) +// //last segment has no outer dummies -> < m_profileCurves.size()-2 +// if(i<(m_profileCurves.size()-2)){ +// for (int k=0; k < _nb_dummies; k++){ +// //calculate distance between k-th outer dummy-pole in v-direction and profile +// double outer_distance = outer_rd/_nb_dummies * (_nb_dummies-k); +// gp_Vec outer_vec(outer_poles_per_col.Coord().X(),outer_poles_per_col.Coord().Y(),outer_poles_per_col.Coord().Z()); +// gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); +// outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction +// outer_vec.Subtract(outer_normalized_vec); +// gp_Pnt new_pole_outer(outer_vec.XYZ()); +// std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; +// std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; +// //save new poles in a vector for each outer dummy profile +// m_pole_matrix.SetValue(current_row,j+1, new_pole_outer); +// current_row+=1; +// } +// } +// //insert actual profile pole +// if(i i_poles(1,m); - std::cerr<< "Column:" << col << std::endl; - for(int i=1; i < m+1; i++){ - i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Edge",col); - } - for(int row=1; row i_poles(1,n); - std::cerr<< "Row:" << row << std::endl; - for(int i=1; i < n+1; i++){ - i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Row",row); - } -} void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ //create knots in v-direction @@ -214,12 +188,7 @@ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ // } -opencascade::handle CTiglRoundedSegmentSurface::buildLoft(){ - ConvertCurves(); - NumberOfPolesIsSameInAllCurves(m_profileCurves); - initializePoleMatrix(); - calculatePoleMatrix(); - calculateKnotsAndMultiplicities(); +opencascade::handle Surface(){ /** TODO IS ALL OF THAT COVERED? * OCC Geom_BSplineSurface(): @@ -233,15 +202,15 @@ opencascade::handle CTiglRoundedSegmentSurface::buildLoft() * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. */ - auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); + //auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); //DEBUG DELETEME - Handle(Geom_Surface) handle_surface = surface; - TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); - tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + // Handle(Geom_Surface) handle_surface = surface; + // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); - return surface; + // return surface; } -} +} diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 192aba61be..3e002a024e 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -12,19 +12,96 @@ namespace tigl { class CTiglRoundedSegmentSurface { public: - TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector&, double inner_rounding_distance, double outer_rounding_distance); + TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, + double inner_rounding_distance, + double outer_rounding_distance); - TIGL_EXPORT TopoDS_Shape& Shape(); + TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); + + TIGL_EXPORT void CheckEdgeCountIsSameInAllProfiles(const std::vector &profiles); + //Row: Profile Curves Col: Edges per Profile + TIGL_EXPORT std::vector> ConvertCurves(std::vector &profiles); private: TIGL_EXPORT void Perform(); - // Converts TopoDS_Wire → Handle(Geom_BSplineCurve) - TIGL_EXPORT void ConvertCurves(); - // Initialize values required for 'buildLoft' - // Determin dimensions of pole matrix + struct RoundedSegment + { + RoundedSegment(std::vector const& start, + std::vector const& end, + double inner_rounding_distance, + double outer_rounding_distance) { + for(int i = 0; i < start.size(); i++){ + firstProfile.SetValue(i+1,start[i]->Pole(i+1)); + lastProfile.SetValue(i+1,end[i]->Pole(i+1)); + } + } + + void insert_inner_rows(int nb_dummies) { + for (int i = 0; i < nb_dummies; i++) { + auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); + // for every profile point in start profile + for(int j = 1; j< firstProfile.Size()+1; j++){ + //calculate Vector between both profile poles and normalize it + gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 + gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); + // interpolate relative position between the point in the start and end profiles for the ith dummy profile + // append interpolated point to row + double inner_distance = inner_rounding_distance/nb_dummies*(i+1); + gp_Vec inner_pole_vec(firstProfile.Value(j).Coord().X(),firstProfile.Value(j).Coord().Y(),firstProfile.Value(j).Coord().Z()); + //save new poles in a vector for each inner dummy profile + gp_Vec inner_vec(normalized_vector_in_v_direction); + inner_vec.Scale(inner_distance); //scaled normalized vector in v-direction + inner_vec.Add(inner_pole_vec); //vector to new k-th pole + gp_Pnt new_pole_inner(inner_vec.XYZ()); + row->SetValue(j+1, new_pole_inner); + } + dummyProfiles.push_back(row); + } + } + + void insert_outer_rows(int nb_dummies) { + for (int i = 0; i < nb_dummies; i++) { + auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); + for (int j=0; j < firstProfile.Size(); j++){ + //calculate Vector between both profile poles and normalize it + gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 + gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); + //calculate distance between k-th outer dummy-pole in v-direction and profile + double outer_distance = outer_rounding_distance/nb_dummies * (nb_dummies-i); + gp_Vec outer_vec(lastProfile.Value(j).Coord().X(),lastProfile.Value(j).Coord().Y(),lastProfile.Value(j).Coord().Z()); + gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); + outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction + outer_vec.Subtract(outer_normalized_vec); + gp_Pnt new_pole_outer(outer_vec.XYZ()); + //save new poles in a vector for each outer dummy profile + row->SetValue(j+1, new_pole_outer); + } + dummyProfiles.push_back(row); + } + } + + TColgp_HArray1OfPnt get_first_profile(){ + return firstProfile; + } + TColgp_HArray1OfPnt get_last_profile(){ + return lastProfile; + } + std::vector getDummyProfiles(){ + return dummyProfiles; + } + + + TColgp_HArray1OfPnt firstProfile; + TColgp_HArray1OfPnt lastProfile; + std::vector dummyProfiles; + double inner_rounding_distance; + double outer_rounding_distance; + }; + + //TODO TIGL_EXPORT void initializePoleMatrix(); - + TIGL_EXPORT void insertBefore(int i); // Calculate required poles to build rounded curves at given sections TIGL_EXPORT void calculatePoleMatrix(); @@ -59,15 +136,13 @@ class CTiglRoundedSegmentSurface TColStd_HArray1OfInteger m_u_multiplicities; TColStd_HArray1OfInteger m_v_multiplicities; - //Input datatype for constructor, to be converted in perform()-method - const std::vector& m_profileWires; - //Storage of inner and outer rounding distance per segment std::vector m_inner_rounding_distance; std::vector m_outer_rounding_distance; // Store as B-spline curves internally (after conversion) std::vector m_profileCurves; + Handle(Geom_BSplineSurface) m_surface; bool _hasPerformed = false; int _maxDegree = 3; From f02542aefb4467e4660c157804e9980e0f814750 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 26 May 2026 09:06:28 +0200 Subject: [PATCH 13/44] add Perform algorithm --- src/geometry/CTiglRoundedSegmentSurface.cpp | 43 ++++++++++++++++++++- src/geometry/CTiglRoundedSegmentSurface.h | 28 +++++--------- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index ef70cb23fb..c00d9a4ec6 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -9,21 +9,60 @@ namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector , +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , double inner_rounding_distance, double outer_rounding_distance): m_pole_matrix({}), m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), m_profileCurves(m_profileCurves), + m_segments({}), m_surface(nullptr){} TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); -void CTiglRoundedSegmentSurface::initializePoleMatrix(){ +void CTiglRoundedSegmentSurface::Perform(){ + //initialize polematrix Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; Standard_Integer n = m_profileCurves[0]->NbPoles(); m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); + //initialize m_segments vector + for(Handle(Geom_BSplineCurve) curve : m_profileCurves){ + m_segments.push_back(RoundedSegment(m_profileCurves[0], + m_profileCurves[m_profileCurves.size()-1], + m_inner_rounding_distance, //TODO access the right values per RoundedSegment + m_outer_rounding_distance)); + } + //update each element in m_segments vector and create all dummy profiles + //outer segments have only inner|outer dummy curves + m_segments[0].insert_outer_rows(_nb_dummies); + m_segments[m_segments.size()-1].insert_inner_rows(_nb_dummies); + //inner segments have both, inner and outer dummy curves + for(int i = 1; i< m_segments.size()-1; i++){ + m_segments[i].insert_inner_rows(_nb_dummies); + m_segments[i].insert_outer_rows(_nb_dummies); + } + + int row=0; //counter for inserted rows + for(RoundedSegment seg: m_segments){ + //fill pole matrix + //Retrieve First Segments Curves + for( int col = 1;col< n+1; col++){ + m_pole_matrix.SetValue(0,col,m_segments[0].get_first_profile().Value(col)); + } + row++; //next row + for(TColgp_HArray1OfPnt profile: m_segments[0].getDummyProfiles()){ + for( int col = 1;col< n+1; col++){ + m_pole_matrix.SetValue(row,col,profile.Value(col)); + } + row++; + } + //Retrieve Last Segments Curves + for( int col = 1;col< n+1; col++){ + m_pole_matrix.SetValue(0,col,m_segments[0].get_last_profile().Value(col)); + } + } + } //void CTiglRoundedSegmentSurface::calculatePoleMatrix() diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 3e002a024e..b10629eac0 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -18,22 +18,18 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); - TIGL_EXPORT void CheckEdgeCountIsSameInAllProfiles(const std::vector &profiles); - //Row: Profile Curves Col: Edges per Profile - TIGL_EXPORT std::vector> ConvertCurves(std::vector &profiles); - private: TIGL_EXPORT void Perform(); struct RoundedSegment { - RoundedSegment(std::vector const& start, - std::vector const& end, + RoundedSegment(Handle(Geom_BSplineCurve) const& start, + Handle(Geom_BSplineCurve) const& end, double inner_rounding_distance, double outer_rounding_distance) { - for(int i = 0; i < start.size(); i++){ - firstProfile.SetValue(i+1,start[i]->Pole(i+1)); - lastProfile.SetValue(i+1,end[i]->Pole(i+1)); + for(int i = 0; i < start->NbPoles(); i++){ + firstProfile.SetValue(i+1,start->Pole(i)); + lastProfile.SetValue(i+1,end->Pole(i)); } } @@ -99,12 +95,6 @@ class CTiglRoundedSegmentSurface double outer_rounding_distance; }; - //TODO - TIGL_EXPORT void initializePoleMatrix(); - TIGL_EXPORT void insertBefore(int i); - // Calculate required poles to build rounded curves at given sections - TIGL_EXPORT void calculatePoleMatrix(); - // Deduce required knot vector and multiplicies from pole matrix properties //TODO: Add mathematical boundaries for required number of knots and multiplicities TIGL_EXPORT void calculateKnotsAndMultiplicities(); @@ -123,7 +113,6 @@ class CTiglRoundedSegmentSurface */ // Call required methods to initialize required values and build surface - TIGL_EXPORT Handle(Geom_BSplineSurface) buildLoft(); TIGL_EXPORT void Invalidate() { _hasPerformed = false; } private: @@ -137,11 +126,12 @@ class CTiglRoundedSegmentSurface TColStd_HArray1OfInteger m_v_multiplicities; //Storage of inner and outer rounding distance per segment - std::vector m_inner_rounding_distance; - std::vector m_outer_rounding_distance; + double m_inner_rounding_distance; + double m_outer_rounding_distance; // Store as B-spline curves internally (after conversion) - std::vector m_profileCurves; + std::vector m_profileCurves; //Vector contains 1 edge per profile Wire, loft ist build edgewise + std::vector m_segments; Handle(Geom_BSplineSurface) m_surface; bool _hasPerformed = false; From 4e91663453857633bce95a502d93b366828c1542 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 26 May 2026 09:49:04 +0200 Subject: [PATCH 14/44] add check in Surface() --- src/geometry/CTiglRoundedSegmentSurface.cpp | 175 +++----------------- 1 file changed, 26 insertions(+), 149 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index c00d9a4ec6..0d2bd6b0e2 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -19,9 +19,33 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree + * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 + * (this is even recommended if you want the curve to start and finish on the first and last pole). + * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. + * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) + * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. + */ + if(_hasPerformed){ + throw CTiglError("Surface cannot be built, must initialize first"); + } + auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); + + //DEBUG DELETEME + // Handle(Geom_Surface) handle_surface = surface; + // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + + return surface; +} void CTiglRoundedSegmentSurface::Perform(){ + calculateKnotsAndMultiplicities(); //initialize polematrix Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; Standard_Integer n = m_profileCurves[0]->NbPoles(); @@ -62,131 +86,9 @@ void CTiglRoundedSegmentSurface::Perform(){ m_pole_matrix.SetValue(0,col,m_segments[0].get_last_profile().Value(col)); } } - + _hasPerformed = true; } -//void CTiglRoundedSegmentSurface::calculatePoleMatrix() -//{ -// //1. loop: iterate through profiles(rows) (index starts with 0 since std::vector -// //2. loop: iterate through profile curves poles(colums) (Geom_Curve) "profileCurves" for each edge -// //i rows, j columns (OCC indizes start with 1, loops start with 1 when iterating through OCC datatypes) -// //note: loop-indices are named i,j,k and refer to row,column,number of dummy-Profile for better geometric/code-orientation -// -// //following variables refer to the values between i-th and (i+1)-th profile curve -// //cases: -// //2 sections: no dummy profiles to build -// //3 sections: dummy profiles around middle section -// //... -// //no dummies after 1.st and before last section -// -// double inner_rd, outer_rd; -// gp_Pnt inner_poles_per_col, outer_poles_per_col; -// -// int m = m_pole_matrix.NbRows(); -// int n = m_pole_matrix.NbColumns(); -// -// //iterate through given profile curves -// for (int i=0; i< m_profileCurves.size(); i++){ -// //determine rounding distances between profiles -// if(i==0){ -// inner_rd =0.; //no value available = no dummies after first section -// outer_rd = m_outer_rounding_distance[i]; -// } -// if(i>0&&!(i==m_profileCurves.size())){ -// inner_rd = m_inner_rounding_distance[i-1]; -// outer_rd = m_outer_rounding_distance[i]; -// } else{ -// inner_rd = m_inner_rounding_distance[i-1]; -// outer_rd = 0.; //no value available = no dummies before last section -// } -// //iterate through columns to create Dummy Profile-Poles between each pair of profiles -// for( int j=0; j< n; j++){ -// //retrieve poles of i-th and (i+1)-th profile (thus out of bounds for outer pole in row before last row) -// inner_poles_per_col = m_profileCurves[i]->Pole(j+1);//v0 -// if(iPole(j+1); //v1 -// } else { -// outer_poles_per_col = inner_poles_per_col; -// } -// //calculate Vector between both profile poles and normalize it -// gp_Vec vector_in_v_direction(inner_poles_per_col, outer_poles_per_col); //v01 -// gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); -// if(inner_poles_per_col.IsEqual(outer_poles_per_col, 1e-14)){ -// throw tigl::CTiglError(std::to_string(inner_poles_per_col.Coord().X())+"x"+ -// std::to_string(inner_poles_per_col.Coord().Y())+"y"+ -// std::to_string(inner_poles_per_col.Coord().Y())+"Z"+ -// std::to_string(outer_poles_per_col.Coord().X())+"x"+ -// std::to_string(outer_poles_per_col.Coord().Y())+"y"+ -// std::to_string(outer_poles_per_col.Coord().Y())+"Z"); -// } -// normalized_vector_in_v_direction.Normalize(); //|v01| -// //create dummy_profiles, which will be ordered as follows in between the sections(profile[i]/[i+1]): -// //(inner)-> profile[0] | ------ dummy_outer1 | dummy_outer2 | dummy_outer3 | profile[i] | dummy_inner1 | dummy_inner2 | dummy_inner3 | ---- profile[i+1] |<-(outer) -// //add profile first -// int current_row; -// if(i==0){ -// current_row =1; -// } else { -// current_row = _nb_dummies+3+(i-1)*(1+_nb_dummies*2); -// } -// //insert first profile pole -// if(current_row==1){ -// std::cerr << "Insert First Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; -// m_pole_matrix.SetValue(current_row,j+1, inner_poles_per_col); //v0 first -// current_row+=1; -// } -// //calculate new poles for inner dummy profiles (from inner to outer) except 1st (i=0) section -// if(i>0&&i _nb_dummies -(k+1)/_nb_dummies) -// //last segment has no outer dummies -> < m_profileCurves.size()-2 -// if(i<(m_profileCurves.size()-2)){ -// for (int k=0; k < _nb_dummies; k++){ -// //calculate distance between k-th outer dummy-pole in v-direction and profile -// double outer_distance = outer_rd/_nb_dummies * (_nb_dummies-k); -// gp_Vec outer_vec(outer_poles_per_col.Coord().X(),outer_poles_per_col.Coord().Y(),outer_poles_per_col.Coord().Z()); -// gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); -// outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction -// outer_vec.Subtract(outer_normalized_vec); -// gp_Pnt new_pole_outer(outer_vec.XYZ()); -// std::cout << "OuterDistance:" << outer_distance << " k:" << k << std::endl; -// std::cerr << "Insert outer " << k << ". Profile pole: i:" << i << " j:" << j << " current_row:" << current_row << std::endl; -// //save new poles in a vector for each outer dummy profile -// m_pole_matrix.SetValue(current_row,j+1, new_pole_outer); -// current_row+=1; -// } -// } -// //insert actual profile pole -// if(i Surface(){ - - /** TODO IS ALL OF THAT COVERED? - * OCC Geom_BSplineSurface(): - * Creates a non-rational b-spline surface (weights default value is 1.). - * The following conditions must be verified. 0 < UDegree <= MaxDegree. - * UKnots.Length() == UMults.Length() >= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree - * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 - * (this is even recommended if you want the curve to start and finish on the first and last pole). - * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. - * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) - * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. - */ - - //auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); - - //DEBUG DELETEME - // Handle(Geom_Surface) handle_surface = surface; - // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); - // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); - - // return surface; -} - - } From 9ff12cba9c1d4bdde89f39f1b648829f74f4c912 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Thu, 28 May 2026 11:00:02 +0200 Subject: [PATCH 15/44] fix indices --- src/geometry/CTiglRoundedSegmentSurface.cpp | 43 ++++++++++--------- src/geometry/CTiglRoundedSegmentSurface.h | 38 +++++++++------- .../TestCTiglRoundedSegmentSurface.cpp | 12 ++++-- 3 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 0d2bd6b0e2..4135d16bfd 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -12,7 +12,7 @@ namespace tigl{ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , double inner_rounding_distance, double outer_rounding_distance): - m_pole_matrix({}), + m_pole_matrix(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())), m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), m_profileCurves(m_profileCurves), @@ -31,25 +31,21 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. */ - if(_hasPerformed){ - throw CTiglError("Surface cannot be built, must initialize first"); - } + Perform(); auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); - //DEBUG DELETEME - // Handle(Geom_Surface) handle_surface = surface; - // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); - // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); - return surface; } void CTiglRoundedSegmentSurface::Perform(){ + if (_hasPerformed) { + return; + } calculateKnotsAndMultiplicities(); - //initialize polematrix - Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; +// //initialize polematrix +// Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; Standard_Integer n = m_profileCurves[0]->NbPoles(); - m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); +// m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); //initialize m_segments vector for(Handle(Geom_BSplineCurve) curve : m_profileCurves){ m_segments.push_back(RoundedSegment(m_profileCurves[0], @@ -67,24 +63,29 @@ void CTiglRoundedSegmentSurface::Perform(){ m_segments[i].insert_outer_rows(_nb_dummies); } - int row=0; //counter for inserted rows + int row=1; //counter for inserted rows + std::cerr << "col:" << m_pole_matrix.NbColumns() << " rows: " << m_pole_matrix.NbRows() << std::endl; for(RoundedSegment seg: m_segments){ //fill pole matrix - //Retrieve First Segments Curves for( int col = 1;col< n+1; col++){ - m_pole_matrix.SetValue(0,col,m_segments[0].get_first_profile().Value(col)); + m_pole_matrix.SetValue(row,col,seg.get_first_profile().Value(col)); } - row++; //next row - for(TColgp_HArray1OfPnt profile: m_segments[0].getDummyProfiles()){ + row++; + std::cerr << row << std::endl; + for(TColgp_HArray1OfPnt profile: seg.getDummyProfiles()){ for( int col = 1;col< n+1; col++){ m_pole_matrix.SetValue(row,col,profile.Value(col)); } row++; + std::cerr << row << std::endl; } - //Retrieve Last Segments Curves - for( int col = 1;col< n+1; col++){ - m_pole_matrix.SetValue(0,col,m_segments[0].get_last_profile().Value(col)); - } + // if(row==m_pole_matrix.RowLength()){ + // for( int col = 1;col< n+1; col++){ + // m_pole_matrix.SetValue(row,col,seg.get_last_profile().Value(col)); + // } + // row++; + // std::cerr << row << std::endl; + // } } _hasPerformed = true; } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index b10629eac0..ff214abd25 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -3,7 +3,6 @@ #include "Geom_BSplineCurve.hxx" #include "Geom_BSplineSurface.hxx" -#include "TopoDS_Wire.hxx" #include "tigl_internal.h" #include @@ -23,21 +22,35 @@ class CTiglRoundedSegmentSurface struct RoundedSegment { + TColgp_HArray1OfPnt firstProfile; + TColgp_HArray1OfPnt lastProfile; + std::vector dummyProfiles; + double inner_rounding_distance; + double outer_rounding_distance; + RoundedSegment(Handle(Geom_BSplineCurve) const& start, Handle(Geom_BSplineCurve) const& end, - double inner_rounding_distance, - double outer_rounding_distance) { - for(int i = 0; i < start->NbPoles(); i++){ - firstProfile.SetValue(i+1,start->Pole(i)); - lastProfile.SetValue(i+1,end->Pole(i)); + double inner_rd, + double outer_rd): + firstProfile(1,start->NbPoles()), + lastProfile(1,start->NbPoles()), + dummyProfiles({}), + inner_rounding_distance(inner_rd), + outer_rounding_distance(outer_rd) + { + for(int i = 1; i < start->NbPoles(); i++){ + firstProfile.SetValue(i,start->Pole(i)); + lastProfile.SetValue(i,end->Pole(i)); } + std::cerr << "Reserve Profile storage" << std::endl; + dummyProfiles.reserve(8); } void insert_inner_rows(int nb_dummies) { for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); // for every profile point in start profile - for(int j = 1; j< firstProfile.Size()+1; j++){ + for(int j = 1; j< firstProfile.Size(); j++){ //calculate Vector between both profile poles and normalize it gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); @@ -52,14 +65,14 @@ class CTiglRoundedSegmentSurface gp_Pnt new_pole_inner(inner_vec.XYZ()); row->SetValue(j+1, new_pole_inner); } - dummyProfiles.push_back(row); + dummyProfiles.push_back(*row); } } void insert_outer_rows(int nb_dummies) { for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); - for (int j=0; j < firstProfile.Size(); j++){ + for (int j=1; j < firstProfile.Size(); j++){ //calculate Vector between both profile poles and normalize it gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); @@ -73,7 +86,7 @@ class CTiglRoundedSegmentSurface //save new poles in a vector for each outer dummy profile row->SetValue(j+1, new_pole_outer); } - dummyProfiles.push_back(row); + dummyProfiles.push_back(*row); } } @@ -88,11 +101,6 @@ class CTiglRoundedSegmentSurface } - TColgp_HArray1OfPnt firstProfile; - TColgp_HArray1OfPnt lastProfile; - std::vector dummyProfiles; - double inner_rounding_distance; - double outer_rounding_distance; }; // Deduce required knot vector and multiplicies from pole matrix properties diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 05b4b909a8..c5ef5cc50c 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -1,4 +1,5 @@ #include "CCPACSWingSection.h" +#include "CTiglRoundedSegmentSurface.h" #include "Debugging.h" #include "test.h" #include "tigl.h" @@ -120,7 +121,12 @@ class TestCTiglRoundedSegmentSurface : public ::testing::Test TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) { - - - + double ird = 0.3; + double ord = 0.2; + tigl::CTiglRoundedSegmentSurface lofter(profileCurves, ird, ord); + auto surface = lofter.Surface(); + //DEBUG DELETEME + // Handle(Geom_Surface) handle_surface = surface; + // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); } From 121e3e6818681df309cb69e60ad2a7276e73eb1a Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 3 Jun 2026 06:43:55 +0200 Subject: [PATCH 16/44] fix indices --- src/geometry/CTiglRoundedSegmentSurface.cpp | 141 ++++++++++++-------- src/geometry/CTiglRoundedSegmentSurface.h | 24 +++- 2 files changed, 104 insertions(+), 61 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 4135d16bfd..327bdaef06 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -11,13 +11,19 @@ namespace tigl{ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , double inner_rounding_distance, - double outer_rounding_distance): + double outer_rounding_distance, int u_degree, int v_degree): m_pole_matrix(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())), + m_u_knots(1,m_profileCurves[0]->NbKnots()), + m_v_knots(1, m_pole_matrix.ColLength()+v_degree-5), + m_u_multiplicities(1, m_pole_matrix.RowLength()+u_degree+1, 1 ), + m_v_multiplicities(1, m_pole_matrix.ColLength()+v_degree-5, 1), m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), m_profileCurves(m_profileCurves), m_segments({}), - m_surface(nullptr){} + m_surface(nullptr), + _u_degree(u_degree), + _v_degree(v_degree){} TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ /** TODO IS ALL OF THAT COVERED? @@ -32,8 +38,37 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. */ Perform(); - auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); + + //BEGIN DEBUG DELETEME + int m = m_pole_matrix.ColLength(); + int n = m_pole_matrix.RowLength(); + + for(int col=1; col i_poles(1,m); + std::cerr<< "Column:" << col << std::endl; + for(int i=1; i < m+1; i++){ + i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Edge",col); + } + for(int row=1; row i_poles(1,n); + std::cerr<< "Row:" << row << std::endl; + for(int i=1; i < n+1; i++){ + i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); + std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + } + auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); + tigl::dumpShape(edge,"makeLoftWing", "Row",row); + } + //END DEBUG DELETEME + + auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); return surface; } @@ -42,14 +77,11 @@ void CTiglRoundedSegmentSurface::Perform(){ return; } calculateKnotsAndMultiplicities(); -// //initialize polematrix -// Standard_Integer m = m_profileCurves.size()+(m_profileCurves.size()-2)*2*_nb_dummies; - Standard_Integer n = m_profileCurves[0]->NbPoles(); -// m_pole_matrix = TColgp_HArray2OfPnt(1,m,1,n); + //initialize m_segments vector - for(Handle(Geom_BSplineCurve) curve : m_profileCurves){ - m_segments.push_back(RoundedSegment(m_profileCurves[0], - m_profileCurves[m_profileCurves.size()-1], + for(int i = 0; i < m_profileCurves.size()-1; i++){ + m_segments.push_back(RoundedSegment(m_profileCurves[i], + m_profileCurves[i+1], m_inner_rounding_distance, //TODO access the right values per RoundedSegment m_outer_rounding_distance)); } @@ -58,34 +90,34 @@ void CTiglRoundedSegmentSurface::Perform(){ m_segments[0].insert_outer_rows(_nb_dummies); m_segments[m_segments.size()-1].insert_inner_rows(_nb_dummies); //inner segments have both, inner and outer dummy curves - for(int i = 1; i< m_segments.size()-1; i++){ - m_segments[i].insert_inner_rows(_nb_dummies); - m_segments[i].insert_outer_rows(_nb_dummies); + if(m_segments.size()>3){ + for(int i = 1; i< m_segments.size()-1; i++){ + m_segments[i].insert_inner_rows(_nb_dummies); + m_segments[i].insert_outer_rows(_nb_dummies); + } } int row=1; //counter for inserted rows std::cerr << "col:" << m_pole_matrix.NbColumns() << " rows: " << m_pole_matrix.NbRows() << std::endl; for(RoundedSegment seg: m_segments){ //fill pole matrix - for( int col = 1;col< n+1; col++){ + for( int col = 1;col< m_profileCurves[0]->NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,seg.get_first_profile().Value(col)); } row++; - std::cerr << row << std::endl; + std::cerr << row << std::endl; //DEBUG DELETEME for(TColgp_HArray1OfPnt profile: seg.getDummyProfiles()){ - for( int col = 1;col< n+1; col++){ + for( int col = 1;col< m_profileCurves[0]->NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,profile.Value(col)); } row++; - std::cerr << row << std::endl; + std::cerr << row << std::endl; //DEBUG DELETEME + } + if(row==m_pole_matrix.ColLength()){ + for( int col = 1;col< m_profileCurves[0]->NbPoles()+1; col++){ + m_pole_matrix.SetValue(row,col,seg.get_last_profile().Value(col)); + } } - // if(row==m_pole_matrix.RowLength()){ - // for( int col = 1;col< n+1; col++){ - // m_pole_matrix.SetValue(row,col,seg.get_last_profile().Value(col)); - // } - // row++; - // std::cerr << row << std::endl; - // } } _hasPerformed = true; } @@ -93,41 +125,42 @@ void CTiglRoundedSegmentSurface::Perform(){ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ //create knots in v-direction auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; - TColStd_Array1OfReal v_knots(1, nb_v_knots); std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); - for(int i=1;iKnots(); + m_u_multiplicities = m_profileCurves[0]->Multiplicities(); //MAYBE CHECK - //if(!(u_knots.Length()==u_multiplicities.Length())){ - // throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(u_knots.Length())+","+std::to_string(u_multiplicities.Length())+")"); - //} - //if(!(v_knots.Length()==v_multiplicities.Length())){ - // throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(v_knots.Length())+","+std::to_string(v_multiplicities.Length())+")"); - //} - //for(int i = 1; i< u_knots.Length()-1;i++){ - // if (!(u_knots.Value(i) < u_knots.Value(i+1))){ - // throw tigl::CTiglError(""+std::to_string(u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(u_knots.Value(i+1))); - // } - //} - //for(int i = 1; i< v_knots.Length()-1;i++){ - // if (!(v_knots.Value(i) < v_knots.Value(i+1))){ - // throw tigl::CTiglError("check knots"); - // } - //} - //if(!(m_profileCurves[0]->NbPoles()==(nb_u_knots+2*3-u_degree-1))){ - // throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ - // std::to_string(m_profileCurves[0]->NbKnots())+"u_degree:"+std::to_string(u_degree)); - //} - //if(!(pole_matrix.ColLength()==(nb_v_knots+2*3-v_degree-1))){ - // throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" - // +std::to_string(pole_matrix.ColLength())+"v_degree:"+std::to_string(v_degree)); - // + if(!(m_u_knots.Length()==m_u_multiplicities.Length())){ + throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(m_u_knots.Length())+","+std::to_string(m_u_multiplicities.Length())+")"); + } + if(!(m_v_knots.Length()==m_v_multiplicities.Length())){ + throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(m_v_knots.Length())+","+std::to_string(m_v_multiplicities.Length())+")"); + } + for(int i = 1; i< m_u_knots.Length()-1;i++){ + if (!(m_u_knots.Value(i) < m_u_knots.Value(i+1))){ + throw tigl::CTiglError(""+std::to_string(m_u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(m_u_knots.Value(i+1))); + } + } + for(int i = 1; i< m_v_knots.Length()-1;i++){ + if (!(m_v_knots.Value(i) < m_v_knots.Value(i+1))){ + throw tigl::CTiglError("check knots"); + } + } + if(!(m_profileCurves[0]->NbPoles()==(m_profileCurves[0]->NbKnots()+2*4-_u_degree-1))){ + throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ + std::to_string(m_u_knots.Length())+"u_degree:"+std::to_string(_u_degree)); + } + if(!(m_pole_matrix.ColLength()==(nb_v_knots+2*3-_v_degree-1))){ + throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" + +std::to_string(m_pole_matrix.ColLength())+"v_degree:"+std::to_string(_v_degree)); + } } } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index ff214abd25..234e42568e 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -13,7 +13,9 @@ class CTiglRoundedSegmentSurface public: TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, double inner_rounding_distance, - double outer_rounding_distance); + double outer_rounding_distance, + int u_degree = 3, + int v_degree = 3); TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); @@ -38,7 +40,7 @@ class CTiglRoundedSegmentSurface inner_rounding_distance(inner_rd), outer_rounding_distance(outer_rd) { - for(int i = 1; i < start->NbPoles(); i++){ + for(int i = 1; i < start->NbPoles()+1; i++){ firstProfile.SetValue(i,start->Pole(i)); lastProfile.SetValue(i,end->Pole(i)); } @@ -47,10 +49,11 @@ class CTiglRoundedSegmentSurface } void insert_inner_rows(int nb_dummies) { + int count =1; //DEBUG DELETEME for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); // for every profile point in start profile - for(int j = 1; j< firstProfile.Size(); j++){ + for(int j = 1; j< firstProfile.Size()+1; j++){ //calculate Vector between both profile poles and normalize it gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); @@ -63,30 +66,37 @@ class CTiglRoundedSegmentSurface inner_vec.Scale(inner_distance); //scaled normalized vector in v-direction inner_vec.Add(inner_pole_vec); //vector to new k-th pole gp_Pnt new_pole_inner(inner_vec.XYZ()); - row->SetValue(j+1, new_pole_inner); + row->SetValue(j, new_pole_inner); } dummyProfiles.push_back(*row); + std::cerr << "Insert inner rows:" << count << std::endl; //DEBUG DELETEME + count ++; } } void insert_outer_rows(int nb_dummies) { + int count =1; //DEBUG DELETEME for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); - for (int j=1; j < firstProfile.Size(); j++){ + for (int j=1; j < firstProfile.Size()+1; j++){ //calculate Vector between both profile poles and normalize it gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); //calculate distance between k-th outer dummy-pole in v-direction and profile double outer_distance = outer_rounding_distance/nb_dummies * (nb_dummies-i); - gp_Vec outer_vec(lastProfile.Value(j).Coord().X(),lastProfile.Value(j).Coord().Y(),lastProfile.Value(j).Coord().Z()); + gp_Vec outer_vec(lastProfile.Value(j).Coord().X(), + lastProfile.Value(j).Coord().Y(), + lastProfile.Value(j).Coord().Z()); gp_Vec outer_normalized_vec(normalized_vector_in_v_direction); outer_normalized_vec.Scale(outer_distance); //scaled normalized vector in v-direction outer_vec.Subtract(outer_normalized_vec); gp_Pnt new_pole_outer(outer_vec.XYZ()); //save new poles in a vector for each outer dummy profile - row->SetValue(j+1, new_pole_outer); + row->SetValue(j, new_pole_outer); } dummyProfiles.push_back(*row); + std::cerr << "Insert outers rows:" << count << std::endl; //DEBUG DELETEME + count ++; } } From 3e7a7dd12e96e8e9c528b04f96927bf3cfc328a1 Mon Sep 17 00:00:00 2001 From: merakulix Date: Mon, 8 Jun 2026 13:18:03 +0200 Subject: [PATCH 17/44] calculate curves in RoundedSegment Constructor --- src/geometry/CTiglRoundedSegmentSurface.cpp | 44 ++++++++++++--------- src/geometry/CTiglRoundedSegmentSurface.h | 10 +++-- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 327bdaef06..b502037734 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -14,9 +14,9 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vectorNbPoles())), m_u_knots(1,m_profileCurves[0]->NbKnots()), - m_v_knots(1, m_pole_matrix.ColLength()+v_degree-5), - m_u_multiplicities(1, m_pole_matrix.RowLength()+u_degree+1, 1 ), - m_v_multiplicities(1, m_pole_matrix.ColLength()+v_degree-5, 1), + m_v_knots(1, m_pole_matrix.ColLength()-v_degree+1), + m_u_multiplicities(m_profileCurves[0]->Multiplicities()), + m_v_multiplicities(1, m_pole_matrix.ColLength()-v_degree+1, 1), m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), m_profileCurves(m_profileCurves), @@ -49,7 +49,7 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ std::cerr<< "Column:" << col << std::endl; for(int i=1; i < m+1; i++){ i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; } auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); @@ -60,14 +60,21 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ std::cerr<< "Row:" << row << std::endl; for(int i=1; i < n+1; i++){ i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << " Y:" << i_poles.Value(i).Coord().Y() << " Z:" << i_poles.Value(i).Coord().Z() << std::endl; + std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; } auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); tigl::dumpShape(edge,"makeLoftWing", "Row",row); } + std::cerr << "Dimensions:\nPolematrix:\nrows: " << m_pole_matrix.ColLength() + << "\ncol: " << m_pole_matrix.RowLength() + << "\n v_knot number: " << m_v_knots.Length() + << "\n u_knot number: " << m_u_knots.Length() + << "\n v_mults number: " << m_v_multiplicities.Length() + << "\n u_mults number: " << m_u_multiplicities.Length() < Put this line back in loop + m_outer_rounding_distance)); + for(int i = 1; i < m_profileCurves.size()-2; i++){ m_segments.push_back(RoundedSegment(m_profileCurves[i], m_profileCurves[i+1], m_inner_rounding_distance, //TODO access the right values per RoundedSegment m_outer_rounding_distance)); } - //update each element in m_segments vector and create all dummy profiles - //outer segments have only inner|outer dummy curves - m_segments[0].insert_outer_rows(_nb_dummies); - m_segments[m_segments.size()-1].insert_inner_rows(_nb_dummies); - //inner segments have both, inner and outer dummy curves - if(m_segments.size()>3){ - for(int i = 1; i< m_segments.size()-1; i++){ - m_segments[i].insert_inner_rows(_nb_dummies); - m_segments[i].insert_outer_rows(_nb_dummies); - } - } + m_segments.push_back(RoundedSegment(m_profileCurves[m_profileCurves.size()-2], + m_profileCurves[m_profileCurves.size()-1], + m_inner_rounding_distance, //TODO access the right values per RoundedSegment later -> Put this line back in loop + 0.)); + //Write poles in pole matrix int row=1; //counter for inserted rows std::cerr << "col:" << m_pole_matrix.NbColumns() << " rows: " << m_pole_matrix.NbRows() << std::endl; for(RoundedSegment seg: m_segments){ @@ -124,7 +129,8 @@ void CTiglRoundedSegmentSurface::Perform(){ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ //create knots in v-direction - auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; + //auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; + auto nb_v_knots = m_pole_matrix.ColLength()-_v_degree+1; std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); for(int i=1;iKnots(); m_u_multiplicities = m_profileCurves[0]->Multiplicities(); diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 234e42568e..11b97f182d 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -44,8 +44,12 @@ class CTiglRoundedSegmentSurface firstProfile.SetValue(i,start->Pole(i)); lastProfile.SetValue(i,end->Pole(i)); } - std::cerr << "Reserve Profile storage" << std::endl; - dummyProfiles.reserve(8); + if(inner_rounding_distance>1e-6){ + insert_inner_rows(3); + } + if(outer_rounding_distance>1e-6){ + insert_outer_rows(3); + } } void insert_inner_rows(int nb_dummies) { @@ -83,7 +87,7 @@ class CTiglRoundedSegmentSurface gp_Vec vector_in_v_direction(firstProfile.Value(j), lastProfile.Value(j)); //v01 gp_Vec normalized_vector_in_v_direction(vector_in_v_direction); //calculate distance between k-th outer dummy-pole in v-direction and profile - double outer_distance = outer_rounding_distance/nb_dummies * (nb_dummies-i); + double outer_distance = (outer_rounding_distance/nb_dummies) * (nb_dummies-i); gp_Vec outer_vec(lastProfile.Value(j).Coord().X(), lastProfile.Value(j).Coord().Y(), lastProfile.Value(j).Coord().Z()); From 7c30c77a7f7a60f4e27fc6f63ebfc6f809124b86 Mon Sep 17 00:00:00 2001 From: merakulix Date: Mon, 8 Jun 2026 15:13:48 +0200 Subject: [PATCH 18/44] fix row/column mixup --- src/geometry/CTiglRoundedSegmentSurface.cpp | 2 +- tests/unittests/TestCTiglRoundedSegmentSurface.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index b502037734..fa4c87da42 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -75,7 +75,7 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ //END DEBUG DELETEME - auto surface = new Geom_BSplineSurface(m_pole_matrix, m_u_knots, m_v_knots, m_u_multiplicities, m_v_multiplicities, _u_degree, _v_degree, false, false); + auto surface = new Geom_BSplineSurface(m_pole_matrix, m_v_knots, m_u_knots, m_v_multiplicities, m_u_multiplicities,_v_degree, _u_degree, false, false); return surface; } diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index c5ef5cc50c..b8b96a1efd 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -121,12 +121,12 @@ class TestCTiglRoundedSegmentSurface : public ::testing::Test TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) { - double ird = 0.3; - double ord = 0.2; + double ird = 0.25; + double ord = 0.25; tigl::CTiglRoundedSegmentSurface lofter(profileCurves, ird, ord); auto surface = lofter.Surface(); - //DEBUG DELETEME - // Handle(Geom_Surface) handle_surface = surface; - // TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); - // tigl::dumpShape(surf, "makeLoftWing", "Surface",1); + // DEBUG DELETEME + Handle(Geom_Surface) handle_surface = surface; + TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); + tigl::dumpShape(surf, "makeLoftWing", "Surface",1); } From 8f9a1955b77054b908762afd7f98a1e9cd629ede Mon Sep 17 00:00:00 2001 From: Jan Kleinert Date: Wed, 20 May 2026 12:54:49 +0200 Subject: [PATCH 19/44] add rounded segment definition to xsd and regenerate CPACS classes --- cpacs_gen_input/cpacs_schema.xsd | 62 ++++++++++++++++++++++++++ src/generated/CPACSDuct.cpp | 25 +++++++++++ src/generated/CPACSDuct.h | 8 ++++ src/generated/CPACSFuselage.cpp | 25 +++++++++++ src/generated/CPACSFuselage.h | 8 ++++ src/generated/CPACSFuselageSegment.cpp | 52 +++++++++++++++++++++ src/generated/CPACSFuselageSegment.h | 12 +++++ src/generated/CPACSWing.cpp | 25 +++++++++++ src/generated/CPACSWing.h | 8 ++++ src/generated/CPACSWingSegment.cpp | 52 +++++++++++++++++++++ src/generated/CPACSWingSegment.h | 12 +++++ 11 files changed, 289 insertions(+) diff --git a/cpacs_gen_input/cpacs_schema.xsd b/cpacs_gen_input/cpacs_schema.xsd index ed12d6f875..f3b882200d 100644 --- a/cpacs_gen_input/cpacs_schema.xsd +++ b/cpacs_gen_input/cpacs_schema.xsd @@ -12740,6 +12740,26 @@ The fuel tank volume type should also be used for the wing fuel tank + + + This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the inner end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + + + + + + + + + + This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the outer end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + + + + + + + @@ -12867,6 +12887,13 @@ The fuel tank volume type should also be used for the wing fuel tank + + + This attribute determines the lofting approach of this fuselage. +If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. +This can be achieved e.g. by activating the approximation setting in the profile definitions. + + @@ -28757,6 +28784,26 @@ The fuel tank volume type should also be used for the wing fuel tank + + + This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the inner end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + + + + + + + + + + This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the outer end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + + + + + + + @@ -29135,6 +29182,14 @@ The fuel tank volume type should also be used for the wing fuel tank + + + This attribute determines the lofting approach of this fuselage. +If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. +This can be achieved e.g. by activating the approximation setting in the profile definitions. + + + @@ -35759,6 +35814,13 @@ The fuel tank volume type should also be used for the wing fuel tank + + + This attribute determines the lofting approach of this fuselage. +If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. +This can be achieved e.g. by activating the approximation setting in the profile definitions. + + diff --git a/src/generated/CPACSDuct.cpp b/src/generated/CPACSDuct.cpp index 51dc522ea9..a16c65832e 100644 --- a/src/generated/CPACSDuct.cpp +++ b/src/generated/CPACSDuct.cpp @@ -101,6 +101,11 @@ namespace generated m_symmetry = stringToTiglSymmetryAxis(tixi::TixiGetAttribute(tixiHandle, xpath, "symmetry")); } + // read attribute roundedSegments + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + m_roundedSegments = tixi::TixiGetAttribute(tixiHandle, xpath, "roundedSegments"); + } + // read element name if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); @@ -187,6 +192,16 @@ namespace generated } } + // write attribute roundedSegments + if (m_roundedSegments) { + tixi::TixiSaveAttribute(tixiHandle, xpath, "roundedSegments", *m_roundedSegments); + } + else { + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + tixi::TixiRemoveAttribute(tixiHandle, xpath, "roundedSegments"); + } + } + // write element name tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/name"); tixi::TixiSaveElement(tixiHandle, xpath + "/name", m_name); @@ -273,6 +288,16 @@ namespace generated m_symmetry = value; } + const boost::optional& CPACSDuct::GetRoundedSegments() const + { + return m_roundedSegments; + } + + void CPACSDuct::SetRoundedSegments(const boost::optional& value) + { + m_roundedSegments = value; + } + const std::string& CPACSDuct::GetName() const { return m_name; diff --git a/src/generated/CPACSDuct.h b/src/generated/CPACSDuct.h index 71cec98cad..958e70a251 100644 --- a/src/generated/CPACSDuct.h +++ b/src/generated/CPACSDuct.h @@ -70,6 +70,9 @@ namespace generated TIGL_EXPORT virtual const boost::optional& GetSymmetry() const; TIGL_EXPORT virtual void SetSymmetry(const boost::optional& value); + TIGL_EXPORT virtual const boost::optional& GetRoundedSegments() const; + TIGL_EXPORT virtual void SetRoundedSegments(const boost::optional& value); + TIGL_EXPORT virtual const std::string& GetName() const; TIGL_EXPORT virtual void SetName(const std::string& value); @@ -109,6 +112,11 @@ namespace generated boost::optional m_symmetry; + /// This attribute determines the lofting approach of this fuselage. + /// If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. + /// This can be achieved e.g. by activating the approximation setting in the profile definitions. + boost::optional m_roundedSegments; + /// Name std::string m_name; diff --git a/src/generated/CPACSFuselage.cpp b/src/generated/CPACSFuselage.cpp index c22878ab0b..290489577b 100644 --- a/src/generated/CPACSFuselage.cpp +++ b/src/generated/CPACSFuselage.cpp @@ -105,6 +105,11 @@ namespace generated m_symmetry = stringToTiglSymmetryAxis(tixi::TixiGetAttribute(tixiHandle, xpath, "symmetry")); } + // read attribute roundedSegments + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + m_roundedSegments = tixi::TixiGetAttribute(tixiHandle, xpath, "roundedSegments"); + } + // read element name if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); @@ -219,6 +224,16 @@ namespace generated } } + // write attribute roundedSegments + if (m_roundedSegments) { + tixi::TixiSaveAttribute(tixiHandle, xpath, "roundedSegments", *m_roundedSegments); + } + else { + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + tixi::TixiRemoveAttribute(tixiHandle, xpath, "roundedSegments"); + } + } + // write element name tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/name"); tixi::TixiSaveElement(tixiHandle, xpath + "/name", m_name); @@ -331,6 +346,16 @@ namespace generated m_symmetry = value; } + const boost::optional& CPACSFuselage::GetRoundedSegments() const + { + return m_roundedSegments; + } + + void CPACSFuselage::SetRoundedSegments(const boost::optional& value) + { + m_roundedSegments = value; + } + const std::string& CPACSFuselage::GetName() const { return m_name; diff --git a/src/generated/CPACSFuselage.h b/src/generated/CPACSFuselage.h index 2ffd6e4e8c..3095ee921e 100644 --- a/src/generated/CPACSFuselage.h +++ b/src/generated/CPACSFuselage.h @@ -76,6 +76,9 @@ namespace generated TIGL_EXPORT virtual const boost::optional& GetSymmetry() const; TIGL_EXPORT virtual void SetSymmetry(const boost::optional& value); + TIGL_EXPORT virtual const boost::optional& GetRoundedSegments() const; + TIGL_EXPORT virtual void SetRoundedSegments(const boost::optional& value); + TIGL_EXPORT virtual const std::string& GetName() const; TIGL_EXPORT virtual void SetName(const std::string& value); @@ -127,6 +130,11 @@ namespace generated boost::optional m_symmetry; + /// This attribute determines the lofting approach of this fuselage. + /// If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. + /// This can be achieved e.g. by activating the approximation setting in the profile definitions. + boost::optional m_roundedSegments; + /// Name of fuselage std::string m_name; diff --git a/src/generated/CPACSFuselageSegment.cpp b/src/generated/CPACSFuselageSegment.cpp index d37c01a8d7..938cfc5844 100644 --- a/src/generated/CPACSFuselageSegment.cpp +++ b/src/generated/CPACSFuselageSegment.cpp @@ -152,6 +152,16 @@ namespace generated } } + // read element innerRoundingDistance + if (tixi::TixiCheckElement(tixiHandle, xpath + "/innerRoundingDistance")) { + m_innerRoundingDistance = tixi::TixiGetElement(tixiHandle, xpath + "/innerRoundingDistance"); + } + + // read element outerRoundingDistance + if (tixi::TixiCheckElement(tixiHandle, xpath + "/outerRoundingDistance")) { + m_outerRoundingDistance = tixi::TixiGetElement(tixiHandle, xpath + "/outerRoundingDistance"); + } + if (m_uidMgr && !m_uID.empty()) m_uidMgr->RegisterObject(m_uID, *this); } @@ -194,6 +204,28 @@ namespace generated } } + // write element innerRoundingDistance + if (m_innerRoundingDistance) { + tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/innerRoundingDistance"); + tixi::TixiSaveElement(tixiHandle, xpath + "/innerRoundingDistance", *m_innerRoundingDistance); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/innerRoundingDistance")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/innerRoundingDistance"); + } + } + + // write element outerRoundingDistance + if (m_outerRoundingDistance) { + tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/outerRoundingDistance"); + tixi::TixiSaveElement(tixiHandle, xpath + "/outerRoundingDistance", *m_outerRoundingDistance); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/outerRoundingDistance")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/outerRoundingDistance"); + } + } + } const std::string& CPACSFuselageSegment::GetUID() const @@ -272,6 +304,26 @@ namespace generated return m_guideCurves; } + const boost::optional& CPACSFuselageSegment::GetInnerRoundingDistance() const + { + return m_innerRoundingDistance; + } + + void CPACSFuselageSegment::SetInnerRoundingDistance(const boost::optional& value) + { + m_innerRoundingDistance = value; + } + + const boost::optional& CPACSFuselageSegment::GetOuterRoundingDistance() const + { + return m_outerRoundingDistance; + } + + void CPACSFuselageSegment::SetOuterRoundingDistance(const boost::optional& value) + { + m_outerRoundingDistance = value; + } + CCPACSGuideCurves& CPACSFuselageSegment::GetGuideCurves(CreateIfNotExistsTag) { if (!m_guideCurves) diff --git a/src/generated/CPACSFuselageSegment.h b/src/generated/CPACSFuselageSegment.h index 3ccb946dc7..dc49f400c4 100644 --- a/src/generated/CPACSFuselageSegment.h +++ b/src/generated/CPACSFuselageSegment.h @@ -80,6 +80,12 @@ namespace generated TIGL_EXPORT virtual const boost::optional& GetGuideCurves() const; TIGL_EXPORT virtual boost::optional& GetGuideCurves(); + TIGL_EXPORT virtual const boost::optional& GetInnerRoundingDistance() const; + TIGL_EXPORT virtual void SetInnerRoundingDistance(const boost::optional& value); + + TIGL_EXPORT virtual const boost::optional& GetOuterRoundingDistance() const; + TIGL_EXPORT virtual void SetOuterRoundingDistance(const boost::optional& value); + TIGL_EXPORT virtual CCPACSGuideCurves& GetGuideCurves(CreateIfNotExistsTag); TIGL_EXPORT virtual void RemoveGuideCurves(); @@ -108,6 +114,12 @@ namespace generated /// the outer geometry. boost::optional m_guideCurves; + /// This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the inner end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + boost::optional m_innerRoundingDistance; + + /// This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the outer end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + boost::optional m_outerRoundingDistance; + private: TIGL_EXPORT const CTiglUIDObject* GetNextUIDObject() const final; TIGL_EXPORT void NotifyUIDChange(const std::string& oldUid, const std::string& newUid) final; diff --git a/src/generated/CPACSWing.cpp b/src/generated/CPACSWing.cpp index 9bcd48d193..bd99a36529 100644 --- a/src/generated/CPACSWing.cpp +++ b/src/generated/CPACSWing.cpp @@ -118,6 +118,11 @@ namespace generated m_symmetry = stringToTiglSymmetryAxis(tixi::TixiGetAttribute(tixiHandle, xpath, "symmetry")); } + // read attribute roundedSegments + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + m_roundedSegments = tixi::TixiGetAttribute(tixiHandle, xpath, "roundedSegments"); + } + // read element name if (tixi::TixiCheckElementHasTextContent(tixiHandle, xpath + "/name")) { m_name = tixi::TixiGetElement(tixiHandle, xpath + "/name"); @@ -210,6 +215,16 @@ namespace generated } } + // write attribute roundedSegments + if (m_roundedSegments) { + tixi::TixiSaveAttribute(tixiHandle, xpath, "roundedSegments", *m_roundedSegments); + } + else { + if (tixi::TixiCheckAttribute(tixiHandle, xpath, "roundedSegments")) { + tixi::TixiRemoveAttribute(tixiHandle, xpath, "roundedSegments"); + } + } + // write element name tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/name"); tixi::TixiSaveElement(tixiHandle, xpath + "/name", m_name); @@ -300,6 +315,16 @@ namespace generated m_symmetry = value; } + const boost::optional& CPACSWing::GetRoundedSegments() const + { + return m_roundedSegments; + } + + void CPACSWing::SetRoundedSegments(const boost::optional& value) + { + m_roundedSegments = value; + } + const std::string& CPACSWing::GetName() const { return m_name; diff --git a/src/generated/CPACSWing.h b/src/generated/CPACSWing.h index 11e06daac3..1a1522fa8e 100644 --- a/src/generated/CPACSWing.h +++ b/src/generated/CPACSWing.h @@ -127,6 +127,9 @@ namespace generated TIGL_EXPORT virtual const boost::optional& GetSymmetry() const; TIGL_EXPORT virtual void SetSymmetry(const boost::optional& value); + TIGL_EXPORT virtual const boost::optional& GetRoundedSegments() const; + TIGL_EXPORT virtual void SetRoundedSegments(const boost::optional& value); + TIGL_EXPORT virtual const std::string& GetName() const; TIGL_EXPORT virtual void SetName(const std::string& value); @@ -167,6 +170,11 @@ namespace generated boost::optional m_symmetry; + /// This attribute determines the lofting approach of this fuselage. + /// If set to true, a different lofting algorithm will be used allowing to specify rounding radii at each section which create a smooth transition between two segments. + /// This can be achieved e.g. by activating the approximation setting in the profile definitions. + boost::optional m_roundedSegments; + /// Name of the wing. std::string m_name; diff --git a/src/generated/CPACSWingSegment.cpp b/src/generated/CPACSWingSegment.cpp index 8b83c4a6f2..af215b7c61 100644 --- a/src/generated/CPACSWingSegment.cpp +++ b/src/generated/CPACSWingSegment.cpp @@ -152,6 +152,16 @@ namespace generated } } + // read element innerRoundingDistance + if (tixi::TixiCheckElement(tixiHandle, xpath + "/innerRoundingDistance")) { + m_innerRoundingDistance = tixi::TixiGetElement(tixiHandle, xpath + "/innerRoundingDistance"); + } + + // read element outerRoundingDistance + if (tixi::TixiCheckElement(tixiHandle, xpath + "/outerRoundingDistance")) { + m_outerRoundingDistance = tixi::TixiGetElement(tixiHandle, xpath + "/outerRoundingDistance"); + } + if (m_uidMgr && !m_uID.empty()) m_uidMgr->RegisterObject(m_uID, *this); } @@ -194,6 +204,28 @@ namespace generated } } + // write element innerRoundingDistance + if (m_innerRoundingDistance) { + tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/innerRoundingDistance"); + tixi::TixiSaveElement(tixiHandle, xpath + "/innerRoundingDistance", *m_innerRoundingDistance); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/innerRoundingDistance")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/innerRoundingDistance"); + } + } + + // write element outerRoundingDistance + if (m_outerRoundingDistance) { + tixi::TixiCreateElementIfNotExists(tixiHandle, xpath + "/outerRoundingDistance"); + tixi::TixiSaveElement(tixiHandle, xpath + "/outerRoundingDistance", *m_outerRoundingDistance); + } + else { + if (tixi::TixiCheckElement(tixiHandle, xpath + "/outerRoundingDistance")) { + tixi::TixiRemoveElement(tixiHandle, xpath + "/outerRoundingDistance"); + } + } + } const std::string& CPACSWingSegment::GetUID() const @@ -272,6 +304,26 @@ namespace generated return m_guideCurves; } + const boost::optional& CPACSWingSegment::GetInnerRoundingDistance() const + { + return m_innerRoundingDistance; + } + + void CPACSWingSegment::SetInnerRoundingDistance(const boost::optional& value) + { + m_innerRoundingDistance = value; + } + + const boost::optional& CPACSWingSegment::GetOuterRoundingDistance() const + { + return m_outerRoundingDistance; + } + + void CPACSWingSegment::SetOuterRoundingDistance(const boost::optional& value) + { + m_outerRoundingDistance = value; + } + CCPACSGuideCurves& CPACSWingSegment::GetGuideCurves(CreateIfNotExistsTag) { if (!m_guideCurves) diff --git a/src/generated/CPACSWingSegment.h b/src/generated/CPACSWingSegment.h index e7a2626533..a32f37619a 100644 --- a/src/generated/CPACSWingSegment.h +++ b/src/generated/CPACSWingSegment.h @@ -83,6 +83,12 @@ namespace generated TIGL_EXPORT virtual const boost::optional& GetGuideCurves() const; TIGL_EXPORT virtual boost::optional& GetGuideCurves(); + TIGL_EXPORT virtual const boost::optional& GetInnerRoundingDistance() const; + TIGL_EXPORT virtual void SetInnerRoundingDistance(const boost::optional& value); + + TIGL_EXPORT virtual const boost::optional& GetOuterRoundingDistance() const; + TIGL_EXPORT virtual void SetOuterRoundingDistance(const boost::optional& value); + TIGL_EXPORT virtual CCPACSGuideCurves& GetGuideCurves(CreateIfNotExistsTag); TIGL_EXPORT virtual void RemoveGuideCurves(); @@ -111,6 +117,12 @@ namespace generated /// the outer geometry. boost::optional m_guideCurves; + /// This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the inner end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + boost::optional m_innerRoundingDistance; + + /// This parameter only has an effect if the roundedSegments attribute in the fuselage/duct definition is set to true. It defines the blending distance at the outer end of this segment to create a smooth segment transition. The distance is provided in absolute length units. + boost::optional m_outerRoundingDistance; + private: TIGL_EXPORT const CTiglUIDObject* GetNextUIDObject() const final; TIGL_EXPORT void NotifyUIDChange(const std::string& oldUid, const std::string& newUid) final; From 623ff570884e5928a5e30389274ca0391144861d Mon Sep 17 00:00:00 2001 From: merakulix Date: Tue, 9 Jun 2026 14:13:46 +0200 Subject: [PATCH 20/44] change rounding distance type to std::vector --- src/geometry/CTiglRoundedSegmentSurface.cpp | 18 +++++------------- src/geometry/CTiglRoundedSegmentSurface.h | 8 ++++---- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index fa4c87da42..3cace13998 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -10,8 +10,8 @@ namespace tigl{ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , - double inner_rounding_distance, - double outer_rounding_distance, int u_degree, int v_degree): + std::vector inner_rounding_distance, + std::vector outer_rounding_distance, int u_degree, int v_degree): m_pole_matrix(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())), m_u_knots(1,m_profileCurves[0]->NbKnots()), m_v_knots(1, m_pole_matrix.ColLength()-v_degree+1), @@ -86,20 +86,12 @@ void CTiglRoundedSegmentSurface::Perform(){ calculateKnotsAndMultiplicities(); //initialize m_segments vector - m_segments.push_back(RoundedSegment(m_profileCurves[0], - m_profileCurves[1], - 0., //TODO access the right values per RoundedSegment later -> Put this line back in loop - m_outer_rounding_distance)); - for(int i = 1; i < m_profileCurves.size()-2; i++){ + for(int i = 0; i < m_profileCurves.size()-1; i++){ m_segments.push_back(RoundedSegment(m_profileCurves[i], m_profileCurves[i+1], - m_inner_rounding_distance, //TODO access the right values per RoundedSegment - m_outer_rounding_distance)); + m_inner_rounding_distance[i], //TODO access the right values per RoundedSegment + m_outer_rounding_distance[i])); } - m_segments.push_back(RoundedSegment(m_profileCurves[m_profileCurves.size()-2], - m_profileCurves[m_profileCurves.size()-1], - m_inner_rounding_distance, //TODO access the right values per RoundedSegment later -> Put this line back in loop - 0.)); //Write poles in pole matrix int row=1; //counter for inserted rows diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 11b97f182d..b03c4f19c4 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -12,8 +12,8 @@ class CTiglRoundedSegmentSurface { public: TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, - double inner_rounding_distance, - double outer_rounding_distance, + std::vector inner_rounding_distance, + std::vector outer_rounding_distance, int u_degree = 3, int v_degree = 3); @@ -148,8 +148,8 @@ class CTiglRoundedSegmentSurface TColStd_HArray1OfInteger m_v_multiplicities; //Storage of inner and outer rounding distance per segment - double m_inner_rounding_distance; - double m_outer_rounding_distance; + std::vector m_inner_rounding_distance; + std::vector m_outer_rounding_distance; // Store as B-spline curves internally (after conversion) std::vector m_profileCurves; //Vector contains 1 edge per profile Wire, loft ist build edgewise From 30c4c01a9912e8db244016a0d703b568fabafa13 Mon Sep 17 00:00:00 2001 From: merakulix Date: Tue, 9 Jun 2026 15:53:27 +0200 Subject: [PATCH 21/44] add rounding distance as a member to provide information for roundedSegment lofting algorithm --- src/geometry/CTiglMakeLoft.cpp | 8 ++++++++ src/geometry/CTiglMakeLoft.h | 24 ++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index b30ace58d1..9d63b3de0c 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -93,6 +93,14 @@ void CTiglMakeLoft::addProfiles(const TopoDS_Shape &profiles) } } +void CTiglMakeLoft::addInnerRoundingDistance(const double innerRoundingDistance){ + m_innerRoundingDistance.push_back(innerRoundingDistance); +} + +void CTiglMakeLoft::addOuterRoundingDistance(const double outerRoundingDistance){ + m_outerRoundingDistance.push_back(outerRoundingDistance); +} + void CTiglMakeLoft::addGuides(const TopoDS_Shape &guides) { if (guides.ShapeType() == TopAbs_COMPOUND) { diff --git a/src/geometry/CTiglMakeLoft.h b/src/geometry/CTiglMakeLoft.h index cc0273f85c..31f245da05 100644 --- a/src/geometry/CTiglMakeLoft.h +++ b/src/geometry/CTiglMakeLoft.h @@ -38,11 +38,29 @@ class CTiglMakeLoft /** * @brief Should be called to add sections/profiles to the algorithm. - * * @param profiles A shape that is either a wire or a compound consisting of multiple wires. */ TIGL_EXPORT void addProfiles(const TopoDS_Shape& profiles); - + + /** + * @brief If the class is used to create a loft with rounded segments, you can add + * inner/outer rounding distances as a vector. Make sure to add a value for each + * segment. + * + * @param innerRoundingDistance This is a distance relative to 1. Make sure to + * provide a value for each segment. + */ + TIGL_EXPORT void addInnerRoundingDistance(const double innerRoundingDistance); + + /** + * @brief If the class is used to create a loft with rounded segments, you can add + * inner/outer rounding distances as a vector. Make sure to add a value for each + * segment. + * @param outerRoundingDistance This is a distance relative to 1. Make sure to + * provide a value for each segment. + */ + TIGL_EXPORT void addOuterRoundingDistance(const double outerRoundingDistance); + /** * This function may be called to add guide curves to * the lofting algo. The shape should be either a wire @@ -104,6 +122,8 @@ class CTiglMakeLoft double _mySameKnotTolerance; std::vector guides, profiles; std::vector uparams, vparams; + std::vector m_innerRoundingDistance; + std::vector m_outerRoundingDistance; bool _hasPerformed, _makeSolid; bool _makeSmooth = false; From 976861d3fe926e3d72619b90310b5f86b515f526 Mon Sep 17 00:00:00 2001 From: merakulix Date: Tue, 9 Jun 2026 17:28:47 +0200 Subject: [PATCH 22/44] integrate CTiglRoundedSegments --- src/geometry/CTiglMakeLoft.cpp | 67 ++++++++++++++++++++++++++++++++++ src/geometry/CTiglMakeLoft.h | 2 + 2 files changed, 69 insertions(+) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index 9d63b3de0c..8f068793c9 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -24,6 +24,7 @@ #include "CTiglBSplineAlgorithms.h" #include "CTiglCurvesToSurface.h" +#include "geometry/CTiglRoundedSegmentSurface.h" #include "CTiglPatchShell.h" #include "Debugging.h" #include "to_string.h" @@ -144,6 +145,8 @@ void CTiglMakeLoft::Perform() // to the loft with guides makeLoftWithGuides(); + } else if (m_innerRoundingDistance.size()>0|m_outerRoundingDistance.size()>0){ + makeLoftWithRoundedSegments(); } else { makeLoftWithoutGuides(); @@ -161,6 +164,70 @@ void CTiglMakeLoft::setMakeSmooth(bool enabled) _makeSmooth = enabled; } +void CTiglMakeLoft::makeLoftWithRoundedSegments(){ + //check if there are both rounding distances defined for each segment + if(!(m_innerRoundingDistance.size() edgeCountPerProfile; + for (const auto& profile : profiles) { + edgeCountPerProfile.push_back(GetNumberOfEdges(profile)); + } + if (!AllSame(edgeCountPerProfile.begin(), edgeCountPerProfile.end())) { + throw tigl::CTiglError("Number of edges not equal in CTiglMakeLoft"); + } + + TopoDS_Shell faces; + BRep_Builder builder; + builder.MakeShell(faces); + + // get number of edges per profile wire + // --> should be the same for all profiles + TopTools_IndexedMapOfShape firstProfileMap; + TopExp::MapShapes(profiles[0], TopAbs_EDGE, firstProfileMap); + int const nEdgesPerProfile = firstProfileMap.Extent(); + + // skin the surface edge by adge + // CAUTION: Here it is assumed that the edges are ordered + // in the same way along each profile (e.g. lower edge, + // upper edge, trailing edge for a wing) + for ( int iE = 1; iE <= nEdgesPerProfile; ++iE ) { + + // get the curves + std::vector profileCurves; + profileCurves.reserve(profiles.size()); + for (unsigned iP=0; iP= iE ); + + TopoDS_Edge edge = TopoDS::Edge(profileMap(iE)); + profileCurves.push_back(GetBSplineCurve(edge)); + } + + + // skin the curves + tigl::CTiglRoundedSegmentSurface surfaceSkinner(profileCurves, m_innerRoundingDistance, m_outerRoundingDistance); + Handle(Geom_BSplineSurface) surface = surfaceSkinner.Surface(); + + // remember the profile parameters used for the skinning + + builder.Add(faces, BRepBuilderAPI_MakeFace(surface, 1e-6).Face()); + } + _result = tigl::CTiglTopoAlgorithms::CutShellAtUVParameters(faces, {}, vparams); + + // make sure the order is the same as for the COONS Patch algorithm + _result = ResortFaces(_result, nEdgesPerProfile, static_cast(vparams.size()-1)); + _result = tigl::CTiglTopoAlgorithms::CutShellAtKinks(_result); + CloseShape(); +} + /** * @brief Builds the loft using profiles and guide curves */ diff --git a/src/geometry/CTiglMakeLoft.h b/src/geometry/CTiglMakeLoft.h index 31f245da05..593707f1fa 100644 --- a/src/geometry/CTiglMakeLoft.h +++ b/src/geometry/CTiglMakeLoft.h @@ -96,6 +96,8 @@ class CTiglMakeLoft TIGL_EXPORT void Perform(); private: + + void makeLoftWithRoundedSegments(); void makeLoftWithGuides(); void makeLoftWithoutGuides(); From 0fa3274c5952c0ce0d2755171031276278e16754 Mon Sep 17 00:00:00 2001 From: merakulix Date: Tue, 9 Jun 2026 17:30:05 +0200 Subject: [PATCH 23/44] remove whitespace --- src/geometry/CTiglRoundedSegmentSurface.cpp | 2 +- src/geometry/CTiglRoundedSegmentSurface.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 3cace13998..adb2ad3198 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -9,7 +9,7 @@ namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , std::vector inner_rounding_distance, std::vector outer_rounding_distance, int u_degree, int v_degree): m_pole_matrix(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())), diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index b03c4f19c4..b16d0a71ef 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -11,7 +11,7 @@ namespace tigl { class CTiglRoundedSegmentSurface { public: - TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, + TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, std::vector inner_rounding_distance, std::vector outer_rounding_distance, int u_degree = 3, From 21d8f53d4f92286afcdfbd28d823be935db07a20 Mon Sep 17 00:00:00 2001 From: merakulix Date: Wed, 10 Jun 2026 13:28:02 +0200 Subject: [PATCH 24/44] update docstrings and complete lofting function --- src/geometry/CTiglMakeLoft.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index 8f068793c9..32efc70eb3 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -145,7 +145,7 @@ void CTiglMakeLoft::Perform() // to the loft with guides makeLoftWithGuides(); - } else if (m_innerRoundingDistance.size()>0|m_outerRoundingDistance.size()>0){ + } else if (m_innerRoundingDistance.size()>0&&m_outerRoundingDistance.size()>0){ makeLoftWithRoundedSegments(); } else { @@ -368,11 +368,7 @@ void CTiglMakeLoft::makeLoftWithoutGuides() builder.Add(faces, BRepBuilderAPI_MakeFace(surface, 1e-6).Face()); } - _result = tigl::CTiglTopoAlgorithms::CutShellAtUVParameters(faces, {}, vparams); - - // make sure the order is the same as for the COONS Patch algorithm - _result = ResortFaces(_result, nEdgesPerProfile, static_cast(vparams.size()-1)); - _result = tigl::CTiglTopoAlgorithms::CutShellAtKinks(_result); + _result = faces; CloseShape(); } From 6268750accec32e054d70c4e99ab1974dfc6c885 Mon Sep 17 00:00:00 2001 From: merakulix Date: Wed, 10 Jun 2026 13:28:51 +0200 Subject: [PATCH 25/44] update docstrings and complete lofting function --- src/geometry/CTiglMakeLoft.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.h b/src/geometry/CTiglMakeLoft.h index 593707f1fa..dba7cd8f03 100644 --- a/src/geometry/CTiglMakeLoft.h +++ b/src/geometry/CTiglMakeLoft.h @@ -45,7 +45,7 @@ class CTiglMakeLoft /** * @brief If the class is used to create a loft with rounded segments, you can add * inner/outer rounding distances as a vector. Make sure to add a value for each - * segment. + * segment. If no rounding distance is given, add '0.' * * @param innerRoundingDistance This is a distance relative to 1. Make sure to * provide a value for each segment. @@ -55,7 +55,7 @@ class CTiglMakeLoft /** * @brief If the class is used to create a loft with rounded segments, you can add * inner/outer rounding distances as a vector. Make sure to add a value for each - * segment. + * segment. If no rounding distance is given, add '0.' * @param outerRoundingDistance This is a distance relative to 1. Make sure to * provide a value for each segment. */ From 52afaba4a701df35c9d53e7030f79a345a836d49 Mon Sep 17 00:00:00 2001 From: merakulix Date: Wed, 10 Jun 2026 13:29:59 +0200 Subject: [PATCH 26/44] integrate rounded segment lofting --- src/geometry/CTiglRoundedSegmentSurface.cpp | 12 +----------- src/wing/CTiglWingBuilder.cpp | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index adb2ad3198..daababe685 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -26,17 +26,7 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector= 2 UKnots(i) < UKnots(i+1) (Knots are increasing) 1 <= UMults(i) <= UDegree - * On a non uperiodic surface the first and last umultiplicities may be UDegree+1 - * (this is even recommended if you want the curve to start and finish on the first and last pole). - * On a uperiodic surface the first and the last umultiplicities must be the same. on non-uperiodic surfaces Poles. - * ColLength() == Sum(UMults(i)) - UDegree - 1 >= 2 on uperiodic surfaces Poles.ColLength() == Sum(UMults(i)) - * except the first or last The previous conditions for U holds also for V, with the RowLength of the poles. - */ + Perform(); diff --git a/src/wing/CTiglWingBuilder.cpp b/src/wing/CTiglWingBuilder.cpp index d3b8090e37..86ecc5d8d6 100644 --- a/src/wing/CTiglWingBuilder.cpp +++ b/src/wing/CTiglWingBuilder.cpp @@ -64,10 +64,28 @@ PNamedShape CTiglWingBuilder::BuildShape() for (int i=1; i <= segments.GetSegmentCount(); i++) { const TopoDS_Shape& startWire = segments.GetSegment(i).GetInnerWire(); + if (hasBluntTE != segments.GetSegment(i).GetInnerConnection().GetProfile().HasBluntTE()) { throw CTiglError("Cannot mix profiles with blunt and sharp trailing edges in one wing.", TIGL_ERROR); } lofter.addProfiles(startWire); + + //Check if Segments are rounded, if so add distances to lofter + if(_wing.GetRoundedSegments()){ + double ird,ord; + if(segments.GetSegment(i).GetInnerRoundingDistance()){ + ird = *segments.GetSegment(i).GetInnerRoundingDistance(); + lofter.addInnerRoundingDistance(ird); + } else { + lofter.addInnerRoundingDistance(0.); + } + if(segments.GetSegment(i).GetOuterRoundingDistance()){ + ord = *segments.GetSegment(i).GetOuterRoundingDistance(); + lofter.addOuterRoundingDistance(ord); + } else { + lofter.addOuterRoundingDistance(0.); + } + } } TopoDS_Wire endWire = segments.GetSegment(segments.GetSegmentCount()).GetOuterWire(); From 7a05b6bb1b2f55cfffb91d3dea482558e32270df Mon Sep 17 00:00:00 2001 From: merakulix Date: Wed, 10 Jun 2026 17:11:02 +0200 Subject: [PATCH 27/44] add test for .xml file --- .../TestCTiglRoundedSegmentSurface.cpp | 200 ++++++++++-------- 1 file changed, 110 insertions(+), 90 deletions(-) diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index b8b96a1efd..6060ac0fc6 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -27,102 +27,95 @@ #include "CCPACSCurvePointListXYZ.h" #include "CCPACSCurveParamPointMap.h" -class TestCTiglRoundedSegmentSurface : public ::testing::Test + +TEST(TestCTiglRoundedSegmentSurface, make_minimal_Shape) { -protected: - - void SetUp() override - { - //Create Profile Curves Vector - TColgp_HArray1OfPnt u_poles(1,7); - u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - TColgp_HArray1OfPnt u1_poles(1,7); - u1_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u1_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u1_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u1_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u1_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u1_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u1_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - TColgp_HArray1OfPnt u2_poles(1,7); - u2_poles.SetValue(1,gp_Pnt(1., 0., 0.)); - u2_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); - u2_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); - u2_poles.SetValue(4,gp_Pnt(0., 0., 0.)); - u2_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); - u2_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); - u2_poles.SetValue(7,gp_Pnt(1., 0., 0.)); - - - TColStd_Array1OfReal u_knots(1,3); - u_knots.SetValue(1,-1.); - u_knots.SetValue(2,0.); - u_knots.SetValue(3,1.); - - TColStd_Array1OfInteger u_mults(1,3); - u_mults.SetValue(1,4); - u_mults.SetValue(2,3); - u_mults.SetValue(3,4); - - int u_degree = 3; - - //Create three profiles for the loft - auto profile_root = new Geom_BSplineCurve(u_poles, u_knots, u_mults, u_degree); - profileCurves.push_back(profile_root); - - Handle(Geom_BSplineCurve) profile_mid = new Geom_BSplineCurve(u1_poles, u_knots, u_mults, u_degree); - //Scale by (0.66,1.,0.66) Translate by (0.2,0.5,0.) - for(int i= 1; i< profile_root->NbPoles() + 1;i++){ - double X = profile_mid->Poles().Value(i).Coord().X()*0.66+0.2; - double Y = profile_mid->Poles().Value(i).Coord().Y()*1.+0.5; - double Z = profile_mid->Poles().Value(i).Coord().Z()*0.66+0.; - gp_Pnt transformed_pole(X,Y,Z); - profile_mid->SetPole(i,transformed_pole); - } - - profileCurves.push_back(profile_mid); - - Handle(Geom_BSplineCurve) profile_tip = new Geom_BSplineCurve(u2_poles, u_knots, u_mults, u_degree); - //Scale by (0.2,1.,0.1) Translate by (1.,2.,0.) - for(int i= 1; i< profile_root->NbPoles() + 1;i++){ - double X = profile_tip->Poles().Value(i).Coord().X()*0.2+1.; - double Y = profile_tip->Poles().Value(i).Coord().Y()*1.+2.; - double Z = profile_tip->Poles().Value(i).Coord().Z()*0.1+0.; - gp_Pnt transformed_pole(X,Y,Z); - profile_tip->SetPole(i,transformed_pole); - } - - profileCurves.push_back(profile_tip); - - for(int i=0; i profileCurves; + //Create Profile Curves Vector + TColgp_HArray1OfPnt u_poles(1,7); + u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u1_poles(1,7); + u1_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u1_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u1_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u1_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u1_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u1_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u1_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + TColgp_HArray1OfPnt u2_poles(1,7); + u2_poles.SetValue(1,gp_Pnt(1., 0., 0.)); + u2_poles.SetValue(2,gp_Pnt(0.66, 0., -0.015)); + u2_poles.SetValue(3,gp_Pnt(0., 0., -0.1)); + u2_poles.SetValue(4,gp_Pnt(0., 0., 0.)); + u2_poles.SetValue(5,gp_Pnt(0., 0., 0.1)); + u2_poles.SetValue(6,gp_Pnt(0.33, 0., 0.05)); + u2_poles.SetValue(7,gp_Pnt(1., 0., 0.)); + + + TColStd_Array1OfReal u_knots(1,3); + u_knots.SetValue(1,-1.); + u_knots.SetValue(2,0.); + u_knots.SetValue(3,1.); + + TColStd_Array1OfInteger u_mults(1,3); + u_mults.SetValue(1,4); + u_mults.SetValue(2,3); + u_mults.SetValue(3,4); + + int u_degree = 3; + + //Create three profiles for the loft + auto profile_root = new Geom_BSplineCurve(u_poles, u_knots, u_mults, u_degree); + profileCurves.push_back(profile_root); + + Handle(Geom_BSplineCurve) profile_mid = new Geom_BSplineCurve(u1_poles, u_knots, u_mults, u_degree); + //Scale by (0.66,1.,0.66) Translate by (0.2,0.5,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_mid->Poles().Value(i).Coord().X()*0.66+0.2; + double Y = profile_mid->Poles().Value(i).Coord().Y()*1.+0.5; + double Z = profile_mid->Poles().Value(i).Coord().Z()*0.66+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_mid->SetPole(i,transformed_pole); } - std::vector profileCurves; + profileCurves.push_back(profile_mid); -}; + Handle(Geom_BSplineCurve) profile_tip = new Geom_BSplineCurve(u2_poles, u_knots, u_mults, u_degree); + //Scale by (0.2,1.,0.1) Translate by (1.,2.,0.) + for(int i= 1; i< profile_root->NbPoles() + 1;i++){ + double X = profile_tip->Poles().Value(i).Coord().X()*0.2+1.; + double Y = profile_tip->Poles().Value(i).Coord().Y()*1.+2.; + double Z = profile_tip->Poles().Value(i).Coord().Z()*0.1+0.; + gp_Pnt transformed_pole(X,Y,Z); + profile_tip->SetPole(i,transformed_pole); + } + profileCurves.push_back(profile_tip); + + for(int i=0; i ird; + std::vector ord; + ird.push_back(0.); + ord.push_back(0.); + for(int i=1; i< profileCurves.size()-1; i++){ + ird.push_back(0.25); + ord.push_back(0.25); + } + ird.push_back(0.); + ord.push_back(0.); -TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) -{ - double ird = 0.25; - double ord = 0.25; tigl::CTiglRoundedSegmentSurface lofter(profileCurves, ird, ord); auto surface = lofter.Surface(); // DEBUG DELETEME @@ -130,3 +123,30 @@ TEST_F(TestCTiglRoundedSegmentSurface, make_minimal_Shape) TopoDS_Shape surf = BRepBuilderAPI_MakeFace(handle_surface, 1e-15); tigl::dumpShape(surf, "makeLoftWing", "Surface",1); } + +TEST(TestCTiglRoundedSegmentSurface, openCpacsRoundedSegments){ + + const char* filename = "TestData/simpletest-roundedSegmentSurface.cpacs.xml"; + ReturnCode tixiRet; + TiglReturnCode tiglRet; + + TixiDocumentHandle tiglHandle = -1; + TiglCPACSConfigurationHandle tixiHandle = -1; + + + tiglHandle = -1; + tixiHandle = -1; + + tixiRet = tixiOpenDocument(filename, &tixiHandle); + ASSERT_TRUE (tixiRet == SUCCESS); + + tiglRet = tiglOpenCPACSConfiguration(tixiHandle, "", &tiglHandle); + ASSERT_TRUE(tiglRet == TIGL_SUCCESS); + + tigl::CCPACSConfigurationManager& manager = tigl::CCPACSConfigurationManager::GetInstance(); + tigl::CCPACSConfiguration& config = manager.GetConfiguration(tiglHandle); + auto wing = config.GetWing(1).GetLoftWithCutouts(); + tigl::dumpShape(wing, "makeLoftWing", "Surface",2); +} + + From abc5ae953b4dec4aa294fcd587f0fcba7b83f479 Mon Sep 17 00:00:00 2001 From: merakulix Date: Thu, 11 Jun 2026 15:58:30 +0200 Subject: [PATCH 28/44] integrate CTiglRoundedSegments for wing loft --- src/geometry/CTiglMakeLoft.cpp | 15 ++++--- src/geometry/CTiglRoundedSegmentSurface.cpp | 43 ++++++++++++++++----- src/geometry/CTiglRoundedSegmentSurface.h | 2 + 3 files changed, 45 insertions(+), 15 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index 32efc70eb3..98b4c43da8 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -166,10 +166,10 @@ void CTiglMakeLoft::setMakeSmooth(bool enabled) void CTiglMakeLoft::makeLoftWithRoundedSegments(){ //check if there are both rounding distances defined for each segment - if(!(m_innerRoundingDistance.size() profileCurves; @@ -208,13 +209,17 @@ void CTiglMakeLoft::makeLoftWithRoundedSegments(){ assert( profileMap.Extent() >= iE ); TopoDS_Edge edge = TopoDS::Edge(profileMap(iE)); - profileCurves.push_back(GetBSplineCurve(edge)); + profileCurves.push_back(GeomConvert::CurveToBSplineCurve(GetBSplineCurve(edge))); } + // CHECK!!! MAYBE create a common knot vector for profileCurves + std::vector compatibleProfileCurves = tigl::CTiglBSplineAlgorithms::createCommonKnotsVectorCurve(profileCurves, 1e-14); // skin the curves - tigl::CTiglRoundedSegmentSurface surfaceSkinner(profileCurves, m_innerRoundingDistance, m_outerRoundingDistance); + tigl::CTiglRoundedSegmentSurface surfaceSkinner(compatibleProfileCurves, m_innerRoundingDistance, m_outerRoundingDistance); Handle(Geom_BSplineSurface) surface = surfaceSkinner.Surface(); + TopoDS_Shape surf = BRepBuilderAPI_MakeFace(surface, 1e-15); + tigl::dumpShape(surf, "makeLoftWing", "CTiglMakeLoftSurfaceNo",iE); // remember the profile parameters used for the skinning diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index daababe685..1a851ea914 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -36,10 +36,10 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ for(int col=1; col i_poles(1,m); - std::cerr<< "Column:" << col << std::endl; + // std::cerr<< "Column:" << col << std::endl; for(int i=1; i < m+1; i++){ i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; + // std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; } auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); @@ -47,10 +47,10 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ } for(int row=1; row i_poles(1,n); - std::cerr<< "Row:" << row << std::endl; + // std::cerr<< "Row:" << row << std::endl; for(int i=1; i < n+1; i++){ i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); - std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; + // std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; } auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); @@ -73,6 +73,20 @@ void CTiglRoundedSegmentSurface::Perform(){ if (_hasPerformed) { return; } + + + std::cerr << "Dimensions:\nPolematrix:\nrows: " << m_pole_matrix.ColLength() + << "\ncol: " << m_pole_matrix.RowLength() + << "\n v_knot number: " << m_v_knots.Length() + << "\n u_knot number: " << m_u_knots.Length() + << "\n v_mults number: " << m_v_multiplicities.Length() + << "\n u_mults number: " << m_u_multiplicities.Length() <NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,seg.get_last_profile().Value(col)); } @@ -122,7 +137,15 @@ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ m_v_multiplicities.SetValue((nb_v_knots),4); //initialize knots in u-direction(copy from originial 1. profile curve fits all) m_u_knots = m_profileCurves[0]->Knots(); - m_u_multiplicities = m_profileCurves[0]->Multiplicities(); + std::cerr << "CalculateKnots :number of multiplicities" << m_u_multiplicities.Length() << std::endl; + if (m_u_multiplicities.Length()==2){ + std::cerr << "IF" << std::endl; +// m_u_multiplicities.SetValue(1,4); +// m_u_multiplicities.SetValue(2,4); + _u_degree =m_profileCurves[0]->Degree(); + } else { + m_u_multiplicities = m_profileCurves[0]->Multiplicities(); + } //MAYBE CHECK if(!(m_u_knots.Length()==m_u_multiplicities.Length())){ @@ -141,10 +164,10 @@ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ throw tigl::CTiglError("check knots"); } } - if(!(m_profileCurves[0]->NbPoles()==(m_profileCurves[0]->NbKnots()+2*4-_u_degree-1))){ - throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ - std::to_string(m_u_knots.Length())+"u_degree:"+std::to_string(_u_degree)); - } +// if(!(m_profileCurves[0]->NbPoles()==(m_profileCurves[0]->NbKnots()+2*3-_u_degree-1))){ +// throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ +// std::to_string(m_u_knots.Length())+"u_degree:"+std::to_string(_u_degree)); +// } if(!(m_pole_matrix.ColLength()==(nb_v_knots+2*3-_v_degree-1))){ throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" +std::to_string(m_pole_matrix.ColLength())+"v_degree:"+std::to_string(_v_degree)); diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index b16d0a71ef..673166bdb8 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -46,9 +46,11 @@ class CTiglRoundedSegmentSurface } if(inner_rounding_distance>1e-6){ insert_inner_rows(3); + std::cerr << "Struct inner rows:" << inner_rd << " " << outer_rd; } if(outer_rounding_distance>1e-6){ insert_outer_rows(3); + std::cerr << "Struct outer rows:" << inner_rd << " " << outer_rd; } } From 4c3ec9b7cb0e79a436dba5cc9639b80c0e8ac020 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Fri, 19 Jun 2026 11:24:00 +0200 Subject: [PATCH 29/44] change constructor signature --- src/geometry/CTiglMakeLoft.cpp | 8 ++--- src/geometry/CTiglRoundedSegmentSurface.cpp | 33 ++++++++++++------- src/geometry/CTiglRoundedSegmentSurface.h | 10 +++--- .../TestCTiglRoundedSegmentSurface.cpp | 2 +- 4 files changed, 30 insertions(+), 23 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index 98b4c43da8..c07e22d4ed 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -200,7 +200,7 @@ void CTiglMakeLoft::makeLoftWithRoundedSegments(){ std::cerr << "Creating surface No " << iE << std::endl; // get the curves - std::vector profileCurves; + std::vector profileCurves; profileCurves.reserve(profiles.size()); for (unsigned iP=0; iP= iE ); TopoDS_Edge edge = TopoDS::Edge(profileMap(iE)); - profileCurves.push_back(GeomConvert::CurveToBSplineCurve(GetBSplineCurve(edge))); + profileCurves.push_back(GetBSplineCurve(edge)); } // CHECK!!! MAYBE create a common knot vector for profileCurves - std::vector compatibleProfileCurves = tigl::CTiglBSplineAlgorithms::createCommonKnotsVectorCurve(profileCurves, 1e-14); + // std::vector compatibleProfileCurves = tigl::CTiglBSplineAlgorithms::createCommonKnotsVectorCurve(profileCurves, 1e-14); // skin the curves - tigl::CTiglRoundedSegmentSurface surfaceSkinner(compatibleProfileCurves, m_innerRoundingDistance, m_outerRoundingDistance); + tigl::CTiglRoundedSegmentSurface surfaceSkinner(profileCurves, m_innerRoundingDistance, m_outerRoundingDistance); Handle(Geom_BSplineSurface) surface = surfaceSkinner.Surface(); TopoDS_Shape surf = BRepBuilderAPI_MakeFace(surface, 1e-15); tigl::dumpShape(surf, "makeLoftWing", "CTiglMakeLoftSurfaceNo",iE); diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 1a851ea914..9f9be9a435 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -6,24 +6,33 @@ #include "TopTools_IndexedMapOfShape.hxx" #include "TopoDS_Edge.hxx" #include "tiglcommonfunctions.h" +#include +#include "CTiglBSplineAlgorithms.h" namespace tigl{ -CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &m_profileCurves , - std::vector inner_rounding_distance, - std::vector outer_rounding_distance, int u_degree, int v_degree): - m_pole_matrix(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())), - m_u_knots(1,m_profileCurves[0]->NbKnots()), - m_v_knots(1, m_pole_matrix.ColLength()-v_degree+1), - m_u_multiplicities(m_profileCurves[0]->Multiplicities()), - m_v_multiplicities(1, m_pole_matrix.ColLength()-v_degree+1, 1), +CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector &profileCurves , + const std::vector &inner_rounding_distance, + const std::vector &outer_rounding_distance): m_inner_rounding_distance(inner_rounding_distance), m_outer_rounding_distance(outer_rounding_distance), - m_profileCurves(m_profileCurves), m_segments({}), - m_surface(nullptr), - _u_degree(u_degree), - _v_degree(v_degree){} + m_surface(nullptr) + { + + m_profileCurves.reserve(profileCurves.size()); + for (std::vector::const_iterator curve_iter = profileCurves.begin(); curve_iter != profileCurves.end(); ++curve_iter) { + m_profileCurves.push_back(GeomConvert::CurveToBSplineCurve(*curve_iter)); + } + + CTiglBSplineAlgorithms::matchDegree(m_profileCurves); + + m_pole_matrix = TColgp_Array2OfPnt(1,m_profileCurves.size()+(m_profileCurves.size()-2)*6,1, (m_profileCurves[0]->NbPoles())); + m_u_knots = TColStd_Array1OfReal(1,m_profileCurves[0]->NbKnots()); + m_v_knots = TColStd_Array1OfReal(1, m_pole_matrix.ColLength()-_v_degree+1); + m_u_multiplicities = m_profileCurves[0]->Multiplicities(); + m_v_multiplicities= TColStd_HArray1OfInteger(1, m_pole_matrix.ColLength()-_v_degree+1, 1); +} TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 673166bdb8..9a6bc632c1 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -11,11 +11,9 @@ namespace tigl { class CTiglRoundedSegmentSurface { public: - TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, - std::vector inner_rounding_distance, - std::vector outer_rounding_distance, - int u_degree = 3, - int v_degree = 3); + TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, + const std::vector &inner_rounding_distance, + const std::vector &outer_rounding_distance); TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); @@ -141,7 +139,7 @@ class CTiglRoundedSegmentSurface private: // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction - TColgp_HArray2OfPnt m_pole_matrix; + TColgp_Array2OfPnt m_pole_matrix; TColStd_Array1OfReal m_u_knots; TColStd_Array1OfReal m_v_knots; diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 6060ac0fc6..44ebc5f8ac 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -30,7 +30,7 @@ TEST(TestCTiglRoundedSegmentSurface, make_minimal_Shape) { - std::vector profileCurves; + std::vector profileCurves; //Create Profile Curves Vector TColgp_HArray1OfPnt u_poles(1,7); u_poles.SetValue(1,gp_Pnt(1., 0., 0.)); From e206ac36a2c200a936c4ef98345364d9ffe62ff3 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Fri, 19 Jun 2026 11:34:24 +0200 Subject: [PATCH 30/44] update loop --- src/geometry/CTiglRoundedSegmentSurface.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 9f9be9a435..d51f959b48 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -21,8 +21,8 @@ CTiglRoundedSegmentSurface::CTiglRoundedSegmentSurface(const std::vector::const_iterator curve_iter = profileCurves.begin(); curve_iter != profileCurves.end(); ++curve_iter) { - m_profileCurves.push_back(GeomConvert::CurveToBSplineCurve(*curve_iter)); + for (Handle(Geom_Curve) curve : profileCurves) { + m_profileCurves.push_back(GeomConvert::CurveToBSplineCurve(curve)); } CTiglBSplineAlgorithms::matchDegree(m_profileCurves); From e922fdde0c918b30109ccbb27834e2a64a03f852 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Fri, 19 Jun 2026 14:25:24 +0200 Subject: [PATCH 31/44] add testfile --- ...simpletest-roundedSegmentSurface.cpacs.xml | 520 ++++++++++++++++++ 1 file changed, 520 insertions(+) create mode 100644 tests/TestData/simpletest-roundedSegmentSurface.cpacs.xml diff --git a/tests/TestData/simpletest-roundedSegmentSurface.cpacs.xml b/tests/TestData/simpletest-roundedSegmentSurface.cpacs.xml new file mode 100644 index 0000000000..369390f82e --- /dev/null +++ b/tests/TestData/simpletest-roundedSegmentSurface.cpacs.xml @@ -0,0 +1,520 @@ + + +
+ Cpacs2Test + 0.2.0 + + + 3.0 + Martin Siggel + Simple Wing for unit testing + 2012-10-09T15:12:47 + + + 3.0 + cpacs2to3 + Converted to cpacs 3.0 using cpacs2to3 - does not include structure update + 2018-01-15T09:22:57 + + +
+ + + + Cpacs2Test + + 1 + 1 + + 0 + 0 + 0 + + + + + name + description + + + 1.0 + 0.5 + 0.5 + + + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + + + +
+ D150_Fuselage_1Section1 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0 + 0 + 0 + + + + + D150_Fuselage_1Section1 + fuselageCircleProfileuID + + + 1.0 + 1.0 + 1.0 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ D150_Fuselage_1Section2 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0.5 + 0 + 0 + + + + + D150_Fuselage_1Section2 + fuselageCircleProfileuID + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ D150_Fuselage_1Section3 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0 + 0 + 0 + + + + + D150_Fuselage_1Section3 + fuselageCircleProfileuID + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ + + D150_Fuselage_1Positioning1 + -0.5 + 90 + 0 + D150_Fuselage_1Section1ID + + + D150_Fuselage_1Positioning3 + 2 + 90 + 0 + D150_Fuselage_1Section1ID + D150_Fuselage_1Section3ID + + + + + D150_Fuselage_1Segment2 + D150_Fuselage_1Section1IDElement1 + D150_Fuselage_1Section2IDElement1 + + + D150_Fuselage_1Segment3 + D150_Fuselage_1Section2IDElement1 + D150_Fuselage_1Section3IDElement1 + + +
+
+ + + Wing + SimpleFuselage + This wing has been generated to test CATIA2CPACS. + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + +
+ Cpacs2Test - Wing Section 1 + Cpacs2Test - Wing Section 1 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 1 Main Element + Cpacs2Test - Wing Section 1 Main Element + NACA0012 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ Cpacs2Test - Wing Section 2 + Cpacs2Test - Wing Section 2 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 2 Main Element + Cpacs2Test - Wing Section 2 Main Element + NACA0012 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ Cpacs2Test - Wing Section 3 + Cpacs2Test - Wing Section 3 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 3 Main Element + Cpacs2Test - Wing Section 3 Main Element + NACA0012 + + + 0.5 + 0.5 + 0.5 + + + 0 + 0 + 0 + + + 0.5 + 0 + 0 + + + + +
+
+ + + Cpacs2Test - Wing Section 1 Positioning + Cpacs2Test - Wing Section 1 Positioning + 0 + 0 + 0 + Cpacs2Test_Wing_Sec1 + + + Cpacs2Test - Wing Section 2 Positioning + Cpacs2Test - Wing Section 2 Positioning + 1 + 0 + 0 + Cpacs2Test_Wing_Sec1 + Cpacs2Test_Wing_Sec2 + + + Cpacs2Test - Wing Section 3 Positioning + Cpacs2Test - Wing Section 3 Positioning + 1 + 0 + 0 + Cpacs2Test_Wing_Sec2 + Cpacs2Test_Wing_Sec3 + + + + + Fuselage Segment from Cpacs2Test - Wing Section 1 Main Element to Cpacs2Test - Wing Section 2 Main Element + Fuselage Segment from Cpacs2Test - Wing Section 1 Main Element to Cpacs2Test - Wing Section 2 Main Element + Cpacs2Test_Wing_Sec1_El1 + Cpacs2Test_Wing_Sec2_El1 + 0.2 + + + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Cpacs2Test_Wing_Sec2_El1 + Cpacs2Test_Wing_Sec3_El1 + 0.3 + + + + + Wing_CS1 + Cpacs2Test_Wing_Sec1_El1 + Cpacs2Test_Wing_Sec3_El1 + + + + + MySkinMat + 0.0 + + + + + + + MyCellMat + 0.0 + + + + 0.8 + 0.8 + + + 1.0 + 1.0 + + + + 0 + WING_CS1 + + + 0 + WING_CS1 + + + + + 0.5 + WING_CS1 + + + 0.5 + WING_CS1 + + + + + + + + + MySkinMat + + + + + + +
+
+
+
+ + + + NACA0.00.00.12 + NACA 4 Series Profile + + 1.0;0.9875;0.975;0.9625;0.95;0.9375;0.925;0.9125;0.9;0.8875;0.875;0.8625;0.85;0.8375;0.825;0.8125;0.8;0.7875;0.775;0.7625;0.75;0.7375;0.725;0.7125;0.7;0.6875;0.675;0.6625;0.65;0.6375;0.625;0.6125;0.6;0.5875;0.575;0.5625;0.55;0.5375;0.525;0.5125;0.5;0.4875;0.475;0.4625;0.45;0.4375;0.425;0.4125;0.4;0.3875;0.375;0.3625;0.35;0.3375;0.325;0.3125;0.3;0.2875;0.275;0.2625;0.25;0.2375;0.225;0.2125;0.2;0.1875;0.175;0.1625;0.15;0.1375;0.125;0.1125;0.1;0.0875;0.075;0.0625;0.05;0.0375;0.025;0.0125;0.0;0.0125;0.025;0.0375;0.05;0.0625;0.075;0.0875;0.1;0.1125;0.125;0.1375;0.15;0.1625;0.175;0.1875;0.2;0.2125;0.225;0.2375;0.25;0.2625;0.275;0.2875;0.3;0.3125;0.325;0.3375;0.35;0.3625;0.375;0.3875;0.4;0.4125;0.425;0.4375;0.45;0.4625;0.475;0.4875;0.5;0.5125;0.525;0.5375;0.55;0.5625;0.575;0.5875;0.6;0.6125;0.625;0.6375;0.65;0.6625;0.675;0.6875;0.7;0.7125;0.725;0.7375;0.75;0.7625;0.775;0.7875;0.8;0.8125;0.825;0.8375;0.85;0.8625;0.875;0.8875;0.9;0.9125;0.925;0.9375;0.95;0.9625;0.975;0.9875;1.0 + 0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0 + -0.00126;-0.0030004180415;-0.00471438572941;-0.00640256842113;-0.00806559133343;-0.00970403933653;-0.0113184567357;-0.0129093470398;-0.0144771727147;-0.0160223549226;-0.0175452732434;-0.0190462653789;-0.0205256268372;-0.0219836105968;-0.0234204267471;-0.024836242105;-0.0262311798047;-0.0276053188583;-0.0289586936852;-0.0302912936071;-0.0316030623052;-0.0328938972373;-0.0341636490097;-0.0354121207001;-0.0366390671268;-0.0378441940595;-0.0390271573644;-0.0401875620783;-0.0413249614032;-0.042438855614;-0.043528690869;-0.0445938579126;-0.0456336906587;-0.04664746464;-0.0476343953088;-0.0485936361694;-0.0495242767241;-0.0504253402064;-0.0512957810767;-0.0521344822472;-0.0529402520006;-0.0537118205596;-0.0544478362583;-0.0551468612564;-0.0558073667285;-0.0564277274483;-0.0570062156697;-0.0575409941929;-0.0580301084765;-0.0584714776309;-0.0588628840933;-0.059201961739;-0.0594861821311;-0.0597128385384;-0.059879027262;-0.0599816256958;-0.060017266394;-0.059982306219;-0.05987278938;-0.0596844028137;-0.059412421875;-0.059051643633;-0.0585963041308;-0.0580399746271;-0.0573754299024;-0.0565944788455;-0.0556877432118;-0.054644363746;-0.0534516022043;-0.0520942903127;-0.0505540468987;-0.0488081315259;-0.0468277042382;-0.0445750655553;-0.0419990347204;-0.0390266537476;-0.0355468568262;-0.0313738751622;-0.0261471986426;-0.0189390266528;0.0;0.0189390266528;0.0261471986426;0.0313738751622;0.0355468568262;0.0390266537476;0.0419990347204;0.0445750655553;0.0468277042382;0.0488081315259;0.0505540468987;0.0520942903127;0.0534516022043;0.054644363746;0.0556877432118;0.0565944788455;0.0573754299024;0.0580399746271;0.0585963041308;0.059051643633;0.059412421875;0.0596844028137;0.05987278938;0.059982306219;0.060017266394;0.0599816256958;0.059879027262;0.0597128385384;0.0594861821311;0.059201961739;0.0588628840933;0.0584714776309;0.0580301084765;0.0575409941929;0.0570062156697;0.0564277274483;0.0558073667285;0.0551468612564;0.0544478362583;0.0537118205596;0.0529402520006;0.0521344822472;0.0512957810767;0.0504253402064;0.0495242767241;0.0485936361694;0.0476343953088;0.04664746464;0.0456336906587;0.0445938579126;0.043528690869;0.042438855614;0.0413249614032;0.0401875620783;0.0390271573644;0.0378441940595;0.0366390671268;0.0354121207001;0.0341636490097;0.0328938972373;0.0316030623052;0.0302912936071;0.0289586936852;0.0276053188583;0.0262311798047;0.024836242105;0.0234204267471;0.0219836105968;0.0205256268372;0.0190462653789;0.0175452732434;0.0160223549226;0.0144771727147;0.0129093470398;0.0113184567357;0.00970403933653;0.00806559133343;0.00640256842113;0.00471438572941;0.0030004180415;0.00126 + + + + + + Circle + Profile build up from set of Points on Circle where may Dimensions are 1..-1 + + 0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0 + 0.0;0.0774924206719;0.154518792808;0.230615870742;0.305325997695;0.378199858172;0.4487991802;0.516699371152;0.581492071288;0.642787609687;0.700217347767;0.753435896328;0.802123192755;0.84598642592;0.884761797177;0.91821610688;0.946148156876;0.968389960528;0.984807753012;0.995302795793;0.999811970449;0.998308158271;0.990800403365;0.977333858251;0.957989512315;0.932883704732;0.902167424781;0.866025403784;0.824675004109;0.778364911924;0.727373641573;0.672007860556;0.612600545193;0.549508978071;0.483112599297;0.413810724505;0.342020143326;0.268172612761;0.192712260548;0.116092914125;0.0387753712568;-0.0387753712568;-0.116092914125;-0.192712260548;-0.268172612761;-0.342020143326;-0.413810724505;-0.483112599297;-0.549508978071;-0.612600545193;-0.672007860556;-0.727373641573;-0.778364911924;-0.824675004109;-0.866025403784;-0.902167424781;-0.932883704732;-0.957989512315;-0.977333858251;-0.990800403365;-0.998308158271;-0.999811970449;-0.995302795793;-0.984807753012;-0.968389960528;-0.946148156876;-0.91821610688;-0.884761797177;-0.84598642592;-0.802123192755;-0.753435896328;-0.700217347767;-0.642787609687;-0.581492071288;-0.516699371152;-0.4487991802;-0.378199858172;-0.305325997695;-0.230615870742;-0.154518792808;-0.0774924206719;0.0 + 1.0;0.996992941168;0.987989849477;0.97304487058;0.952247885338;0.925723969269;0.893632640323;0.85616689953;0.813552070263;0.766044443119;0.713929734558;0.657521368569;0.597158591703;0.533204432802;0.466043519703;0.396079766039;0.323733942058;0.249441144058;0.173648177667;0.0968108707032;0.0193913317718;-0.0581448289105;-0.13533129975;-0.211703872229;-0.286803232711;-0.360177724805;-0.431386065681;-0.5;-0.565606875487;-0.627812124672;-0.686241637869;-0.740544013109;-0.790392669519;-0.835487811413;-0.875558231302;-0.910362940966;-0.939692620786;-0.963370878616;-0.981255310627;-0.993238357742;-0.999247952504;-0.999247952504;-0.993238357742;-0.981255310627;-0.963370878616;-0.939692620786;-0.910362940966;-0.875558231302;-0.835487811413;-0.790392669519;-0.740544013109;-0.686241637869;-0.627812124672;-0.565606875487;-0.5;-0.431386065681;-0.360177724805;-0.286803232711;-0.211703872229;-0.13533129975;-0.0581448289105;0.0193913317718;0.0968108707032;0.173648177667;0.249441144058;0.323733942058;0.396079766039;0.466043519703;0.533204432802;0.597158591703;0.657521368569;0.713929734558;0.766044443119;0.813552070263;0.85616689953;0.893632640323;0.925723969269;0.952247885338;0.97304487058;0.987989849477;0.996992941168;1.0 + + + + +
+ + + + halfCube + 10.0 + 1. + + + +
From da51db0d7d45f3bcb4e7bf699723ea1d824f6aa0 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Fri, 19 Jun 2026 14:37:06 +0200 Subject: [PATCH 32/44] restore deleted code --- src/geometry/CTiglMakeLoft.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index c07e22d4ed..a776f5b23b 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -373,6 +373,11 @@ void CTiglMakeLoft::makeLoftWithoutGuides() builder.Add(faces, BRepBuilderAPI_MakeFace(surface, 1e-6).Face()); } + _result = tigl::CTiglTopoAlgorithms::CutShellAtUVParameters(faces, {}, vparams); + + // make sure the order is the same as for the COONS Patch algorithm + _result = ResortFaces(_result, nEdgesPerProfile, static_cast(vparams.size()-1)); + _result = tigl::CTiglTopoAlgorithms::CutShellAtKinks(_result); _result = faces; CloseShape(); } From cd24e654963e1b4f13d99086d652069b33bc5c12 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 23 Jun 2026 15:51:54 +0200 Subject: [PATCH 33/44] add test-xml --- ...impletest-roundedSegmentSurface2.cpacs.xml | 573 ++++++++++++++++++ 1 file changed, 573 insertions(+) create mode 100644 tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml diff --git a/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml b/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml new file mode 100644 index 0000000000..21a05fc1bd --- /dev/null +++ b/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml @@ -0,0 +1,573 @@ + + +
+ Cpacs2Test + 0.2.0 + + + 3.0 + Martin Siggel + Simple Wing for unit testing + 2012-10-09T15:12:47 + + + 3.0 + cpacs2to3 + Converted to cpacs 3.0 using cpacs2to3 - does not include structure update + 2018-01-15T09:22:57 + + +
+ + + + Cpacs2Test + + 1 + 1 + + 0 + 0 + 0 + + + + + name + description + + + 1.0 + 0.5 + 0.5 + + + 0.0 + 0.0 + 0.0 + + + 0.0 + 0.0 + 0.0 + + + +
+ D150_Fuselage_1Section1 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0 + 0 + 0 + + + + + D150_Fuselage_1Section1 + fuselageCircleProfileuID + + + 1.0 + 1.0 + 1.0 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ D150_Fuselage_1Section2 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0.5 + 0 + 0 + + + + + D150_Fuselage_1Section2 + fuselageCircleProfileuID + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ D150_Fuselage_1Section3 + + + 1.0 + 1.0 + 1.0 + + + 0.0 + 0.0 + 0.0 + + + 0 + 0 + 0 + + + + + D150_Fuselage_1Section3 + fuselageCircleProfileuID + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ + + D150_Fuselage_1Positioning1 + -0.5 + 90 + 0 + D150_Fuselage_1Section1ID + + + D150_Fuselage_1Positioning3 + 2 + 90 + 0 + D150_Fuselage_1Section1ID + D150_Fuselage_1Section3ID + + + + + D150_Fuselage_1Segment2 + D150_Fuselage_1Section1IDElement1 + D150_Fuselage_1Section2IDElement1 + + + D150_Fuselage_1Segment3 + D150_Fuselage_1Section2IDElement1 + D150_Fuselage_1Section3IDElement1 + + +
+
+ + + Wing + SimpleFuselage + This wing has been generated to test CATIA2CPACS. + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + +
+ Cpacs2Test - Wing Section 1 + Cpacs2Test - Wing Section 1 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 1 Main Element + Cpacs2Test - Wing Section 1 Main Element + NACA0012 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ Cpacs2Test - Wing Section 2 + Cpacs2Test - Wing Section 2 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 2 Main Element + Cpacs2Test - Wing Section 2 Main Element + NACA0012 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + +
+
+ Cpacs2Test - Wing Section 3 + Cpacs2Test - Wing Section 3 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 3 Main Element + Cpacs2Test - Wing Section 3 Main Element + NACA0012 + + + 0.5 + 0.5 + 0.5 + + + 0 + 0 + 0 + + + 0.75 + 0.0 + 0 + + + + +
+
+ Cpacs2Test - Wing Section 4 + Cpacs2Test - Wing Section 4 + + + 1 + 1 + 1 + + + 0 + 0 + 0 + + + 0 + 0 + 0 + + + + + Cpacs2Test - Wing Section 4 Main Element + Cpacs2Test - Wing Section 4 Main Element + NACA0012 + + + 0.25 + 0.25 + 0.25 + + + 0 + 0 + 0 + + + 1.0 + 2.25 + 0.0 + + + + +
+
+ + + Cpacs2Test - Wing Section 1 Positioning + Cpacs2Test - Wing Section 1 Positioning + 0 + 0 + 0 + Cpacs2Test_Wing_Sec1 + + + Cpacs2Test - Wing Section 2 Positioning + Cpacs2Test - Wing Section 2 Positioning + 1 + 0 + 0 + Cpacs2Test_Wing_Sec1 + Cpacs2Test_Wing_Sec2 + + + Cpacs2Test - Wing Section 3 Positioning + Cpacs2Test - Wing Section 3 Positioning + 1 + 0 + 0 + Cpacs2Test_Wing_Sec2 + Cpacs2Test_Wing_Sec3 + + + + + Fuselage Segment from Cpacs2Test - Wing Section 1 Main Element to Cpacs2Test - Wing Section 2 Main Element + Fuselage Segment from Cpacs2Test - Wing Section 1 Main Element to Cpacs2Test - Wing Section 2 Main Element + Cpacs2Test_Wing_Sec1_El1 + Cpacs2Test_Wing_Sec2_El1 + 0.2 + + + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Cpacs2Test_Wing_Sec2_El1 + Cpacs2Test_Wing_Sec3_El1 + 0.3 + 0.2 + + + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Fuselage Segment from Cpacs2Test - Wing Section 2 Main Element to Cpacs2Test - Wing Section 3 Main Element + Cpacs2Test_Wing_Sec3_El1 + Cpacs2Test_Wing_Sec4_El1 + 0.3 + + + + + Wing_CS1 + Cpacs2Test_Wing_Sec1_El1 + Cpacs2Test_Wing_Sec3_El1 + + + + + MySkinMat + 0.0 + + + + + + + MyCellMat + 0.0 + + + + 0.8 + 0.8 + + + 1.0 + 1.0 + + + + 0 + WING_CS1 + + + 0 + WING_CS1 + + + + + 0.5 + WING_CS1 + + + 0.5 + WING_CS1 + + + + + + + + + MySkinMat + + + + + + +
+
+
+
+ + + + NACA0.00.00.12 + NACA 4 Series Profile + + 1.0;0.9875;0.975;0.9625;0.95;0.9375;0.925;0.9125;0.9;0.8875;0.875;0.8625;0.85;0.8375;0.825;0.8125;0.8;0.7875;0.775;0.7625;0.75;0.7375;0.725;0.7125;0.7;0.6875;0.675;0.6625;0.65;0.6375;0.625;0.6125;0.6;0.5875;0.575;0.5625;0.55;0.5375;0.525;0.5125;0.5;0.4875;0.475;0.4625;0.45;0.4375;0.425;0.4125;0.4;0.3875;0.375;0.3625;0.35;0.3375;0.325;0.3125;0.3;0.2875;0.275;0.2625;0.25;0.2375;0.225;0.2125;0.2;0.1875;0.175;0.1625;0.15;0.1375;0.125;0.1125;0.1;0.0875;0.075;0.0625;0.05;0.0375;0.025;0.0125;0.0;0.0125;0.025;0.0375;0.05;0.0625;0.075;0.0875;0.1;0.1125;0.125;0.1375;0.15;0.1625;0.175;0.1875;0.2;0.2125;0.225;0.2375;0.25;0.2625;0.275;0.2875;0.3;0.3125;0.325;0.3375;0.35;0.3625;0.375;0.3875;0.4;0.4125;0.425;0.4375;0.45;0.4625;0.475;0.4875;0.5;0.5125;0.525;0.5375;0.55;0.5625;0.575;0.5875;0.6;0.6125;0.625;0.6375;0.65;0.6625;0.675;0.6875;0.7;0.7125;0.725;0.7375;0.75;0.7625;0.775;0.7875;0.8;0.8125;0.825;0.8375;0.85;0.8625;0.875;0.8875;0.9;0.9125;0.925;0.9375;0.95;0.9625;0.975;0.9875;1.0 + 0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0 + -0.00126;-0.0030004180415;-0.00471438572941;-0.00640256842113;-0.00806559133343;-0.00970403933653;-0.0113184567357;-0.0129093470398;-0.0144771727147;-0.0160223549226;-0.0175452732434;-0.0190462653789;-0.0205256268372;-0.0219836105968;-0.0234204267471;-0.024836242105;-0.0262311798047;-0.0276053188583;-0.0289586936852;-0.0302912936071;-0.0316030623052;-0.0328938972373;-0.0341636490097;-0.0354121207001;-0.0366390671268;-0.0378441940595;-0.0390271573644;-0.0401875620783;-0.0413249614032;-0.042438855614;-0.043528690869;-0.0445938579126;-0.0456336906587;-0.04664746464;-0.0476343953088;-0.0485936361694;-0.0495242767241;-0.0504253402064;-0.0512957810767;-0.0521344822472;-0.0529402520006;-0.0537118205596;-0.0544478362583;-0.0551468612564;-0.0558073667285;-0.0564277274483;-0.0570062156697;-0.0575409941929;-0.0580301084765;-0.0584714776309;-0.0588628840933;-0.059201961739;-0.0594861821311;-0.0597128385384;-0.059879027262;-0.0599816256958;-0.060017266394;-0.059982306219;-0.05987278938;-0.0596844028137;-0.059412421875;-0.059051643633;-0.0585963041308;-0.0580399746271;-0.0573754299024;-0.0565944788455;-0.0556877432118;-0.054644363746;-0.0534516022043;-0.0520942903127;-0.0505540468987;-0.0488081315259;-0.0468277042382;-0.0445750655553;-0.0419990347204;-0.0390266537476;-0.0355468568262;-0.0313738751622;-0.0261471986426;-0.0189390266528;0.0;0.0189390266528;0.0261471986426;0.0313738751622;0.0355468568262;0.0390266537476;0.0419990347204;0.0445750655553;0.0468277042382;0.0488081315259;0.0505540468987;0.0520942903127;0.0534516022043;0.054644363746;0.0556877432118;0.0565944788455;0.0573754299024;0.0580399746271;0.0585963041308;0.059051643633;0.059412421875;0.0596844028137;0.05987278938;0.059982306219;0.060017266394;0.0599816256958;0.059879027262;0.0597128385384;0.0594861821311;0.059201961739;0.0588628840933;0.0584714776309;0.0580301084765;0.0575409941929;0.0570062156697;0.0564277274483;0.0558073667285;0.0551468612564;0.0544478362583;0.0537118205596;0.0529402520006;0.0521344822472;0.0512957810767;0.0504253402064;0.0495242767241;0.0485936361694;0.0476343953088;0.04664746464;0.0456336906587;0.0445938579126;0.043528690869;0.042438855614;0.0413249614032;0.0401875620783;0.0390271573644;0.0378441940595;0.0366390671268;0.0354121207001;0.0341636490097;0.0328938972373;0.0316030623052;0.0302912936071;0.0289586936852;0.0276053188583;0.0262311798047;0.024836242105;0.0234204267471;0.0219836105968;0.0205256268372;0.0190462653789;0.0175452732434;0.0160223549226;0.0144771727147;0.0129093470398;0.0113184567357;0.00970403933653;0.00806559133343;0.00640256842113;0.00471438572941;0.0030004180415;0.00126 + + + + + + Circle + Profile build up from set of Points on Circle where may Dimensions are 1..-1 + + 0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0;0.0 + 0.0;0.0774924206719;0.154518792808;0.230615870742;0.305325997695;0.378199858172;0.4487991802;0.516699371152;0.581492071288;0.642787609687;0.700217347767;0.753435896328;0.802123192755;0.84598642592;0.884761797177;0.91821610688;0.946148156876;0.968389960528;0.984807753012;0.995302795793;0.999811970449;0.998308158271;0.990800403365;0.977333858251;0.957989512315;0.932883704732;0.902167424781;0.866025403784;0.824675004109;0.778364911924;0.727373641573;0.672007860556;0.612600545193;0.549508978071;0.483112599297;0.413810724505;0.342020143326;0.268172612761;0.192712260548;0.116092914125;0.0387753712568;-0.0387753712568;-0.116092914125;-0.192712260548;-0.268172612761;-0.342020143326;-0.413810724505;-0.483112599297;-0.549508978071;-0.612600545193;-0.672007860556;-0.727373641573;-0.778364911924;-0.824675004109;-0.866025403784;-0.902167424781;-0.932883704732;-0.957989512315;-0.977333858251;-0.990800403365;-0.998308158271;-0.999811970449;-0.995302795793;-0.984807753012;-0.968389960528;-0.946148156876;-0.91821610688;-0.884761797177;-0.84598642592;-0.802123192755;-0.753435896328;-0.700217347767;-0.642787609687;-0.581492071288;-0.516699371152;-0.4487991802;-0.378199858172;-0.305325997695;-0.230615870742;-0.154518792808;-0.0774924206719;0.0 + 1.0;0.996992941168;0.987989849477;0.97304487058;0.952247885338;0.925723969269;0.893632640323;0.85616689953;0.813552070263;0.766044443119;0.713929734558;0.657521368569;0.597158591703;0.533204432802;0.466043519703;0.396079766039;0.323733942058;0.249441144058;0.173648177667;0.0968108707032;0.0193913317718;-0.0581448289105;-0.13533129975;-0.211703872229;-0.286803232711;-0.360177724805;-0.431386065681;-0.5;-0.565606875487;-0.627812124672;-0.686241637869;-0.740544013109;-0.790392669519;-0.835487811413;-0.875558231302;-0.910362940966;-0.939692620786;-0.963370878616;-0.981255310627;-0.993238357742;-0.999247952504;-0.999247952504;-0.993238357742;-0.981255310627;-0.963370878616;-0.939692620786;-0.910362940966;-0.875558231302;-0.835487811413;-0.790392669519;-0.740544013109;-0.686241637869;-0.627812124672;-0.565606875487;-0.5;-0.431386065681;-0.360177724805;-0.286803232711;-0.211703872229;-0.13533129975;-0.0581448289105;0.0193913317718;0.0968108707032;0.173648177667;0.249441144058;0.323733942058;0.396079766039;0.466043519703;0.533204432802;0.597158591703;0.657521368569;0.713929734558;0.766044443119;0.813552070263;0.85616689953;0.893632640323;0.925723969269;0.952247885338;0.97304487058;0.987989849477;0.996992941168;1.0 + + + + +
+ + + + halfCube + 10.0 + 1. + + + +
From b6a387254a3027cb96da0572953f66f4aa09e26d Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 23 Jun 2026 21:48:13 +0200 Subject: [PATCH 34/44] remove print debug and obsolete docstrings --- src/geometry/CTiglRoundedSegmentSurface.cpp | 84 +-------------------- src/geometry/CTiglRoundedSegmentSurface.h | 16 ---- 2 files changed, 1 insertion(+), 99 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index d51f959b48..05d4c738b0 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -38,42 +38,6 @@ TIGL_EXPORT Handle(Geom_BSplineSurface) CTiglRoundedSegmentSurface::Surface(){ Perform(); - - //BEGIN DEBUG DELETEME - int m = m_pole_matrix.ColLength(); - int n = m_pole_matrix.RowLength(); - - for(int col=1; col i_poles(1,m); - // std::cerr<< "Column:" << col << std::endl; - for(int i=1; i < m+1; i++){ - i_poles.SetValue(i,(m_pole_matrix.Value(i,col))); - // std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, m_v_knots, m_v_multiplicities, _v_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Edge",col); - } - for(int row=1; row i_poles(1,n); - // std::cerr<< "Row:" << row << std::endl; - for(int i=1; i < n+1; i++){ - i_poles.SetValue(i,(m_pole_matrix.Value(row,i))); - // std::cerr << "X:" << i_poles.Value(i).Coord().X() << "\t Y:" << i_poles.Value(i).Coord().Y() << "\t Z:" << i_poles.Value(i).Coord().Z() << std::endl; - } - auto spline = new Geom_BSplineCurve(i_poles, m_u_knots, m_u_multiplicities, _u_degree); - TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(spline); - tigl::dumpShape(edge,"makeLoftWing", "Row",row); - } - std::cerr << "Dimensions:\nPolematrix:\nrows: " << m_pole_matrix.ColLength() - << "\ncol: " << m_pole_matrix.RowLength() - << "\n v_knot number: " << m_v_knots.Length() - << "\n u_knot number: " << m_u_knots.Length() - << "\n v_mults number: " << m_v_multiplicities.Length() - << "\n u_mults number: " << m_u_multiplicities.Length() <NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,seg.get_first_profile().Value(col)); } row++; - std::cerr << row << std::endl; //DEBUG DELETEME for(TColgp_HArray1OfPnt profile: seg.getDummyProfiles()){ for( int col = 1;col< m_profileCurves[0]->NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,profile.Value(col)); } row++; - // std::cerr << row << "ROW: " << m_pole_matrix.ColLength() << std::endl; //DEBUG DELETEME } if(row==m_pole_matrix.ColLength()){ - // std::cerr << row << "ROW: " << m_pole_matrix.ColLength() << std::endl; //DEBUG DELETEME + for( int col = 1;col< m_profileCurves[0]->NbPoles()+1; col++){ m_pole_matrix.SetValue(row,col,seg.get_last_profile().Value(col)); } @@ -146,41 +94,11 @@ void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ m_v_multiplicities.SetValue((nb_v_knots),4); //initialize knots in u-direction(copy from originial 1. profile curve fits all) m_u_knots = m_profileCurves[0]->Knots(); - std::cerr << "CalculateKnots :number of multiplicities" << m_u_multiplicities.Length() << std::endl; if (m_u_multiplicities.Length()==2){ - std::cerr << "IF" << std::endl; -// m_u_multiplicities.SetValue(1,4); -// m_u_multiplicities.SetValue(2,4); _u_degree =m_profileCurves[0]->Degree(); } else { m_u_multiplicities = m_profileCurves[0]->Multiplicities(); } - - //MAYBE CHECK - if(!(m_u_knots.Length()==m_u_multiplicities.Length())){ - throw tigl::CTiglError("u_knots and mults number mismatch:("+std::to_string(m_u_knots.Length())+","+std::to_string(m_u_multiplicities.Length())+")"); - } - if(!(m_v_knots.Length()==m_v_multiplicities.Length())){ - throw tigl::CTiglError("v_knots and mults number mismatch:("+std::to_string(m_v_knots.Length())+","+std::to_string(m_v_multiplicities.Length())+")"); - } - for(int i = 1; i< m_u_knots.Length()-1;i++){ - if (!(m_u_knots.Value(i) < m_u_knots.Value(i+1))){ - throw tigl::CTiglError(""+std::to_string(m_u_knots.Value(i))+"i:"+std::to_string(i)+" check knots"+std::to_string(m_u_knots.Value(i+1))); - } - } - for(int i = 1; i< m_v_knots.Length()-1;i++){ - if (!(m_v_knots.Value(i) < m_v_knots.Value(i+1))){ - throw tigl::CTiglError("check knots"); - } - } -// if(!(m_profileCurves[0]->NbPoles()==(m_profileCurves[0]->NbKnots()+2*3-_u_degree-1))){ -// throw tigl::CTiglError("poles != knots- u_degree-1 Poles:"+std::to_string(m_profileCurves[0]->NbPoles())+"Knots:"+ -// std::to_string(m_u_knots.Length())+"u_degree:"+std::to_string(_u_degree)); -// } - if(!(m_pole_matrix.ColLength()==(nb_v_knots+2*3-_v_degree-1))){ - throw tigl::CTiglError("poles != knots- v_degree-1 Poles:"+std::to_string(nb_v_knots)+"Knots:" - +std::to_string(m_pole_matrix.ColLength())+"v_degree:"+std::to_string(_v_degree)); - } } } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 9a6bc632c1..15fbed98c7 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -117,24 +117,8 @@ class CTiglRoundedSegmentSurface }; - // Deduce required knot vector and multiplicies from pole matrix properties - //TODO: Add mathematical boundaries for required number of knots and multiplicities TIGL_EXPORT void calculateKnotsAndMultiplicities(); - /* - * @brief Creates a surface with rounded sections - Steps: Create Matrix that contains all poles of each profile curve and - Dummy-Profile-Curves that contain poles that are required to build the curve in v-Direction - TODO: Add mathematical description of the rounded segment curve building process - - i-th row represents a profile in u-direction - - j-th columnrepresents a curve in v-direction - - Steps: Retrieve poles from inner and outer profile - Calculate distance between poles, apply inner/outer rounding distance relative to number of dummy profile - store new poles and original poles all in one matrix - */ - - // Call required methods to initialize required values and build surface TIGL_EXPORT void Invalidate() { _hasPerformed = false; } private: From fe3b5fbbe4a2a76115a0131866d265d6bdeb078d Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Tue, 23 Jun 2026 22:27:33 +0200 Subject: [PATCH 35/44] update docstrings --- src/geometry/CTiglRoundedSegmentSurface.cpp | 41 +++++++++---------- src/geometry/CTiglRoundedSegmentSurface.h | 30 +++++++++----- .../TestCTiglRoundedSegmentSurface.cpp | 29 ++++++++++++- 3 files changed, 67 insertions(+), 33 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 05d4c738b0..0427f88358 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -47,13 +47,30 @@ void CTiglRoundedSegmentSurface::Perform(){ return; } - calculateKnotsAndMultiplicities(); + //create knots in v-direction + auto nb_v_knots = m_pole_matrix.ColLength()-_v_degree+1; + std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); + for(int i=1;iKnots(); + if (m_u_multiplicities.Length()==2){ + _u_degree =m_profileCurves[0]->Degree(); + } else { + m_u_multiplicities = m_profileCurves[0]->Multiplicities(); + } //initialize m_segments vector for(int i = 0; i < m_profileCurves.size()-1; i++){ m_segments.push_back(RoundedSegment(m_profileCurves[i], m_profileCurves[i+1], - m_inner_rounding_distance[i], //TODO access the right values per RoundedSegment + m_inner_rounding_distance[i], m_outer_rounding_distance[i])); } @@ -81,24 +98,4 @@ void CTiglRoundedSegmentSurface::Perform(){ _hasPerformed = true; } -void CTiglRoundedSegmentSurface::calculateKnotsAndMultiplicities(){ - //create knots in v-direction - //auto nb_v_knots = m_pole_matrix.ColLength()+_v_degree-5; - auto nb_v_knots = m_pole_matrix.ColLength()-_v_degree+1; - std::vector tmp_v = LinspaceWithBreaks(0., 1., nb_v_knots,{}); - for(int i=1;iKnots(); - if (m_u_multiplicities.Length()==2){ - _u_degree =m_profileCurves[0]->Degree(); - } else { - m_u_multiplicities = m_profileCurves[0]->Multiplicities(); - } -} - } diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 15fbed98c7..5b2083599a 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -11,6 +11,18 @@ namespace tigl { class CTiglRoundedSegmentSurface { public: + /** + * @brief CTiglRoundedSegmentSurface + * Surface skinning algorithm to create a loft for a given set of + * profile curves with rounded sections. + * @param m_profileCurves + * @param inner_rounding_distance Vector of numbers between 0.< 1. per section + * with a size of m_profileCurves.size()-2 + * (outer section has no inner rounding distance) + * @param outer_rounding_distance Vector of numbers between 0.< 1. per section + * with a size of m_profileCurves.size()-2 + * (inner section has no outer rounding distance) + */ TIGL_EXPORT CTiglRoundedSegmentSurface(const std::vector &m_profileCurves, const std::vector &inner_rounding_distance, const std::vector &outer_rounding_distance); @@ -18,8 +30,16 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT Handle(Geom_BSplineSurface) Surface(); private: + TIGL_EXPORT void Perform(); + + /** + * @brief The RoundedSegment class + * A Rounded Segment is a helper container for each segment of the surface to create. + * It gets two profile curves and two rounding distances, and creates a vector for + * the poles of each dummy-profile curve from this information. + */ struct RoundedSegment { TColgp_HArray1OfPnt firstProfile; @@ -44,16 +64,13 @@ class CTiglRoundedSegmentSurface } if(inner_rounding_distance>1e-6){ insert_inner_rows(3); - std::cerr << "Struct inner rows:" << inner_rd << " " << outer_rd; } if(outer_rounding_distance>1e-6){ insert_outer_rows(3); - std::cerr << "Struct outer rows:" << inner_rd << " " << outer_rd; } } void insert_inner_rows(int nb_dummies) { - int count =1; //DEBUG DELETEME for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); // for every profile point in start profile @@ -73,13 +90,10 @@ class CTiglRoundedSegmentSurface row->SetValue(j, new_pole_inner); } dummyProfiles.push_back(*row); - std::cerr << "Insert inner rows:" << count << std::endl; //DEBUG DELETEME - count ++; } } void insert_outer_rows(int nb_dummies) { - int count =1; //DEBUG DELETEME for (int i = 0; i < nb_dummies; i++) { auto row = new TColgp_HArray1OfPnt(1, firstProfile.Size()); for (int j=1; j < firstProfile.Size()+1; j++){ @@ -99,8 +113,6 @@ class CTiglRoundedSegmentSurface row->SetValue(j, new_pole_outer); } dummyProfiles.push_back(*row); - std::cerr << "Insert outers rows:" << count << std::endl; //DEBUG DELETEME - count ++; } } @@ -117,8 +129,6 @@ class CTiglRoundedSegmentSurface }; - TIGL_EXPORT void calculateKnotsAndMultiplicities(); - TIGL_EXPORT void Invalidate() { _hasPerformed = false; } private: diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 44ebc5f8ac..0a86cc062a 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -124,7 +124,7 @@ TEST(TestCTiglRoundedSegmentSurface, make_minimal_Shape) tigl::dumpShape(surf, "makeLoftWing", "Surface",1); } -TEST(TestCTiglRoundedSegmentSurface, openCpacsRoundedSegments){ +TEST(TestCTiglRoundedSegmentSurface, openCpacsTwoRoundedSegments){ const char* filename = "TestData/simpletest-roundedSegmentSurface.cpacs.xml"; ReturnCode tixiRet; @@ -147,6 +147,33 @@ TEST(TestCTiglRoundedSegmentSurface, openCpacsRoundedSegments){ tigl::CCPACSConfiguration& config = manager.GetConfiguration(tiglHandle); auto wing = config.GetWing(1).GetLoftWithCutouts(); tigl::dumpShape(wing, "makeLoftWing", "Surface",2); + // auto wing = config.GetWing(1).GetWingCleanShape(); + // ASSERT_TRUE(BRepCheck_Analyzer(wing.IsValid())); } +TEST(TestCTiglRoundedSegmentSurface, openCpacsThreeRoundedSegments3){ + + const char* filename = "TestData/simpletest-roundedSegmentSurface2.cpacs.xml"; + ReturnCode tixiRet; + TiglReturnCode tiglRet; + + TixiDocumentHandle tiglHandle = -1; + TiglCPACSConfigurationHandle tixiHandle = -1; + + + tiglHandle = -1; + tixiHandle = -1; + + tixiRet = tixiOpenDocument(filename, &tixiHandle); + ASSERT_TRUE (tixiRet == SUCCESS); + + tiglRet = tiglOpenCPACSConfiguration(tixiHandle, "", &tiglHandle); + ASSERT_TRUE(tiglRet == TIGL_SUCCESS); + + tigl::CCPACSConfigurationManager& manager = tigl::CCPACSConfigurationManager::GetInstance(); + tigl::CCPACSConfiguration& config = manager.GetConfiguration(tiglHandle); + auto wing = config.GetWing(1).GetLoftWithCutouts(); + // ASSERT_TRUE(BRepCheck_Analyzer(wing.IsValid())); + tigl::dumpShape(wing, "makeLoftWing", "Surface",3); +} From 8f77aa3719d751793df2e7c24880677736795b77 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Mon, 29 Jun 2026 13:59:58 +0200 Subject: [PATCH 36/44] update tests --- tests/unittests/TestCTiglRoundedSegmentSurface.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp index 0a86cc062a..a8b3b3de24 100644 --- a/tests/unittests/TestCTiglRoundedSegmentSurface.cpp +++ b/tests/unittests/TestCTiglRoundedSegmentSurface.cpp @@ -14,6 +14,7 @@ #include "CCPACSWing.h" #include +#include #include #include #include @@ -146,12 +147,11 @@ TEST(TestCTiglRoundedSegmentSurface, openCpacsTwoRoundedSegments){ tigl::CCPACSConfigurationManager& manager = tigl::CCPACSConfigurationManager::GetInstance(); tigl::CCPACSConfiguration& config = manager.GetConfiguration(tiglHandle); auto wing = config.GetWing(1).GetLoftWithCutouts(); - tigl::dumpShape(wing, "makeLoftWing", "Surface",2); - // auto wing = config.GetWing(1).GetWingCleanShape(); - // ASSERT_TRUE(BRepCheck_Analyzer(wing.IsValid())); + ASSERT_TRUE(BRepCheck_Analyzer(wing).IsValid()); } -TEST(TestCTiglRoundedSegmentSurface, openCpacsThreeRoundedSegments3){ + +TEST(TestCTiglRoundedSegmentSurface, openCpacsThreeRoundedSegments){ const char* filename = "TestData/simpletest-roundedSegmentSurface2.cpacs.xml"; ReturnCode tixiRet; @@ -173,7 +173,6 @@ TEST(TestCTiglRoundedSegmentSurface, openCpacsThreeRoundedSegments3){ tigl::CCPACSConfigurationManager& manager = tigl::CCPACSConfigurationManager::GetInstance(); tigl::CCPACSConfiguration& config = manager.GetConfiguration(tiglHandle); auto wing = config.GetWing(1).GetLoftWithCutouts(); - // ASSERT_TRUE(BRepCheck_Analyzer(wing.IsValid())); - tigl::dumpShape(wing, "makeLoftWing", "Surface",3); + ASSERT_TRUE(BRepCheck_Analyzer(wing).IsValid()); } From 2a38e1c5e6e8b20fba5247e440d5967a82a9a97d Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 1 Jul 2026 11:03:53 +0200 Subject: [PATCH 37/44] add check for rounding distance = 0 in inner segment --- src/geometry/CTiglRoundedSegmentSurface.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/geometry/CTiglRoundedSegmentSurface.cpp b/src/geometry/CTiglRoundedSegmentSurface.cpp index 0427f88358..987afef3f0 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.cpp +++ b/src/geometry/CTiglRoundedSegmentSurface.cpp @@ -95,6 +95,10 @@ void CTiglRoundedSegmentSurface::Perform(){ } } } + //Check if number of rows matches expected total number of profile curves + if (row Date: Wed, 1 Jul 2026 13:44:20 +0200 Subject: [PATCH 38/44] remove debug code --- src/geometry/CTiglMakeLoft.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index a776f5b23b..dc1cf3eed0 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -197,7 +197,6 @@ void CTiglMakeLoft::makeLoftWithRoundedSegments(){ // in the same way along each profile (e.g. lower edge, // upper edge, trailing edge for a wing) for ( int iE = 1; iE <= nEdgesPerProfile; ++iE ) { - std::cerr << "Creating surface No " << iE << std::endl; // get the curves std::vector profileCurves; @@ -218,8 +217,6 @@ void CTiglMakeLoft::makeLoftWithRoundedSegments(){ // skin the curves tigl::CTiglRoundedSegmentSurface surfaceSkinner(profileCurves, m_innerRoundingDistance, m_outerRoundingDistance); Handle(Geom_BSplineSurface) surface = surfaceSkinner.Surface(); - TopoDS_Shape surf = BRepBuilderAPI_MakeFace(surface, 1e-15); - tigl::dumpShape(surf, "makeLoftWing", "CTiglMakeLoftSurfaceNo",iE); // remember the profile parameters used for the skinning From 70b648ad38393d692459a160a0c0596dc08d6d74 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 1 Jul 2026 13:44:41 +0200 Subject: [PATCH 39/44] pix typo --- tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml b/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml index 21a05fc1bd..454b6e4516 100644 --- a/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml +++ b/tests/TestData/simpletest-roundedSegmentSurface2.cpacs.xml @@ -386,7 +386,7 @@ 0 0 - + 0 0 0 From 12e219d2919b4cb053d9e76ae3a817942855d750 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Mon, 6 Jul 2026 16:20:13 +0200 Subject: [PATCH 40/44] remove line --- src/geometry/CTiglMakeLoft.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index dc1cf3eed0..940d9f46ea 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -375,7 +375,6 @@ void CTiglMakeLoft::makeLoftWithoutGuides() // make sure the order is the same as for the COONS Patch algorithm _result = ResortFaces(_result, nEdgesPerProfile, static_cast(vparams.size()-1)); _result = tigl::CTiglTopoAlgorithms::CutShellAtKinks(_result); - _result = faces; CloseShape(); } From 77b0ec79f90aff25c20c76612e6a18a1c29df0cf Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 8 Jul 2026 16:53:14 +0200 Subject: [PATCH 41/44] add docstrings --- src/geometry/CTiglRoundedSegmentSurface.h | 42 ++++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/geometry/CTiglRoundedSegmentSurface.h b/src/geometry/CTiglRoundedSegmentSurface.h index 5b2083599a..373291430f 100644 --- a/src/geometry/CTiglRoundedSegmentSurface.h +++ b/src/geometry/CTiglRoundedSegmentSurface.h @@ -7,7 +7,13 @@ #include namespace tigl { - +/** + * @brief This class can be used to create a surface from a given set of profile curves, + * that is rounded in two seperate definable distances to each side of the profile: + * The 'innerRoundingDistance', and 'outerRoundingDistance' + * In case of an aircraft wing 'inner' refers to the direction from profile curve to fuselage, + * 'outer' refers to the direction from profile curve to wing tip. + */ class CTiglRoundedSegmentSurface { public: @@ -36,9 +42,12 @@ class CTiglRoundedSegmentSurface /** * @brief The RoundedSegment class - * A Rounded Segment is a helper container for each segment of the surface to create. - * It gets two profile curves and two rounding distances, and creates a vector for - * the poles of each dummy-profile curve from this information. + * A Rounded Segment is a helper container to simplify keeping the order of the profile + * and 'dummy-curves' when creating the required pole matrix for the lofting-algorithm. + * + * It represents one sement, with first and last profile and two rounding distances. + * From these parameters it takes care of creating the poles of 3 dummy-profile curves + * for each direction, 'inner' and 'outer', given they are greater than zero. */ struct RoundedSegment { @@ -132,21 +141,38 @@ class CTiglRoundedSegmentSurface TIGL_EXPORT void Invalidate() { _hasPerformed = false; } private: - // Rows represent profile curves (u-direction) and dummy curves, Columns define poles of curves in v-direction + // Rows represent the poles of the given profile curves (u-direction) and dummy curves + // Columns represent the poles of the curves in v-direction TColgp_Array2OfPnt m_pole_matrix; + // Knots and poles in u_direction are equal to the profile curves' knots and pole TColStd_Array1OfReal m_u_knots; + + // The knots are distributed linearly, the number of knots is calculated als follows: + // number of poles - curve degree + 1 + // This already takes into account: The number of multiplicities at the start + // and the end of the curve must be 4, else 1 + TColStd_Array1OfReal m_v_knots; + // Multiplicities in u_direction are equal to the profile curves' multiplicities TColStd_HArray1OfInteger m_u_multiplicities; + + // Multiplicites in v_direction are 4 at start and end of the curve, else 1 + // The number of multiplicities must be equal to the number of TColStd_HArray1OfInteger m_v_multiplicities; - //Storage of inner and outer rounding distance per segment + // Stores given inner and outer rounding distance per segment! + // This means: + // First Segment gets an inner rounding distance of 0. -> first entry in this list is 0. + // analogue: Last segment gets a outer rounding distance of 0. -> last entry in this list is 0. std::vector m_inner_rounding_distance; std::vector m_outer_rounding_distance; - // Store as B-spline curves internally (after conversion) - std::vector m_profileCurves; //Vector contains 1 edge per profile Wire, loft ist build edgewise + // The given profile curves (or list of edges of the profile curves) + std::vector m_profileCurves; + + // A list of rounded segments is used to create the pole_matrix std::vector m_segments; Handle(Geom_BSplineSurface) m_surface; From 4ad712b898a9e082ca6c95274f8a08f838909d6a Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 8 Jul 2026 17:27:38 +0200 Subject: [PATCH 42/44] add classes to python bindings --- bindings/python_internal/geometry.i | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bindings/python_internal/geometry.i b/bindings/python_internal/geometry.i index f9ee06ac36..06b9f800ed 100644 --- a/bindings/python_internal/geometry.i +++ b/bindings/python_internal/geometry.i @@ -73,6 +73,7 @@ #include "CTiglInterpolateCurveNetwork.h" #include "CTiglPointsToBSplineInterpolation.h" #include "CTiglCurvesToSurface.h" +#include "CTiglRoundedSegmentSurface.h" #include "CTiglIntersectBSplines.h" #include "CTiglInterpolatePointsWithKinks.h" #include "CTiglApproxResult.h" @@ -107,6 +108,7 @@ %include "CTiglPointsToBSplineInterpolation.h" %include "CTiglInterpolateCurveNetwork.h" %include "CTiglCurvesToSurface.h" +%include "CTiglRoundedSegmentSurface.h" %include "tiglcommonfunctions.h" %include "CTiglProjectOnLinearSpline.h" %include "CTiglMakeLoft.h" From 88d66b486a94cf94f2bc988228e5758de61395ad Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Wed, 8 Jul 2026 17:46:24 +0200 Subject: [PATCH 43/44] update changelog.md --- ChangeLog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ChangeLog.md b/ChangeLog.md index 0458b05e93..8208e2d406 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -5,6 +5,7 @@ Changes since last release ---------------- 2025/09/26 -General changes + - Add new lofting algorithm to create wing surfaces with rounded segments [#1284](https://github.com/DLR-SC/tigl/pull/1338) - TiGLCreator: Draw option menus are now updated when adding new wings or fuselages. - TiGLCreator: Bi-directional selection of shapes via the GUI or the CPACSTree is supported now [#1275](https://github.com/DLR-SC/tigl/issues/1275). - TIGLCreator: Use NACA profiles and standard profiles in the TIGLCreator templates ([#1367](https://github.com/DLR-SC/tigl/issues/1367)) From 9d7ea767213a1022be4ca2e3efce085cf1264c98 Mon Sep 17 00:00:00 2001 From: Meike Kobold Date: Thu, 6 Aug 2026 12:47:22 +0200 Subject: [PATCH 44/44] update setter function for rounding distances --- src/geometry/CTiglMakeLoft.cpp | 8 ++++---- src/geometry/CTiglMakeLoft.h | 16 ++++++++-------- src/wing/CTiglWingBuilder.cpp | 14 ++++++++++---- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/geometry/CTiglMakeLoft.cpp b/src/geometry/CTiglMakeLoft.cpp index 940d9f46ea..17596536cf 100644 --- a/src/geometry/CTiglMakeLoft.cpp +++ b/src/geometry/CTiglMakeLoft.cpp @@ -94,12 +94,12 @@ void CTiglMakeLoft::addProfiles(const TopoDS_Shape &profiles) } } -void CTiglMakeLoft::addInnerRoundingDistance(const double innerRoundingDistance){ - m_innerRoundingDistance.push_back(innerRoundingDistance); +void CTiglMakeLoft::setInnerRoundingDistance(std::vector innerRoundingDistance){ + m_innerRoundingDistance = innerRoundingDistance; } -void CTiglMakeLoft::addOuterRoundingDistance(const double outerRoundingDistance){ - m_outerRoundingDistance.push_back(outerRoundingDistance); +void CTiglMakeLoft::setOuterRoundingDistance(std::vector outerRoundingDistance){ + m_outerRoundingDistance = outerRoundingDistance; } void CTiglMakeLoft::addGuides(const TopoDS_Shape &guides) diff --git a/src/geometry/CTiglMakeLoft.h b/src/geometry/CTiglMakeLoft.h index dba7cd8f03..1913d5504d 100644 --- a/src/geometry/CTiglMakeLoft.h +++ b/src/geometry/CTiglMakeLoft.h @@ -45,21 +45,21 @@ class CTiglMakeLoft /** * @brief If the class is used to create a loft with rounded segments, you can add * inner/outer rounding distances as a vector. Make sure to add a value for each - * segment. If no rounding distance is given, add '0.' + * segment. If no rounding distance is given the value must be '0.' * - * @param innerRoundingDistance This is a distance relative to 1. Make sure to - * provide a value for each segment. + * @param innerRoundingDistance This is a set of distances relative to 1 + * for each segment of a surface. Make sure to provide a value for each segment. */ - TIGL_EXPORT void addInnerRoundingDistance(const double innerRoundingDistance); + TIGL_EXPORT void setInnerRoundingDistance(std::vector innerRoundingDistance); /** * @brief If the class is used to create a loft with rounded segments, you can add * inner/outer rounding distances as a vector. Make sure to add a value for each - * segment. If no rounding distance is given, add '0.' - * @param outerRoundingDistance This is a distance relative to 1. Make sure to - * provide a value for each segment. + * segment. If no rounding distance is given the value must be '0.' + * @param outerRoundingDistance This is a set of distances relative to 1 + * for each segment of a surface. Make sure to provide a value for each segment. */ - TIGL_EXPORT void addOuterRoundingDistance(const double outerRoundingDistance); + TIGL_EXPORT void setOuterRoundingDistance(std::vector outerRoundingDistance); /** * This function may be called to add guide curves to diff --git a/src/wing/CTiglWingBuilder.cpp b/src/wing/CTiglWingBuilder.cpp index 86ecc5d8d6..1bfa266f33 100644 --- a/src/wing/CTiglWingBuilder.cpp +++ b/src/wing/CTiglWingBuilder.cpp @@ -61,6 +61,8 @@ PNamedShape CTiglWingBuilder::BuildShape() CTiglMakeLoft lofter; lofter.setMakeSolid(true); + std::vector innerRoundingDistance; + std::vector outerRoundingDistance; for (int i=1; i <= segments.GetSegmentCount(); i++) { const TopoDS_Shape& startWire = segments.GetSegment(i).GetInnerWire(); @@ -75,17 +77,21 @@ PNamedShape CTiglWingBuilder::BuildShape() double ird,ord; if(segments.GetSegment(i).GetInnerRoundingDistance()){ ird = *segments.GetSegment(i).GetInnerRoundingDistance(); - lofter.addInnerRoundingDistance(ird); + innerRoundingDistance.push_back(ird); } else { - lofter.addInnerRoundingDistance(0.); + innerRoundingDistance.push_back(0.); } if(segments.GetSegment(i).GetOuterRoundingDistance()){ ord = *segments.GetSegment(i).GetOuterRoundingDistance(); - lofter.addOuterRoundingDistance(ord); + outerRoundingDistance.push_back(ord); } else { - lofter.addOuterRoundingDistance(0.); + outerRoundingDistance.push_back(0.); } } + + lofter.setInnerRoundingDistance(innerRoundingDistance); + lofter.setOuterRoundingDistance(outerRoundingDistance); + } TopoDS_Wire endWire = segments.GetSegment(segments.GetSegmentCount()).GetOuterWire();