diff --git a/src/BRepFill/BRepFill_Draft.cxx b/src/BRepFill/BRepFill_Draft.cxx index 75b704e97b..fb63cfd0fc 100755 --- a/src/BRepFill/BRepFill_Draft.cxx +++ b/src/BRepFill/BRepFill_Draft.cxx @@ -525,7 +525,7 @@ static Standard_Boolean GoodOrientation(const Bnd_Box& B, BRepFill_Sweep Sweep(mySec, myLoc, Standard_True); Sweep.SetTolerance(myTol); Sweep.SetAngularControl(angmin, angmax); - Sweep.Build(myStyle, GeomFill_Location, myCont); + Sweep.Build(myStyle, myCont); if (Sweep.IsDone()) { myShape = Sweep.Shape(); myShell = TopoDS::Shell(myShape); diff --git a/src/BRepFill/BRepFill_Pipe.cdl b/src/BRepFill/BRepFill_Pipe.cdl index a8a6da8626..46ee387e69 100755 --- a/src/BRepFill/BRepFill_Pipe.cdl +++ b/src/BRepFill/BRepFill_Pipe.cdl @@ -41,8 +41,8 @@ uses Edge from TopoDS, Vertex from TopoDS, Pnt from gp, - Trsf from gp - + Trsf from gp, + Trihedron from GeomFill raises DomainError from Standard, @@ -57,6 +57,21 @@ is GeneratePartCase : Boolean from Standard = Standard_False) returns Pipe from BRepFill; + SetMode(me : in out; + aMode : Trihedron from GeomFill); + ---Purpose: Set the mode of sweeping + -- It can be: + -- - Frenet + -- - Corrected Frenet + -- - Discrete Trihedron + -- By default the mode is Corrected Frenet + + SetForceApproxC1(me : in out; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + Perform (me : in out; Spine : Wire from TopoDS; Profile : Shape from TopoDS; GeneratePartCase : Boolean from Standard = Standard_False) @@ -175,4 +190,7 @@ fields myDegmax : Integer from Standard; mySegmax : Integer from Standard; + myMode : Trihedron from GeomFill; + myForceApproxC1 : Boolean from Standard; + end Pipe; diff --git a/src/BRepFill/BRepFill_Pipe.cxx b/src/BRepFill/BRepFill_Pipe.cxx index 2b4d5b990d..c27ed8ce87 100755 --- a/src/BRepFill/BRepFill_Pipe.cxx +++ b/src/BRepFill/BRepFill_Pipe.cxx @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include @@ -70,6 +72,8 @@ BRepFill_Pipe::BRepFill_Pipe() { myDegmax = 10; mySegmax = 100; + myMode = GeomFill_IsCorrectedFrenet; + myForceApproxC1 = Standard_False; } @@ -84,9 +88,39 @@ BRepFill_Pipe::BRepFill_Pipe(const TopoDS_Wire& Spine, { myDegmax = 10; mySegmax = 100; + myMode = GeomFill_IsCorrectedFrenet; + myForceApproxC1 = Standard_False; Perform(Spine, Profile, KPart); } +//======================================================================= +//function : SetMode +//purpose : Set the mode of sweeping +// It can be: +// - Frenet +// - Corrected Frenet +// - Discrete Trihedron +//======================================================================= + +void BRepFill_Pipe::SetMode(const GeomFill_Trihedron aMode) +{ + if (aMode == GeomFill_IsFrenet || + aMode == GeomFill_IsCorrectedFrenet || + aMode == GeomFill_IsDiscreteTrihedron) + myMode = aMode; +} + +//======================================================================= +//function : SetForceApproxC1 +//purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= + +void BRepFill_Pipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myForceApproxC1 = ForceApproxC1; +} //======================================================================= @@ -111,9 +145,19 @@ void BRepFill_Pipe::Perform(const TopoDS_Wire& Spine, BRepTools_WireExplorer wexp; TopoDS_Shape TheProf; - - Handle(GeomFill_CorrectedFrenet) TLaw = - new (GeomFill_CorrectedFrenet) (); + Handle(GeomFill_TrihedronLaw) TLaw; + switch (myMode) + { + case GeomFill_IsFrenet: + TLaw = new GeomFill_Frenet(); + break; + case GeomFill_IsCorrectedFrenet: + TLaw = new GeomFill_CorrectedFrenet(); + break; + case GeomFill_IsDiscreteTrihedron: + TLaw = new GeomFill_DiscreteTrihedron(); + break; + } Handle(GeomFill_CurveAndTrihedron) Loc = new (GeomFill_CurveAndTrihedron) (TLaw); myLoc = new (BRepFill_Edge3DLaw) (mySpine, Loc); @@ -366,7 +410,8 @@ TopoDS_Wire BRepFill_Pipe::PipeLine(const gp_Pnt& Point) const // Sweeping BRepFill_Sweep MkSw(Section, myLoc, Standard_True); - MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax ); + MkSw.SetForceApproxC1(myForceApproxC1); + MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax ); TopoDS_Shape aLocalShape = MkSw.Shape(); return TopoDS::Wire(aLocalShape); // return TopoDS::Wire(MkSw.Shape()); @@ -491,7 +536,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, Handle(BRepFill_ShapeLaw) Section = new (BRepFill_ShapeLaw) (TopoDS::Vertex(TheS)); BRepFill_Sweep MkSw(Section, myLoc, Standard_True); - MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax ); + MkSw.SetForceApproxC1(myForceApproxC1); + MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax ); result = MkSw.Shape(); } @@ -501,7 +547,8 @@ TopoDS_Shape BRepFill_Pipe::MakeShape(const TopoDS_Shape& S, BRepFill_Sweep MkSw(Section, myLoc, Standard_True); MkSw.SetBounds(TopoDS::Wire(TheFirst), TopoDS::Wire(TheLast)); - MkSw.Build( BRepFill_Modified, GeomFill_Location, GeomAbs_C2, myDegmax, mySegmax ); + MkSw.SetForceApproxC1(myForceApproxC1); + MkSw.Build( BRepFill_Modified, GeomAbs_C2, GeomFill_Location, myDegmax, mySegmax ); result = MkSw.Shape(); // Labeling of elements diff --git a/src/BRepFill/BRepFill_PipeShell.cdl b/src/BRepFill/BRepFill_PipeShell.cdl index 6fd41847c2..50018107ed 100755 --- a/src/BRepFill/BRepFill_PipeShell.cdl +++ b/src/BRepFill/BRepFill_PipeShell.cdl @@ -66,6 +66,12 @@ is ---Level: Public ---See Also:GeomFill_IsCorrectedFrenet + SetDiscrete(me : mutable); + ---Purpose: Set a Discrete trihedron + -- to perform the sweeping + ---Level: Public + ---See Also:GeomFill_IsDiscreteTrihedron + Set(me : mutable; Axe : Ax2 from gp); ---Purpose: Set an fixed trihedron to perform the sweeping -- all sections will be parallel. @@ -106,6 +112,13 @@ is ---Level: Public + SetForceApproxC1(me : mutable; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + + -- ================================= -- Methodes to define section(s) -- ================================= @@ -271,8 +284,9 @@ fields myTol3d : Real; myBoundTol : Real; - myTolAngular : Real; + myTolAngular : Real; angmin, angmax : Real; + myForceApproxC1 : Boolean; myLaw : Function from Law; myLocation : LocationLaw from BRepFill; diff --git a/src/BRepFill/BRepFill_PipeShell.cxx b/src/BRepFill/BRepFill_PipeShell.cxx index 208af33901..e6aadaf7b7 100755 --- a/src/BRepFill/BRepFill_PipeShell.cxx +++ b/src/BRepFill/BRepFill_PipeShell.cxx @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -211,6 +212,7 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) : mySpine(Spine), myTrihedron(GeomFill_IsCorrectedFrenet), myTransition(BRepFill_Modified), + myForceApproxC1(Standard_False), myStatus(GeomFill_PipeOk) { myLocation.Nullify(); @@ -247,6 +249,23 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) mySection.Nullify(); //It is required to relocalize sections. } +//======================================================================= +//function : SetDiscrete +//purpose : Define a law of Discrete Trihedron +//======================================================================= + void BRepFill_PipeShell::SetDiscrete() +{ + Handle(GeomFill_TrihedronLaw) TLaw; + + myTrihedron = GeomFill_IsDiscreteTrihedron; + TLaw = new (GeomFill_DiscreteTrihedron) (); + + Handle(GeomFill_CurveAndTrihedron) Loc = + new (GeomFill_CurveAndTrihedron) (TLaw); + myLocation = new (BRepFill_Edge3DLaw) (mySpine, Loc); + mySection.Nullify(); //It is required to relocalize sections. +} + //======================================================================= //function : Set //purpose : Define a law Constant @@ -384,6 +403,17 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) mySection.Nullify(); //It is required to relocalize the sections. } +//======================================================================= +//function : SetForceApproxC1 +//purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= +void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myForceApproxC1 = ForceApproxC1; +} + //======================================================================= //function : Add //purpose : Add a Section @@ -629,9 +659,13 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) BRepFill_Sweep MkSw(mySection, myLocation, Standard_True); MkSw.SetTolerance(myTol3d, myBoundTol, 1.e-5, myTolAngular); MkSw.SetAngularControl(angmin, angmax); + MkSw.SetForceApproxC1(myForceApproxC1); MkSw.SetBounds(TopoDS::Wire(myFirst), TopoDS::Wire(myLast)); - MkSw.Build(myTransition); + GeomAbs_Shape theContinuity = GeomAbs_C2; + if (myTrihedron == GeomFill_IsDiscreteTrihedron) + theContinuity = GeomAbs_C0; + MkSw.Build(myTransition, theContinuity); myStatus = myLocation->GetStatus(); Ok = (MkSw.IsDone() && (myStatus == GeomFill_PipeOk)); diff --git a/src/BRepFill/BRepFill_Sweep.cdl b/src/BRepFill/BRepFill_Sweep.cdl index 6b4356ab6a..cf6a678ff8 100755 --- a/src/BRepFill/BRepFill_Sweep.cdl +++ b/src/BRepFill/BRepFill_Sweep.cdl @@ -80,10 +80,17 @@ is -- Transition "Round" replace the Transition "Right" is static; + SetForceApproxC1(me: in out; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + + Build(me : in out; Transition : TransitionStyle = BRepFill_Modified; - Approx : ApproxStyle = GeomFill_Location; Continuity : Shape from GeomAbs = GeomAbs_C2; + Approx : ApproxStyle = GeomFill_Location; Degmax : Integer = 11; Segmax : Integer = 30); @@ -170,6 +177,7 @@ fields myContinuity : Shape from GeomAbs; myDegmax : Integer; mySegmax : Integer; + myForceApproxC1 : Boolean; myShape : Shape from TopoDS; myLoc : LocationLaw from BRepFill; mySec : SectionLaw from BRepFill; diff --git a/src/BRepFill/BRepFill_Sweep.cxx b/src/BRepFill/BRepFill_Sweep.cxx index f9ceecaf53..7df0994dd8 100755 --- a/src/BRepFill/BRepFill_Sweep.cxx +++ b/src/BRepFill/BRepFill_Sweep.cxx @@ -1685,6 +1685,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, myContinuity = GeomAbs_C2; myDegmax = 11; mySegmax = 30; + myForceApproxC1 = Standard_False; } //======================================================================= @@ -1752,6 +1753,17 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, myAngMax = Min (MaxAngle, 6.28); } +//======================================================================= +//function : SetForceApproxC1 +//purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= + void BRepFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myForceApproxC1 = ForceApproxC1; +} + ///======================================================================= //function : CorrectApproxParameters //purpose : @@ -1820,6 +1832,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, // Curve by iso value GeomFill_Sweep Sweep(myLoc->Law(ipath), KPart); Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular); + Sweep.SetForceApproxC1(myForceApproxC1); Sweep.Build(mySec->Law(isec), myApproxStyle, myContinuity, myDegmax, mySegmax); if (!Sweep.IsDone()) return Standard_False; @@ -1985,6 +1998,7 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, GeomFill_Sweep Sweep(myLoc->Law(IPath), KPart); Sweep.SetTolerance(myTol3d, myBoundTol, myTol2d, myTolAngular); + Sweep.SetForceApproxC1(myForceApproxC1); // Case of evolutionary section, definition of parametric correspondence if (!constSection) { @@ -2491,13 +2505,13 @@ BRepFill_Sweep::BRepFill_Sweep(const Handle(BRepFill_SectionLaw)& Section, //purpose : Construt the result of sweeping //====================================================================== void BRepFill_Sweep::Build(const BRepFill_TransitionStyle Transition, - const GeomFill_ApproxStyle Approx, const GeomAbs_Shape Continuity, + const GeomFill_ApproxStyle Approx, const Standard_Integer Degmax, const Standard_Integer Segmax) { - myApproxStyle = Approx; myContinuity = Continuity; + myApproxStyle = Approx; myDegmax = Degmax; mySegmax = Segmax; diff --git a/src/BRepOffsetAPI/BRepOffsetAPI.cdl b/src/BRepOffsetAPI/BRepOffsetAPI.cdl index dbdadcdc44..47963d9293 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI.cdl @@ -28,7 +28,8 @@ uses StdFail, gp, GeomAbs, - Geom, + Geom, + GeomFill, Approx, TopoDS, TopTools, diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cdl index 1d1b6032cd..a0f8b4e741 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cdl @@ -35,6 +35,7 @@ class MakePipe from BRepOffsetAPI inherits MakeSweep from BRepPrimAPI -- with G1 continuous spines only. uses Pipe from BRepFill, + Trihedron from GeomFill, Wire from TopoDS, Shape from TopoDS, Edge from TopoDS, @@ -58,6 +59,21 @@ is -- composite solid. returns MakePipe from BRepOffsetAPI; + SetMode(me : in out; + aMode : Trihedron from GeomFill); + ---Purpose: Set the mode of sweeping + -- It can be: + -- - Frenet + -- - Corrected Frenet + -- - Discrete Trihedron + -- By default the mode is Corrected Frenet + + SetForceApproxC1(me : in out; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + Pipe(me) returns Pipe from BRepFill ---C++: return const & diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cxx index f98ffe37fb..5b0374b750 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipe.cxx @@ -40,6 +40,32 @@ BRepOffsetAPI_MakePipe::BRepOffsetAPI_MakePipe(const TopoDS_Wire& Spine , Build(); } +//======================================================================= +//function : SetMode +//purpose : Set the mode of sweeping +// It can be: +// - Frenet +// - Corrected Frenet +// - Discrete Trihedron +//======================================================================= + +void BRepOffsetAPI_MakePipe::SetMode(const GeomFill_Trihedron aMode) +{ + myPipe.SetMode(aMode); +} + +//======================================================================= +//function : SetForceApproxC1 +//purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= + +void BRepOffsetAPI_MakePipe::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myPipe.SetForceApproxC1(ForceApproxC1); +} + //======================================================================= //function : Pipe //purpose : diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl index 1141a12fac..d53613f48c 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl @@ -73,6 +73,10 @@ is -- to perform the sweeping -- If IsFrenet is false, a corrected Frenet trihedron is used. + SetDiscreteMode(me : in out); + ---Purpose: Sets a Discrete trihedron + -- to perform the sweeping + SetMode(me : in out; Axe : Ax2 from gp); ---Purpose: Sets a fixed trihedron to perform the sweeping -- all sections will be parallel. @@ -110,6 +114,7 @@ is ---Level: Public + -- ================================= -- Methodes to define section(s) -- ================================= @@ -212,6 +217,12 @@ is -- - boundary tolerance BoundTol -- - angular tolerance TolAngular. + SetForceApproxC1(me : in out; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + SetTransitionMode(me : in out; Mode :TransitionMode from BRepBuilderAPI = BRepBuilderAPI_Transformed) ---Purpose: Sets the transition mode to manage discontinuities on diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx index f1189fa3ec..551488cde0 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx @@ -49,6 +49,15 @@ BRepOffsetAPI_MakePipeShell::BRepOffsetAPI_MakePipeShell(const TopoDS_Wire& Spin myPipe->Set(IsFrenet); } +//======================================================================= +//function : SetDiscreteMode +//purpose : +//======================================================================= + void BRepOffsetAPI_MakePipeShell::SetDiscreteMode() +{ + myPipe->SetDiscrete(); +} + //======================================================================= //function : SetMode //purpose : @@ -185,8 +194,9 @@ void BRepOffsetAPI_MakePipeShell::Delete( const TopoDS_Shape& Profile) } return Status; } + //======================================================================= -//function : SetTransitionMode +//function : SetTolerance //purpose : //======================================================================= void BRepOffsetAPI_MakePipeShell::SetTolerance(const Standard_Real Tol3d, @@ -196,6 +206,17 @@ void BRepOffsetAPI_MakePipeShell::Delete( const TopoDS_Shape& Profile) myPipe->SetTolerance(Tol3d, BoundTol, TolAngular); } +//======================================================================= +//function : SetForceApproxC1 +//purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= + void BRepOffsetAPI_MakePipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myPipe->SetForceApproxC1(ForceApproxC1); +} + //======================================================================= //function : SetTransitionMode //purpose : diff --git a/src/BRepTest/BRepTest_SweepCommands.cxx b/src/BRepTest/BRepTest_SweepCommands.cxx index 631d9f15ff..f493fd7044 100755 --- a/src/BRepTest/BRepTest_SweepCommands.cxx +++ b/src/BRepTest/BRepTest_SweepCommands.cxx @@ -431,6 +431,7 @@ static Standard_Integer setsweep(Draw_Interpretor& di, di << " -FR : Tangent and Normal are given by Frenet trihedron" <<"\n"; di << " -CF : Tangente is given by Frenet," << "\n"; di << " the Normal is computed to minimize the torsion " << "\n"; + di << " -DT : discrete trihedron" << "\n"; di << " -DX Surf : Tangent and Normal are given by Darboux trihedron," <<"\n"; di << " Surf have to be a shell or a face" <<"\n"; di << " -CN dx dy dz : BiNormal is given by dx dy dz" << "\n"; @@ -450,6 +451,9 @@ static Standard_Integer setsweep(Draw_Interpretor& di, else if (!strcmp(a[1],"-CF")) { Sweep->SetMode(Standard_False); } + else if (!strcmp(a[1],"-DT")) { + Sweep->SetDiscreteMode(); + } else if (!strcmp(a[1],"-DX")) { if (n!=3) { //cout << "bad arguments !" << endl; diff --git a/src/GeomFill/GeomFill.cdl b/src/GeomFill/GeomFill.cdl index a849f1d062..12bc078641 100755 --- a/src/GeomFill/GeomFill.cdl +++ b/src/GeomFill/GeomFill.cdl @@ -67,7 +67,7 @@ is enumeration Trihedron is IsCorrectedFrenet, IsFixed, IsFrenet, IsConstantNormal, IsDarboux, IsGuideAC, IsGuidePlan, - IsGuideACWithContact, IsGuidePlanWithContact end; + IsGuideACWithContact, IsGuidePlanWithContact, IsDiscreteTrihedron end; class Filling; ---Purpose: Root class for Filling; @@ -195,6 +195,13 @@ is class SequenceOfTrsf instantiates Sequence from TCollection (Trsf from gp); + class SequenceOfAx2 + instantiates Sequence from TCollection (Ax2 from gp); + + class HSequenceOfAx2 + instantiates HSequence from TCollection (Ax2 from gp, + SequenceOfAx2 from GeomFill); + -- -- private classes -- @@ -226,6 +233,7 @@ is class Fixed; class Frenet; class CorrectedFrenet; + class DiscreteTrihedron; class ConstantBiNormal; class Darboux; class DraftTrihedron; diff --git a/src/GeomFill/GeomFill_CorrectedFrenet.cdl b/src/GeomFill/GeomFill_CorrectedFrenet.cdl index 1fb4f7dd13..dfd809e83b 100755 --- a/src/GeomFill/GeomFill_CorrectedFrenet.cdl +++ b/src/GeomFill/GeomFill_CorrectedFrenet.cdl @@ -37,7 +37,8 @@ uses HArray1OfReal from TColStd, SequenceOfReal from TColStd, HArray1OfVec from TColgp, - SequenceOfVec from TColgp + SequenceOfVec from TColgp, + Trihedron from GeomFill raises OutOfRange, ConstructionError @@ -45,11 +46,14 @@ is Create returns CorrectedFrenet from GeomFill; + Create (ForEvaluation: Boolean) + returns CorrectedFrenet from GeomFill; + Copy(me) returns TrihedronLaw from GeomFill is redefined; - Init(me: mutable) + Init(me: mutable) is static private; InitInterval(me; First, Last, Step: Real; @@ -59,7 +63,7 @@ is SeqPoles: out SequenceOfReal from TColStd; SeqAngle: out SequenceOfReal from TColStd; SeqTangent: out SequenceOfVec from TColgp; - SeqNormal: out SequenceOfVec from TColgp) + SeqNormal: out SequenceOfVec from TColgp) returns Boolean --- Purpose: Computes BSpline representation of Normal evolution at one --- interval of continuity of Frenet. Returns True if FuncInt = 0 @@ -142,6 +146,20 @@ is OutOfRange from Standard is redefined; + +-- =================== To define the best trihedron mode =============== + + EvaluateBestMode(me : mutable) + returns Trihedron from GeomFill; + ---Purpose: Tries to define the best trihedron mode + -- for the curve. It can be: + -- - Frenet + -- - CorrectedFrenet + -- - DiscreteTrihedron + -- Warning: the CorrectedFrenet must be constructed + -- with option ForEvaluation = True, + -- the curve must be set by method SetCurve. + -- =================== To help computation of Tolerance =============== GetAverageLaw(me : mutable; @@ -165,11 +183,13 @@ is is redefined; fields - frenet : Frenet from GeomFill; - EvolAroundT : Function from Law; - TLaw : Function from Law; - AT, AN : Vec from gp; - isFrenet : Boolean; + frenet : Frenet from GeomFill; + EvolAroundT : Function from Law; + TLaw : Function from Law; + AT, AN : Vec from gp; + isFrenet : Boolean; + myForEvaluation : Boolean; + ---OCC78 HArrPoles : HArray1OfReal from TColStd; HArrAngle : HArray1OfReal from TColStd; diff --git a/src/GeomFill/GeomFill_CorrectedFrenet.cxx b/src/GeomFill/GeomFill_CorrectedFrenet.cxx index c670ea28dd..862bae8d20 100755 --- a/src/GeomFill/GeomFill_CorrectedFrenet.cxx +++ b/src/GeomFill/GeomFill_CorrectedFrenet.cxx @@ -44,6 +44,7 @@ #include #include + #ifdef DEB static Standard_Boolean Affich=0; #endif @@ -90,6 +91,30 @@ static void draw(const Handle(Law_Function)& law) } #endif + +static Standard_Real ComputeTorsion(const Standard_Real Param, + const Handle(Adaptor3d_HCurve)& aCurve) +{ + Standard_Real Torsion; + + gp_Pnt aPoint; + gp_Vec DC1, DC2, DC3; + aCurve->D3(Param, aPoint, DC1, DC2, DC3); + gp_Vec DC1crossDC2 = DC1 ^ DC2; + Standard_Real Norm_DC1crossDC2 = DC1crossDC2.Magnitude(); + + Standard_Real DC1DC2DC3 = DC1crossDC2 * DC3 ; //mixed product + + Standard_Real Tol = gp::Resolution(); + Standard_Real SquareNorm_DC1crossDC2 = Norm_DC1crossDC2 * Norm_DC1crossDC2; + if (SquareNorm_DC1crossDC2 <= Tol) + Torsion = 0.; + else + Torsion = DC1DC2DC3 / SquareNorm_DC1crossDC2 ; + + return Torsion; +} + //=============================================================== // Function : smoothlaw // Purpose : to smooth a law : Reduce the number of knots @@ -280,13 +305,25 @@ static Standard_Boolean FindPlane ( const Handle(Adaptor3d_HCurve)& c, } //=============================================================== -// Function : +// Function : Constructor // Purpose : //=============================================================== GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet() : isFrenet(Standard_False) { frenet = new GeomFill_Frenet(); + myForEvaluation = Standard_False; +} + +//=============================================================== +// Function : Constructor +// Purpose : +//=============================================================== +GeomFill_CorrectedFrenet::GeomFill_CorrectedFrenet(const Standard_Boolean ForEvaluation) + : isFrenet(Standard_False) +{ + frenet = new GeomFill_Frenet(); + myForEvaluation = ForEvaluation; } Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const @@ -314,6 +351,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const { // No probleme isFrenet isFrenet = Standard_True; + break; } default : { @@ -382,8 +420,12 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const for(i = 1; i <= NbI; i++) { NbStep = Max(Standard_Integer((T(i+1) - T(i))/AvStep), 3); Step = (T(i+1) - T(i))/NbStep; - if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func, SeqPoles, SeqAngle, SeqTangent, SeqNormal)) - if(isFrenet) isFrenet = Standard_False; + if(!InitInterval(T(i), T(i+1), Step, StartAng, Tangent, Normal, AT, AN, Func, + SeqPoles, SeqAngle, SeqTangent, SeqNormal)) + { + if(isFrenet) + isFrenet = Standard_False; + } Handle(Law_Composite)::DownCast(EvolAroundT)->ChangeLaws().Append(Func); } if(myTrimmed->IsPeriodic()) @@ -402,7 +444,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const HArrTangent->ChangeValue(i) = SeqTangent(i); HArrNormal->ChangeValue(i) = SeqNormal(i); }; - + #if DRAW if (Affich) { draw(EvolAroundT); @@ -431,6 +473,7 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const TColStd_SequenceOfReal EvolAT; Standard_Real Param = First, LengthMin, L, norm; Standard_Boolean isZero = Standard_True, isConst = Standard_True; + const Standard_Real minnorm = 1.e-16; Standard_Integer i; gp_Pnt PonC; gp_Vec D1; @@ -446,7 +489,9 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const Standard_Real angleAT, currParam, currStep = Step; Handle( Geom_Plane ) aPlane; - Standard_Boolean isPlanar = FindPlane( myCurve, aPlane ); + Standard_Boolean isPlanar = Standard_False; + if (!myForEvaluation) + isPlanar = FindPlane( myCurve, aPlane ); i = 1; currParam = Param; @@ -493,13 +538,21 @@ Handle(GeomFill_TrihedronLaw) GeomFill_CorrectedFrenet::Copy() const //Evaluate the Next step CS.D1(Param, PonC, D1); - L = Max(PonC.XYZ().Modulus()/2, LengthMin); + + L = PonC.XYZ().Modulus()/2; norm = D1.Magnitude(); - if (norm < Precision::Confusion()) { - norm = Precision::Confusion(); + if (norm <= gp::Resolution()) + { + //norm = 2.*gp::Resolution(); + norm = minnorm; } currStep = L / norm; - if (currStep > Step) currStep = Step;//default value + if (currStep <= gp::Resolution()) //L = 0 => curvature = 0, linear segment + currStep = Step; + if (currStep < Precision::Confusion()) //too small step + currStep = Precision::Confusion(); + if (currStep > Step) //too big step + currStep = Step;//default value } else currStep /= 2; // Step too long ! @@ -887,6 +940,59 @@ Standard_Real GeomFill_CorrectedFrenet::GetAngleAT(const Standard_Real Param) co Precision::PConfusion()/2); } +//=============================================================== +// Function : EvaluateBestMode +// Purpose : +//=============================================================== +GeomFill_Trihedron GeomFill_CorrectedFrenet::EvaluateBestMode() +{ + if (EvolAroundT.IsNull()) + return GeomFill_IsFrenet; //Frenet + + const Standard_Real MaxAngle = 3.*M_PI/4.; + const Standard_Real MaxTorsion = 100.; + + Standard_Real Step, u, v, tmin, tmax; + Standard_Integer NbInt, i, j, k = 1; + NbInt = EvolAroundT->NbIntervals(GeomAbs_CN); + TColStd_Array1OfReal Int(1, NbInt+1); + EvolAroundT->Intervals(Int, GeomAbs_CN); + gp_Pnt2d old; + gp_Vec2d aVec, PrevVec; + + Standard_Integer NbSamples = 10; + for(i = 1; i <= NbInt; i++){ + tmin = Int(i); + tmax = Int(i+1); + Standard_Real Torsion = ComputeTorsion(tmin, myTrimmed); + if (Abs(Torsion) > MaxTorsion) + return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron + + Handle(Law_Function) trimmedlaw = EvolAroundT->Trim(tmin, tmax, Precision::PConfusion()/2); + Step = (Int(i+1)-Int(i))/NbSamples; + for (j = 0; j <= NbSamples; j++) { + u = tmin + j*Step; + v = trimmedlaw->Value(u); + gp_Pnt2d point2d(u,v); + if (j != 0) + { + aVec.SetXY(point2d.XY() - old.XY()); + if (k > 2) + { + Standard_Real theAngle = PrevVec.Angle(aVec); + if (Abs(theAngle) > MaxAngle) + return GeomFill_IsDiscreteTrihedron; //DiscreteTrihedron + } + PrevVec = aVec; + } + old = point2d; + k++; + } + } + + return GeomFill_IsCorrectedFrenet; //CorrectedFrenet +} + //=============================================================== // Function : GetAverageLaw // Purpose : diff --git a/src/GeomFill/GeomFill_DiscreteTrihedron.cdl b/src/GeomFill/GeomFill_DiscreteTrihedron.cdl new file mode 100644 index 0000000000..0f556653a8 --- /dev/null +++ b/src/GeomFill/GeomFill_DiscreteTrihedron.cdl @@ -0,0 +1,154 @@ +-- Created on: 2013-02-05 +-- Created by: Julia GERASIMOVA +-- Copyright (c) 2001-2013 OPEN CASCADE SAS +-- +-- The content of this file is subject to the Open CASCADE Technology Public +-- License Version 6.5 (the "License"). You may not use the content of this file +-- except in compliance with the License. Please obtain a copy of the License +-- at http://www.opencascade.org and read it completely before using this file. +-- +-- The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +-- main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +-- +-- The Original Code and all software distributed under the License is +-- distributed on an "AS IS" basis, without warranty of any kind, and the +-- Initial Developer hereby disclaims all such warranties, including without +-- limitation, any warranties of merchantability, fitness for a particular +-- purpose or non-infringement. Please see the License for the specific terms +-- and conditions governing the rights and limitations under the License. + + +class DiscreteTrihedron from GeomFill + inherits TrihedronLaw from GeomFill + + ---Purpose: Defined Discrete Trihedron Law. + -- The requirement for path curve is only G1. + -- The result is C0-continuous surface + -- that can be later approximated to C1. + +uses + HCurve from Adaptor3d, + Shape from GeomAbs, + Pnt from gp, + Vec from gp, + Array1OfReal from TColStd, + Frenet from GeomFill, + HSequenceOfAx2 from GeomFill, + HSequenceOfReal from TColStd + +raises + OutOfRange, ConstructionError +is + + Create + returns DiscreteTrihedron from GeomFill + raises ConstructionError; + + Copy(me) + returns TrihedronLaw from GeomFill + is redefined; + + Init(me: mutable) + is static; + + SetCurve(me : mutable; C : HCurve from Adaptor3d) + is redefined; + +-- +-- +--========== To compute Location and derivatives Location +-- + D0(me : mutable; + Param: Real; + Tangent : out Vec from gp; + Normal : out Vec from gp; + BiNormal : out Vec from gp) + ---Purpose: compute Trihedron on curve at parameter + returns Boolean is redefined; + + D1(me : mutable; + Param: Real; + Tangent : out Vec from gp; + DTangent : out Vec from gp; + Normal : out Vec from gp; + DNormal : out Vec from gp; + BiNormal : out Vec from gp; + DBiNormal : out Vec from gp) + ---Purpose: compute Trihedron and derivative Trihedron on curve + -- at parameter + -- Warning : It used only for C1 or C2 aproximation + -- For the moment it returns null values for DTangent, DNormal + -- and DBiNormal. + returns Boolean + is redefined; + + D2(me : mutable; + Param: Real; + Tangent : out Vec from gp; + DTangent : out Vec from gp; + D2Tangent : out Vec from gp; + Normal : out Vec from gp; + DNormal : out Vec from gp; + D2Normal : out Vec from gp; + BiNormal : out Vec from gp; + DBiNormal : out Vec from gp; + D2BiNormal : out Vec from gp) + ---Purpose: compute Trihedron on curve + -- first and seconde derivatives. + -- Warning : It used only for C2 aproximation + -- For the moment it returns null values for DTangent, DNormal + -- DBiNormal, D2Tangent, D2Normal, D2BiNormal. + returns Boolean + is redefined; +-- +-- =================== Management of continuity =================== +-- + NbIntervals(me; S : Shape from GeomAbs) + ---Purpose: Returns the number of intervals for continuity + -- . + -- May be one if Continuity(me) >= + returns Integer is redefined; + + Intervals(me; T : in out Array1OfReal from TColStd; + S : Shape from GeomAbs) + ---Purpose: Stores in the parameters bounding the intervals + -- of continuity . + -- + -- The array must provide enough room to accomodate + -- for the parameters. i.e. T.Length() > NbIntervals() + raises + OutOfRange from Standard + is redefined; + + +-- =================== To help computation of Tolerance =============== + GetAverageLaw(me : mutable; + ATangent : out Vec from gp; + ANormal : out Vec from gp; + ABiNormal : out Vec from gp) + ---Purpose: Get average value of Tangent(t) and Normal(t) it is usful to + -- make fast approximation of rational surfaces. + is redefined; + +-- =================== To help Particular case =============== + + IsConstant(me) + ---Purpose: Say if the law is Constant. + returns Boolean + is redefined; + + IsOnlyBy3dCurve(me) + ---Purpose: Return True. + returns Boolean + is redefined; + + +fields + + myPoint : Pnt from gp; + myTrihedrons : HSequenceOfAx2 from GeomFill; + myKnots : HSequenceOfReal from TColStd; + myFrenet : Frenet from GeomFill; + myUseFrenet : Boolean from Standard; + +end DiscreteTrihedron; diff --git a/src/GeomFill/GeomFill_DiscreteTrihedron.cxx b/src/GeomFill/GeomFill_DiscreteTrihedron.cxx new file mode 100644 index 0000000000..6a74bfbf0f --- /dev/null +++ b/src/GeomFill/GeomFill_DiscreteTrihedron.cxx @@ -0,0 +1,392 @@ +// Created on: 2013-02-05 +// Created by: Julia GERASIMOVA +// Copyright (c) 2001-2013 OPEN CASCADE SAS +// +// The content of this file is subject to the Open CASCADE Technology Public +// License Version 6.5 (the "License"). You may not use the content of this file +// except in compliance with the License. Please obtain a copy of the License +// at http://www.opencascade.org and read it completely before using this file. +// +// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its +// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France. +// +// The Original Code and all software distributed under the License is +// distributed on an "AS IS" basis, without warranty of any kind, and the +// Initial Developer hereby disclaims all such warranties, including without +// limitation, any warranties of merchantability, fitness for a particular +// purpose or non-infringement. Please see the License for the specific terms +// and conditions governing the rights and limitations under the License. + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const Standard_Real TolConf = Precision::Confusion(); + +//======================================================================= +//function : GeomFill_DiscreteTrihedron +//purpose : Constructor +//======================================================================= + +GeomFill_DiscreteTrihedron::GeomFill_DiscreteTrihedron() +{ + myFrenet = new GeomFill_Frenet(); + myKnots = new TColStd_HSequenceOfReal(); + myTrihedrons = new GeomFill_HSequenceOfAx2(); +} + +//======================================================================= +//function : Copy +//purpose : +//======================================================================= + +Handle(GeomFill_TrihedronLaw) GeomFill_DiscreteTrihedron::Copy() const +{ + Handle(GeomFill_DiscreteTrihedron) copy = new (GeomFill_DiscreteTrihedron)(); + if (!myCurve.IsNull()) copy->SetCurve(myCurve); + return copy; +} + +//======================================================================= +//function : SetCurve +//purpose : +//======================================================================= + +void GeomFill_DiscreteTrihedron::SetCurve(const Handle(Adaptor3d_HCurve)& C) +{ + GeomFill_TrihedronLaw::SetCurve(C); + if (! C.IsNull()) { + GeomAbs_CurveType type; + type = C->GetType(); + switch (type) { + case GeomAbs_Circle: + case GeomAbs_Ellipse: + case GeomAbs_Hyperbola: + case GeomAbs_Parabola: + case GeomAbs_Line: + { + // No probleme + myUseFrenet = Standard_True; + myFrenet->SetCurve(C); + break; + } + default : + { + myUseFrenet = Standard_False; + // We have to fill and + Init(); + break; + } + } + } +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= + +void GeomFill_DiscreteTrihedron::Init() +{ + Standard_Integer NbIntervals = myTrimmed->NbIntervals(GeomAbs_CN); + TColStd_Array1OfReal Knots(1, NbIntervals+1); + myTrimmed->Intervals(Knots, GeomAbs_CN); + + //Standard_Real Tol = Precision::Confusion(); + Standard_Integer NbSamples = 10; + + Standard_Integer i, j; + for (i = 1; i <= NbIntervals; i++) + { + Standard_Real delta = (Knots(i+1) - Knots(i))/NbSamples; + for (j = 0; j < NbSamples; j++) + { + Standard_Real Param = Knots(i) + j*delta; + myKnots->Append(Param); + } + } + myKnots->Append(Knots(NbIntervals+1)); + + + gp_Pnt Origin(0.,0.,0.), Pnt, SubPnt; + gp_Vec Tangent; + gp_Dir TangDir; + Standard_Real norm; + for (i = 1; i <= myKnots->Length(); i++) + { + Standard_Real Param = myKnots->Value(i); + myTrimmed->D1(Param, Pnt, Tangent); + norm = Tangent.Magnitude(); + if (norm < TolConf) + { + Standard_Real subdelta = (myKnots->Value(i+1) - myKnots->Value(i))/NbSamples; + if (subdelta < Precision::PConfusion()) + subdelta = myKnots->Value(i+1) - myKnots->Value(i); + SubPnt = myTrimmed->Value(Param + subdelta); + Tangent.SetXYZ(SubPnt.XYZ() - Pnt.XYZ()); + } + //Tangent.Normalize(); + TangDir = Tangent; //normalize; + Tangent = TangDir; + if (i == 1) //first point + { + gp_Ax2 FirstAxis(Origin, TangDir); + myTrihedrons->Append(FirstAxis); + } + else + { + gp_Ax2 LastAxis = myTrihedrons->Value(myTrihedrons->Length()); + gp_Vec LastTangent = LastAxis.Direction(); + gp_Vec AxisOfRotation = LastTangent ^ Tangent; + if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal or opposite + { + Standard_Real ScalarProduct = LastTangent * Tangent; + if (ScalarProduct > 0.) //tangents are equal + myTrihedrons->Append(LastAxis); + else //tangents are opposite + { + Standard_Real NewParam = (myKnots->Value(i-1) + myKnots->Value(i))/2.; + if (NewParam - myKnots->Value(i-1) < gp::Resolution()) + Standard_ConstructionError::Raise("GeomFill_DiscreteTrihedron : impassable singularities on path curve"); + myKnots->InsertBefore(i, NewParam); + i--; + } + } + else //good value of angle + { + Standard_Real theAngle = LastTangent.AngleWithRef(Tangent, AxisOfRotation); + gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation); + gp_Ax2 NewAxis = LastAxis.Rotated(theAxisOfRotation, theAngle); + NewAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error + myTrihedrons->Append(NewAxis); + } + } + } +} + +//======================================================================= +//function : D0 +//purpose : +//======================================================================= + +Standard_Boolean GeomFill_DiscreteTrihedron::D0(const Standard_Real Param, + gp_Vec& Tangent, + gp_Vec& Normal, + gp_Vec& BiNormal) +{ + if (myUseFrenet) + { + myFrenet->D0(Param, Tangent, Normal, BiNormal); + } + else + { + //Locate in the sequence + Standard_Integer Index = -1; + Standard_Real TolPar = Precision::PConfusion(); + //Standard_Real TolConf = Precision::Confusion(); + Standard_Integer NbSamples = 10; + gp_Pnt Origin(0.,0.,0.); + + Standard_Integer i; + //gp_Ax2 PrevAxis; + //Standard_Real PrevParam; + + Standard_Integer I1, I2; + I1 = 1; + I2 = myKnots->Length(); + for (;;) + { + i = (I1 + I2)/2; + if (Param <= myKnots->Value(i)) + I2 = i; + else + I1 = i; + if (I2 - I1 <= 1) + break; + } + Index = I1; + if (Abs(Param - myKnots->Value(I2)) < TolPar) + Index = I2; + + Standard_Real PrevParam = myKnots->Value(Index); + gp_Ax2 PrevAxis = myTrihedrons->Value(Index); + gp_Ax2 theAxis; + if (Abs(Param - PrevParam) < TolPar) + theAxis = PrevAxis; + else // is between knots + { + myTrimmed->D1(Param, myPoint, Tangent); + Standard_Real norm = Tangent.Magnitude(); + if (norm < TolConf) + { + Standard_Real subdelta = (myKnots->Value(Index+1) - Param)/NbSamples; + if (subdelta < Precision::PConfusion()) + subdelta = myKnots->Value(Index+1) - Param; + gp_Pnt SubPnt = myTrimmed->Value(Param + subdelta); + Tangent.SetXYZ(SubPnt.XYZ() - myPoint.XYZ()); + } + //Tangent.Normalize(); + gp_Dir TangDir(Tangent); //normalize; + Tangent = TangDir; + gp_Vec PrevTangent = PrevAxis.Direction(); + gp_Vec AxisOfRotation = PrevTangent ^ Tangent; + if (AxisOfRotation.Magnitude() <= gp::Resolution()) //tangents are equal + { + //we assume that tangents can not be opposite + theAxis = PrevAxis; + } + else //good value of angle + { + Standard_Real theAngle = PrevTangent.AngleWithRef(Tangent, AxisOfRotation); + gp_Ax1 theAxisOfRotation(Origin, AxisOfRotation); + theAxis = PrevAxis.Rotated(theAxisOfRotation, theAngle); + } + theAxis.SetDirection(TangDir); //to prevent accumulation of floating computations error + } //end of else (Param is between knots) + + Tangent = theAxis.Direction(); + Normal = theAxis.XDirection(); + BiNormal = theAxis.YDirection(); + } + return Standard_True; +} + +//======================================================================= +//function : D1 +//purpose : +//======================================================================= + +Standard_Boolean GeomFill_DiscreteTrihedron::D1(const Standard_Real Param, + gp_Vec& Tangent, + gp_Vec& DTangent, + gp_Vec& Normal, + gp_Vec& DNormal, + gp_Vec& BiNormal, + gp_Vec& DBiNormal) +{ + if (myUseFrenet) + { + myFrenet->D1(Param, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal); + } + else + { + D0(Param, Tangent, Normal, BiNormal); + + DTangent.SetCoord(0.,0.,0.); + DNormal.SetCoord(0.,0.,0.); + DBiNormal.SetCoord(0.,0.,0.); + } + return Standard_True; +} + +//======================================================================= +//function : D2 +//purpose : +//======================================================================= + +Standard_Boolean GeomFill_DiscreteTrihedron::D2(const Standard_Real Param, + gp_Vec& Tangent, + gp_Vec& DTangent, + gp_Vec& D2Tangent, + gp_Vec& Normal, + gp_Vec& DNormal, + gp_Vec& D2Normal, + gp_Vec& BiNormal, + gp_Vec& DBiNormal, + gp_Vec& D2BiNormal) +{ + if (myUseFrenet) + { + myFrenet->D2(Param, Tangent, DTangent, D2Tangent, + Normal, DNormal, D2Normal, + BiNormal, DBiNormal, D2BiNormal); + } + else + { + D0(Param, Tangent, Normal, BiNormal); + + DTangent.SetCoord(0.,0.,0.); + DNormal.SetCoord(0.,0.,0.); + DBiNormal.SetCoord(0.,0.,0.); + D2Tangent.SetCoord(0.,0.,0.); + D2Normal.SetCoord(0.,0.,0.); + D2BiNormal.SetCoord(0.,0.,0.); + } + return Standard_True; +} + +//======================================================================= +//function : NbIntervals +//purpose : +//======================================================================= + +Standard_Integer GeomFill_DiscreteTrihedron::NbIntervals(const GeomAbs_Shape S) const +{ + return (myTrimmed->NbIntervals(GeomAbs_CN)); +} + +//======================================================================= +//function : Intervals +//purpose : +//======================================================================= + +void GeomFill_DiscreteTrihedron::Intervals(TColStd_Array1OfReal& T, + const GeomAbs_Shape S) const +{ + myTrimmed->Intervals(T, GeomAbs_CN); +} + + void GeomFill_DiscreteTrihedron::GetAverageLaw(gp_Vec& ATangent, + gp_Vec& ANormal, + gp_Vec& ABiNormal) +{ + Standard_Integer Num = 20; //order of digitalization + gp_Vec T, N, BN; + ATangent = gp_Vec(0, 0, 0); + ANormal = gp_Vec(0, 0, 0); + ABiNormal = gp_Vec(0, 0, 0); + Standard_Real Step = (myTrimmed->LastParameter() - + myTrimmed->FirstParameter()) / Num; + Standard_Real Param; + for (Standard_Integer i = 0; i <= Num; i++) { + Param = myTrimmed->FirstParameter() + i*Step; + if (Param > myTrimmed->LastParameter()) Param = myTrimmed->LastParameter(); + D0(Param, T, N, BN); + ATangent += T; + ANormal += N; + ABiNormal += BN; + } + ATangent /= Num + 1; + ANormal /= Num + 1; + + ATangent.Normalize(); + ABiNormal = ATangent.Crossed(ANormal).Normalized(); + ANormal = ABiNormal.Crossed(ATangent); +} + +//======================================================================= +//function : IsConstant +//purpose : +//======================================================================= + + Standard_Boolean GeomFill_DiscreteTrihedron::IsConstant() const +{ + return (myCurve->GetType() == GeomAbs_Line); +} + +//======================================================================= +//function : IsOnlyBy3dCurve +//purpose : +//======================================================================= + + Standard_Boolean GeomFill_DiscreteTrihedron::IsOnlyBy3dCurve() const +{ + return Standard_True; +} diff --git a/src/GeomFill/GeomFill_Frenet.cdl b/src/GeomFill/GeomFill_Frenet.cdl index 16a95e49df..2036593a55 100755 --- a/src/GeomFill/GeomFill_Frenet.cdl +++ b/src/GeomFill/GeomFill_Frenet.cdl @@ -141,7 +141,8 @@ is DoSingular(me: mutable; U: Real; Index: Integer; Tangent, BiNormal: out Vec from gp; - n, k, TFlag, BNFlag: out Integer) + n, k, TFlag, BNFlag: out Integer; + Delta: out Real) returns Boolean is private; @@ -149,7 +150,8 @@ is Param: Real; Index: Integer; Tangent : out Vec from gp; Normal : out Vec from gp; - BiNormal : out Vec from gp) + BiNormal : out Vec from gp; + Delta : out Real) ---Purpose: computes Triedrhon on curve at parameter returns Boolean is private; @@ -161,7 +163,8 @@ is Normal : out Vec from gp; DNormal : out Vec from gp; BiNormal : out Vec from gp; - DBiNormal : out Vec from gp) + DBiNormal : out Vec from gp; + Delta : out Real) ---Purpose: computes Triedrhon and derivative Trihedron on curve -- at parameter -- Warning : It used only for C1 or C2 aproximation @@ -178,7 +181,8 @@ is D2Normal : out Vec from gp; BiNormal : out Vec from gp; DBiNormal : out Vec from gp; - D2BiNormal : out Vec from gp) + D2BiNormal : out Vec from gp; + Delta : out Real) ---Purpose: computes Trihedron on curve -- first and seconde derivatives. -- Warning : It used only for C2 aproximation diff --git a/src/GeomFill/GeomFill_Frenet.cxx b/src/GeomFill/GeomFill_Frenet.cxx index 0008c740c6..964f0040d3 100755 --- a/src/GeomFill/GeomFill_Frenet.cxx +++ b/src/GeomFill/GeomFill_Frenet.cxx @@ -326,11 +326,13 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const { Standard_Real norm; Standard_Integer Index; + Standard_Real Delta = 0.; if(IsSingular(Param, Index)) - if (SingularD0(Param, Index, Tangent, Normal, BiNormal)) + if (SingularD0(Param, Index, Tangent, Normal, BiNormal, Delta)) return Standard_True; - myTrimmed->D2(Param, P, Tangent, BiNormal); + Standard_Real theParam = Param + Delta; + myTrimmed->D2(theParam, P, Tangent, BiNormal); Tangent.Normalize(); BiNormal = Tangent.Crossed(BiNormal); norm = BiNormal.Magnitude(); @@ -360,13 +362,15 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const gp_Vec& DBiNormal) { Standard_Integer Index; + Standard_Real Delta = 0.; if(IsSingular(Param, Index)) - if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal)) + if (SingularD1(Param, Index, Tangent, DTangent, Normal, DNormal, BiNormal, DBiNormal, Delta)) return Standard_True; // Standard_Real Norma; + Standard_Real theParam = Param + Delta; gp_Vec DC1, DC2, DC3; - myTrimmed->D3(Param, P, DC1, DC2, DC3); + myTrimmed->D3(theParam, P, DC1, DC2, DC3); Tangent = DC1.Normalized(); //if (DC2.Magnitude() <= NullTol || Tangent.Crossed(DC2).Magnitude() <= NullTol) { @@ -412,16 +416,19 @@ Handle(GeomFill_TrihedronLaw) GeomFill_Frenet::Copy() const gp_Vec& D2BiNormal) { Standard_Integer Index; + Standard_Real Delta = 0.; if(IsSingular(Param, Index)) if(SingularD2(Param, Index, Tangent, DTangent, D2Tangent, Normal, DNormal, D2Normal, - BiNormal, DBiNormal, D2BiNormal)) + BiNormal, DBiNormal, D2BiNormal, + Delta)) return Standard_True; // Standard_Real Norma; + Standard_Real theParam = Param + Delta; gp_Vec DC1, DC2, DC3, DC4; - myTrimmed->D3(Param, P, DC1, DC2, DC3); - DC4 = myTrimmed->DN(Param, 4); + myTrimmed->D3(theParam, P, DC1, DC2, DC3); + DC4 = myTrimmed->DN(theParam, 4); Tangent = DC1.Normalized(); @@ -604,9 +611,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, Standard_Integer& n, Standard_Integer& k, Standard_Integer& TFlag, - Standard_Integer& BNFlag) + Standard_Integer& BNFlag, + Standard_Real& Delta) { Standard_Integer i, MaxN = 20; + Delta = 0.; Standard_Real h; h = 2*mySnglLen->Value(Index); @@ -615,7 +624,8 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, TFlag = 1; BNFlag = 1; GetInterval(A, B); - if (U >= (A + B)/2) h = -h; + if (U >= (A + B)/2) + h = -h; for(i = 1; i <= MaxN; i++) { Tangent = myTrimmed->DN(U, i); if(Tangent.Magnitude() > Precision::Confusion()) break; @@ -641,7 +651,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, break; } } - if (i > MaxN) return Standard_False; + if (i > MaxN) + { + Delta = h; + return Standard_False; + } + BiNormal.Normalize(); k = i; @@ -657,11 +672,14 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, const Standard_Integer Index, gp_Vec& Tangent, gp_Vec& Normal, - gp_Vec& BiNormal) + gp_Vec& BiNormal, + Standard_Real& Delta) { Standard_Integer n, k, TFlag, BNFlag; if(!DoSingular(Param, Index, Tangent, BiNormal, - n, k, TFlag, BNFlag)) return Standard_False; + n, k, TFlag, BNFlag, Delta)) + return Standard_False; + Tangent *= TFlag; BiNormal *= BNFlag; Normal = BiNormal; @@ -674,10 +692,12 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, const Standard_Integer Index, gp_Vec& Tangent,gp_Vec& DTangent, gp_Vec& Normal,gp_Vec& DNormal, - gp_Vec& BiNormal,gp_Vec& DBiNormal) + gp_Vec& BiNormal,gp_Vec& DBiNormal, + Standard_Real& Delta) { Standard_Integer n, k, TFlag, BNFlag; - if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag)) return Standard_False; + if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta)) + return Standard_False; gp_Vec F, DF, Dtmp; F = myTrimmed->DN(Param, n); @@ -715,10 +735,11 @@ Standard_Boolean GeomFill_Frenet::DoSingular(const Standard_Real U, gp_Vec& D2Normal, gp_Vec& BiNormal, gp_Vec& DBiNormal, - gp_Vec& D2BiNormal) + gp_Vec& D2BiNormal, + Standard_Real& Delta) { Standard_Integer n, k, TFlag, BNFlag; - if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag)) + if(!DoSingular(Param, Index, Tangent, BiNormal, n, k, TFlag, BNFlag, Delta)) return Standard_False; gp_Vec F, DF, D2F, Dtmp1, Dtmp2; diff --git a/src/GeomFill/GeomFill_Sweep.cdl b/src/GeomFill/GeomFill_Sweep.cdl index 2ed676fa82..9cddc73480 100755 --- a/src/GeomFill/GeomFill_Sweep.cdl +++ b/src/GeomFill/GeomFill_Sweep.cdl @@ -78,7 +78,12 @@ is -- beetween tangents on the section law and -- tangent of iso-v on approximed surface - + SetForceApproxC1(me : in out; + ForceApproxC1 : Boolean from Standard); + ---Purpose: Set the flag that indicates attempt to approximate + -- a C1-continuous surface if a swept surface proved + -- to be C0. + ExchangeUV(me) ---Purpose: returns true if sections are U-Iso -- This can be produce in some cases when is True. @@ -184,8 +189,9 @@ fields First, Last : Real; SFirst, SLast: Real; Tol3d, BoundTol, Tol2d, TolAngular : Real; - SError : Real; - + SError : Real; + myForceApproxC1 : Boolean; + myLoc : LocationLaw from GeomFill; mySec : SectionLaw from GeomFill; mySurface : Surface from Geom; diff --git a/src/GeomFill/GeomFill_Sweep.cxx b/src/GeomFill/GeomFill_Sweep.cxx index 317649b302..431a30ef2d 100755 --- a/src/GeomFill/GeomFill_Sweep.cxx +++ b/src/GeomFill/GeomFill_Sweep.cxx @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,7 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location, myLoc = Location; myKPart = WithKpart; SetTolerance(1.e-4); + myForceApproxC1 = Standard_False; myLoc->GetDomain(First, Last); SFirst = SLast = 30.081996; @@ -157,6 +159,18 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location, TolAngular = ToleranceAngular; } +//======================================================================= +//Function : SetForceApproxC1 +//Purpose : Set the flag that indicates attempt to approximate +// a C1-continuous surface if a swept surface proved +// to be C0. +//======================================================================= + void GeomFill_Sweep::SetForceApproxC1(const Standard_Boolean ForceApproxC1) +{ + myForceApproxC1 = ForceApproxC1; +} + + //=============================================================== // Function : ExchangeUV // Purpose : @@ -298,56 +312,101 @@ GeomFill_Sweep::GeomFill_Sweep(const Handle(GeomFill_LocationLaw)& Location, Approx.UDegree(), Approx.VDegree(), mySec->IsUPeriodic()); SError = Approx. MaxErrorOnSurf(); + + if (myForceApproxC1 && !mySurface->IsCNv(1)) + { + Standard_Real theTol = 1.e-4; + GeomAbs_Shape theUCont = GeomAbs_C1, theVCont = GeomAbs_C1; + Standard_Integer degU = 14, degV = 14; + Standard_Integer nmax = 16; + Standard_Integer thePrec = 1; + + GeomConvert_ApproxSurface ConvertApprox(mySurface,theTol,theUCont,theVCont, + degU,degV,nmax,thePrec); + if (ConvertApprox.HasResult()) + { + mySurface = ConvertApprox.Surface(); + myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2); + CError = new (TColStd_HArray2OfReal) (1,2, 1,2); + + const Handle(Geom_BSplineSurface)& BSplSurf = + Handle(Geom_BSplineSurface)::DownCast(mySurface); + + gp_Dir2d D(0., 1.); + gp_Pnt2d P(BSplSurf->UKnot(1), 0); + Handle(Geom2d_Line) LC1 = new (Geom2d_Line) (P, D); + Handle(Geom2d_TrimmedCurve) TC1 = + new (Geom2d_TrimmedCurve) (LC1, 0, BSplSurf->VKnot(BSplSurf->NbVKnots())); + + myCurve2d->SetValue(1, TC1); + CError->SetValue(1, 1, 0.); + CError->SetValue(2, 1, 0.); + + P.SetCoord(BSplSurf->UKnot(BSplSurf->NbUKnots()), 0); + Handle(Geom2d_Line) LC2 = new (Geom2d_Line) (P, D); + Handle(Geom2d_TrimmedCurve) TC2 = + new (Geom2d_TrimmedCurve) (LC2, 0, BSplSurf->VKnot(BSplSurf->NbVKnots())); + + myCurve2d->SetValue(myCurve2d->Length(), TC2); + CError->SetValue(1, myCurve2d->Length(), 0.); + CError->SetValue(2, myCurve2d->Length(), 0.); + + SError = theTol; + } + } //if (!mySurface->IsCNv(1)) // Les Courbes 2d - myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber()); - CError = new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber()); - Standard_Integer kk,ii, ifin = 1, ideb; - - if (myLoc->HasFirstRestriction()) { - ideb = 1; - } - else { - ideb = 2; - } - ifin += myLoc->TraceNumber(); - if (myLoc->HasLastRestriction()) ifin++; - - for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) { - Handle(Geom2d_BSplineCurve) C - = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk), - Approx.Curves2dKnots(), - Approx.Curves2dMults(), - Approx.Curves2dDegree()); - myCurve2d->SetValue(ii, C); - CError->SetValue(1, ii, Approx.Max2dError(kk)); - CError->SetValue(2, ii, Approx.Max2dError(kk)); - } - - // Si les courbes de restriction, ne sont pas calcules, on prend - // les iso Bords. - if (! myLoc->HasFirstRestriction()) { - gp_Dir2d D(0., 1.); - gp_Pnt2d P(UKnots(UKnots.Lower()), 0); - Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D); - Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve) - (LC, First, Last); - - myCurve2d->SetValue(1, TC); - CError->SetValue(1, 1, 0.); - CError->SetValue(2, 1, 0.); - } - - if (! myLoc->HasLastRestriction()) { - gp_Dir2d D(0., 1.); - gp_Pnt2d P(UKnots(UKnots.Upper()), 0); - Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D); - Handle(Geom2d_TrimmedCurve) TC = - new (Geom2d_TrimmedCurve) (LC, First, Last); - myCurve2d->SetValue(myCurve2d->Length(), TC); - CError->SetValue(1, myCurve2d->Length(), 0.); - CError->SetValue(2, myCurve2d->Length(), 0.); - } + if (myCurve2d.IsNull()) + { + myCurve2d = new (TColGeom2d_HArray1OfCurve) (1, 2+myLoc->TraceNumber()); + CError = new (TColStd_HArray2OfReal) (1,2, 1, 2+myLoc->TraceNumber()); + Standard_Integer kk,ii, ifin = 1, ideb; + + if (myLoc->HasFirstRestriction()) { + ideb = 1; + } + else { + ideb = 2; + } + ifin += myLoc->TraceNumber(); + if (myLoc->HasLastRestriction()) ifin++; + + for (ii=ideb, kk=1; ii<=ifin; ii++, kk++) { + Handle(Geom2d_BSplineCurve) C + = new (Geom2d_BSplineCurve) (Approx.Curve2dPoles(kk), + Approx.Curves2dKnots(), + Approx.Curves2dMults(), + Approx.Curves2dDegree()); + myCurve2d->SetValue(ii, C); + CError->SetValue(1, ii, Approx.Max2dError(kk)); + CError->SetValue(2, ii, Approx.Max2dError(kk)); + } + + // Si les courbes de restriction, ne sont pas calcules, on prend + // les iso Bords. + if (! myLoc->HasFirstRestriction()) { + gp_Dir2d D(0., 1.); + gp_Pnt2d P(UKnots(UKnots.Lower()), 0); + Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D); + Handle(Geom2d_TrimmedCurve) TC = new (Geom2d_TrimmedCurve) + (LC, First, Last); + + myCurve2d->SetValue(1, TC); + CError->SetValue(1, 1, 0.); + CError->SetValue(2, 1, 0.); + } + + if (! myLoc->HasLastRestriction()) { + gp_Dir2d D(0., 1.); + gp_Pnt2d P(UKnots(UKnots.Upper()), 0); + Handle(Geom2d_Line) LC = new (Geom2d_Line) (P, D); + Handle(Geom2d_TrimmedCurve) TC = + new (Geom2d_TrimmedCurve) (LC, First, Last); + myCurve2d->SetValue(myCurve2d->Length(), TC); + CError->SetValue(1, myCurve2d->Length(), 0.); + CError->SetValue(2, myCurve2d->Length(), 0.); + } + } //if (myCurve2d.IsNull()) } return Ok; } diff --git a/tests/bugs/modalg_5/bug23824_1 b/tests/bugs/modalg_5/bug23824_1 new file mode 100755 index 0000000000..08189cb801 --- /dev/null +++ b/tests/bugs/modalg_5/bug23824_1 @@ -0,0 +1,33 @@ +puts "============" +puts "OCC23824" +puts "============" +puts "" +####################################################################### +# Bad results of sweep operation when a path curve has unpredictable torsion along its way. +####################################################################### + +set BugNumber OCC23824 + +restore [locate_data_file bug23824_AXE.brep] spine +restore [locate_data_file bug23824_profil.brep] profile + +wire spine spine + +mksweep spine +setsweep -DT +addsweep profile +buildsweep result + +set square 516.633 + +set nb_v_good 8 +set nb_e_good 10 +set nb_w_good 3 +set nb_f_good 3 +set nb_sh_good 1 +set nb_sol_good 0 +set nb_compsol_good 0 +set nb_compound_good 0 +set nb_shape_good 25 + +set 2dviewer 1 diff --git a/tests/bugs/modalg_5/bug23824_2 b/tests/bugs/modalg_5/bug23824_2 new file mode 100755 index 0000000000..2bf29b7b83 --- /dev/null +++ b/tests/bugs/modalg_5/bug23824_2 @@ -0,0 +1,34 @@ +puts "============" +puts "OCC23824" +puts "============" +puts "" +####################################################################### +# Bad results of sweep operation when a path curve has unpredictable torsion along its way. +####################################################################### + +set BugNumber OCC23824 + +restore [locate_data_file bug23824_Case1_Path.brep] spine +restore [locate_data_file bug23824_Case1_Profile.brep] profile + +wire spine spine +wire profile profile + +mksweep spine +setsweep -DT +addsweep profile +buildsweep result + +set square 8997.97 + +set nb_v_good 2 +set nb_e_good 3 +set nb_w_good 1 +set nb_f_good 1 +set nb_sh_good 1 +set nb_sol_good 0 +set nb_compsol_good 0 +set nb_compound_good 0 +set nb_shape_good 8 + +set 2dviewer 1 diff --git a/tests/bugs/modalg_5/bug23824_3 b/tests/bugs/modalg_5/bug23824_3 new file mode 100755 index 0000000000..81f9803d4d --- /dev/null +++ b/tests/bugs/modalg_5/bug23824_3 @@ -0,0 +1,35 @@ +puts "============" +puts "OCC23824" +puts "============" +puts "" +####################################################################### +# Bad results of sweep operation when a path curve has unpredictable torsion along its way. +####################################################################### + +set BugNumber OCC23824 + +restore [locate_data_file bug23824_Case2_Path.brep] spine +restore [locate_data_file bug23824_Case2_Profile.brep] profile + +wire spine spine +wire profile profile + +mksweep spine +setsweep -DT +addsweep profile + +buildsweep result + +set square 848.989 + +set nb_v_good 2 +set nb_e_good 3 +set nb_w_good 1 +set nb_f_good 1 +set nb_sh_good 1 +set nb_sol_good 0 +set nb_compsol_good 0 +set nb_compound_good 0 +set nb_shape_good 8 + +set 2dviewer 1 diff --git a/tests/bugs/modalg_5/bug23824_4 b/tests/bugs/modalg_5/bug23824_4 new file mode 100755 index 0000000000..baa5da5f2f --- /dev/null +++ b/tests/bugs/modalg_5/bug23824_4 @@ -0,0 +1,35 @@ +puts "============" +puts "OCC23824" +puts "============" +puts "" +####################################################################### +# Bad results of sweep operation when a path curve has unpredictable torsion along its way. +####################################################################### + +set BugNumber OCC23824 + +restore [locate_data_file bug23824_Case3_Path.brep] spine +restore [locate_data_file bug23824_Case3_Profile.brep] profile + +wire profile profile +explode spine +wire spine spine_1 + +mksweep spine +setsweep -DT +addsweep profile +buildsweep result + +set square 38260.5 + +set nb_v_good 2 +set nb_e_good 3 +set nb_w_good 1 +set nb_f_good 1 +set nb_sh_good 1 +set nb_sol_good 0 +set nb_compsol_good 0 +set nb_compound_good 0 +set nb_shape_good 8 + +set 2dviewer 1