From f9032cf2ee2110d4772e323f3d1004c8fa518ba3 Mon Sep 17 00:00:00 2001 From: jgv Date: Thu, 14 Nov 2013 12:37:05 +0400 Subject: [PATCH] 0024305: New option in BRepOffsetAPI_MakePipeShell algorithm: the swept shell with varying width of section bounded by auxiliary spine Test case for issue CR24305 --- src/BRepFill/BRepFill.cdl | 3 + src/BRepFill/BRepFill_PipeShell.cdl | 9 +- src/BRepFill/BRepFill_PipeShell.cxx | 94 ++++++++++++++++-- .../BRepOffsetAPI_MakePipeShell.cdl | 6 +- .../BRepOffsetAPI_MakePipeShell.cxx | 4 +- src/BRepTest/BRepTest_SweepCommands.cxx | 15 ++- src/GeomFill/GeomFill_GuideTrihedronAC.cxx | 3 + src/GeomFill/GeomFill_LocationGuide.cdl | 2 + src/GeomFill/GeomFill_LocationGuide.cxx | 99 ++++++++++++++----- src/GeomFill/GeomFill_TrihedronWithGuide.cdl | 9 +- src/GeomFill/GeomFill_TrihedronWithGuide.cxx | 8 ++ tests/bugs/modalg_5/bug24305 | 33 +++++++ 12 files changed, 241 insertions(+), 44 deletions(-) create mode 100755 tests/bugs/modalg_5/bug24305 diff --git a/src/BRepFill/BRepFill.cdl b/src/BRepFill/BRepFill.cdl index c7268f422c..7202152007 100755 --- a/src/BRepFill/BRepFill.cdl +++ b/src/BRepFill/BRepFill.cdl @@ -72,6 +72,9 @@ is enumeration TransitionStyle is Modified, Right, Round end; + enumeration TypeOfContact + is NoContact, Contact, ContactOnBorder end; + -- private class FilledPair; ---Purpose: A pair of bound shapes with the result. diff --git a/src/BRepFill/BRepFill_PipeShell.cdl b/src/BRepFill/BRepFill_PipeShell.cdl index 50018107ed..1056d60edf 100755 --- a/src/BRepFill/BRepFill_PipeShell.cdl +++ b/src/BRepFill/BRepFill_PipeShell.cdl @@ -41,8 +41,8 @@ uses Section from BRepFill, Sweep from BRepFill, DataMapOfShapeListOfShape from TopTools, - SequenceOfSection from BRepFill - + SequenceOfSection from BRepFill, + TypeOfContact from BRepFill raises DomainError from Standard, @@ -96,7 +96,7 @@ is Set(me : mutable; AuxiliarySpine : Wire from TopoDS; CurvilinearEquivalence : Boolean = Standard_True; - KeepContact : Boolean = Standard_False ); + KeepContact : TypeOfContact from BRepFill = BRepFill_NoContact ); ---Purpose: Set an auxiliary spine to define the Normal -- For each Point of the Spine P, an Point Q is evalued @@ -269,7 +269,7 @@ is param : out Real from Standard) is private; ResetLoc(me : mutable) is private; - + BuildHistory(me: mutable; theSweep: Sweep from BRepFill) is private; @@ -289,6 +289,7 @@ fields myForceApproxC1 : Boolean; myLaw : Function from Law; + myIsAutomaticLaw : Boolean from Standard; myLocation : LocationLaw from BRepFill; mySection : SectionLaw from BRepFill; myFaces : HArray2OfShape from TopTools; diff --git a/src/BRepFill/BRepFill_PipeShell.cxx b/src/BRepFill/BRepFill_PipeShell.cxx index e9aef4dc7a..fb2400aec0 100755 --- a/src/BRepFill/BRepFill_PipeShell.cxx +++ b/src/BRepFill/BRepFill_PipeShell.cxx @@ -75,6 +75,14 @@ #include +#include +#include +#include +#include +#include +#include +#include + #ifdef DRAW #include #include @@ -211,7 +219,8 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace, BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) : mySpine(Spine), myForceApproxC1(Standard_False), - myTrihedron(GeomFill_IsCorrectedFrenet), + myIsAutomaticLaw(Standard_False), + myTrihedron(GeomFill_IsCorrectedFrenet), myTransition(BRepFill_Modified), myStatus(GeomFill_PipeOk) { @@ -325,7 +334,7 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) //======================================================================= void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine, const Standard_Boolean CurvilinearEquivalence, - const Standard_Boolean KeepContact) + const BRepFill_TypeOfContact KeepContact) { // Reorganization of the guide (pb of orientation and origin) TopoDS_Wire TheGuide; @@ -333,6 +342,9 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) Standard_Boolean SpClose = mySpine.Closed(), GuideClose = AuxiliarySpine.Closed(); + if (KeepContact == BRepFill_ContactOnBorder) + myIsAutomaticLaw = Standard_True; + if (!SpClose && !GuideClose) { // Case open reorientation of the guide TopoDS_Wire sp = mySpine; @@ -377,7 +389,8 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) Guide->ChangeCurve().SetPeriodic(Standard_True); if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa - if (KeepContact) + if (KeepContact == BRepFill_Contact || + KeepContact == BRepFill_ContactOnBorder) myTrihedron = GeomFill_IsGuideACWithContact; // with rotation else myTrihedron = GeomFill_IsGuideAC; // without rotation @@ -389,7 +402,8 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) myLocation = new (BRepFill_ACRLaw) (mySpine, Loc); } else {// trihedron by plane - if (KeepContact) + if (KeepContact == BRepFill_Contact || + KeepContact == BRepFill_ContactOnBorder) myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation else myTrihedron = GeomFill_IsGuidePlan; // without rotation @@ -438,10 +452,74 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1) const Standard_Boolean WithCorrection) { Delete(Profile); // No duplication - BRepFill_Section S (Profile, Location, WithContact, WithCorrection); - mySeq.Append(S); - mySection.Nullify(); - ResetLoc(); + if (myIsAutomaticLaw) + { + mySeq.Clear(); + BRepFill_Section S (Profile, Location, WithContact, WithCorrection); + S.Set(Standard_True); + mySeq.Append(S); + mySection.Nullify(); + ResetLoc(); + + Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1)); + Handle(TColgp_HArray1OfPnt2d) ParAndRad; + Loc->ComputeAutomaticLaw(ParAndRad); + + //Compuite initial width of section (this will be 1.) + GProp_GProps GlobalProps; + BRepGProp::LinearProperties(Profile, GlobalProps); + gp_Pnt BaryCenter = GlobalProps.CentreOfMass(); + + TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane + Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace); + Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane); + IntCurveSurface_HInter Intersector; + Handle(Adaptor3d_HCurve) aHCurve [2]; + aHCurve[0] = Loc->GetCurve(); + aHCurve[1] = Loc->Guide(); + gp_Pnt PointsOnSpines [2]; + Standard_Integer i, j; + + for (i = 0; i < 2; i++) + { + Intersector.Perform(aHCurve[i], GAHplane); + Standard_Real MinDist = RealLast(); + for (j = 1; j <= Intersector.NbPoints(); j++) + { + gp_Pnt aPint = Intersector.Point(j).Pnt(); + Standard_Real aDist = BaryCenter.Distance(aPint); + if (aDist < MinDist) + { + MinDist = aDist; + PointsOnSpines[i] = aPint; + } + } + } + + //Correct according to + Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]); + Standard_Integer NbParRad = ParAndRad->Upper(); + for (i = 1; i <= NbParRad; i++) + { + gp_Pnt2d aParRad = ParAndRad->Value(i); + aParRad.SetY( aParRad.Y() / InitialWidth ); + ParAndRad->SetValue(i, aParRad); + } + + myLaw = new Law_Interpol(); + + Standard_Boolean IsPeriodic = + (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion()); + + (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic); + } + else + { + BRepFill_Section S (Profile, Location, WithContact, WithCorrection); + mySeq.Append(S); + mySection.Nullify(); + ResetLoc(); + } } //======================================================================= diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl index d53613f48c..2ec58d85de 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl @@ -53,7 +53,8 @@ uses Vertex from TopoDS, TransitionMode from BRepBuilderAPI, PipeError from BRepBuilderAPI, - PipeShell from BRepFill + PipeShell from BRepFill, + TypeOfContact from BRepFill raises DomainError from Standard, @@ -98,7 +99,7 @@ is SetMode(me : in out; AuxiliarySpine : Wire from TopoDS; CurvilinearEquivalence : Boolean; - KeepContact : Boolean = Standard_False ); + KeepContact : TypeOfContact from BRepFill = BRepFill_NoContact ); ---Purpose: Sets an auxiliary spine to define the Normal -- For each Point of the Spine P, an Point Q is evalued @@ -332,6 +333,7 @@ is is redefined; fields + myPipe : PipeShell from BRepFill; end MakePipeShell; diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx index 551488cde0..3c7edeb7a3 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx @@ -90,8 +90,8 @@ BRepOffsetAPI_MakePipeShell::BRepOffsetAPI_MakePipeShell(const TopoDS_Wire& Spin //purpose : //======================================================================= void BRepOffsetAPI_MakePipeShell::SetMode(const TopoDS_Wire& AuxiliarySpine, - const Standard_Boolean CurvilinearEquivalence, - const Standard_Boolean KeepContact) + const Standard_Boolean CurvilinearEquivalence, + const BRepFill_TypeOfContact KeepContact) { myPipe->Set(AuxiliarySpine, CurvilinearEquivalence, KeepContact); } diff --git a/src/BRepTest/BRepTest_SweepCommands.cxx b/src/BRepTest/BRepTest_SweepCommands.cxx index 71a4abf538..13597feb11 100755 --- a/src/BRepTest/BRepTest_SweepCommands.cxx +++ b/src/BRepTest/BRepTest_SweepCommands.cxx @@ -65,6 +65,7 @@ static BRepOffsetAPI_MakePipeShell* Sweep= 0; #include #include + //======================================================================= // prism //======================================================================= @@ -464,7 +465,7 @@ static Standard_Integer setsweep(Draw_Interpretor& di, di << " Surf have to be a shell or a face" <<"\n"; di << " -CN dx dy dz : BiNormal is given by dx dy dz" << "\n"; di << " -FX Tx Ty TZ [Nx Ny Nz] : Tangent and Normal are fixed" <<"\n"; - di << " -G guide 0|1(ACR|Plan) 0|1(contact|no contact) : with guide"<<"\n"; + di << " -G guide 0|1(Plan|ACR) 0|1|2(no contact|contact|contact on border) : with guide"<<"\n"; return 0; } @@ -534,7 +535,11 @@ static Standard_Integer setsweep(Draw_Interpretor& di, else { TopoDS_Shape Guide = DBRep::Get(a[2],TopAbs_WIRE); - Sweep->SetMode(TopoDS::Wire(Guide), Draw::Atoi(a[3]), Draw::Atoi(a[4])); + Standard_Integer CurvilinearEquivalence = Draw::Atoi(a[3]); + Standard_Integer KeepContact = Draw::Atoi(a[4]); + Sweep->SetMode(TopoDS::Wire(Guide), + CurvilinearEquivalence, + (BRepFill_TypeOfContact)KeepContact); } } @@ -623,9 +628,9 @@ static Standard_Integer addsweep(Draw_Interpretor& di, Standard_Integer ii, L= nbreal/2; TColgp_Array1OfPnt2d ParAndRad(1, L); for (ii=1; ii<=L; ii++, cur+=2) { - ParAndRad(ii).SetX(Draw::Atof(a[cur])); - ParAndRad(ii).SetY(Draw::Atof(a[cur+1])); - } + ParAndRad(ii).SetX(Draw::Atof(a[cur])); + ParAndRad(ii).SetY(Draw::Atof(a[cur+1])); + } thelaw = new (Law_Interpol) (); thelaw->Set(ParAndRad, Abs(ParAndRad(1).Y() - ParAndRad(L).Y()) < Precision::Confusion()); diff --git a/src/GeomFill/GeomFill_GuideTrihedronAC.cxx b/src/GeomFill/GeomFill_GuideTrihedronAC.cxx index 536f4964de..7a4c61a60d 100755 --- a/src/GeomFill/GeomFill_GuideTrihedronAC.cxx +++ b/src/GeomFill/GeomFill_GuideTrihedronAC.cxx @@ -80,6 +80,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur gp_Vec To, B; myTrimmed->D1(Param, P, To);//point et derivee au parametre Param sur myCurve myTrimG->D0(tG, PG);// point au parametre tG sur myGuide + myCurPointOnGuide = PG; gp_Vec n (P, PG); // vecteur definissant la normale @@ -118,6 +119,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur myTrimmed->D2(Param, P, To, DTo); myTrimG->D1(tG, PG, TG); + myCurPointOnGuide = PG; gp_Vec n (P, PG), dn; Standard_Real Norm = n.Magnitude(); @@ -188,6 +190,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur myTrimmed->D3(Param, P, To, DTo, D2To); myTrimG->D2(tG, PG, TG, DTG); + myCurPointOnGuide = PG; Standard_Real NTo = To.Magnitude(); Standard_Real N2To = To.SquareMagnitude(); diff --git a/src/GeomFill/GeomFill_LocationGuide.cdl b/src/GeomFill/GeomFill_LocationGuide.cdl index dd4386a8cc..e87c3afabb 100755 --- a/src/GeomFill/GeomFill_LocationGuide.cdl +++ b/src/GeomFill/GeomFill_LocationGuide.cdl @@ -278,6 +278,8 @@ is Param2 : Real) is static; + ComputeAutomaticLaw(me; ParAndRad : out HArray1OfPnt2d from TColgp) + returns PipeError from GeomFill; fields myLaw : TrihedronWithGuide from GeomFill; -- loi de triedre diff --git a/src/GeomFill/GeomFill_LocationGuide.cxx b/src/GeomFill/GeomFill_LocationGuide.cxx index 2a548c6806..78ae6beb94 100755 --- a/src/GeomFill/GeomFill_LocationGuide.cxx +++ b/src/GeomFill/GeomFill_LocationGuide.cxx @@ -44,7 +44,6 @@ #include #include -#include #include #include #include @@ -62,6 +61,9 @@ #include #include +#include +#include + #if DRAW static Standard_Integer Affich = 0; #include @@ -228,13 +230,12 @@ static void InGoodPeriod(const Standard_Real Prec, Standard_Integer ii, Deg; Standard_Boolean isconst, israt=Standard_False; Standard_Real t, v,w, OldAngle=0, Angle, DeltaG, DeltaU, Diff; - Standard_Real CurAngle = PrecAngle, a1, a2; + Standard_Real CurAngle = PrecAngle, a1/*, a2*/; gp_Pnt2d p1,p2; Handle(Geom_SurfaceOfRevolution) Revol; // surface de revolution Handle(GeomAdaptor_HSurface) Pl; // = Revol Handle(Geom_TrimmedCurve) S; IntCurveSurface_IntersectionPoint PInt; // intersection guide/Revol - IntCurveSurface_HInter Int; Handle(TColStd_HArray1OfInteger) Mult; Handle(TColStd_HArray1OfReal) Knots, Weights; Handle(TColgp_HArray1OfPnt) Poles; @@ -338,13 +339,18 @@ static void InGoodPeriod(const Standard_Real Prec, (Handle(Geom_Curve)::DownCast(mySection->Copy()), Uf, Ul); } S->Transform(Transfo); - + // Surface de revolution Revol = new(Geom_SurfaceOfRevolution) (S, Ax); - Pl = new (GeomAdaptor_HSurface)(Revol); - Int.Perform(myGuide, Pl); // intersection surf. revol / guide - if (Int.NbPoints() == 0) { + GeomAdaptor_Surface GArevol(Revol); + Extrema_ExtCS DistMini(myGuide->Curve(), GArevol, + Precision::Confusion(), Precision::Confusion()); + Extrema_POnCurv Pc; + Extrema_POnSurf Ps; + Standard_Real theU = 0., theV = 0.; + + if (!DistMini.IsDone() || DistMini.NbExt() == 0) { #if DEB cout <<"LocationGuide : Pas d'intersection"<1) { Diff = w - myPoles2d->Value(1, ii-1).Y(); if (Abs(Diff) > DeltaG) { @@ -419,7 +435,8 @@ static void InGoodPeriod(const Standard_Real Prec, #endif } //Recadrage de l'angle. - Angle = PInt.U(); + Angle = theU; + if (ii > 1) { Diff = Angle - OldAngle; if (Abs(Diff) > M_PI) { @@ -435,7 +452,8 @@ static void InGoodPeriod(const Standard_Real Prec, //Recadrage du V - v = PInt.V(); + v = theV; + if (ii > 1) { if (uperiodic) { InGoodPeriod (myPoles2d->Value(2, ii-1).Y(), UPeriod, v); @@ -1442,3 +1460,40 @@ void GeomFill_LocationGuide::SetOrigine(const Standard_Real Param1, OrigParam2 = Param2; } +//================================================================== +//Function : ComputeAutomaticLaw +//Purpose : +//================================================================== +GeomFill_PipeError GeomFill_LocationGuide::ComputeAutomaticLaw(Handle(TColgp_HArray1OfPnt2d)& ParAndRad) const +{ + gp_Pnt P; + gp_Vec T,N,B; + Standard_Integer ii; + Standard_Real t; + + GeomFill_PipeError theStatus = GeomFill_PipeOk; + + Standard_Real f = myCurve->FirstParameter(); + Standard_Real l = myCurve->LastParameter(); + + ParAndRad = new TColgp_HArray1OfPnt2d(1, myNbPts); + for (ii = 1; ii <= myNbPts; ii++) + { + t = Standard_Real(myNbPts - ii)*f + Standard_Real(ii - 1)*l; + t /= (myNbPts-1); + myCurve->D0(t, P); + Standard_Boolean Ok = myLaw->D0(t, T, N, B); + if (!Ok) + { + theStatus = myLaw->ErrorStatus(); + return theStatus; + } + gp_Pnt PointOnGuide = myLaw->CurrentPointOnGuide(); + Standard_Real CurWidth = P.Distance(PointOnGuide); + + gp_Pnt2d aParamWithRadius(t, CurWidth); + ParAndRad->SetValue(ii, aParamWithRadius); + } + + return theStatus; +} diff --git a/src/GeomFill/GeomFill_TrihedronWithGuide.cdl b/src/GeomFill/GeomFill_TrihedronWithGuide.cdl index 42315f9239..6b8d20d2dd 100755 --- a/src/GeomFill/GeomFill_TrihedronWithGuide.cdl +++ b/src/GeomFill/GeomFill_TrihedronWithGuide.cdl @@ -29,7 +29,8 @@ inherits TrihedronLaw from GeomFill uses HCurve from Adaptor3d, - Real from Standard + Real from Standard, + Pnt from gp raises OutOfRange, NotImplemented @@ -45,9 +46,15 @@ is Param2 : Real) is deferred; + CurrentPointOnGuide(me) + ---Purpose: Returns the current point on guide + -- found by D0, D1 or D2. + returns Pnt from gp; + fields myGuide : HCurve from Adaptor3d is protected; myTrimG : HCurve from Adaptor3d is protected; + myCurPointOnGuide : Pnt from gp is protected; end TrihedronWithGuide; diff --git a/src/GeomFill/GeomFill_TrihedronWithGuide.cxx b/src/GeomFill/GeomFill_TrihedronWithGuide.cxx index 12deaf14b2..74b36f72fb 100755 --- a/src/GeomFill/GeomFill_TrihedronWithGuide.cxx +++ b/src/GeomFill/GeomFill_TrihedronWithGuide.cxx @@ -28,4 +28,12 @@ Handle(Adaptor3d_HCurve) GeomFill_TrihedronWithGuide::Guide()const return myGuide; } +//======================================================================= +//function : CurrentPointOnGuide +//purpose : +//======================================================================= +gp_Pnt GeomFill_TrihedronWithGuide::CurrentPointOnGuide() const +{ + return myCurPointOnGuide; +} diff --git a/tests/bugs/modalg_5/bug24305 b/tests/bugs/modalg_5/bug24305 new file mode 100755 index 0000000000..bd0a132400 --- /dev/null +++ b/tests/bugs/modalg_5/bug24305 @@ -0,0 +1,33 @@ +puts "============" +puts "OCC24305" +puts "============" +puts "" +####################################################################### +# New option in BRepOffsetAPI_MakePipeShell algofithm: the swept shell with varying width of section bounded by auxiliary spine +####################################################################### + +restore [locate_data_file bug24305_mainSpine.brep] sp +restore [locate_data_file bug24305_auxSpine.brep] aux +restore [locate_data_file bug24305_profile.brep] pr + +wire sp sp +wire aux aux +mksweep sp + +setsweep -G aux 1 2 +addsweep pr +buildsweep result + +set square 69608 + +set nb_v_good 12 +set nb_e_good 16 +set nb_w_good 5 +set nb_f_good 5 +set nb_sh_good 1 +set nb_sol_good 0 +set nb_compsol_good 0 +set nb_compound_good 0 +set nb_shape_good 39 + +set 2dviewer 1