OCAF : VISUALIZATION, OCAFKERNEL
DATAEXCHANGE : XDE, VISUALIZATION
XDE : DATAEXCHANGEKERNEL, XDEDRAW
+HELIX : TestHelix
+UNFOLDING : TestUnfolding
FULL : MODELING, OCAFKERNEL, VISUALIZATION
-ALL : MODELING, OCAFKERNEL, DATAEXCHANGE
+ALL : MODELING, OCAFKERNEL, DATAEXCHANGE, HELIX, UNFOLDING
+
TOPTEST : TKTopTest
DCAF : TKDCAF
DFBROWSER : TKDFBrowser
QAcommands : TKQADraw
VIS : TKIVtkDraw
+TestHelix : TKHelix
+TestUnfolding : TKUnfoldingTest
\ No newline at end of file
--- /dev/null
+! Description of available plugins for DRAW Test Harness
+! *****************************************************************************
+!
+! Format of the file is compliant with the standard Open CASCADE resource files
+! (see the Resource_Manager.cdl file for details).
+!
+! Each key defines a sequence of either further keys or a name of the dynamic
+! library. Keys can be nested down to an arbitrary level. However, make sure
+! there are no cyclic dependencies (internal checks are not performed).
+!
+! For details how to implement a DRAW plugin refer to the Test Harness User's
+! Guide.
+!
+! To load a plugin use the following command in DRAW:
+!
+! Draw> pload [-PluginFileName] [[Key1] [Key2]...], where:
+! <-PluginFileName> - Defines the name of a resource file.
+! If this parameter is omitted then the default name DrawPlugin
+! is used.
+! According to the Open CASCADE resource file management rules
+! the environment variable CSF_<PluginFileName>Defaults must
+! be set and point to the directory storing the file. If it is
+! omitted then it defaults to $CASROOT/src/DrawResources.
+! [Key] - Defines the key(s) enumerating plugins to be loaded.
+! If no keys are specified then the key named DEFAULT is used
+! (if there is no such in the file then no plugins are loaded).
+!
+!
+! NOTE: Make sure the DATAEXCHANGE or XDE key succeeds the OCAF key in a sequence
+!
+
+DEFAULT : MODELING
+MODELING : TOPTEST
+VISUALIZATION : AISV
+OCAFKERNEL : DCAF
+DATAEXCHANGEKERNEL : XSDRAW
+OCAF : VISUALIZATION, OCAFKERNEL
+DATAEXCHANGE : XDE, VISUALIZATION
+XDE : DATAEXCHANGEKERNEL, XDEDRAW
+FULL : MODELING, OCAFKERNEL, VISUALIZATION
+ALL : MODELING, OCAFKERNEL, DATAEXCHANGE
+
+TOPTEST : TKTopTest
+DCAF : TKDCAF
+AISV : TKViewerTest
+XSDRAW : TKXSDRAW
+XDEDRAW : TKXDEDRAW
+TOBJ : TKTObjDRAW
+DFBROWSER : TKDFBrowser
+QAcommands : TKQADraw
+VIS : TKIVtkDraw
--- /dev/null
+-- File: HelixBRep.cdl
+
+
+package HelixBRep
+
+ ---Purpose:
+
+uses
+ gp,
+ TopoDS,
+ GeomAbs,
+ TColStd,
+ TopTools,
+ HelixGeom
+
+is
+ class BuilderHelix;
+
+
+end HelixBRep;
+
--- /dev/null
+-- File: HelixBRep_BuilderHelix.cdl
+
+class BuilderHelix from HelixBRep
+ ---Purpose: Implementation of building helix wire
+ -- Values of Error Status returned by algo:
+ -- 0 - OK
+ -- 1 - object is just initialized, it means that no input parameters were set
+ -- 2 - approximation fails
+ --
+ -- 10 - R < tolerance - starting point is too close to axis
+ -- 11 - step (Pitch) < tolerancee
+ -- 12 - Height < tolerance
+ -- 13 - TaperAngle < 0 or TaperAngle > Pi/2 - TolAng
+ -- Warning Status:
+ -- 0 - OK
+ -- 1 - tolerance reached by approximation > requested tolerance.
+
+uses
+ Ax1 from gp,
+ Ax3 from gp,
+ Pnt from gp,
+ Array1OfReal from TColStd,
+ HArray1OfReal from TColStd,
+ Array1OfBoolean from TColStd,
+ HArray1OfBoolean from TColStd,
+ Shape from GeomAbs,
+ Shape from TopoDS,
+ Wire from TopoDS,
+ Edge from TopoDS,
+ ListOfShape from TopTools
+
+is
+
+ Create
+ ---Purpose: Empty constructor
+ returns BuilderHelix from HelixBRep;
+ ---C++: alias "Standard_EXPORT virtual ~HelixBRep_BuilderHelix();"
+
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiams: Array1OfReal from TColStd;
+ theHeights: Array1OfReal from TColStd ;
+ thePitches: Array1OfReal from TColStd ;
+ theIsPitches: Array1OfBoolean from TColStd);
+ ---Purpose: Sets parameters of general composite helix
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiam: Real from Standard;
+ theHeights: Array1OfReal from TColStd ;
+ thePitches: Array1OfReal from TColStd ;
+ theIsPitches: Array1OfBoolean from TColStd);
+ ---Purpose: Sets parameters of pure helix
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiam1: Real from Standard;
+ theDiam2: Real from Standard;
+ theHeights: Array1OfReal from TColStd ;
+ thePitches: Array1OfReal from TColStd ;
+ theIsPitches: Array1OfBoolean from TColStd);
+ ---Purpose: Sets parameters of pure spiral
+
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiams: Array1OfReal from TColStd;
+ thePitches: Array1OfReal from TColStd ;
+ theNbTurns: Array1OfReal from TColStd);
+ ---Purpose: Sets parameters of general composite helix
+
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiam: Real from Standard;
+ thePitches: Array1OfReal from TColStd ;
+ theNbTurns: Array1OfReal from TColStd);
+ ---Purpose: Sets parameters of pure helix
+
+ SetParameters(me:out; theAxis: Ax3 from gp;
+ theDiam1: Real from Standard;
+ theDiam2: Real from Standard;
+ thePitches: Array1OfReal from TColStd ;
+ theNbTurns: Array1OfReal from TColStd);
+ ---Purpose: Sets parameters of pure spiral
+
+
+ SetApproxParameters(me:out; theTolerance: Real from Standard;
+ theMaxDegree: Integer from Standard;
+ theContinuity: Shape from GeomAbs);
+ ---Purpose: Sets parameters for approximation
+
+
+ Perform(me:out) ;
+ ---Purpose: Performs calculations
+
+ ToleranceReached(me) returns Real from Standard;
+ ---Purpose: Gets tolerance reached by approximation
+
+ ErrorStatus(me)
+ ---Purpose: Returns error status of algorithm
+ returns Integer from Standard;
+
+ WarningStatus(me)
+ ---Purpose: Returns warning status of algorithm
+ returns Integer from Standard;
+
+ Shape(me) returns Shape from TopoDS;
+ ---Purpose: Gets result of algorithm
+ ---C++: return const &
+
+ BuildPart(me:in out; theAxis: Ax1 from gp;
+ thePStart: Pnt from gp;
+ theHeight: Real from Standard;
+ thePitch: Real from Standard;
+ theTaperAngle: Real from Standard;
+ theIsClockwise: Boolean from Standard;
+ thePart: out Wire from TopoDS)
+
+ is private;
+
+ Smoothing(me: in out; theParts: in out ListOfShape from TopTools)
+ is private;
+
+ SmoothingEdges(me: in out; thePrev, theNext: in out Edge from TopoDS)
+ is private;
+
+fields
+ myAxis3: Ax3 from gp is protected;
+ myDiams: HArray1OfReal from TColStd is protected;
+ myHeights: HArray1OfReal from TColStd is protected;
+ myPitches: HArray1OfReal from TColStd is protected;
+ myIsPitches: HArray1OfBoolean from TColStd is protected;
+ myNParts: Integer from Standard;
+
+ myTolerance: Real from Standard is protected;
+ myTolReached: Real from Standard is protected;
+ myContinuity: Shape from GeomAbs is protected;
+ myMaxDegree: Integer from Standard is protected;
+ myMaxSegments: Integer from Standard is protected;
+
+ myErrorStatus : Integer from Standard is protected;
+ myWarningStatus : Integer from Standard is protected;
+
+ myShape: Shape from TopoDS is protected;
+
+
+end BuilderHelix;
+
--- /dev/null
+// File: HelixBRep_BuilderHelix.cxx
+
+#include <HelixBRep_BuilderHelix.ixx>
+
+#include <HelixGeom_BuilderHelix.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <BRep_Builder.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <gp_Pnt.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Wire.hxx>
+#include <gp.hxx>
+#include <Precision.hxx>
+#include <gp_Lin.hxx>
+#include <gp_Vec.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Vec.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Standard_ConstructionError.hxx>
+#include <TopExp.hxx>
+#include <BRep_Tool.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <BRepBuilderAPI_MakeWire.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <Geom_BSplineCurve.hxx>
+
+//=======================================================================
+//function :
+//purpose :
+//=======================================================================
+HelixBRep_BuilderHelix::HelixBRep_BuilderHelix()
+
+{
+ gp_Pnt aP0(0.,0.,0);
+ //
+ myAxis3.SetDirection(gp::DZ());
+ myAxis3.SetLocation(aP0);
+ myDiams = NULL;
+ myHeights = NULL;
+ myPitches = NULL;
+ myIsPitches = NULL;
+ myNParts = 1;
+ myShape.Nullify();
+
+ //
+ myTolerance=0.0001;
+ myContinuity=GeomAbs_C1;
+ myMaxDegree=8;
+ myMaxSegments=1000;
+ //
+ myTolReached=99.;
+ //
+ myErrorStatus = 1;
+ myWarningStatus = 1;
+}
+//=======================================================================
+//function : ~
+//purpose :
+//=======================================================================
+HelixBRep_BuilderHelix::~HelixBRep_BuilderHelix()
+{
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ myNParts = theDiams.Length() - 1;
+
+ myAxis3 = theAxis;
+
+ myDiams = NULL;
+ myHeights = NULL;
+ myPitches = NULL;
+ myShape.Nullify();
+
+ myErrorStatus = 1;
+ myWarningStatus = 1;
+
+ if(myNParts != theHeights.Length() || myNParts != thePitches.Length() || myNParts != bIsPitches.Length()) {
+ Standard_ConstructionError::
+ Raise("HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ myDiams = new TColStd_HArray1OfReal(1, myNParts+1);
+ myHeights = new TColStd_HArray1OfReal(1, myNParts);
+ myPitches = new TColStd_HArray1OfReal(1, myNParts);
+ myIsPitches = new TColStd_HArray1OfBoolean(1, myNParts);
+
+
+ myDiams->ChangeArray1() = theDiams;
+ myHeights->ChangeArray1() = theHeights;
+ myPitches->ChangeArray1() = thePitches;
+ myIsPitches->ChangeArray1() = bIsPitches;
+
+ myErrorStatus = 0;
+ myWarningStatus = 0;
+
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ Standard_Integer aNbParts = theHeights.Length();
+ TColStd_Array1OfReal aDiams(1, aNbParts+1);
+ aDiams.Init(theDiam);
+ SetParameters(theAxis, aDiams, theHeights, thePitches, bIsPitches);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& theHeights,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfBoolean& bIsPitches)
+{
+ Standard_Integer aNbParts = theHeights.Length();
+ TColStd_Array1OfReal aDiams(1, aNbParts+1);
+
+ Standard_Integer i, j;
+ Standard_Real anH = 0.;
+ for(i = theHeights.Lower(); i <= theHeights.Upper(); ++i) {
+ anH += theHeights(i);
+ }
+ Standard_Real K = (theDiam2 - theDiam1)/anH;
+ aDiams(1) = theDiam1;
+ aDiams(aNbParts+1) = theDiam2;
+
+ anH = theHeights(1);
+ for(i = theHeights.Lower()+1, j = 2; i <= theHeights.Upper(); ++i, ++j) {
+ aDiams(j) = theDiam1 + K * anH;
+ anH += theHeights(i);
+ }
+
+ SetParameters(theAxis, aDiams, theHeights, thePitches, bIsPitches);
+}
+
+//=======================================================================
+//function : SetApproxParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetApproxParameters(const Standard_Real aTolerance,
+ const Standard_Integer aMaxDegree,
+ const GeomAbs_Shape aCont)
+{
+ myTolerance=aTolerance;
+ myMaxDegree=aMaxDegree;
+ myContinuity=aCont;
+}
+
+//=======================================================================
+//function : ToleranceReached
+//purpose :
+//=======================================================================
+Standard_Real HelixBRep_BuilderHelix::ToleranceReached()const
+{
+ return myTolReached;
+}
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::Perform()
+{
+
+ if(myErrorStatus != 0) return;
+
+ Standard_Integer i;
+
+ myTolReached = 0.;
+ myShape.Nullify();
+ BRep_Builder aBB;
+ //aBB.MakeCompound(TopoDS::Compound(myShape));
+
+ TopTools_ListOfShape anLst;
+
+ gp_Ax1 anAxis(myAxis3.Axis());
+ gp_Pnt aPStart = myAxis3.Location();
+ aPStart.Translate(.5*myDiams->Value(1)*myAxis3.XDirection());
+ Standard_Boolean bIsClockwise = myAxis3.Direct();
+
+ Standard_Real aHeight;
+ Standard_Real aPitch;
+ Standard_Real aTaperAngle;
+
+ for(i = 1; i <= myNParts; ++i) {
+
+ aHeight = myHeights->Value(i);
+
+ if(myIsPitches->Value(i)) {
+ aPitch = myPitches->Value(i);
+ }
+ else {
+ aPitch = aHeight/myPitches->Value(i);
+ }
+
+ aTaperAngle = ATan(.5*(myDiams->Value(i+1) - myDiams->Value(i))/aHeight);
+
+ TopoDS_Wire aPart;
+ aBB.MakeWire(aPart);
+
+ BuildPart(anAxis, aPStart, aHeight, aPitch, aTaperAngle, bIsClockwise, aPart);
+ if(myErrorStatus != 0) return;
+
+ TopoDS_Vertex V1, V2;
+
+ TopExp::Vertices(aPart, V1, V2);
+
+ aPStart = BRep_Tool::Pnt(V2);
+
+ anAxis.SetLocation(anAxis.Location().Translated(aHeight*anAxis.Direction()));
+
+ anLst.Append(aPart);
+ //aBB.Add(myShape, aPart);
+ }
+
+ Smoothing(anLst);
+
+ TopTools_ListIteratorOfListOfShape anIt(anLst);
+ BRepBuilderAPI_MakeWire aMkWire(TopoDS::Wire(anLst.First()));
+ anIt.Next();
+ for(; anIt.More(); anIt.Next()) {
+ aMkWire.Add(TopoDS::Wire(anIt.Value()));
+ }
+
+ myShape = aMkWire.Shape();
+
+}
+
+//=======================================================================
+//function : BuildPart
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::BuildPart(const gp_Ax1& theAxis,
+ const gp_Pnt& thePStart,
+ const Standard_Real theHeight,
+ const Standard_Real thePitch,
+ const Standard_Real theTaperAngle,
+ const Standard_Boolean bIsClockwise,
+ TopoDS_Wire& thePart)
+{
+
+ if(myErrorStatus != 0) return;
+
+ myErrorStatus=0;
+ myWarningStatus=0;
+
+ //
+ // 1. check & prepare data
+ Standard_Real aTolPrec, aDist, aDM, aTwoPI, aC1, aT2, aT1, aT0;
+ //
+ aTolPrec=myTolerance;
+ Standard_Real aTolAng = 1.e-7;
+ //
+
+ if (theTaperAngle > M_PI/2. - aTolAng) {
+ myErrorStatus=13; // invalid TaperAngle value
+ return;
+ }
+ if (theHeight<aTolPrec) {
+ myErrorStatus=12; // invalid Height value
+ return;
+ }
+ if (thePitch<aTolPrec) {
+ myErrorStatus=11; // invalid Pitch value
+ return;
+ }
+ //
+ gp_Lin aLin(theAxis);
+ aDist=aLin.Distance(thePStart);
+ if (aDist<aTolPrec) {
+ myErrorStatus=10; // myPStart belongs to the myAxis
+ return;
+ }
+
+ aTolAng = aTolPrec/aDist;
+ Standard_Real aAngleStart = 0.;
+
+ Standard_Boolean bIsOutWard = Standard_False;
+ if(theTaperAngle > 0.) bIsOutWard = Standard_True;
+ //
+ const gp_Dir& aDir=theAxis.Direction();
+ gp_Vec aVec1 = gp_Vec(aDir);
+ gp_Pnt aM0 = theAxis.Location();
+ gp_Vec aVec(aM0, thePStart);
+ aDM=aVec1.Dot(aVec);
+ gp_Pnt aM1= aM0.Translated(aDM*aVec1);
+ gp_Vec aVecX(aM1, thePStart);
+ gp_Dir aDirX(aVecX);
+ gp_Ax2 aAx2(aM1, aDir, aDirX);
+ //
+ aTwoPI=2.*M_PI;
+ aC1=thePitch/aTwoPI;
+ aT0 = 0.;
+ aT1=aAngleStart;
+
+ aT2=theHeight/aC1;
+ //
+ // 2. compute
+ Standard_Boolean bIsDone;
+ Standard_Integer iErr, aNbC, i;
+ HelixGeom_BuilderHelix aBH;
+ gp_Pnt aP1, aP2;
+ BRep_Builder aBB;
+ BRepBuilderAPI_MakeEdge aBME;
+ TopoDS_Vertex aV1, aV2;
+ //TopoDS_Wire aW;
+ TopoDS_Edge aE;
+ //
+ aBH.SetPosition(aAx2);
+ aBH.SetCurveParameters(aT0, aT2, thePitch, aDist, theTaperAngle, bIsClockwise);
+ aBH.SetTolerance(myTolerance);
+ aBH.SetApproxParameters(myContinuity, myMaxDegree, myMaxSegments);
+ //
+ aBH.Perform();
+ iErr=aBH.ErrorStatus();
+ if (iErr) {
+ myErrorStatus=2;
+ return;
+ }
+ //
+ aBB.MakeWire(thePart);
+ //
+ myTolReached=Max(myTolReached, aBH.ToleranceReached());
+ TColGeom_SequenceOfCurve aSC;
+ aSC.Assign(aBH.Curves());
+ if(aT1 < 0.) {
+ HelixGeom_BuilderHelix aBH1;
+ aBH1.SetPosition(aAx2);
+ aBH1.SetCurveParameters(aT1, aT0, thePitch, aDist, theTaperAngle, bIsClockwise);
+ aBH1.SetTolerance(myTolerance);
+ aBH1.SetApproxParameters(myContinuity, myMaxDegree, myMaxSegments);
+ //
+ aBH1.Perform();
+ iErr=aBH1.ErrorStatus();
+ if (iErr) {
+ myErrorStatus=2;
+ return;
+ }
+
+ myTolReached = Max(myTolReached, aBH1.ToleranceReached());
+ const TColGeom_SequenceOfCurve& aSC1=aBH1.Curves();
+ Standard_Integer nbc = aSC1.Length();
+ for(i = nbc; i >= 1; i--) {
+ aSC.Prepend(aSC1.Value(i));
+ }
+ }
+
+ aNbC=aSC.Length();
+ for (i=1; i<=aNbC; ++i) {
+ Handle(Geom_Curve) aC=aSC(i);
+ //
+ if (i==1) {
+ if(aT1 > 0.) {
+ aT2=aC->LastParameter();
+ Handle(Geom_TrimmedCurve) aCT = new Geom_TrimmedCurve(aC, aT1, aT2);
+ aC = aCT;
+ }
+ aT1=aC->FirstParameter();
+ aC->D0(aT1, aP1);
+ aBB.MakeVertex(aV1, aP1, myTolReached);
+ aV1.Orientation(TopAbs_FORWARD);
+ }
+ //
+ aT2=aC->LastParameter();
+ aC->D0(aT2, aP2);
+ aBB.MakeVertex(aV2, aP2, myTolReached);
+ aV2.Orientation(TopAbs_REVERSED);
+ //
+ aBME.Init(aC, aV1, aV2);
+ bIsDone=aBME.IsDone();
+ if (!bIsDone) {
+ myErrorStatus=3;
+ return;
+ }
+ aE=aBME.Edge();
+ aBB.UpdateEdge(aE, myTolReached);
+ aBB.Add(thePart, aE);
+
+ //
+ aV1=aV2;
+ aV1.Orientation(TopAbs_FORWARD);
+ }
+ //
+ if(myTolReached > myTolerance) myWarningStatus = 1;
+
+}
+
+//=======================================================================
+//function : Smoothing
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::Smoothing(TopTools_ListOfShape& theParts)
+{
+ if(theParts.Extent() == 1) return;
+
+ BRepTools_WireExplorer anExpl;
+
+ TopoDS_Wire aPrevWire = TopoDS::Wire(theParts.First());
+ anExpl.Init(aPrevWire);
+ TopoDS_Edge aPrevEdge;
+ for(; anExpl.More(); anExpl.Next()) {
+ aPrevEdge = anExpl.Current();
+ }
+
+ TopTools_ListIteratorOfListOfShape anIter(theParts);
+ anIter.Next();
+ for(; anIter.More(); anIter.Next()) {
+ TopoDS_Wire aNextWire = TopoDS::Wire(anIter.Value());
+ anExpl.Clear();
+ anExpl.Init(aNextWire);
+ TopoDS_Edge aNextEdge = anExpl.Current();
+
+ //Smoothing curves
+ SmoothingEdges(aPrevEdge, aNextEdge);
+
+ for(; anExpl.More(); anExpl.Next()) {
+ aPrevEdge = anExpl.Current();
+ }
+ }
+
+}
+//=======================================================================
+//function : Smoothing
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SmoothingEdges(TopoDS_Edge& thePrev,
+ TopoDS_Edge& theNext)
+{
+
+ static const Standard_Real EpsAng = 1.e-7;
+ BRep_Builder aBB;
+
+ Standard_Real f1, l1, f2, l2;
+ Handle(Geom_BSplineCurve) aCPrev =
+ Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(thePrev, f1, l1));
+
+ Handle(Geom_BSplineCurve) aCNext =
+ Handle(Geom_BSplineCurve)::DownCast(BRep_Tool::Curve(theNext, f2, l2));
+
+ gp_Pnt P1, P2;
+ gp_Vec V1, V2;
+
+ aCPrev->D1(l1, P1, V1);
+ aCNext->D1(f2, P2, V2);
+
+
+ if(V1.Angle(V2) < EpsAng) return;
+
+ V1 = 0.5*(V1 + V2);
+ V2 = V1;
+
+ Standard_Integer anErrorStatus = 1;
+ Standard_Integer aDegMax = Geom_BSplineCurve::MaxDegree();
+ Standard_Integer aDeg = aCPrev->Degree();
+ Standard_Integer i;
+ Standard_Boolean bPrevOK = Standard_False;
+ Standard_Boolean bNextOK = Standard_False;
+
+ aCPrev->MovePointAndTangent(l1, P1, V1, myTolerance, 1, -1, anErrorStatus);
+ if(anErrorStatus != 0) {
+ for(i = aDeg + 1; i <= aDegMax; ++i) {
+ aCPrev->IncreaseDegree(i);
+ aCPrev->MovePointAndTangent(l1, P1, V1, myTolerance, 1, -1, anErrorStatus);
+ if(anErrorStatus == 0) {
+ bPrevOK = Standard_True;
+ break;
+ }
+ }
+
+ }
+ else {
+ bPrevOK = Standard_True;
+ }
+
+ if(bPrevOK) {
+ aBB.UpdateEdge(thePrev, aCPrev, BRep_Tool::Tolerance(thePrev));
+ }
+
+ aDeg = aCNext->Degree();
+ aCNext->MovePointAndTangent(f2, P2, V2, myTolerance, -1, 1, anErrorStatus);
+ if(anErrorStatus != 0) {
+ for(i = aDeg + 1; i <= aDegMax; ++i) {
+ aCNext->IncreaseDegree(i);
+ aCNext->MovePointAndTangent(f2, P2, V2, myTolerance, -1, 1, anErrorStatus);
+ if(anErrorStatus == 0) {
+ bNextOK = Standard_True;
+ break;
+ }
+ }
+
+ }
+ else {
+ bNextOK = Standard_True;
+ }
+
+ if(bNextOK) {
+ aBB.UpdateEdge(theNext, aCNext, BRep_Tool::Tolerance(theNext));
+ }
+
+}
+//=======================================================================
+//function : ErrorStatus
+//purpose :
+//=======================================================================
+Standard_Integer HelixBRep_BuilderHelix::ErrorStatus()const
+{
+ return myErrorStatus;
+}
+
+//=======================================================================
+//function : WarningStatus
+//purpose :
+//=======================================================================
+Standard_Integer HelixBRep_BuilderHelix::WarningStatus()const
+{
+ return myWarningStatus;
+}
+
+//=======================================================================
+//function : Shape
+//purpose :
+//=======================================================================
+const TopoDS_Shape& HelixBRep_BuilderHelix::Shape() const
+{
+ return myShape;
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const TColStd_Array1OfReal& theDiams,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+
+{
+ Standard_Integer aNbParts = theDiams.Length() - 1;
+
+ if(aNbParts != thePitches.Length() || aNbParts != theNbTurns.Length()) {
+ Standard_ConstructionError::
+ Raise("HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for(i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length(); ++i, ip++, in++) {
+ aHeights(i) = thePitches(ip)*theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiams, aHeights, thePitches, bIsPitches);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+{
+ Standard_Integer aNbParts = thePitches.Length();
+
+ if(aNbParts != theNbTurns.Length()) {
+ Standard_ConstructionError::
+ Raise("HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for(i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length(); ++i, ip++, in++) {
+ aHeights(i) = thePitches(ip)*theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiam, aHeights, thePitches, bIsPitches);
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+void HelixBRep_BuilderHelix::SetParameters(const gp_Ax3& theAxis,
+ const Standard_Real theDiam1,
+ const Standard_Real theDiam2,
+ const TColStd_Array1OfReal& thePitches,
+ const TColStd_Array1OfReal& theNbTurns)
+{
+ Standard_Integer aNbParts = thePitches.Length();
+
+ if(aNbParts != theNbTurns.Length()) {
+ Standard_ConstructionError::
+ Raise("HelixBRep_BuilderHelix::SetParameters: wrong array dimension");
+ }
+
+ TColStd_Array1OfReal aHeights(1, aNbParts);
+ TColStd_Array1OfBoolean bIsPitches(1, aNbParts);
+ bIsPitches.Init(Standard_True);
+ Standard_Integer i, ip, in;
+ for(i = 1, ip = thePitches.Lower(), in = theNbTurns.Lower(); i <= thePitches.Length(); ++i, ip++, in++) {
+ aHeights(i) = thePitches(ip)*theNbTurns(in);
+ }
+
+ SetParameters(theAxis, theDiam1, theDiam2, aHeights, thePitches, bIsPitches);
+}
--- /dev/null
+-- File: HelixGeom.cdl
+
+
+package HelixGeom
+
+ ---Purpose:
+
+uses
+ MMgt,
+ gp,
+ TColStd,
+ GeomAbs,
+ Geom,
+ TColGeom,
+ GeomAdaptor,
+ Adaptor3d,
+ GeomFill
+
+is
+
+ deferred class BuilderApproxCurve;
+ deferred class BuilderHelixGen;
+
+ class HelixCurve;
+ class HHelixCurve;
+ class BuilderHelixCoil;
+ class BuilderHelix;
+ class Tools;
+
+ --
+ private class GHHelixCurve instantiates GenHCurve from Adaptor3d
+ (HelixCurve from HelixGeom);
+
+end HelixGeom;
+
--- /dev/null
+-- File: HelixGeom_BuilderApproxCurve.cdl
+
+
+deferred class BuilderApproxCurve from HelixGeom
+
+ ---Purpose: Root class for algorithm of building helix curves
+
+uses
+ Shape from GeomAbs,
+ SequenceOfCurve from TColGeom
+
+--raises
+
+is
+ Initialize
+ ---Purpose: Sets default values of aprroximation parameters
+ returns BuilderApproxCurve from HelixGeom;
+ ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderApproxCurve();"
+
+ SetApproxParameters(me:out;
+ aCont : Shape from GeomAbs;
+ aMaxDegree: Integer from Standard;
+ aMaxSeg : Integer from Standard);
+ ---Purpose: Sets aprroximation parameters
+
+ ApproxParameters(me;
+ aCont :out Shape from GeomAbs;
+ aMaxDegree:out Integer from Standard;
+ aMaxSeg :out Integer from Standard);
+ ---Purpose: Gets aprroximation parameters
+
+ SetTolerance(me:out;
+ aTolerance: Real from Standard);
+ ---Purpose: Sets aprroximation tolerance
+
+ Tolerance(me)
+ returns Real from Standard;
+ ---Purpose: Gets aprroximation tolerance
+
+ ToleranceReached(me)
+ ---Purpose: Gets actual tolerance reached by approximation algorithm
+ returns Real from Standard;
+
+ Curves(me)
+ ---Purpose: Gets sequence of Bspline curves representing helix coins.
+ returns SequenceOfCurve from TColGeom;
+ ---C++: return const &
+
+ ErrorStatus(me)
+ ---Purpose: Returns error status of algorithm
+ returns Integer from Standard;
+
+ WarningStatus(me)
+ ---Purpose: Returns warning status of algorithm
+ returns Integer from Standard;
+
+ Perform(me:out)
+ ---Purpose: Performs calculations.
+ -- Must be redefined.
+ is deferred;
+fields
+ myErrorStatus : Integer from Standard is protected;
+ myWarningStatus : Integer from Standard is protected;
+ myTolerance : Real from Standard is protected;
+ myCont : Shape from GeomAbs is protected;
+ myMaxDegree : Integer from Standard is protected;
+ myMaxSeg : Integer from Standard is protected;
+ --
+ myTolReached : Real from Standard is protected;
+ myCurves : SequenceOfCurve from TColGeom is protected;
+
+end BuilderApproxCurve;
--- /dev/null
+// File: HelixGeom_BuilderApproxCurve.cxx
+
+#include <HelixGeom_BuilderApproxCurve.ixx>
+
+//=======================================================================
+//function :
+//purpose :
+//=======================================================================
+HelixGeom_BuilderApproxCurve::HelixGeom_BuilderApproxCurve()
+{
+ myTolerance=0.0001;
+ myCont=GeomAbs_C2;
+ myMaxDegree=8;
+ myMaxSeg=150;
+ //
+ myTolReached=99.;
+}
+//=======================================================================
+//function : ~
+//purpose :
+//=======================================================================
+HelixGeom_BuilderApproxCurve::~HelixGeom_BuilderApproxCurve()
+{
+}
+//=======================================================================
+//function : SetApproxParameters
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::SetApproxParameters(const GeomAbs_Shape aCont,
+ const Standard_Integer aMaxDegree,
+ const Standard_Integer aMaxSeg)
+{
+
+ myCont=aCont;
+ myMaxDegree=aMaxDegree;
+ myMaxSeg=aMaxSeg;
+}
+//=======================================================================
+//function : ApproxParameters
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::ApproxParameters(GeomAbs_Shape& aCont,
+ Standard_Integer& aMaxDegree,
+ Standard_Integer& aMaxSeg)const
+{
+ aCont=myCont;
+ aMaxDegree=myMaxDegree;
+ aMaxSeg=myMaxSeg;
+}
+//=======================================================================
+//function : SetTolerance
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderApproxCurve::SetTolerance(const Standard_Real aTolerance)
+{
+ myTolerance=aTolerance;
+}
+//=======================================================================
+//function : Tolerance
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_BuilderApproxCurve::Tolerance()const
+{
+ return myTolerance;
+}
+//=======================================================================
+//function : ToleranceReached
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_BuilderApproxCurve::ToleranceReached()const
+{
+ return myTolReached;
+}
+
+//=======================================================================
+//function : Curves
+//purpose :
+//=======================================================================
+const TColGeom_SequenceOfCurve& HelixGeom_BuilderApproxCurve::Curves()const
+{
+ return myCurves;
+}
+
+//=======================================================================
+//function : ErrorStatus
+//purpose :
+//=======================================================================
+Standard_Integer HelixGeom_BuilderApproxCurve::ErrorStatus()const
+{
+ return myErrorStatus;
+}
+
+//=======================================================================
+//function : WarningStatus
+//purpose :
+//=======================================================================
+Standard_Integer HelixGeom_BuilderApproxCurve::WarningStatus()const
+{
+ return myWarningStatus;
+}
--- /dev/null
+-- File: HelixGeom_BuilderHelix.cdl
+
+
+class BuilderHelix from HelixGeom
+ inherits BuilderHelixGen from HelixGeom
+
+ ---Purpose: Upper level class for geometrical algorithm of building
+ -- helix curves using arbitrary axis
+
+uses
+ Ax2 from gp
+
+--raises
+
+is
+ Create
+ ---Purpose: Empty constructor
+ returns BuilderHelix from HelixGeom;
+ ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelix();"
+
+ SetPosition (me:out;
+ ---Purpose: Sets coordinate axes for helix
+ aAx2 : Ax2 from gp);
+
+ Position (me)
+ ---Purpose: Gets coordinate axes for helix
+ returns Ax2 from gp;
+ ---C++: return const &
+
+ Perform(me:out)
+ ---Purpose: Performs calculations
+ is redefined;
+
+fields
+ myPosition: Ax2 from gp is protected;
+
+end BuilderHelix;
+
--- /dev/null
+// File: HelixGeom_BuilderHelix.cxx
+
+
+#include <HelixGeom_BuilderHelix.ixx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <Geom_Curve.hxx>
+#include <gp_Trsf.hxx>
+#include <gp_Ax3.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+
+
+//=======================================================================
+//function :
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelix::HelixGeom_BuilderHelix()
+:
+ HelixGeom_BuilderHelixGen()
+{
+}
+//=======================================================================
+//function : ~
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelix::~HelixGeom_BuilderHelix()
+{
+}
+//=======================================================================
+//function : SetPosition
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderHelix::SetPosition(const gp_Ax2& aAx2)
+{
+ myPosition=aAx2;
+}
+//=======================================================================
+//function : Position
+//purpose :
+//=======================================================================
+const gp_Ax2& HelixGeom_BuilderHelix::Position()const
+{
+ return myPosition;
+}
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderHelix::Perform()
+{
+ myErrorStatus=0;
+ myWarningStatus=0;
+ //
+ Standard_Integer iErr, aN, i, aNbC;
+ Standard_Real aTwoPI, dT, aT1x, aT2x, aTR;
+ //HelixGeom_HelixCurve aHC;
+ HelixGeom_BuilderHelixCoil aBHC;
+ //
+ myCurves.Clear();
+ myTolReached=-1.;
+ aTwoPI=2.*M_PI;
+ //
+ aBHC.SetTolerance(myTolerance);
+ aBHC.SetApproxParameters(myCont, myMaxDegree, myMaxSeg);
+ //
+ dT=myT2-myT1;
+ aN=(Standard_Integer)(dT/aTwoPI);
+ //
+ if (!aN) {
+ aBHC.SetCurveParameters(myT1, myT2, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aBHC.Perform();
+ iErr=aBHC.ErrorStatus();
+ if (iErr) {
+ myErrorStatus=2;
+ return;
+ }
+ const TColGeom_SequenceOfCurve& aSC=aBHC.Curves();
+ const Handle(Geom_Curve)& aC=aSC(1);
+ myCurves.Append(aC);
+ myTolReached=aBHC.ToleranceReached();
+ }
+ //
+ else {
+ Standard_Boolean bIsCylindrical;
+ Standard_Real aTolAngle;
+ //
+ aTolAngle=1.e-4;
+ bIsCylindrical=fabs(myTaperAngle)<aTolAngle;
+ //
+ aT1x=myT1;
+ aT2x=myT1+aTwoPI;
+ for (i=1; i<=aN; ++i) {
+ //
+ if (i>1 && bIsCylindrical) {
+ Handle(Geom_Curve) aCi;
+ gp_Pnt aP1, aPi;
+ //
+ const Handle(Geom_Curve)& aC1=myCurves(1);
+ aC1->D0(aC1->FirstParameter(), aP1);
+ aPi.SetCoord(aP1.X(), aP1.Y(), aP1.Z()+(i-1)*myPitch);
+ aCi=Handle(Geom_Curve)::DownCast(aC1->Translated(aP1, aPi));
+ //
+ myCurves.Append(aCi);
+ //
+ aT1x=aT2x;
+ aT2x=aT1x+aTwoPI;
+ //
+ continue;
+ }
+
+ aBHC.SetCurveParameters(aT1x, aT2x, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ //
+ aBHC.Perform();
+ iErr=aBHC.ErrorStatus();
+ if (iErr) {
+ myErrorStatus=2;
+ return;
+ }
+ //
+ const TColGeom_SequenceOfCurve& aSC=aBHC.Curves();
+ const Handle(Geom_Curve)& aC=aSC(1);
+ myCurves.Append(aC);
+ aTR=aBHC.ToleranceReached();
+ if(aTR>myTolReached) {
+ myTolReached=aTR;
+ }
+ //
+ aT1x=aT2x;
+ aT2x=aT1x+aTwoPI;
+ } // for (i=1; i<=aN; ++i) {
+ //
+ aT2x=myT2;
+ Standard_Real eps = 1.e-7*aTwoPI;
+ if (fabs (aT2x-aT1x)>eps) {
+ aBHC.SetCurveParameters(aT1x, aT2x, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aBHC.Perform();
+ iErr=aBHC.ErrorStatus();
+ if (iErr) {
+ myErrorStatus=2;
+ return;
+ }
+ //
+ const TColGeom_SequenceOfCurve& aSC=aBHC.Curves();
+ const Handle(Geom_Curve)& aC=aSC(1);
+ myCurves.Append(aC);
+ aTR=aBHC.ToleranceReached();
+ if(aTR>myTolReached) {
+ myTolReached=aTR;
+ }
+ }
+ }
+ //
+ // Transformation
+ gp_Trsf aTrsf;
+ gp_Ax3 aAx3, aAx3x(myPosition);
+ //
+ aTrsf.SetDisplacement(aAx3, aAx3x);
+ //
+ aNbC=myCurves.Length();
+ for (i=1; i<=aNbC; ++i) {
+ Handle(Geom_Curve)& aC=myCurves(i);
+ aC->Transform(aTrsf);
+ }
+ //
+}
+
--- /dev/null
+-- File: HelixGeom_BuilderHelixCoil.cdl
+
+class BuilderHelixCoil from HelixGeom
+ inherits BuilderHelixGen from HelixGeom
+
+ ---Purpose: Implementation of algorithm for building helix coil with
+ -- axis OZ
+
+--uses
+--raises
+
+is
+ Create
+ ---Purpose: Empty constructor
+ returns BuilderHelixCoil from HelixGeom;
+ ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelixCoil();"
+
+ Perform(me:out)
+ ---Purpose: Performs calculations
+ is redefined;
+
+end BuilderHelixCoil;
+
+
--- /dev/null
+// File: HelixGeom_BuilderHelixCoil.cxx
+
+
+#include <HelixGeom_BuilderHelixCoil.ixx>
+#include <HelixGeom_Tools.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+
+//=======================================================================
+//function : HelixGeom_BuilderHelixCoil
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelixCoil::HelixGeom_BuilderHelixCoil()
+:
+ HelixGeom_BuilderHelixGen()
+{
+ myT1=0.;
+ myT2=2.*M_PI;
+ myPitch=1.;
+ myRStart=1.;
+ myTaperAngle=0.;
+ myIsClockWise=Standard_True;
+}
+//=======================================================================
+//function : ~
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelixCoil::~HelixGeom_BuilderHelixCoil()
+{
+}
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderHelixCoil::Perform()
+{
+ myErrorStatus=0;
+ myWarningStatus=0;
+ //
+ Standard_Integer iErr;
+ HelixGeom_HelixCurve aAdaptor;
+ Handle(HelixGeom_HHelixCurve) aHAdaptor;
+ Handle(Geom_BSplineCurve)aBC;
+ //
+ myCurves.Clear();
+ //
+ aAdaptor.Load(myT1, myT2, myPitch, myRStart, myTaperAngle, myIsClockWise);
+ aHAdaptor=new HelixGeom_HHelixCurve(aAdaptor);
+ //
+ iErr=HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ myTolerance, myCont, myMaxSeg, myMaxDegree,
+ aBC, myTolReached);
+ if(iErr) {
+ myErrorStatus=2;
+ }
+ else {
+ myCurves.Append(aBC);
+ }
+}
+
+
+
--- /dev/null
+-- File: HelixGeom_BuilderHelixGen.cdl
+
+deferred class BuilderHelixGen from HelixGeom
+ inherits BuilderApproxCurve from HelixGeom
+
+ ---Purpose: Root class for algorithms of building helix curves
+
+
+--uses
+--raises
+
+is
+ Initialize
+ ---Purpose: Sets default parameters
+ returns BuilderHelixGen from HelixGeom;
+ ---C++: alias "Standard_EXPORT virtual ~HelixGeom_BuilderHelixGen();"
+
+ SetCurveParameters(me:out;
+ aT1 :Real from Standard;
+ aT2 :Real from Standard;
+ aPitch :Real from Standard;
+ aRStart :Real from Standard;
+ aTaperAngle :Real from Standard;
+ bIsClockwise :Boolean from Standard);
+ ---Purpose: Sets parameters for building helix curves
+
+ CurveParameters(me;
+ aT1 :out Real from Standard;
+ aT2 :out Real from Standard;
+ aPitch :out Real from Standard;
+ aRStart :out Real from Standard;
+ aTaperAngle :out Real from Standard;
+ bIsClockwise :out Boolean from Standard);
+ ---Purpose: Gets parameters for building helix curves
+
+fields
+ myT1 : Real from Standard is protected;
+ myT2 : Real from Standard is protected;
+ myPitch : Real from Standard is protected;
+ myRStart : Real from Standard is protected;
+ myTaperAngle : Real from Standard is protected;
+ myIsClockWise: Boolean from Standard is protected;
+
+end BuilderHelixGen;
+
--- /dev/null
+// File: HelixGeom_BuilderHelixGen.cxx
+
+#include <HelixGeom_BuilderHelixGen.ixx>
+
+//=======================================================================
+//function :
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelixGen::HelixGeom_BuilderHelixGen()
+:
+ HelixGeom_BuilderApproxCurve()
+{
+}
+//=======================================================================
+//function : ~
+//purpose :
+//=======================================================================
+HelixGeom_BuilderHelixGen::~HelixGeom_BuilderHelixGen()
+{
+}
+//=======================================================================
+//function : SetCurveParameters
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderHelixGen::SetCurveParameters(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW)
+{
+ myT1=aT1;
+ myT2=aT2;
+ myPitch=aPitch;
+ myRStart=aRStart;
+ myTaperAngle=aTaperAngle;
+ myIsClockWise=aIsCW;
+}
+//=======================================================================
+//function : CurveParameters
+//purpose :
+//=======================================================================
+void HelixGeom_BuilderHelixGen::CurveParameters(Standard_Real& aT1,
+ Standard_Real& aT2,
+ Standard_Real& aPitch,
+ Standard_Real& aRStart,
+ Standard_Real& aTaperAngle,
+ Standard_Boolean& aIsClockWise)const
+{
+ aT1=myT1;
+ aT2=myT2;
+ aPitch=myPitch;
+ aRStart=myRStart;
+ aTaperAngle=myTaperAngle;
+ aIsClockWise=myIsClockWise;
+}
+
+
--- /dev/null
+-- File: HelixGeom_HHelixCurve.cdl
+
+class HHelixCurve from HelixGeom
+ inherits GHHelixCurve from HelixGeom
+
+ ---Purpose: HAdaptor class for helix curve
+
+uses
+ HelixCurve from HelixGeom
+
+--raises
+
+is
+ Create
+ ---Purpose: Empty constructor
+ returns HHelixCurve from HelixGeom;
+
+ Create(aC: HelixCurve from HelixGeom)
+ ---Purpose: Constructor by corresponding adaptor curve
+ returns HHelixCurve from HelixGeom;
+
+ Create(aT1:Real from Standard;
+ aT2:Real from Standard;
+ aPitch:Real from Standard;
+ aRStart:Real from Standard;
+ aTaperAngle:Real from Standard;
+ aIsCW:Boolean from Standard)
+ ---Purpose: Constructor by parameters
+ returns HHelixCurve from HelixGeom;
+
+--fields
+
+end HHelixCurve;
+
+
--- /dev/null
+// File: HelixGeom_HHelixCurve.cxx
+
+#include <HelixGeom_HHelixCurve.ixx>
+
+//=======================================================================
+//function : HelixGeom_HHelixCurve
+//purpose :
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve()
+{
+}
+//=======================================================================
+//function : HelixGeom_HHelixCurve// Lastly modified by :
+// +---------------------------------------------------------------------------+
+// ! ifv ! Creation !$Date: 2007-10-19 18:21:42 $! %V%-%L%!
+// +---------------------------------------------------------------------------+
+
+
+//purpose :
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve(const HelixGeom_HelixCurve& aC)
+: HelixGeom_GHHelixCurve(aC)
+{
+}
+//=======================================================================
+//function : HelixGeom_HHelixCurve
+//purpose :
+//=======================================================================
+HelixGeom_HHelixCurve::HelixGeom_HHelixCurve(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW)
+{
+ ChangeCurve().Load(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsCW);
+}
+
+
--- /dev/null
+-- File: HelixGeom_HelixCurve.cdl
+
+class HelixCurve from HelixGeom
+ inherits Curve from Adaptor3d
+
+ ---Purpose: Adaptor class for calculation helix curve
+
+uses
+ Shape from GeomAbs,
+ Pnt from gp,
+ Vec from gp,
+ Array1OfReal from TColStd
+
+raises
+ ConstructionError from Standard,
+ OutOfRange from Standard,
+ DomainError from Standard
+is
+ Create
+ ---Purpose: Adaptor class for calculation helix curve
+ -- implementation of analytical expressions
+ returns HelixCurve from HelixGeom;
+
+ Load(me:out);
+ ---Purpose: Sets default values for parameters
+
+ Load(me:out;
+ aT1:Real from Standard;
+ aT2:Real from Standard;
+ aPitch:Real from Standard;
+ aRStart:Real from Standard;
+ aTaperAngle:Real from Standard;
+ aIsCW:Boolean from Standard)
+ ---Purpose: Sets helix parameters
+ raises ConstructionError from Standard;
+
+ FirstParameter(me)
+ ---Purpose: Gets first parameter
+ returns Real from Standard
+ is redefined;
+
+ LastParameter(me)
+ ---Purpose: Gets last parameter
+ returns Real from Standard
+ is redefined;
+
+ Continuity(me)
+ ---Purpose: Gets continuity
+ returns Shape from GeomAbs
+ is redefined;
+
+ NbIntervals(me;
+ S : Shape from GeomAbs)
+ ---Purpose: Gets number of intervals
+ returns Integer from Standard
+ is redefined;
+
+ Intervals(me;
+ T :out Array1OfReal from TColStd;
+ S : Shape from GeomAbs)
+ ---Purpose: Gets parametric intervals
+ is redefined;
+
+ Resolution(me; R3d :Real from Standard)
+ ---Purpose: Gets parametric resolution
+ returns Real from Standard
+ is redefined;
+
+ IsClosed(me)
+ ---Purpose: Returns False
+ returns Boolean from Standard
+ is redefined;
+
+ IsPeriodic(me)
+ ---Purpose: Returns False
+ returns Boolean from Standard
+ is redefined;
+
+ Period(me)
+ ---Purpose: Returns 2*PI
+ returns Real from Standard
+ raises DomainError from Standard
+ is redefined;
+
+ Value(me;
+ U : Real from Standard)
+ ---Purpose: Gets curve point for parameter U
+ returns Pnt from gp
+ is redefined;
+
+ D0 (me;
+ U : Real from Standard;
+ P : out Pnt from gp)
+ ---Purpose: Gets curve point for parameter U
+ is redefined;
+
+ D1 (me;
+ U : Real from Standard;
+ P : out Pnt from gp;
+ V1: out Vec from gp)
+ ---Purpose: Gets curve point and first derivatives
+ -- for parameter U
+ is redefined;
+
+
+ D2 (me;
+ U : Real from Standard;
+ P : out Pnt from gp;
+ V1 : out Vec from gp;
+ V2 : out Vec from gp)
+ ---Purpose: Gets curve point, first and second derivatives
+ -- for parameter U
+ is redefined;
+
+
+ DN (me;
+ U : Real from Standard;
+ N : Integer from Standard)
+ ---Purpose: Gets curve derivative of demanded order
+ -- for parameter U
+ returns Vec from gp
+ raises OutOfRange from Standard
+ is redefined;
+
+fields
+ myFirst : Real from Standard is protected;
+ myLast : Real from Standard is protected;
+ myPitch : Real from Standard is protected;
+ myRStart : Real from Standard is protected;
+ myTaperAngle : Real from Standard is protected;
+ myIsClockWise: Boolean from Standard is protected;
+ --
+ -- private
+ myC1 : Real from Standard is protected;
+ myTgBeta : Real from Standard is protected;
+ myTolAngle : Real from Standard is protected;
+
+end HelixCurve;
+
+
--- /dev/null
+// File: HelixGeom_HelixCurve.cxx
+
+#include <HelixGeom_HelixCurve.ixx>
+#include <math.h>
+#include <gp_Vec.hxx>
+#include <gp_Pnt.hxx>
+#include <Standard_NotImplemented.hxx>
+#include <Standard_DomainError.hxx>
+
+//=======================================================================
+//function : HelixGeom_HelixCurve
+//purpose :
+//=======================================================================
+HelixGeom_HelixCurve::HelixGeom_HelixCurve()
+{
+ myFirst=0.;
+ myLast=2.*M_PI;
+ myPitch=1.;
+ myRStart=1.;
+ myTaperAngle=0.;
+ myIsClockWise=Standard_True;
+ //
+ myC1=myPitch/myLast;
+ myTgBeta=0.;
+ myTolAngle=1.e-4;
+}
+//=======================================================================
+//function : Load
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::Load()
+{
+ Load(myFirst, myLast, myPitch, myRStart, myTaperAngle, myIsClockWise);
+}
+//=======================================================================
+//function : Load
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::Load(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW)
+{
+ char buf[]={"HelixGeom_HelixCurve::Load"};
+ Standard_Real aTwoPI, aHalfPI;
+ //
+ aTwoPI=2.*M_PI;
+ aHalfPI=0.5*M_PI;
+ //
+ myFirst=aT1;
+ myLast=aT2;
+ myPitch=aPitch;
+ myRStart=aRStart;
+ myTaperAngle=aTaperAngle;
+ myIsClockWise=aIsCW;
+ //
+ if (aT1>=aT2) {
+ Standard_ConstructionError::Raise(buf);
+ }
+ if (myPitch<0.) {
+ Standard_ConstructionError::Raise(buf);
+ }
+ if (myRStart<0.) {
+ Standard_ConstructionError::Raise(buf);
+ }
+ if (myTaperAngle<=-aHalfPI ||
+ myTaperAngle>=aHalfPI) {
+ Standard_ConstructionError::Raise(buf);
+ }
+ //
+ myC1=myPitch/aTwoPI;
+ if (fabs(myTaperAngle)>myTolAngle) {
+ myTgBeta=tan(myTaperAngle);
+ }
+}
+//=======================================================================
+//function : FirstParameter
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::FirstParameter() const
+{
+ return myFirst;
+}
+//=======================================================================
+//function : LastParameter
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::LastParameter() const
+{
+ return myLast;
+}
+//=======================================================================
+//function : Continuity
+//purpose :
+//=======================================================================
+GeomAbs_Shape HelixGeom_HelixCurve::Continuity() const
+{
+ return GeomAbs_CN;
+}
+//=======================================================================
+//function : NbIntervals
+//purpose :
+//=======================================================================
+Standard_Integer HelixGeom_HelixCurve::NbIntervals(const GeomAbs_Shape ) const
+{
+ return 1;
+}
+//=======================================================================
+//function : Intervals
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::Intervals(TColStd_Array1OfReal& T,
+ const GeomAbs_Shape) const
+{
+ T(1)=myFirst;
+ T(2)=myLast;
+}
+//=======================================================================
+//function : Resolution
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::Resolution(const Standard_Real) const
+{
+ Standard_NotImplemented::Raise("HelixGeom_HelixCurve::Resolution");
+ return 0.;
+}
+//=======================================================================
+//function : IsClosed
+//purpose :
+//=======================================================================
+Standard_Boolean HelixGeom_HelixCurve::IsClosed() const
+{
+ Standard_NotImplemented::Raise("HelixGeom_HelixCurve::IsClosed");
+ return Standard_False;
+}
+//=======================================================================
+//function : IsPeriodic
+//purpose :
+//=======================================================================
+Standard_Boolean HelixGeom_HelixCurve::IsPeriodic() const
+{
+ Standard_NotImplemented::Raise("HelixGeom_HelixCurve::IsPeriodic");
+ return Standard_False;
+}
+//=======================================================================
+//function : Period
+//purpose :
+//=======================================================================
+Standard_Real HelixGeom_HelixCurve::Period()const
+{
+ Standard_DomainError::Raise("HelixGeom_HelixCurve::Periodic");
+ return 0.;
+}
+//=======================================================================
+//function : Value
+//purpose :
+//=======================================================================
+gp_Pnt HelixGeom_HelixCurve::Value(const Standard_Real aT) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1;
+ //
+ aCT=cos(aT);
+ aST=sin(aT);
+ a1=myRStart+myC1*myTgBeta*aT;
+ //
+ aX=a1*aCT;
+ aY=a1*aST;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=myC1*aT;
+ return gp_Pnt(aX, aY, aZ);
+}
+//=======================================================================
+//function : D0
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::D0(const Standard_Real aT,
+ gp_Pnt& aP) const
+{
+ aP=Value(aT);
+}
+//=======================================================================
+//function : D1
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::D1(const Standard_Real aT,
+ gp_Pnt& aP,
+ gp_Vec& aV1) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1, a2;
+ //
+ aCT=cos(aT);
+ aST=sin(aT);
+ //
+ a1=myRStart+myC1*myTgBeta*aT;
+ //
+ aX=a1*aCT;
+ aY=a1*aST;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=myC1*aT;
+ aP.SetCoord(aX, aY, aZ);
+ //
+ a1=myC1*myTgBeta;
+ a2=myRStart+a1*aT;
+ //
+ aX=a1*aCT-a2*aST;
+ aY=a1*aST+a2*aCT;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=myC1;
+ aV1.SetCoord(aX, aY, aZ);
+}
+//=======================================================================
+//function : D2
+//purpose :
+//=======================================================================
+void HelixGeom_HelixCurve::D2(const Standard_Real aT,
+ gp_Pnt& aP,
+ gp_Vec& aV1,
+ gp_Vec& aV2) const
+{
+ Standard_Real aST, aCT, aX, aY, aZ, a1, a2;
+ //
+ aCT=cos(aT);
+ aST=sin(aT);
+ //
+ a1=myRStart+myC1*myTgBeta*aT;
+ //
+ aX=a1*aCT;
+ aY=a1*aST;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=myC1*aT;
+ aP.SetCoord(aX, aY, aZ);
+ //
+ a1=myC1*myTgBeta;
+ a2=myRStart+a1*aT;
+ //
+ aX=a1*aCT-a2*aST;
+ aY=a1*aST+a2*aCT;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=myC1;
+ aV1.SetCoord(aX, aY, aZ);
+ //
+ a1=2.*a1;
+ aX=-a2*aCT-a1*aST;
+ aY=-a2*aST-a1*aCT;
+ if (!myIsClockWise) {
+ aY=-aY;
+ }
+ aZ=0.;
+ aV2.SetCoord(aX, aY, aZ);
+}
+
+//=======================================================================
+//function : DN
+//purpose :
+//=======================================================================
+gp_Vec HelixGeom_HelixCurve::DN(const Standard_Real aT,
+ const Standard_Integer aN) const
+{
+ gp_Pnt aP;
+ gp_Vec aV1, aV2;
+ //
+ switch (aN) {
+ case 1:
+ D1(aT, aP, aV1);
+ break;
+ case 2:
+ D2(aT, aP, aV1, aV2);
+ break;
+ default:
+ Standard_NotImplemented::Raise("HelixGeom_HelixCurve::DN");
+ break;
+ }
+ return gp_Vec(aV1);
+}
+
+
--- /dev/null
+-- File: HelixGeom_Tools.cdl
+
+
+class Tools from HelixGeom
+
+ ---Purpose: Approximation algorithms for bulding helix curves
+
+uses
+ HCurve from Adaptor3d,
+ BSplineCurve from Geom,
+ Shape from GeomAbs
+--raises
+
+is
+ ApprHelix(myclass;
+ aT1 :Real from Standard;
+ aT2 :Real from Standard;
+ aPitch :Real from Standard;
+ aRStart :Real from Standard;
+ aTaperAngle:Real from Standard;
+ aIsCW :Boolean from Standard;
+ aTol :Real from Standard;
+ theBSpl :out BSplineCurve from Geom;
+ theMaxError:out Real from Standard)
+ ---Purpose: Bulding helix curves
+ returns Integer from Standard;
+
+ ApprCurve3D(myclass;
+ theHC :out HCurve from Adaptor3d;
+ theTol : Real from Standard;
+ theCont : Shape from GeomAbs;
+ theMaxSeg : Integer from Standard;
+ theMaxDeg : Integer from Standard;
+ theBSpl :out BSplineCurve from Geom;
+ theMaxError:out Real from Standard)
+ ---Purpose: Reaprroximation of adaptor curve
+ returns Integer from Standard;
+--fields
+
+end Tools;
+
+
--- /dev/null
+// File: HelixGeom_Tools.cxx
+
+
+
+#include <HelixGeom_Tools.ixx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <AdvApprox_DichoCutting.hxx>
+#include <AdvApprox_EvaluatorFunction.hxx>
+#include <AdvApprox_ApproxAFunction.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <HelixGeom_HHelixCurve.hxx>
+
+//=======================================================================
+//class : HelixGeom_Tools_Eval
+//purpose: evaluator class for approximation
+//=======================================================================
+
+class HelixGeom_Tools_Eval : public AdvApprox_EvaluatorFunction
+{
+ public:
+ HelixGeom_Tools_Eval (const Handle(Adaptor3d_HCurve)& theFunc)
+ : fonct(theFunc) {}
+
+ virtual void Evaluate (Standard_Integer *Dimension,
+ Standard_Real StartEnd[2],
+ Standard_Real *Parameter,
+ Standard_Integer *DerivativeRequest,
+ Standard_Real *Result, // [Dimension]
+ Standard_Integer *ErrorCode);
+
+ private:
+ Handle(Adaptor3d_HCurve) fonct;
+};
+
+void HelixGeom_Tools_Eval::Evaluate (Standard_Integer *Dimension,
+ Standard_Real /*StartEnd*/[2],
+ Standard_Real *Param, // Parameter at which evaluation
+ Standard_Integer *Order, // Derivative Request
+ Standard_Real *Result,// [Dimension]
+ Standard_Integer *ErrorCode)
+{
+ *ErrorCode = 0;
+ Standard_Real par = *Param;
+
+// Dimension is incorrect
+ if (*Dimension!=3) {
+ *ErrorCode = 1;
+ }
+ gp_Pnt pnt;
+ gp_Vec v1, v2;
+
+ switch (*Order) {
+ case 0:
+ pnt = fonct->Value(par);
+ Result[0] = pnt.X();
+ Result[1] = pnt.Y();
+ Result[2] = pnt.Z();
+ break;
+ case 1:
+ fonct->D1(par, pnt, v1);
+ Result[0] = v1.X();
+ Result[1] = v1.Y();
+ Result[2] = v1.Z();
+ break;
+ case 2:
+ fonct->D2(par, pnt, v1, v2);
+ Result[0] = v2.X();
+ Result[1] = v2.Y();
+ Result[2] = v2.Z();
+ break;
+ default:
+ Result[0] = Result[1] = Result[2] = 0.;
+ *ErrorCode = 3;
+ break;
+ }
+}
+
+//=======================================================================
+//function : ApprCurve3D
+//purpose :
+//=======================================================================
+Standard_Integer HelixGeom_Tools::ApprCurve3D(Handle(Adaptor3d_HCurve)& theHC,
+ const Standard_Real theTol,
+ const GeomAbs_Shape theCont,
+ const Standard_Integer theMaxSeg,
+ const Standard_Integer theMaxDeg,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError)
+{
+ Standard_Boolean anIsDone, aHasResult;
+ Standard_Integer Num1DSS, Num2DSS, Num3DSS;
+ Standard_Real First, Last;
+ Handle(TColStd_HArray1OfReal) OneDTolNul, TwoDTolNul, ThreeDTol;
+ AdvApprox_DichoCutting aCutTool;
+ //
+ Num1DSS=0;
+ Num2DSS=0;
+ Num3DSS=1;
+ ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS);
+ ThreeDTol->Init(theTol);
+ //
+ First = theHC->FirstParameter();
+ Last = theHC->LastParameter();
+ //
+ HelixGeom_Tools_Eval ev (theHC);
+ AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS,
+ OneDTolNul, TwoDTolNul, ThreeDTol,
+ First, Last, theCont,
+ theMaxDeg, theMaxSeg,
+ ev, aCutTool);
+ //
+ anIsDone = aApprox.IsDone();
+ if(!anIsDone) {
+ return 1;
+ }
+ //
+ theMaxError = 0.;
+ //
+ aHasResult = aApprox.HasResult();
+ if (!aHasResult) {
+ return 2;
+ }
+ //
+ TColgp_Array1OfPnt Poles(1,aApprox.NbPoles());
+ aApprox.Poles(1,Poles);
+ Handle(TColStd_HArray1OfReal) Knots = aApprox.Knots();
+ Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities();
+ Standard_Integer Degree = aApprox.Degree();
+ theBSpl = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree);
+ theMaxError = aApprox.MaxError(3, 1);
+ //
+ return 0;
+}
+//=======================================================================
+//function : ApprHelix
+//purpose :
+//=======================================================================
+Standard_Integer HelixGeom_Tools::ApprHelix(const Standard_Real aT1,
+ const Standard_Real aT2,
+ const Standard_Real aPitch,
+ const Standard_Real aRStart,
+ const Standard_Real aTaperAngle,
+ const Standard_Boolean aIsCW,
+ const Standard_Real theTol,
+ Handle(Geom_BSplineCurve)& theBSpl,
+ Standard_Real& theMaxError)
+{
+ Standard_Integer iErr, aMaxDegree, aMaxSeg;
+ GeomAbs_Shape aCont;
+ HelixGeom_HelixCurve aAdaptor;
+ Handle(HelixGeom_HHelixCurve) aHAdaptor;
+ //
+ aAdaptor.Load(aT1, aT2, aPitch, aRStart, aTaperAngle, aIsCW);
+ aHAdaptor=new HelixGeom_HHelixCurve(aAdaptor);
+ //
+ aCont=GeomAbs_C2;
+ aMaxDegree = 8;
+ aMaxSeg=150;
+ //
+ iErr=HelixGeom_Tools::ApprCurve3D(aHAdaptor,
+ theTol, aCont, aMaxSeg, aMaxDegree,
+ theBSpl, theMaxError);
+ return iErr;
+}
+
--- /dev/null
+HelixTest.cxx
+HelixTest_HelixCommands.cxx
--- /dev/null
+-- File: HelixTest.cdl
+
+
+package HelixTest
+
+ ---Purpose:
+
+uses
+ Draw,
+ DBRep,
+ TopoDS,
+ gp
+is
+ AllCommands (aDI:out Interpretor from Draw);
+ HelixCommands (aDI:out Interpretor from Draw);
+ Factory (aDI:out Interpretor from Draw);
+
+end HelixTest;
+
--- /dev/null
+// File: HelixTest.cxx
+
+#include <HelixTest.ixx>
+#include <stdio.h>
+
+//=======================================================================
+//function : AllCommands
+//purpose :
+//=======================================================================
+ void HelixTest::AllCommands(Draw_Interpretor& theCommands)
+{
+ static Standard_Boolean done = Standard_False;
+ if (done) return;
+ done = Standard_True;
+ //
+ HelixTest::HelixCommands (theCommands);
+}
+//=======================================================================
+//function : Factory
+//purpose :
+//=======================================================================
+ void HelixTest::Factory(Draw_Interpretor& theCommands)
+{
+ static Standard_Boolean FactoryDone = Standard_False;
+ if (FactoryDone) return;
+
+ FactoryDone = Standard_True;
+
+ HelixTest::AllCommands(theCommands);
+ Printf(" Helix Plugin is loaded\n");
+}
+#include <Draw_PluginMacro.hxx>
+DPLUGIN(HelixTest)
+
+
--- /dev/null
+// File: HelixTest_HelixCommands.cxx
+
+#include <HelixTest.ixx>
+#include <Draw_Interpretor.hxx>
+#include <HelixGeom_HelixCurve.hxx>
+#include <Draw.hxx>
+#include <Draw_Viewer.hxx>
+#include <Draw_Marker3D.hxx>
+#include <Draw_Segment3D.hxx>
+#include <Draw_Color.hxx>
+#include <HelixGeom_Tools.hxx>
+
+#include <DrawTrSurf.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <HelixGeom_BuilderHelixCoil.hxx>
+#include <TColGeom_SequenceOfCurve.hxx>
+#include <HelixGeom_BuilderHelix.hxx>
+
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Line.hxx>
+
+#include <gp_Pln.hxx>
+#include <gp_Ax1.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Ax2.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Vec.hxx>
+
+#include <HelixBRep_BuilderHelix.hxx>
+#include <DBRep.hxx>
+#include <TopoDS_Shape.hxx>
+#include <gp.hxx>
+#include <TColgp_Array1OfPnt.hxx>
+#include <GeomAdaptor_Curve.hxx>
+#include <GeomAdaptor_HCurve.hxx>
+#include <TColGeom_HArray1OfCurve.hxx>
+#include <TColStd_Array1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+
+
+//
+Standard_IMPORT Draw_Viewer dout;
+//
+static gp_Ax3 theHelixAxis(gp_Pnt(0., 0., 0), gp_Dir(0., 0., 1.), gp_Dir(1., 0., 0.));
+
+static Standard_Integer comphelix (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer helix (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer spiral (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer setaxis (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer comphelix2 (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer helix2 (Draw_Interpretor& , Standard_Integer , const char ** );
+static Standard_Integer spiral2 (Draw_Interpretor& , Standard_Integer , const char ** );
+//=======================================================================
+//function : HelixTest::HelixCommands
+//purpose :
+//=======================================================================
+ void HelixTest::HelixCommands(Draw_Interpretor& theCommands)
+{
+ static Standard_Boolean done = Standard_False;
+ if (done) return;
+ done = Standard_True;
+ // Chapters name
+ const char* g = "Helix commands";
+ // Commands
+ theCommands.Add("setaxis", "setaxis x y z Nx Ny Nz Xx Xy Xz",
+ __FILE__, setaxis, g);
+ theCommands.Add("comphelix", "comphelix name np D1 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__, comphelix, g);
+ theCommands.Add("helix", "helix name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__, helix, g);
+ theCommands.Add("spiral", "spiral name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]",
+ __FILE__, spiral, g);
+ theCommands.Add("comphelix2", "comphelix2 name np D1 [Di...] P1 [Pi...] N1 [Ni...]",
+ __FILE__, comphelix2, g);
+ theCommands.Add("helix2", "helix2 name np D1 P1 [Pi...] N1 [Ni...]",
+ __FILE__, helix2, g);
+ theCommands.Add("spiral2", "spiral2 name np D1 D2 P1 [Pi...] N1 [Ni...]",
+ __FILE__, spiral2, g);
+}
+
+//=======================================================================
+//function : setaxis
+//purpose :
+//=======================================================================
+ Standard_Integer setaxis(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 10) {
+ di << "Usage : " << a[0] << " x y z Nx Ny Nz Xx Xy Xz" <<"\n";
+ di << " " << "x y z - location" <<"\n";
+ di << " " << "Nx Ny Nz - direction" <<"\n";
+ di << " " << "Xx Xy Xz - X direction" <<"\n";
+ return 1;
+ }
+ Standard_Real xx[9];
+ Standard_Integer i;
+ for(i = 0; i < 9; ++i) {
+ xx[i] = Draw::Atof(a[i+1]);
+ }
+
+ theHelixAxis.SetLocation(gp_Pnt(xx[0], xx[1], xx[2]));
+ theHelixAxis.SetDirection(gp_Dir(xx[3], xx[4], xx[5]));
+ theHelixAxis.SetXDirection(gp_Dir(xx[6], xx[7], xx[8]));
+
+ return 0;
+}
+//
+//=======================================================================
+//function : comphelix
+//purpose :
+//=======================================================================
+ Standard_Integer comphelix(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 8) {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 ... (must be np+1 values) - diameters" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + (aNb+1) + aNb*3) {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 ... (must be np+1 values) - diameters" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, aNb + 1);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= aNb+1; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ bIsPitches(i) = Draw::Atoi(a[ic]);
+ ++ic;
+ }
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams, aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : helix
+//purpose :
+//=======================================================================
+ Standard_Integer helix(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 7) {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 - diameter" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 1 + aNb*3) {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 - diameter" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, 1);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= 1; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ bIsPitches(i) = Draw::Atoi(a[ic]);
+ ++ic;
+ }
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : spiral
+//purpose :
+//=======================================================================
+ Standard_Integer spiral(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 8) {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 - first and last diameters" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 2 + aNb*3) {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 - first and last diameters" <<"\n";
+ di << " " << "H1, H2 ... (must be np values) - heights" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches or numbers of turns" <<"\n";
+ di << " " << "PF1, PF2 ... (must be np values) - 0 or 1, if PFi = 1, Pi is pitch, otherwise Pi is number of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, 2);
+ TColStd_Array1OfReal aHeights(1, aNb);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfBoolean bIsPitches(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= 2; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aHeights(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ bIsPitches(i) = Draw::Atoi(a[ic]);
+ ++ic;
+ }
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aDiams(2), aHeights, aPitches, bIsPitches);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : comphelix2
+//purpose :
+//=======================================================================
+ Standard_Integer comphelix2(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 7) {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] P1 [Pi...] N1 [Ni...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2, ... (must be np+1 values) - diameters" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + (aNb+1) + aNb*2) {
+ di << "Usage : " << a[0] << " name np D1 D2 [Di...] P1 [Pi...] N1 [Ni...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2, ... (must be np+1 values) - diameters" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, aNb + 1);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= aNb+1; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams, aPitches, aNbTurns);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : helix2
+//purpose :
+//=======================================================================
+ Standard_Integer helix2(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 6) {
+ di << "Usage : " << a[0] << " name np D1 P1 [Pi...] N1 [Ni...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 - diameter" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 1 + aNb*2) {
+ di << "Usage : " << a[0] << " name np D1 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 - diameter" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, 1);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= 1; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aPitches, aNbTurns);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : spiral2
+//purpose :
+//=======================================================================
+ Standard_Integer spiral2(Draw_Interpretor& di, Standard_Integer n, const char ** a)
+{
+ if (n < 7) {
+ di << "Usage : " << a[0] << " name np D1 D2 P1 [Pi...] N1 [Ni...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 - first and last diameters" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+ Standard_Integer i, aNb, ic;
+ HelixBRep_BuilderHelix aBH;
+ //
+ aNb = Draw::Atoi(a[2]);
+ if (n != 3 + 2 + aNb*2) {
+ di << "Usage : " << a[0] << " name np D1 D2 H1 [Hi...] P1 [Pi...] PF1 [PFi...]" <<"\n";
+ di << " " << "name - name of result" <<"\n";
+ di << " " << "np - number of helix parts" <<"\n";
+ di << " " << "D1 D2 - first and last diameters" <<"\n";
+ di << " " << "P1, P2, ... (must be np values) - pitches" <<"\n";
+ di << " " << "N1, N2, ... (must be np values) - numbers of turns" <<"\n";
+ return 1;
+ }
+ //
+
+ TColStd_Array1OfReal aDiams(1, 2);
+ TColStd_Array1OfReal aPitches(1, aNb);
+ TColStd_Array1OfReal aNbTurns(1, aNb);
+
+ ic = 3;
+ for(i = 1; i <= 2; ++i) {
+ aDiams(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aPitches(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+
+ for(i = 1; i <= aNb; ++i) {
+ aNbTurns(i) = Draw::Atof(a[ic]);
+ ++ic;
+ }
+ //
+
+ aBH.SetParameters(theHelixAxis, aDiams(1), aDiams(2), aPitches, aNbTurns);
+
+ aBH.Perform();
+
+ if(aBH.ErrorStatus() == 0) {
+ Standard_Real aMaxError=aBH.ToleranceReached();
+ di << "WarningStatus = " << aBH.WarningStatus() <<"\n";
+ di << "ToleranceReached = " << aMaxError <<"\n";
+ //
+ const TopoDS_Shape& aW=aBH.Shape();
+ DBRep::Set(a[1], aW);
+ }
+ else {
+ di << "ErrorStatus = " << aBH.ErrorStatus() << "\n";
+ }
+
+ return 0;
+}
srcinc:::Visualization.tcl
srcinc:::ApplicationFramework.tcl
srcinc:::DataExchange.tcl
+srcinc:::Helix.tcl
+srcinc:::Unfolding.tcl
--- /dev/null
+# Definitions for a product: Helix
+
+# List of toolkits
+proc Helix:toolkits { } {
+ return [list TKHelix]
+}
+
+# List of non-toolkits (resource units, executables etc., with associated info)
+proc Helix:ressources { } {
+ return {}
+}
+
+# Product name
+proc Helix:name { } {
+ return Helix
+}
+
+# And short alias
+proc Helix:alias { } {
+ return Helix
+}
+
+# Dependency on other products
+proc Helix:depends { } {
+ return {}
+}
+
+proc Helix:CompileWith { } {
+}
+
+proc Helix:LinksoWith { } {
+}
+
+proc Helix:Export { } {
+ return [list source runtime wokadm api]
+}
ApplicationFramework \
DataExchange \
Draw \
+ Helix \
+ Unfolding \
]
return $ret
}
--- /dev/null
+# Definitions for a product: Unfolding
+
+# List of toolkits
+proc Unfolding:toolkits { } {
+ return [list TKUnfolding TKUnfoldingTest]
+}
+
+# List of non-toolkits (resource units, executables etc., with associated info)
+proc Unfolding:ressources { } {
+ return {}
+}
+
+# Product name
+proc Unfolding:name { } {
+ return Unfolding
+}
+
+# And short alias
+proc Unfolding:alias { } {
+ return Unfolding
+}
+
+# Dependency on other products
+proc Unfolding:depends { } {
+ return {}
+}
+
+proc Unfolding:CompileWith { } {
+}
+
+proc Unfolding:LinksoWith { } {
+}
+
+proc Unfolding:Export { } {
+ return [list source runtime wokadm api]
+}
mutable volatile int myIsRaceDetected;
};
-//=======================================================================
-//function : OCC25545
-//purpose : Tests data race when concurrently accessing TopLoc_Location::Transformation()
-//=======================================================================
-#ifdef HAVE_TBB
-static Standard_Integer OCC25545 (Draw_Interpretor& di,
- Standard_Integer,
- const char **)
-{
- // Place vertices in a vector, giving the i-th vertex the
- // transformation that translates it on the vector (i,0,0) from the origin.
- size_t n = 1000;
- std::vector<TopoDS_Shape> aShapeVec (n);
- std::vector<TopLoc_Location> aLocVec (n);
- TopoDS_Shape aShape = BRepBuilderAPI_MakeVertex (gp::Origin ());
- aShapeVec[0] = aShape;
- for (size_t i = 1; i < n; ++i) {
- gp_Trsf aT;
- aT.SetTranslation (gp_Vec (1, 0, 0));
- aLocVec[i] = aLocVec[i - 1] * aT;
- aShapeVec[i] = aShape.Moved (aLocVec[i]);
- }
-
- // Evaluator function will access vertices geometry
- // concurrently
- OCC25545_Functor aFunc(aShapeVec);
-
- //concurrently process
- tbb::parallel_for (size_t (0), n, aFunc, tbb::simple_partitioner ());
- QVERIFY (!aFunc.myIsRaceDetected);
- return 0;
-}
-#else
-static Standard_Integer OCC25545 (Draw_Interpretor&,
- Standard_Integer,
- const char **argv)
-{
- cout << "Test skipped: command " << argv[0] << " requires TBB library" << endl;
- return 0;
-}
-#endif
//=======================================================================
//function : OCC25547
theCommands.Add ("OCC25348", "OCC25348", __FILE__, OCC25348, group);
theCommands.Add ("OCC25413", "OCC25413 shape", __FILE__, OCC25413, group);
theCommands.Add ("OCC25446", "OCC25446 res b1 b2 op", __FILE__, OCC25446, group);
- theCommands.Add ("OCC25545",
- "no args; tests data race when concurrently accessing \n"
- "\t\tTopLoc_Location::Transformation()",
- __FILE__, OCC25545, group);
theCommands.Add ("OCC25547", "OCC25547", __FILE__, OCC25547, group);
theCommands.Add ("OCC24881", "OCC24881 shape", __FILE__, OCC24881, group);
theCommands.Add ("OCC26172", "OCC26172", __FILE__, OCC26172, group);
--- /dev/null
+TKBRep
+TKMath
+TKernel
+TKG2d
+TKG3d
+TKDraw
+TKTopAlgo
--- /dev/null
+HelixGeom
+HelixBRep
+HelixTest
--- /dev/null
+TKBRep
+TKMath
+TKernel
+TKG2d
+TKG3d
+TKDraw
+TKTopAlgo
+TKGeomAlgo
+TKShHealing
+TKGeomBase
--- /dev/null
+TKBRep
+TKMath
+TKernel
+TKG3d
+TKDraw
+TKUnfolding
\ No newline at end of file
--- /dev/null
+UnfoldingTest
--- /dev/null
+-- File: Unfolding.cdl
+-- Created: Tue Jul 22 12:48:05 2008
+-- Author: Sergey KHROMOV
+-- <skv@dimox>
+---Copyright: Open CASCADE 2008
+
+package Unfolding
+ ---Purpose: This package contains a tool for unfolding a surface on a plane.
+
+uses
+
+ TopoDS,
+ TopTools,
+ gp,
+ Standard,
+ TCollection,
+ TColgp,
+ math
+
+is
+
+ ---Purpose: Enumeration that defines an error status of an operation.
+ enumeration ErrorStatus
+ is
+ Done,
+ NotDone,
+ Failure,
+ InvalidSurface,
+ InvalidInput,
+ InvalidShape,
+ ComplexShape
+ end;
+
+ class Surface;
+
+ class Point;
+
+ class FunctionWithDerivative;
+
+ class Shell;
+
+ class FaceDataContainer;
+
+ class FaceDataMapHasher;
+
+ class Array2OfPoint
+ instantiates Array2 from TCollection (Point from Unfolding);
+
+ class HArray2OfPoint
+ instantiates HArray2 from TCollection (Point from Unfolding,
+ Array2OfPoint from Unfolding);
+
+ class IndexedMapOfFaceDataContainer
+ instantiates IndexedMap from TCollection
+ (FaceDataContainer from Unfolding,
+ FaceDataMapHasher from Unfolding);
+
+ ToShell(theShape : Shape from TopoDS;
+ theTolerance : Real from Standard;
+ theStatus : out ErrorStatus from Unfolding)
+ ---Purpose: This method converts theShape to a shell. It sewes faces of the
+ -- shell if it is necessary and possible with the given tolerance.
+ -- If it is not possible to construct a single shell from theShape,
+ -- this method returns null shell and the corresponding error
+ -- status. The status can have the following values:
+ -- - Unfolding_Done: the operation succeeded
+ -- - Unfolding_InvalidInput: input shape type is less then
+ -- TopAbs_SHELL.
+ -- - Unfolding_Failure: sewing failure.
+ -- - Unfolding_InvalidShape: the shape after sewing does not
+ -- contain shells.
+ -- - Unfolding_ComplexShape: the shape after sewing contains
+ -- either more then one shell or one shell and other not
+ -- connected shapes.
+ returns Shell from TopoDS;
+
+ NbSamples(theEdge : Edge from TopoDS;
+ theFaces : ListOfShape from TopTools;
+ theTolerance: Real from Standard)
+ ---Purpose: This method returns the number of sample points for theEdge.
+ -- theFaces is a list of faces that contain theEdge.
+ returns Integer from Standard;
+
+ GetMaxNbSamples
+ ---Purpose: This method returns the maximal number of points for sampling of
+ -- edges and/or faces.
+ ---C++: inline
+ returns Integer from Standard;
+
+end Unfolding;
--- /dev/null
+// File: Unfolding.cxx
+// Created: Wed Sep 17 09:16:05 2008
+// Author: Sergey KHROMOV
+// <skv@kurox>
+
+
+#include <Unfolding.hxx>
+#include <BRepBuilderAPI_Sewing.hxx>
+#include <BRep_Tool.hxx>
+#include <GCPnts_AbscissaPoint.hxx>
+#include <Geom2dAdaptor_Curve.hxx>
+#include <Geom2d_BezierCurve.hxx>
+#include <Geom2d_BSplineCurve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_ListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+
+//=======================================================================
+//function : ToShell
+//purpose :
+//=======================================================================
+
+TopoDS_Shell Unfolding::ToShell(const TopoDS_Shape &theShape,
+ const Standard_Real theTolerance,
+ Unfolding_ErrorStatus &theStatus)
+{
+ TopoDS_Shell aShell;
+ TopAbs_ShapeEnum aType = theShape.ShapeType();
+
+ if (aType != TopAbs_COMPOUND && aType != TopAbs_COMPSOLID &&
+ aType != TopAbs_SOLID && aType != TopAbs_SHELL) {
+ theStatus = Unfolding_InvalidInput;
+ return aShell;
+ }
+
+ if (aType == TopAbs_SHELL) {
+ // theShape is a shell. Nothing to be done.
+ theStatus = Unfolding_Done;
+ aShell = TopoDS::Shell(theShape);
+ return aShell;
+ }
+
+ BRepBuilderAPI_Sewing aSewing(theTolerance);
+
+ aSewing.Add(theShape);
+ aSewing.Perform();
+
+ const TopoDS_Shape &aShape = aSewing.SewedShape();
+
+ if (aShape.IsNull()) {
+ theStatus = Unfolding_Failure;
+ return aShell;
+ }
+
+ // Explore shape to extract a shell.
+ TopExp_Explorer anExp(aShape, TopAbs_SHELL);
+
+ if (!anExp.More()) {
+ theStatus = Unfolding_InvalidShape;
+ return aShell;
+ }
+
+ TopoDS_Shape aSingleShell = anExp.Current();
+
+ anExp.Next();
+
+ if (anExp.More()) {
+ theStatus = Unfolding_ComplexShape;
+ return aShell;
+ }
+
+ // Check if there is no other redundant shapes that are not in the shell.
+ anExp.Init(aShape, TopAbs_VERTEX, TopAbs_SHELL);
+
+ if (anExp.More()) {
+ theStatus = Unfolding_ComplexShape;
+ return aShell;
+ }
+
+ // Get the single shell.
+ theStatus = Unfolding_Done;
+ aShell = TopoDS::Shell(aSingleShell);
+
+ return aShell;
+}
+
+//=======================================================================
+//function : ToShell
+//purpose :
+//=======================================================================
+
+Standard_Integer Unfolding::NbSamples(const TopoDS_Edge &theEdge,
+ const TopTools_ListOfShape &theFaces,
+ const Standard_Real theTolerance)
+{
+ Standard_Integer aNbPointsLimit = Unfolding::GetMaxNbSamples() / 2;
+ Standard_Integer aMaxNbPoints = 11;
+ Standard_Integer aNbPoints;
+ TopTools_ListIteratorOfListOfShape anIt( theFaces );
+
+ for ( ; anIt.More(); anIt.Next() ) {
+ TopoDS_Shape aCurShape = anIt.Value();
+ TopoDS_Face aFace = TopoDS::Face( aCurShape );
+ aFace.Orientation(TopAbs_FORWARD);
+
+ Standard_Integer aNbPnt = 2;
+ Standard_Real aParam[2];
+ Handle(Geom2d_Curve) aCurve =
+ BRep_Tool::CurveOnSurface(theEdge, aFace, aParam[0], aParam[1]);
+ Handle(Standard_Type) aType = aCurve->DynamicType();
+
+ while (aType == STANDARD_TYPE(Geom2d_TrimmedCurve)) {
+ Handle(Geom2d_TrimmedCurve) aTrCurve =
+ Handle(Geom2d_TrimmedCurve)::DownCast(aCurve);
+ aCurve = aTrCurve->BasisCurve();
+ aType = aCurve->DynamicType();
+ }
+
+ if (aType == STANDARD_TYPE(Geom2d_BezierCurve)) {
+ Handle(Geom2d_BezierCurve) aBezier =
+ Handle(Geom2d_BezierCurve)::DownCast(aCurve);
+ aNbPnt = 3 + aBezier->NbPoles();
+
+
+ if (aNbPnt < 11)
+ aNbPnt = 11;
+ } else if (aType == STANDARD_TYPE(Geom2d_BSplineCurve)) {
+ Handle(Geom2d_BSplineCurve) aBSpline =
+ Handle(Geom2d_BSplineCurve)::DownCast(aCurve);
+ aNbPnt = aBSpline->NbKnots()*aBSpline->Degree();
+
+ if (aNbPnt < 11)
+ aNbPnt = 11;
+ } else {
+ aNbPnt = 11;
+ }
+ aMaxNbPoints = ( aMaxNbPoints < aNbPnt ) ? aNbPnt : aMaxNbPoints;
+
+ Geom2dAdaptor_Curve aCurve1(aCurve);
+ Standard_Real L = GCPnts_AbscissaPoint::Length(aCurve1, aParam[0], aParam[1]) ;
+ // estimate number of points taking into account the curvature of radius myTolContour * 2.
+ Standard_Real sizeR = 0.125 * L / theTolerance + 2;
+
+ if ( aNbPointsLimit > sizeR )
+ aNbPointsLimit = (Standard_Integer) sizeR;
+ }
+
+ // Check if the number of points exceeds the maximum number of points.
+
+ if(aMaxNbPoints > aNbPointsLimit)
+ aMaxNbPoints = aNbPointsLimit;
+
+ aNbPoints = aMaxNbPoints;
+
+ return aNbPoints;
+}
--- /dev/null
+// File: Unfolding.lxx
+// Created: Tue Jul 22 13:12:24 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+inline Standard_Integer Unfolding::GetMaxNbSamples()
+{
+ static Standard_Integer aMaxNbSamples = 1000;
+
+ return aMaxNbSamples;
+}
--- /dev/null
+-- File: Unfolding_FaceDataContainer.cdl
+-- Created: Fri Sep 19 16:52:05 2008
+-- Author: Sergey KHROMOV
+-- <skv@kurox>
+---Copyright: Matra Datavision 2008
+
+class FaceDataContainer from Unfolding inherits TShared from MMgt
+ ---Purpose: This class represents a data container for data constructed
+ -- during unfolding operation.
+
+uses
+
+ Face from TopoDS,
+ Edge from TopoDS,
+ Trsf from gp,
+ Real from Standard,
+ ListOfShape from TopTools,
+ DataMapOfShapeListOfShape from TopTools
+
+is
+
+ Create
+ ---Purpose: Empty constructor
+ ---C++: inline
+ returns FaceDataContainer from Unfolding;
+
+ SetFace(me: mutable; theFace: Face from TopoDS);
+ ---Purpose: Sets the original face.
+
+ GetFace(me)
+ ---Purpose: Returns the original face.
+ ---C++: inline
+ ---C++: return const &
+ returns Face from TopoDS;
+
+ SetUnfoldedFace(me: mutable; theUnfoldedFace: Face from TopoDS);
+ ---Purpose: Sets the unfolded face for the original one.
+ ---C++: inline
+
+ GetUnfoldedFace(me)
+ ---Purpose: Returns the unfolded face for the original one.
+ ---C++: inline
+ ---C++: return const &
+ returns Face from TopoDS;
+
+ SetDistortionArea(me: mutable; theDistortionArea: Real from Standard);
+ ---Purpose: Sets the distortion area.
+ ---C++: inline
+
+ GetDistortionArea(me)
+ ---Purpose: Returns the distortion area.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetMaxGaussCurvature(me: mutable; theCurvature: Real from Standard);
+ ---Purpose: Sets the maximal Gauss curvature.
+ ---C++: inline
+
+ GetMaxGaussCurvature(me)
+ ---Purpose: Returns the maximal Gauss curvature.
+ ---C++: inline
+ returns Real from Standard;
+
+ Reset(me: mutable);
+ ---Purpose: Resets the data container.
+ ---C++: inline
+
+ ApplyTrsf(me: mutable; theTrsf: Trsf from gp);
+ ---Purpose: Applies the transformation to all unfolded shapes.
+
+ SetEdgesForEdge(me: mutable;
+ theEdge : Edge from TopoDS;
+ theUnfoldedEdges: ListOfShape from TopTools);
+ ---Purpose: Associates unfolded edges with the source edge.
+
+ GetEdgesForEdge(me; theEdge: Edge from TopoDS)
+ ---Purpose: Returns unfolded edges associated to the source edge.
+ ---C++: return const &
+ returns ListOfShape from TopTools;
+
+fields
+
+ myFace : Face from TopoDS;
+ myUnfoldedFace : Face from TopoDS;
+ myEdgeMap : DataMapOfShapeListOfShape from TopTools;
+ myDistortionArea : Real from Standard;
+ myCurvature : Real from Standard;
+
+end;
--- /dev/null
+// File: Unfolding_FaceDataContainer.cxx
+// Created: Tue Jul 22 13:12:24 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+#include <Unfolding_FaceDataContainer.ixx>
+#include <BRepBuilderAPI_Transform.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+
+
+//=======================================================================
+//function : SetFace
+//purpose :
+//=======================================================================
+
+void Unfolding_FaceDataContainer::SetFace(const TopoDS_Face &theFace)
+{
+ Standard_Boolean isSame = theFace.IsSame(myFace);
+ myFace = theFace;
+
+ if (!isSame) {
+ // Update the map myEdgeMap
+ myEdgeMap.Clear();
+
+ TopExp_Explorer anExp(myFace, TopAbs_EDGE);
+ TopTools_ListOfShape anEmptyList;
+
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &anEdge = anExp.Current();
+
+ myEdgeMap.Bind(anEdge, anEmptyList);
+ }
+ }
+}
+
+//=======================================================================
+//function : ApplyTrsf
+//purpose :
+//=======================================================================
+
+void Unfolding_FaceDataContainer::ApplyTrsf(const gp_Trsf &theTrsf)
+{
+ BRepBuilderAPI_Transform aTrsf(theTrsf);
+
+ if (!myUnfoldedFace.IsNull()) {
+ aTrsf.Perform(myUnfoldedFace);
+
+ if (aTrsf.IsDone())
+ myUnfoldedFace = TopoDS::Face(aTrsf.Shape());
+ }
+
+ TopTools_DataMapIteratorOfDataMapOfShapeListOfShape anEdgeIter(myEdgeMap);
+ TopTools_ListIteratorOfListOfShape aUEIter;
+
+ for (; anEdgeIter.More(); anEdgeIter.Next()) {
+ const TopoDS_Shape &anEdge = anEdgeIter.Key();
+ TopTools_ListOfShape &anEdges = myEdgeMap.ChangeFind(anEdge);
+ TopTools_ListOfShape aTrsfEdges;
+
+ for (aUEIter.Initialize(anEdges); aUEIter.More(); aUEIter.Next()) {
+ const TopoDS_Shape &aUEdge = aUEIter.Value();
+
+ aTrsf.Perform(aUEdge);
+
+ if (aTrsf.IsDone())
+ aTrsfEdges.Append(aTrsf.Shape());
+ }
+
+ anEdges.Clear();
+ anEdges.Append(aTrsfEdges);
+ }
+}
+
+//=======================================================================
+//function : SetEdgesForEdge
+//purpose :
+//=======================================================================
+
+void Unfolding_FaceDataContainer::SetEdgesForEdge
+ (const TopoDS_Edge &theEdge,
+ const TopTools_ListOfShape &theUnfoldedEdges)
+{
+ if (myEdgeMap.IsBound(theEdge)) {
+ TopTools_ListOfShape &anEdges = myEdgeMap.ChangeFind(theEdge);
+
+ anEdges = theUnfoldedEdges;
+ }
+}
+
+//=======================================================================
+//function : GetEdgesForEdge
+//purpose :
+//=======================================================================
+
+const TopTools_ListOfShape &Unfolding_FaceDataContainer::GetEdgesForEdge
+ (const TopoDS_Edge &theEdge) const
+{
+ if (myEdgeMap.IsBound(theEdge)) {
+ const TopTools_ListOfShape &anEdges = myEdgeMap.Find(theEdge);
+
+ return anEdges;
+ }
+
+ static TopTools_ListOfShape anEmptyList;
+
+ return anEmptyList;
+}
--- /dev/null
+// File: Unfolding_FaceDataContainer.lxx
+// Created: Tue Jul 22 13:12:24 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+//=======================================================================
+//function : Empty constructor
+//purpose :
+//=======================================================================
+
+inline Unfolding_FaceDataContainer::Unfolding_FaceDataContainer()
+ : myDistortionArea(0.),
+ myCurvature(0.)
+{
+}
+
+//=======================================================================
+//function : GetFace
+//purpose :
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_FaceDataContainer::GetFace() const
+{
+ return myFace;
+}
+
+//=======================================================================
+//function : SetUnfoldedFace
+//purpose :
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetUnfoldedFace
+ (const TopoDS_Face &theUnfoldedFace)
+{
+ myUnfoldedFace = theUnfoldedFace;
+}
+
+//=======================================================================
+//function : GetUnfoldedFace
+//purpose :
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_FaceDataContainer::GetUnfoldedFace() const
+{
+ return myUnfoldedFace;
+}
+
+//=======================================================================
+//function : SetDistortionArea
+//purpose :
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetDistortionArea
+ (const Standard_Real theDistortionArea)
+{
+ myDistortionArea = theDistortionArea;
+}
+
+//=======================================================================
+//function : GetDistortionArea
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_FaceDataContainer::GetDistortionArea() const
+{
+ return myDistortionArea;
+}
+
+//=======================================================================
+//function : SetMaxGaussCurvature
+//purpose :
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::SetMaxGaussCurvature
+ (const Standard_Real theCurvature)
+{
+ myCurvature = theCurvature;
+}
+
+//=======================================================================
+//function : GetMaxGaussCurvature
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_FaceDataContainer::GetMaxGaussCurvature() const
+{
+ return myCurvature;
+}
+
+//=======================================================================
+//function : Reset
+//purpose :
+//=======================================================================
+
+inline void Unfolding_FaceDataContainer::Reset()
+{
+ myUnfoldedFace.Nullify();
+ myDistortionArea = 0.;
+ myCurvature = 0.;
+}
--- /dev/null
+-- File: Unfolding_FaceDataMapHasher.cdl
+-- Created: Fri Sep 19 16:52:05 2008
+-- Author: Sergey KHROMOV
+-- <skv@kurox>
+---Copyright: Matra Datavision 2008
+
+class FaceDataMapHasher from Unfolding
+ ---Purpose: Hash tool, used for generating maps of face data containers.
+
+uses
+
+ FaceDataContainer from Unfolding,
+ Integer from Standard,
+ Boolean from Standard
+
+is
+
+ HashCode(myclass; theKey : FaceDataContainer from Unfolding;
+ theUpper: Integer from Standard)
+ ---Purpose: Returns a HasCode value for the Key <K> in the
+ -- range 0..theUpper.
+ ---C++: inline
+ returns Integer from Standard;
+
+ IsEqual(myclass; theKey1, theKey2 : FaceDataContainer from Unfolding)
+ ---Purpose: Returns True when the two keys are the same. Two
+ -- same keys must have the same hashcode, the
+ -- contrary is not necessary.
+ ---C++: inline
+ returns Boolean from Standard;
+
+end;
--- /dev/null
+// File: Unfolding_FaceDataMapHasher.cxx
+// Created: Mon Sep 22 09:01:04 2008
+// Author: Sergey KHROMOV
+// <skv@kurox>
+
+
+#include <Unfolding_FaceDataMapHasher.ixx>
--- /dev/null
+// File: Unfolding_FaceDataMapHasher.lxx
+// Created: Mon Sep 22 08:54:51 2008
+// Author: Sergey KHROMOV
+// <skv@kurox>
+
+
+//=======================================================================
+//function : HashCode
+//purpose :
+//=======================================================================
+
+inline Standard_Integer Unfolding_FaceDataMapHasher::HashCode
+ (const Handle(Unfolding_FaceDataContainer) &theKey,
+ const Standard_Integer theUpper)
+{
+ return (theKey.IsNull()) ? 0 : theKey->GetFace().HashCode(theUpper);
+}
+
+//=======================================================================
+//function : IsEqual
+//purpose :
+//=======================================================================
+
+inline Standard_Boolean Unfolding_FaceDataMapHasher::IsEqual
+ (const Handle(Unfolding_FaceDataContainer) &theKey1,
+ const Handle(Unfolding_FaceDataContainer) &theKey2)
+{
+ return !theKey1.IsNull() && !theKey2.IsNull() &&
+ theKey1->GetFace().IsSame(theKey2->GetFace());
+}
--- /dev/null
+-- File: Unfolding_FunctionWithDerivative.cdl
+-- Created: Fri Sep 5 17:44:29 2008
+-- Author: Mikhail KLOKOV
+-- <mkk@kurox>
+---Copyright: Open CASCADE 2008
+
+class FunctionWithDerivative from Unfolding inherits FunctionWithDerivative from math
+uses
+ Array1OfXY from TColgp,
+ Trsf2d from gp,
+ Dir2d from gp
+is
+
+ Create (theMaster, theSlave: Array1OfXY from TColgp;
+ theDir: Dir2d from gp;
+ theTrsf: Trsf2d from gp)
+ returns FunctionWithDerivative from Unfolding;
+ ---Purpose:
+
+ Value(me: in out; X: Real; F: out Real)
+ ---Purpose: Computes the value <F>of the function for the variable <X>.
+ -- Returns True if the calculation were successfully done,
+ -- False otherwise.
+
+ returns Boolean
+ is redefined;
+
+ Derivative(me: in out; X: Real; D: out Real)
+ ---Purpose: Computes the derivative <D> of the function
+ -- for the variable <X>.
+ -- Returns True if the calculation were successfully done,
+ -- False otherwise.
+
+ returns Boolean
+ is redefined;
+
+ Values(me: in out; X: Real; F, D: out Real)
+ ---Purpose: Computes the value <F> and the derivative <D> of the
+ -- function for the variable <X>.
+ -- Returns True if the calculation were successfully done,
+ -- False otherwise.
+
+ returns Boolean
+ is redefined;
+
+ GetStateNumber (me: in out) returns Integer from Standard
+ is redefined;
+
+ Area(me)
+ returns Real from Standard;
+
+fields
+ myMasterPolyLine: Array1OfXY from TColgp;
+ mySlavePolyLine: Array1OfXY from TColgp;
+ myTrsf: Trsf2d from gp;
+ myShiftDir: Dir2d from gp;
+ myShift: Real from Standard;
+ myArea: Real from Standard;
+
+end FunctionWithDerivative from Unfolding;
--- /dev/null
+// File: Unfolding_FunctionWithDerivative.cxx
+// Created: Fri Sep 5 17:51:58 2008
+// Author: Mikhail KLOKOV
+// <mkk@kurox>
+
+
+#include <Unfolding_FunctionWithDerivative.ixx>
+
+
+static Standard_Boolean ComputeArea(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const gp_Dir2d& theShiftDir,
+ const Standard_Real& theShift,
+ const gp_Trsf2d theTrsf,
+ Standard_Real& theArea);
+
+
+static Standard_Boolean ComputeAreaDeriv(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const gp_Dir2d& theShiftDir,
+ const Standard_Real& theShift,
+ const gp_Trsf2d theTrsf,
+ Standard_Real& theArea,
+ Standard_Real& theDeriv);
+
+
+//=============================================================================
+// function: Constructor
+//=============================================================================
+Unfolding_FunctionWithDerivative::Unfolding_FunctionWithDerivative(const TColgp_Array1OfXY& theMaster,
+ const TColgp_Array1OfXY& theSlave,
+ const gp_Dir2d& theDir,
+ const gp_Trsf2d& theTrsf):
+myMasterPolyLine(theMaster.Lower(), theMaster.Upper()),
+mySlavePolyLine(theSlave.Lower(), theSlave.Upper())
+{
+ myMasterPolyLine.Assign(theMaster);
+ mySlavePolyLine.Assign(theSlave);
+ myTrsf = theTrsf;
+ myShiftDir = theDir;
+ myShift = 0.;
+ myArea = 0.;
+}
+
+
+//=============================================================================
+// function: Value
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Value(const Standard_Real X,Standard_Real& F)
+{
+ myShift = X;
+ F = 0.;
+ Standard_Real A = 0.;
+ Standard_Real D = 0.;
+ if ( !ComputeAreaDeriv(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift, myTrsf, A, D) )
+ return Standard_False;
+
+ myArea = A;
+
+ gp_XY aP1P2(0, A);
+ gp_XY vecD(1,D);
+ Standard_Real modD = vecD.Modulus();
+ if ( modD < gp::Resolution() ) {
+ Standard_Real delta = 1.e-7;
+ if ( !ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift - delta, myTrsf, A) )
+ return Standard_False;
+ gp_XY P1(0,A);
+ if ( !ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift + delta, myTrsf, A) )
+ return Standard_False;
+ gp_XY P2(0,A);
+ gp_XY V = P2-P1;
+ modD = V.Modulus();
+ if ( modD < gp::Resolution() )
+ return Standard_False;
+ }
+ F = aP1P2 * vecD;
+ F /= modD;
+
+ return Standard_True;
+}
+
+//=============================================================================
+// function: Derivative
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Derivative(const Standard_Real X,Standard_Real& D)
+{
+ Standard_Real F = 0.;
+ return Values(X,F,D);
+}
+
+//=============================================================================
+// function: Values
+//=============================================================================
+Standard_Boolean Unfolding_FunctionWithDerivative::Values(const Standard_Real X,Standard_Real& F,Standard_Real& D)
+{
+ Standard_Real F1 = 0., F2 = 0.;
+ Standard_Real aDelta = 1.e-05;
+ if ( fabs(X) > aDelta )
+ aDelta = fabs(X) * aDelta;
+ if ( !Value(X + aDelta, F2) )
+ return Standard_False;
+
+ if ( !Value(X, F1) )
+ return Standard_False;
+
+ myShift = X;
+ F = F1;
+ D = F2 - F1;
+ D /= aDelta;
+
+ return Standard_True;
+}
+
+//=============================================================================
+// function: GetStateNumber
+//=============================================================================
+Standard_Integer Unfolding_FunctionWithDerivative::GetStateNumber()
+{
+ ComputeArea(myMasterPolyLine, mySlavePolyLine, myShiftDir, myShift, myTrsf, myArea);
+ return 0;
+}
+
+//=============================================================================
+// function: Area
+//=============================================================================
+Standard_Real Unfolding_FunctionWithDerivative::Area() const
+{
+ return myArea;
+}
+
+//-----------------------------------------------------------------------------
+// function: ComputeAreaDeriv
+//-----------------------------------------------------------------------------
+static Standard_Boolean ComputeAreaDeriv(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const gp_Dir2d& theShiftDir,
+ const Standard_Real& theShift,
+ const gp_Trsf2d theTrsf,
+ Standard_Real& theArea,
+ Standard_Real& theDeriv)
+{
+ theArea = 0.;
+ theDeriv = 0.;
+ Standard_Real X = theShift;
+ Standard_Real F1 = 0., F2 = 0.;
+ if ( !ComputeArea(theMasterPolyLine, theSlavePolyLine, theShiftDir, X, theTrsf, F1) )
+ return Standard_False;
+ theArea = F1;
+ Standard_Real aDelta = 1.e-05;
+ if ( fabs(X) > aDelta )
+ aDelta = fabs(X) * aDelta;
+ if ( !ComputeArea(theMasterPolyLine, theSlavePolyLine, theShiftDir, X + aDelta, theTrsf, F2) )
+ return Standard_False;
+
+ theDeriv = F2 - F1;
+ theDeriv /= aDelta;
+ return Standard_True;
+}
+
+//-----------------------------------------------------------------------------
+// function: ComputeArea
+//-----------------------------------------------------------------------------
+static Standard_Boolean ComputeArea(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const gp_Dir2d& theShiftDir,
+ const Standard_Real& theShift,
+ const gp_Trsf2d theTrsf,
+ Standard_Real& theArea)
+{
+ if ( ( theMasterPolyLine.Length() < 2 ) || ( theSlavePolyLine.Length() < 2 ) ||
+ ( theSlavePolyLine.Length() != theMasterPolyLine.Length() ) )
+ return Standard_False;
+ theArea = 0.;
+
+ gp_Vec2d aTranslation( theShiftDir.XY() * theShift );
+
+ gp_Trsf2d aTransTrsf;
+ aTransTrsf.SetTranslation( aTranslation );
+ gp_Trsf2d aTrans;
+ aTrans = aTransTrsf * theTrsf;
+
+ //
+ TColgp_Array1OfXY aTransformedSlave(theSlavePolyLine.Lower(), theSlavePolyLine.Upper());
+ Standard_Integer i = 0;
+ for ( i = aTransformedSlave.Lower(); i <= aTransformedSlave.Upper(); i++ ) {
+ gp_Pnt2d aP( theSlavePolyLine.Value( i ) );
+ aP.Transform( aTrans );
+ aTransformedSlave.SetValue( i, aP.XY() );
+ }
+ //
+
+ // compute area
+ // This method assumes that the polylines shape is similar
+ // if the shape is completely different, the compute area will be wrong.
+ // But it will grow, that can be considered as a condition of distortion.
+ // So, the method can be acceptable.
+ gp_XY aFirstPoint = aTransformedSlave( aTransformedSlave.Lower() );
+ aFirstPoint += theMasterPolyLine( theMasterPolyLine.Lower() );
+ aFirstPoint *= 0.5;
+
+ gp_XY aLastPoint = aTransformedSlave( aTransformedSlave.Upper() );
+ aLastPoint += theMasterPolyLine( theMasterPolyLine.Upper() );
+ aLastPoint *= 0.5;
+ Standard_Integer nIndexDif = theMasterPolyLine.Lower() - aTransformedSlave.Lower();
+
+ gp_XY aP1 = aFirstPoint;
+ gp_XY aP3 = aFirstPoint;
+
+ for ( i = theMasterPolyLine.Lower() + 1; i <= theMasterPolyLine.Upper(); i++ ) {
+ gp_XY aP2 = theMasterPolyLine(i);
+ gp_XY aP4 = aTransformedSlave(i-nIndexDif);
+ if ( i == theMasterPolyLine.Upper() ) {
+ aP2 = aLastPoint;
+ aP4 = aLastPoint;
+ }
+ gp_XY aP1P4 = aP4 - aP1;
+ gp_XY aP1P2 = aP2 - aP1;
+ gp_XY aP1P3 = aP3 - aP1;
+ Standard_Real aprod1 = aP1P4 ^ aP1P3;
+ Standard_Real aprod2 = aP1P4 ^ aP1P2;
+ if ( aprod1 * aprod2 <= 0. ) {
+ theArea += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+ }
+ else {
+ gp_XY aP3P2 = aP2 - aP3;
+ gp_XY aP3P4 = aP4 - aP3;
+ gp_XY aP3P1 = -aP1P3;
+
+ Standard_Real asum = 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+ aprod1 = aP3P2 ^ aP3P4;
+ aprod2 = aP3P2 ^ aP3P1;
+ if ( aprod1 * aprod2 <= 0. ) {
+ theArea += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+ }
+ else {
+ asum += 0.5 * ( fabs( aprod1 ) + fabs( aprod2 ) );
+ asum *= 0.5;
+ theArea += asum;
+ }
+ }
+
+ aP1 = aP2;
+ aP3 = aP4;
+ }
+
+ return Standard_True;
+}
--- /dev/null
+-- File: Unfolding_Point.cdl
+-- Created: Mon Jul 28 14:56:12 2008
+-- Author: Sergey KHROMOV
+-- <skv@dimox>
+---Copyright: Matra Datavision 2008
+
+
+class Point from Unfolding
+ ---Purpose: This class represents a data container for a point. It contains
+ -- a point on a surface, its U and V parameters on a surface,
+ -- corresponding point on an unfolding plane.
+
+uses
+
+ XY from gp,
+ XYZ from gp,
+ Real from Standard
+
+is
+
+ Create
+ ---Purpose: Empty constructor.
+ ---C++: inline
+ returns Point from Unfolding;
+
+ SetPointOnSurface(me: in out; thePOnSurface: XYZ from gp);
+ ---Purpose: Sets the point on a surface.
+ ---C++: inline
+
+ GetPointOnSurface(me)
+ ---Purpose: Returns the point on a surface.
+ ---C++: return const &
+ ---C++: inline
+ returns XYZ from gp;
+
+ SetParameters(me: in out; theU: Real from Standard;
+ theV: Real from Standard);
+ ---Purpose: Sets the U and V parameters of the point on a surface.
+ ---C++: inline
+
+ GetParameters(me; theU: out Real from Standard;
+ theV: out Real from Standard);
+ ---Purpose: Returns the U and V parameters of the point on a surface.
+ ---C++: inline
+
+ GetU(me)
+ ---Purpose: Returns the U parameter of the point on a surface.
+ ---C++: inline
+ returns Real from Standard;
+
+ GetV(me)
+ ---Purpose: Returns the V parameter of the point on a surface.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetAngle(me: in out; theAngle: Real from Standard);
+ ---Purpose: Sets the angle between DU and DV directions.
+ ---C++: inline
+
+ GetAngle(me)
+ ---Purpose: Returns the angle between DU and DV directions.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetPointOnPlane(me: in out; thePOnPlane: XY from gp);
+ ---Purpose: Sets the point on an unfolding plane.
+ ---C++: inline
+
+ GetPointOnPlane(me)
+ ---Purpose: Returns the point on an unfolding plane.
+ ---C++: return const &
+ ---C++: inline
+ returns XY from gp;
+
+fields
+
+ myPoint2d : XY from gp;
+ myPOnSurface : XYZ from gp;
+ myPOnPlane : XY from gp;
+ myAngle : Real from Standard;
+
+end;
--- /dev/null
+// File: Unfolding_Point.cxx
+// Created: Mon Jul 28 15:27:34 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+#include <Unfolding_Point.hxx>
+
--- /dev/null
+// File: Unfolding_Point.lxx
+// Created: Mon Jul 28 15:18:15 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+//=======================================================================
+//function : Empty constructor
+//purpose :
+//=======================================================================
+
+inline Unfolding_Point::Unfolding_Point()
+ : myAngle(-1.)
+{
+}
+
+//=======================================================================
+//function : SetPointOnSurface
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Point::SetPointOnSurface(const gp_XYZ &thePOnSurface)
+{
+ myPOnSurface = thePOnSurface;
+}
+//=======================================================================
+//function : GetPointOnSurface
+//purpose :
+//=======================================================================
+
+inline const gp_XYZ &Unfolding_Point::GetPointOnSurface() const
+{
+ return myPOnSurface;
+}
+
+//=======================================================================
+//function : SetParameters
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Point::SetParameters(const Standard_Real theU,
+ const Standard_Real theV)
+{
+ myPoint2d.SetCoord(theU, theV);
+}
+
+//=======================================================================
+//function : GetParameters
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Point::GetParameters(Standard_Real &theU,
+ Standard_Real &theV) const
+{
+ myPoint2d.Coord(theU, theV);
+}
+
+//=======================================================================
+//function : GetU
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetU() const
+{
+ return myPoint2d.X();
+}
+
+//=======================================================================
+//function : GetV
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetV() const
+{
+ return myPoint2d.Y();
+}
+
+//=======================================================================
+//function : GetAngle
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Point::SetAngle(const Standard_Real theAngle)
+{
+ myAngle = theAngle;
+}
+
+//=======================================================================
+//function : GetAngle
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_Point::GetAngle() const
+{
+ return myAngle;
+}
+
+//=======================================================================
+//function : SetPointOnPlane
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Point::SetPointOnPlane(const gp_XY &thePOnPlane)
+{
+ myPOnPlane = thePOnPlane;
+}
+
+//=======================================================================
+//function : GetPointOnPlane
+//purpose :
+//=======================================================================
+
+inline const gp_XY &Unfolding_Point::GetPointOnPlane() const
+{
+ return myPOnPlane;
+}
--- /dev/null
+-- File: Unfolding_Shell.cdl
+-- Created: Tue Sep 9 16:56:09 2008
+-- Author: Mikhail KLOKOV
+-- <mkk@kurox>
+---Copyright: Open CASCADE 2008
+
+class Shell from Unfolding
+
+ ---Purpose: This class is used to perform unfolding of a shell onto a plane.
+ -- To perform this operation it is necessary to initialize the
+ -- object by a shell to be unfolded, a plane and a tolerance for
+ -- operation. Then to call the method Perform. The result planar
+ -- shell can be obtained using the method GetResult. Error status
+ -- can be obtained by the method ErrorStatus.
+
+uses
+
+ ErrorStatus from Unfolding,
+ Shell from TopoDS,
+ Face from TopoDS,
+ ListOfShape from TopTools,
+ Pln from gp,
+ Real from Standard,
+ IndexedMapOfFaceDataContainer from Unfolding,
+ FaceDataContainer from Unfolding
+
+is
+
+ Create
+ ---Purpose: Empty constructor
+ returns Shell from Unfolding;
+
+ Create (theShell : Shell from TopoDS;
+ thePlane : Pln from gp;
+ theContourTolerance: Real from Standard;
+ theCurvatureTolerance: Real from Standard = 0.001;
+ theDeflection: Real from Standard = 0.001)
+ ---Purpose: Constructor. Initializes the object with the shell, the plane and
+ -- the tolerances for operation.
+ returns Shell from Unfolding;
+
+ SetShell (me: in out; theShell: Shell from TopoDS);
+ ---Purpose: Sets the face.
+ ---C++: inline
+
+ GetShell (me)
+ ---Purpose: Returns the shell.
+ ---C++: inline
+ ---C++: return const &
+ returns Shell from TopoDS;
+
+ SetPlane (me: in out; thePlane: Pln from gp);
+ ---Purpose: Sets the plane.
+ ---C++: inline
+
+ GetPlane (me)
+ ---Purpose: Returns the plane.
+ ---C++: inline
+ ---C++: return const &
+ returns Pln from gp;
+
+ SetCurvatureTolerance (me: in out; theTolerance: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetCurvatureTolerance (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetContourTolerance (me: in out; theTolerance: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetContourTolerance (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetDeflection (me: in out; theDeflection: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetDeflection (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ Perform (me: in out)
+ ---Purpose: Performs computation of the unfolded surface. It returns
+ -- Standard_True if the operation succeeds otherwise returns
+ -- Standard_False. It is possible to get the error status of
+ -- the performed operation using the method ErrorStatus().
+ returns Boolean from Standard;
+
+ ErrorStatus (me)
+ ---Purpose: Returns error status of the operation. The error status can have
+ -- one of the following values:
+ -- - Unfolding_Done: operation is succeeded;
+ -- - Unfolding_NotDone: the method Perform() is not called yet;
+ -- - Unfolding_Failure: the operation is failed;
+ -- - Unfolding_InvalidSurface: the surface cannot be unfolded
+ -- without distortion;
+ -- - Unfolding_InvalidInput: invalid input for the operation;
+ -- - Unfolding_InvalidShape: can be returned by
+ -- Unfolding::ToShape method;
+ -- - Unfolding_ComplexShape: can be returned by
+ -- Unfolding::ToShape method;
+ ---C++: inline
+ returns ErrorStatus from Unfolding;
+
+ GetResult (me)
+ ---Purpose: Returns the result of the operation. If the operation is failed,
+ -- it returns a null shape.
+ ---C++: inline
+ ---C++: return const &
+ returns Face from TopoDS;
+
+
+ GetAreaError(me)
+ ---Purpose: Returns the area cumulated during primitive patches mergin.
+ -- It shows computed distortion.
+ ---C++: inline
+ returns Real from Standard;
+
+ GetMaxGaussCurvature(me)
+ ---Purpose: Returns the gauss curvature computed in the mesh points.
+ ---C++: inline
+ returns Real from Standard;
+
+
+
+ --protected
+ Reset(me: in out)
+ ---Purpose: Resets data to the initial state.
+ ---C++: inline
+ is protected;
+
+ --private
+ ComputeTransformed(me: in out; theResult: in out ListOfShape from TopTools)
+ returns Boolean from Standard
+ is private;
+
+ MoveFace2ToFace1(me: in out; theFaceData1 : FaceDataContainer from Unfolding;
+ theFaceData2 : FaceDataContainer from Unfolding;
+ theCommonEdges: ListOfShape from TopTools;
+ theIsFixed : Boolean from Standard)
+ ---Purpose: Perform transformation of unfolded face2 to glue with unfolded
+ -- face1. If theIsFixed is Standard_True, the face 2 is not
+ -- transformed only estimations of distortions are performed.
+ returns Boolean from Standard
+ is private;
+
+fields
+
+ myShell : Shell from TopoDS;
+ myPlane : Pln from gp;
+ myTolContour : Real from Standard;
+ myTolCurvature : Real from Standard;
+ myDeflection : Real from Standard;
+ myMapFaceData : IndexedMapOfFaceDataContainer from Unfolding;
+ myResult : Face from TopoDS;
+ myErrorStatus : ErrorStatus from Unfolding;
+ myDistortionArea : Real from Standard;
+ myCurvature : Real from Standard;
+
+end Shell from Unfolding;
--- /dev/null
+// File: Unfolding_Shell.cxx
+// Created: Tue Sep 9 17:14:33 2008
+// Author: Mikhail KLOKOV
+// <mkk@kurox>
+
+
+#include <Unfolding_Shell.ixx>
+#include <Unfolding.hxx>
+#include <Unfolding_FunctionWithDerivative.hxx>
+#include <Unfolding_Surface.hxx>
+#include <BRepBuilderAPI_MakeFace.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <Geom_Plane.hxx>
+#include <math_FunctionRoot.hxx>
+#include <math_NewtonFunctionRoot.hxx>
+#include <ShapeAnalysis_FreeBoundData.hxx>
+#include <ShapeAnalysis_FreeBoundsProperties.hxx>
+#include <TColgp_Array1OfXY.hxx>
+#include <TColgp_HArray1OfXY.hxx>
+#include <TColgp_SequenceOfXY.hxx>
+#include <TColStd_ListOfInteger.hxx>
+#include <TColStd_MapOfInteger.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Vertex.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+#include <TopTools_IndexedMapOfShape.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <BRepCheck_Analyzer.hxx>
+
+
+static Standard_Boolean CombineCurves(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const Standard_Boolean IsFixed,
+ const Standard_Real theConfTolerance,
+ const Standard_Real theAreaTolerance,
+ gp_Trsf2d& theTransformation,
+ Standard_Real& theDistortionArea);
+
+// ==============================================================================
+// function: GetCommonEdges
+// purpose : This function returns the list of common edges of two faces.
+// ==============================================================================
+static void GetCommonEdges(const TopoDS_Face &theFace1,
+ const TopoDS_Face &theFace2,
+ TopTools_ListOfShape &theCommonEdges)
+{
+ TopTools_IndexedMapOfShape aMapEdges1;
+ TopExp_Explorer anExp2(theFace2, TopAbs_EDGE);
+
+ TopExp::MapShapes(theFace1, TopAbs_EDGE, aMapEdges1);
+ theCommonEdges.Clear();
+
+ for (; anExp2.More(); anExp2.Next()) {
+ const TopoDS_Shape &anEdge2 = anExp2.Current();
+
+ if (aMapEdges1.Contains(anEdge2))
+ theCommonEdges.Append(anEdge2);
+ }
+}
+
+// ==============================================================================
+// function: GetWires
+// purpose : This function returns a list of wires edges composed from theEdges.
+// ==============================================================================
+static Standard_Boolean GetWires(const TopTools_ListOfShape &theEdges,
+ TopTools_ListOfShape &theWires)
+{
+ TopTools_ListIteratorOfListOfShape anEdgeIter(theEdges);
+ TopTools_DataMapOfShapeListOfShape aMapVE;
+ TopExp_Explorer anExp;
+ TopTools_MapOfShape aMapUsed;
+
+ for (; anEdgeIter.More(); anEdgeIter.Next()) {
+ const TopoDS_Shape &anEdge = anEdgeIter.Value();
+
+ if (!aMapUsed.Add(anEdge) || BRep_Tool::Degenerated(TopoDS::Edge(anEdge)))
+ continue;
+
+ for (anExp.Init(anEdge, TopAbs_VERTEX); anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &aVertex = anExp.Current();
+
+ if (!aMapVE.IsBound(aVertex)) {
+ TopTools_ListOfShape aList;
+ aMapVE.Bind(aVertex, aList);
+ }
+
+ TopTools_ListOfShape &aListAncEdges = aMapVE.ChangeFind(aVertex);
+
+ aListAncEdges.Append(anEdge);
+ }
+ }
+
+ // Construct wires as chains of edges.
+ Standard_Boolean isToTreat = Standard_True;
+ TopoDS_Vertex aFirstVtx;
+ TopoDS_Edge aCurEdge;
+ TopoDS_Vertex aV[2];
+ BRep_Builder aBuilder;
+
+ for(;;) {
+ isToTreat = Standard_False;
+
+ // Get the bounding vertex, i.e. the vertex that contains only one edge in
+ // the list of ancestors.
+ TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aMapIter(aMapVE);
+
+ for (; aMapIter.More(); aMapIter.Next()) {
+ const TopTools_ListOfShape &anEdges = aMapIter.Value();
+
+ if (anEdges.Extent() == 1) {
+ isToTreat = Standard_True;
+ break;
+ }
+ }
+
+ if (!isToTreat) {
+ // Get a closed loop.
+ for (aMapIter.Initialize(aMapVE); aMapIter.More(); aMapIter.Next()) {
+ const TopTools_ListOfShape &anEdges = aMapIter.Value();
+
+ if (anEdges.Extent() == 1) {
+ isToTreat = Standard_True;
+ break;
+ }
+ }
+ }
+
+ // Stop treatment if there is no more edges.
+ if (!isToTreat)
+ break;
+
+ // Treat the list of edges starting from the current iterator.
+ TopoDS_Wire aWire;
+
+ aBuilder.MakeWire(aWire);
+ aFirstVtx = TopoDS::Vertex(aMapIter.Key());
+
+ while (!aFirstVtx.IsNull()) {
+ const TopTools_ListOfShape &anEdges = aMapVE.ChangeFind(aFirstVtx);
+
+ aCurEdge = TopoDS::Edge(anEdges.First());
+ TopExp::Vertices(aCurEdge, aV[0], aV[1], Standard_True);
+
+ if (aFirstVtx.IsSame(aV[1])) {
+ aV[1] = aV[0];
+ aV[0] = aFirstVtx;
+ aCurEdge.Reverse();
+ }
+
+ aBuilder.Add(aWire, aCurEdge);
+
+ TopTools_ListOfShape &anEdges1 = aMapVE.ChangeFind(aV[0]);
+ TopTools_ListOfShape &anEdges2 = aMapVE.ChangeFind(aV[1]);
+
+ // Remove the current edge from aMapVE.
+ anEdges1.RemoveFirst();
+
+ if (anEdges1.IsEmpty())
+ aMapVE.UnBind(aV[0]);
+
+ if (anEdges2.IsEmpty() || anEdges2.Extent() > 2)
+ return Standard_False;
+
+ if (aCurEdge.IsSame(anEdges2.First())) {
+ // Remove first element.
+ anEdges2.RemoveFirst();
+ } else if (aCurEdge.IsSame(anEdges2.Last())) {
+ // Remove last element.
+ TopTools_ListIteratorOfListOfShape anEdgeIt(anEdges2);
+
+ anEdgeIt.Next();
+ anEdges2.Remove(anEdgeIt);
+ } else {
+ return Standard_False;
+ }
+
+ if (anEdges2.IsEmpty()) {
+ aMapVE.UnBind(aV[1]);
+ aFirstVtx.Nullify();
+ } else {
+ aFirstVtx = aV[1];
+ }
+ }
+
+ theWires.Append(aWire);
+ }
+
+ return Standard_True;
+}
+
+// ==============================================================================
+// function: Constructor
+// ==============================================================================
+Unfolding_Shell::Unfolding_Shell()
+ : myTolContour(0.001),
+ myTolCurvature(0.001),
+ myDeflection(0.001),
+ myDistortionArea(0.),
+ myCurvature(0.)
+{
+ Reset();
+}
+
+// ==============================================================================
+// function: Constructor
+// ==============================================================================
+Unfolding_Shell::Unfolding_Shell(const TopoDS_Shell& theShell,
+ const gp_Pln& thePlane,
+ const Standard_Real theContourTolerance,
+ const Standard_Real theCurvatureTolerance,
+ const Standard_Real theDeflection)
+ : myShell(theShell),
+ myPlane(thePlane),
+ myTolContour(theContourTolerance),
+ myTolCurvature(theCurvatureTolerance),
+ myDeflection(theDeflection),
+ myDistortionArea(0.),
+ myCurvature(0.)
+{
+ Reset();
+}
+
+// ==============================================================================
+// function: Perform
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::Perform()
+{
+ // Check if the operation is already performed and there is nothing to do.
+ if (myErrorStatus != Unfolding_NotDone)
+ return (myErrorStatus == Unfolding_Done);
+
+ // Check input data validity.
+ if (myShell.IsNull() ||
+ ( myTolContour <= RealEpsilon() ) ||
+ ( myTolCurvature <= RealEpsilon() ) ||
+ ( myDeflection <= RealEpsilon() ) ) {
+ myErrorStatus = Unfolding_InvalidInput;
+ return Standard_False;
+ }
+
+ // Compute number of samples for each edge of the shell.
+ TopTools_DataMapOfShapeInteger aMapEdgeNbSamples;
+ TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+ Standard_Integer i;
+ Standard_Integer aNbEdges;
+
+
+ TopExp::MapShapesAndAncestors(myShell, TopAbs_EDGE, TopAbs_FACE, aMapEF);
+ aNbEdges = aMapEF.Extent();
+
+ for (i = 1; i <= aNbEdges; i++) {
+ TopoDS_Edge anEdge = TopoDS::Edge(aMapEF.FindKey(i));
+ const TopTools_ListOfShape &aFaces = aMapEF.FindFromIndex(i);
+ Standard_Integer aNbPoints = Unfolding::NbSamples(anEdge, aFaces,
+ myTolContour);
+
+ aMapEdgeNbSamples.Bind(anEdge, aNbPoints);
+ }
+
+ // Perform unfolding of each face.
+ TopTools_ListOfShape aList2Sew;
+ myDistortionArea = 0.;
+ myCurvature = 0.;
+ TopExp_Explorer anExp( myShell, TopAbs_FACE );
+ Standard_Boolean isFirstReversed = Standard_False;
+
+ for ( ; anExp.More(); anExp.Next() ) {
+ TopoDS_Face aFaceOriginal = TopoDS::Face( anExp.Current() );
+ TopoDS_Face aFace = aFaceOriginal;
+ aFace.Orientation( TopAbs_FORWARD );
+
+ Unfolding_Surface anUnfoldFace(aFace, myPlane, myTolContour,
+ myTolCurvature, myDeflection);
+
+ Standard_Boolean isDone =
+ anUnfoldFace.Perform(aMapEdgeNbSamples);
+ Handle(Unfolding_FaceDataContainer) aFaceData = anUnfoldFace.GetDataContainer();
+
+ // Keep the original orientation of unfolding data container.
+ aFaceData->SetFace(aFaceOriginal);
+
+ if ( myCurvature < aFaceData->GetMaxGaussCurvature() )
+ myCurvature = aFaceData->GetMaxGaussCurvature();
+ myDistortionArea += aFaceData->GetDistortionArea();
+
+ if ( !isDone ) {
+ myErrorStatus = anUnfoldFace.ErrorStatus();
+ return Standard_False;
+ }
+ if ( myMapFaceData.IsEmpty() ) {
+ isFirstReversed = ( aFaceOriginal.Orientation() == TopAbs_REVERSED );
+ }
+
+ TopoDS_Face aNewFace = aFaceData->GetUnfoldedFace();
+
+ Standard_Boolean toReverse = ( aFaceOriginal.Orientation() == TopAbs_REVERSED );
+ if ( isFirstReversed )
+ toReverse = !toReverse;
+ gp_Trsf aTrsfPln;
+
+ if ( toReverse ) {
+ // Take into account the faces of different orientation are unfolded
+ // as mirror compared to the first unfolded face representation
+ aTrsfPln.SetMirror( gp_Ax1( myPlane.Location(), myPlane.Position().XDirection() ) );
+ aFaceData->ApplyTrsf(aTrsfPln);
+ }
+
+ myMapFaceData.Add(aFaceData);
+ }
+ //
+
+ if ( !ComputeTransformed( aList2Sew ) ) {
+ return Standard_False;
+ }
+
+ //
+ BRep_Builder aBuilder;
+ TopoDS_Compound aCompound;
+ TopTools_ListIteratorOfListOfShape anIt( aList2Sew );
+
+ aBuilder.MakeCompound(aCompound);
+
+ for ( ; anIt.More(); anIt.Next() )
+ aBuilder.Add(aCompound, anIt.Value());
+
+ Unfolding_ErrorStatus aStatus;
+ TopoDS_Shell aShell = Unfolding::ToShell(aCompound,
+ myTolContour, aStatus);
+
+ if (aShell.IsNull()) {
+ switch (aStatus) {
+ case Unfolding_ComplexShape:
+ myErrorStatus = Unfolding_ComplexShape;
+ break;
+ case Unfolding_InvalidShape:
+ myErrorStatus = Unfolding_InvalidShape;
+ break;
+ default:
+ myErrorStatus = Unfolding_Failure;
+ break;
+ }
+ return Standard_False;
+ }
+
+ ShapeAnalysis_FreeBoundsProperties aFreeBoundAlgo(aShell);
+
+ if ( !aFreeBoundAlgo.Perform() ) {
+ myErrorStatus = Unfolding_Failure;
+ return Standard_False;
+ }
+
+ Handle(ShapeAnalysis_HSequenceOfFreeBounds) aSeqWire;
+ aSeqWire = aFreeBoundAlgo.ClosedFreeBounds();
+
+ BRepBuilderAPI_MakeFace aFaceMaker(myPlane);
+
+ if ( !aSeqWire.IsNull() ) {
+ for ( Standard_Integer w = 1; w <= aSeqWire->Length(); w++ ) {
+ aFaceMaker.Add( aSeqWire->Value(w)->FreeBound() );
+ }
+ }
+ myResult = aFaceMaker.Face();
+
+#ifdef DEB
+ cout << "Checking the result..." << endl;
+#endif
+ BRepCheck_Analyzer aChecker( myResult, Standard_True );
+ if ( !aChecker.IsValid() ) {
+ myErrorStatus = Unfolding_ComplexShape;
+ return Standard_False;
+ }
+ return Standard_True;
+}
+
+// ==============================================================================
+// function: ComputeTransformed
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::ComputeTransformed(TopTools_ListOfShape& theResult)
+{
+ theResult.Clear();
+
+ // If the map of face data is empty, nothing to do.
+ if (myMapFaceData.IsEmpty())
+ return Standard_True;
+
+ TopTools_MapOfShape aMapTreated;
+ TColStd_MapOfInteger aMapTreatedIndices;
+ TopTools_IndexedDataMapOfShapeListOfShape aMapEF;
+ Standard_Integer i;
+ Standard_Integer aNbFaces = myMapFaceData.Extent();
+ TColStd_ListOfInteger aListToTreat;
+ Handle(Unfolding_FaceDataContainer) aDummyFaceData;
+
+ aDummyFaceData = new Unfolding_FaceDataContainer;
+ TopExp::MapShapesAndAncestors( myShell, TopAbs_EDGE, TopAbs_FACE, aMapEF );
+
+ for (i = 1; i <= aNbFaces; i++) {
+ // Skip index already treated.
+ if (aMapTreatedIndices.Contains(i))
+ continue;
+
+ aListToTreat.Append(i);
+
+ while (!aListToTreat.IsEmpty()) {
+ Standard_Integer anIndex = aListToTreat.First();
+
+ if (!aMapTreatedIndices.Add(anIndex))
+ continue;
+
+ aListToTreat.RemoveFirst();
+
+ const Handle(Unfolding_FaceDataContainer) &aFaceData =
+ myMapFaceData.FindKey(anIndex);
+ const TopoDS_Face &aFace =
+ aFaceData->GetFace();
+
+ aMapTreated.Add(aFace);
+
+ TopExp_Explorer anEdgeExp(aFace, TopAbs_EDGE);
+
+ for ( ; anEdgeExp.More(); anEdgeExp.Next() ) {
+ const TopoDS_Shape &anEdge = anEdgeExp.Current();
+
+ if (!aMapTreated.Add(anEdge) || !aMapEF.Contains(anEdge)) {
+ // This edge is already treated or it is absent in aMapEF. Skip it.
+ continue;
+ }
+
+ // Treat faces share the edge anEdge with the face aFace.
+ const TopTools_ListOfShape &aFaces = aMapEF.FindFromKey(anEdge);
+ TopTools_ListIteratorOfListOfShape aFaceIter(aFaces);
+
+ for (; aFaceIter.More(); aFaceIter.Next()) {
+ const TopoDS_Shape &aNeighborFace = aFaceIter.Value();
+
+ // Skip aFace
+ if (aFace.IsSame(aNeighborFace))
+ continue;
+
+ aDummyFaceData->SetFace(TopoDS::Face(aNeighborFace));
+
+ Standard_Boolean isFixed = !aMapTreated.Add(aNeighborFace);
+ Standard_Integer aNeighborIndex = myMapFaceData.FindIndex(aDummyFaceData);
+
+ if (aNeighborIndex == 0) {
+ myErrorStatus = Unfolding_Failure;
+
+ return Standard_False; // This is an invalid case.
+ }
+
+ const Handle(Unfolding_FaceDataContainer) &aNeighborFaceData =
+ myMapFaceData.FindKey(aNeighborIndex);
+ TopTools_ListOfShape aCommonEdges;
+
+ GetCommonEdges(aFace, aNeighborFaceData->GetFace(), aCommonEdges);
+
+ if (!MoveFace2ToFace1(aFaceData, aNeighborFaceData,
+ aCommonEdges, isFixed))
+ return Standard_False;
+
+ // Add common edge to the map of treated shapes.
+ TopTools_ListIteratorOfListOfShape anEdgeIter(aCommonEdges);
+
+ for (; anEdgeIter.More(); anEdgeIter.Next())
+ aMapTreated.Add(anEdgeIter.Value());
+
+ if (!isFixed)
+ aListToTreat.Append(aNeighborIndex);
+ }
+ }
+
+ theResult.Append(aFaceData->GetUnfoldedFace());
+ }
+ }
+
+ return Standard_True;
+}
+
+
+// ==============================================================================
+// function: MoveFace2ToFace1
+// ==============================================================================
+Standard_Boolean Unfolding_Shell::MoveFace2ToFace1
+ (const Handle(Unfolding_FaceDataContainer) &theFaceData1,
+ const Handle(Unfolding_FaceDataContainer) &theFaceData2,
+ const TopTools_ListOfShape &theCommonEdges,
+ const Standard_Boolean theIsFixed)
+{
+ TopTools_ListOfShape aWires;
+
+ if (!GetWires(theCommonEdges, aWires)) {
+ myErrorStatus = Unfolding_Failure;
+
+ return Standard_False;
+ }
+
+ // Get a wire with the greatest distance between first and last vertices.
+ TopoDS_Wire aRefWire;
+ TopoDS_Wire aWire;
+ TopTools_ListIteratorOfListOfShape anIter(aWires);
+ Standard_Real aMaxDist = -1;
+ Standard_Real aDist;
+ TopoDS_Vertex aV[2];
+
+ for (; anIter.More(); anIter.Next()) {
+ aWire = TopoDS::Wire(anIter.Value());
+ TopExp::Vertices(aWire, aV[0], aV[1]);
+
+ gp_Pnt aP1 = BRep_Tool::Pnt(aV[0]);
+ gp_Pnt aP2 = BRep_Tool::Pnt(aV[1]);
+
+ aDist = aP1.Distance(aP2);
+
+ if (aDist > aMaxDist) {
+ aMaxDist = aDist;
+ aRefWire = aWire;
+ }
+ }
+
+ if (aRefWire.IsNull()) {
+ myErrorStatus = Unfolding_Failure;
+
+ return Standard_False;
+ }
+
+ // Compute points.
+ Standard_Boolean isReversedOn1 = Standard_False;
+ Standard_Boolean isReversedOn2 = Standard_False;
+ TopExp_Explorer anExp(aRefWire, TopAbs_EDGE);
+
+ if (anExp.More()) {
+ TopoDS_Edge aFirstEdge = TopoDS::Edge(anExp.Current());
+ TopoDS_Face aFace1 = theFaceData1->GetFace();
+ TopoDS_Face aFace2 = theFaceData2->GetFace();
+
+ TopExp_Explorer aFaceExp(aFace1, TopAbs_EDGE);
+
+ for (; aFaceExp.More(); aFaceExp.Next()) {
+ const TopoDS_Shape &anEdgeOnF1 = aFaceExp.Current();
+
+ if (aFirstEdge.IsSame(anEdgeOnF1)) {
+ if (aFirstEdge.Orientation() != anEdgeOnF1.Orientation())
+ isReversedOn1 = Standard_True;
+
+ break;
+ }
+ }
+
+ // If aFirstEdge is not found on the face1. It is not possible by construction.
+ // Return with error status.
+ if (!aFaceExp.More()) {
+ myErrorStatus = Unfolding_Failure;
+
+ return Standard_False;
+ }
+
+ if (aFace1.Orientation() == aFace2.Orientation())
+ isReversedOn2 = !isReversedOn1;
+ else
+ isReversedOn2 = isReversedOn1;
+ }
+
+ // Collect points.
+ TopoDS_Shape aFace1 = theFaceData1->GetUnfoldedFace();
+ TopoDS_Shape aFace2 = theFaceData2->GetUnfoldedFace();
+ TColgp_SequenceOfXY aMasterPoints;
+ TColgp_SequenceOfXY aSlavePoints;
+ gp_Pnt2d aUV[2];
+ Handle(Geom_Surface) aSurface = new Geom_Plane(myPlane);
+ TopLoc_Location aLoc;
+
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
+ const TopTools_ListOfShape &anUnfld1 = theFaceData1->GetEdgesForEdge(anEdge);
+ const TopTools_ListOfShape &anUnfld2 = theFaceData2->GetEdgesForEdge(anEdge);
+
+ // Fill aMasterPoints.
+ for (anIter.Initialize(anUnfld1); anIter.More(); anIter.Next()) {
+ TopoDS_Edge anUnfoldEdge = TopoDS::Edge(anIter.Value());
+
+ if (isReversedOn1)
+ BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[1], aUV[0]);
+ else
+ BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[0], aUV[1]);
+
+ // Add the first point if the collection is empty.
+ if (aMasterPoints.IsEmpty())
+ aMasterPoints.Append(aUV[0].XY());
+
+ // Add the last point.
+ if (isReversedOn1)
+ aMasterPoints.Prepend(aUV[1].XY());
+ else
+ aMasterPoints.Append(aUV[1].XY());
+ }
+
+ // Fill aSlavePoints.
+ for (anIter.Initialize(anUnfld2); anIter.More(); anIter.Next()) {
+ TopoDS_Edge anUnfoldEdge = TopoDS::Edge(anIter.Value());
+
+ if (isReversedOn2)
+ BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[1], aUV[0]);
+ else
+ BRep_Tool::UVPoints(anUnfoldEdge, aSurface, aLoc, aUV[0], aUV[1]);
+
+ // Add the first point if the collection is empty.
+ if (aSlavePoints.IsEmpty())
+ aSlavePoints.Append(aUV[0].XY());
+
+ // Add the last point.
+ if (isReversedOn2)
+ aSlavePoints.Prepend(aUV[1].XY());
+ else
+ aSlavePoints.Append(aUV[1].XY());
+ }
+ }
+
+ // Construct array of points.
+ Handle(TColgp_HArray1OfXY) aMasterPolyLine;
+ Handle(TColgp_HArray1OfXY) aSlavePolyLine;
+ Standard_Integer i = 0;
+
+ aMasterPolyLine = new TColgp_HArray1OfXY( 1, aMasterPoints.Length() );
+ aSlavePolyLine = new TColgp_HArray1OfXY( 1, aSlavePoints.Length() );
+
+ for ( i = aMasterPolyLine->Lower(); i <= aMasterPolyLine->Upper(); i++ )
+ aMasterPolyLine->SetValue( i, aMasterPoints(i) );
+
+ for ( i = aSlavePolyLine->Lower(); i <= aSlavePolyLine->Upper(); i++ )
+ aSlavePolyLine->SetValue( i, aSlavePoints(i) );
+
+ // Compute transformation
+ gp_Trsf2d aTransformation2d;
+ Standard_Real aDistortionArea;
+
+ if ( !CombineCurves(aMasterPolyLine->Array1(), aSlavePolyLine->Array1(),
+ theIsFixed, myTolContour, myTolContour*myTolContour,
+ aTransformation2d, aDistortionArea) ) {
+ myDistortionArea += aDistortionArea;
+ myErrorStatus = Unfolding_InvalidSurface;
+
+ return Standard_False;
+ }
+
+ myDistortionArea += aDistortionArea;
+
+ // Trasform face
+ if (!theIsFixed) {
+ gp_Trsf aTrsf2dTo3d( aTransformation2d );
+ gp_Trsf aTrsfPln1, aTrsfPln2;
+ gp_Ax3 anAx3( gp_Pnt(0,0,0), gp_Dir(0,0,1), gp_Dir(1,0,0));
+
+ aTrsfPln1.SetDisplacement( myPlane.Position(), anAx3 );
+ aTrsfPln2.SetDisplacement( anAx3, myPlane.Position() );
+
+ gp_Trsf aTransformation = aTrsf2dTo3d * aTrsfPln1;
+
+ aTransformation = aTrsfPln2 * aTransformation;
+ theFaceData2->ApplyTrsf(aTransformation);
+ }
+
+ return Standard_True;
+}
+
+//-----------------------------------------------------------------------
+//function : CombineCurves
+//purpose :
+//-----------------------------------------------------------------------
+static Standard_Boolean CombineCurves(const TColgp_Array1OfXY& theMasterPolyLine,
+ const TColgp_Array1OfXY& theSlavePolyLine,
+ const Standard_Boolean IsFixed,
+ const Standard_Real theConfTolerance,
+ const Standard_Real theAreaTolerance,
+ gp_Trsf2d& theTransformation,
+ Standard_Real& theDistortionArea)
+{
+ theDistortionArea = 0.;
+
+ if ( ( theMasterPolyLine.Length() < 2 ) || ( theSlavePolyLine.Length() < 2 ) )
+ return Standard_False;
+
+ gp_XY aPMasterFirst = theMasterPolyLine.Value(theMasterPolyLine.Lower());
+ gp_XY aPMasterLast = theMasterPolyLine.Value(theMasterPolyLine.Upper());
+ gp_XY aPSlaveFirst = theSlavePolyLine.Value(theSlavePolyLine.Lower());
+ gp_XY aPSlaveLast = theSlavePolyLine.Value(theSlavePolyLine.Upper());
+
+ if (aPMasterFirst.IsEqual(aPMasterLast, theConfTolerance) ||
+ aPSlaveFirst.IsEqual(aPSlaveLast, theConfTolerance)) {
+ // One of polylines is closed. Get the points previous to the last ones.
+ aPMasterLast = theMasterPolyLine.Value(theMasterPolyLine.Upper() - 1);
+ aPSlaveLast = theSlavePolyLine.Value(theSlavePolyLine.Upper() - 1);
+
+ if (aPMasterFirst.IsEqual(aPMasterLast, theConfTolerance) ||
+ aPSlaveFirst.IsEqual(aPSlaveLast, theConfTolerance))
+ return Standard_False;
+ }
+
+ Standard_Real aRotation = 0.;
+ gp_XY aTranslation;
+
+ gp_Vec2d aLineDir1(aPMasterLast - aPMasterFirst);
+ gp_Vec2d aLineDir2(aPSlaveLast - aPSlaveFirst);
+
+ aTranslation = aPMasterFirst - aPSlaveFirst;
+ Standard_Real aLen1 = aLineDir1.Magnitude();
+ Standard_Real aLen2 = aLineDir2.Magnitude();
+ Standard_Real aShift = ( aLen2 - aLen1 ) * 0.5;
+ if ( aLen1 > gp::Resolution() ) {
+ aTranslation = aTranslation - aLineDir1.XY() * (aShift / aLen1);
+ if ( aLen2 > gp::Resolution() )
+ aRotation = aLineDir1.Angle( aLineDir2 );
+ }
+
+ // compute base transformation
+ gp_Trsf2d aRotTrsf;
+ aRotTrsf.SetRotation(aPSlaveFirst, -aRotation);
+
+ gp_Trsf2d aTransTrsf;
+ aTransTrsf.SetTranslation( gp_Vec2d(aTranslation) );
+
+ theTransformation = aTransTrsf * aRotTrsf;
+ //
+
+ // Compute transformation of shift to minimize the area of
+ // poly-lines difference
+ gp_Dir2d aDir(1,0);
+ if ( aLen1 > gp::Resolution() )
+ aDir = gp_Dir2d( gp_XY(-aLineDir1.Y(), aLineDir1.X() ) ) ;
+ Unfolding_FunctionWithDerivative aFunc( theMasterPolyLine, theSlavePolyLine, aDir, theTransformation );
+
+ if (IsFixed) {
+ Standard_Real aVal;
+
+ aFunc.Value(0, aVal);
+ theDistortionArea = aFunc.Area();
+
+ return Standard_True;
+ } else {
+ Standard_Real aBoundary = aShift * 20.;
+ const Standard_Real aTolX = 1.e-05;
+ if ( fabs(aBoundary) < aTolX * 2. ) {
+ Standard_Real aVal = 0.;
+ aFunc.Value(0, aVal);
+ theDistortionArea = aFunc.Area();
+ return Standard_True;
+ }
+ const Standard_Real aTolF = ( theAreaTolerance < 1.e-06 ) ? 1.e-06 : theAreaTolerance;
+
+ math_NewtonFunctionRoot R( aFunc, 0., aTolX, aTolF, -aBoundary, aBoundary, 10 );
+
+ if ( R.IsDone() ) {
+ gp_Trsf2d aTransTrsfAdd;
+ aTransTrsfAdd.SetTranslation( gp_Vec2d(aDir.XY() * R.Root() ) );
+ theTransformation = aTransTrsfAdd * theTransformation;
+ theDistortionArea = aFunc.Area();
+ }
+ else {
+ math_FunctionRoot R2( aFunc, 0., aTolX, -aBoundary, aBoundary );
+ if ( R2.IsDone() ) {
+ gp_Trsf2d aTransTrsfAdd;
+ aTransTrsfAdd.SetTranslation( gp_Vec2d(aDir.XY() * R2.Root() ) );
+ theTransformation = aTransTrsfAdd * theTransformation;
+ theDistortionArea = aFunc.Area();
+ }
+ }
+ }
+
+ return Standard_True;
+}
--- /dev/null
+// File: Unfolding_Shell.lxx
+// Created: Tue Sep 9 17:14:56 2008
+// Author: Mikhail KLOKOV
+// <mkk@kurox>
+
+
+inline void Unfolding_Shell::SetShell(const TopoDS_Shell& theShell)
+{
+ myShell = theShell;
+}
+
+
+inline const TopoDS_Shell& Unfolding_Shell::GetShell() const
+{
+ return myShell;
+}
+
+
+inline void Unfolding_Shell::SetPlane(const gp_Pln& thePlane)
+{
+ myPlane = thePlane;
+}
+
+
+inline const gp_Pln& Unfolding_Shell::GetPlane() const
+{
+ return myPlane;
+}
+
+
+inline void Unfolding_Shell::SetCurvatureTolerance(const Standard_Real theTolerance)
+{
+ myTolCurvature = theTolerance;
+}
+
+
+inline Standard_Real Unfolding_Shell::GetCurvatureTolerance() const
+{
+ return myTolCurvature;
+}
+
+
+inline void Unfolding_Shell::SetContourTolerance(const Standard_Real theTolerance)
+{
+ myTolContour = theTolerance;
+}
+
+
+inline Standard_Real Unfolding_Shell::GetContourTolerance() const
+{
+ return myTolContour;
+}
+
+
+inline void Unfolding_Shell::SetDeflection(const Standard_Real theDeflection)
+{
+ myDeflection = theDeflection;
+}
+
+
+inline Standard_Real Unfolding_Shell::GetDeflection() const
+{
+ return myDeflection;
+}
+
+
+inline Unfolding_ErrorStatus Unfolding_Shell::ErrorStatus() const
+{
+ return myErrorStatus;
+}
+
+
+inline const TopoDS_Face& Unfolding_Shell::GetResult() const
+{
+ return myResult;
+}
+
+
+inline Standard_Real Unfolding_Shell::GetAreaError() const
+{
+ return myDistortionArea;
+}
+
+
+inline Standard_Real Unfolding_Shell::GetMaxGaussCurvature() const
+{
+ return myCurvature;
+}
+
+
+inline void Unfolding_Shell::Reset()
+{
+ myDistortionArea = 0.;
+ myCurvature = 0.;
+ myErrorStatus = Unfolding_NotDone;
+
+ myMapFaceData.Clear();
+ myResult.Nullify();
+}
--- /dev/null
+-- File: Unfolding_Surface.cdl
+-- Created: Tue Jul 22 12:50:10 2008
+-- Author: Sergey KHROMOV
+-- <skv@dimox>
+---Copyright: Open CASCADE 2008
+
+
+class Surface from Unfolding
+ ---Purpose: This class is used to perform unfolding of a face onto a plane.
+ -- To perform this operation it is necessary to initialize the
+ -- object by a face to be unfolded, a plane and a tolerance for
+ -- operation. Then to call the method Perform. The result planar
+ -- face can be obtained using the method GetResult. Error status
+ -- can be obtained by the method ErrorStatus.
+
+uses
+
+ ErrorStatus from Unfolding,
+ HArray2OfPoint from Unfolding,
+ FaceDataContainer from Unfolding,
+ Face from TopoDS,
+ Wire from TopoDS,
+ Edge from TopoDS,
+ Vertex from TopoDS,
+ ListOfShape from TopTools,
+ Pln from gp,
+ XY from gp,
+ Real from Standard,
+ DataMapOfShapeInteger from TopTools
+
+is
+
+ Create
+ ---Purpose: Empty constructor
+ ---C++: inline
+ returns Surface from Unfolding;
+
+ Create (theFace : Face from TopoDS;
+ thePlane : Pln from gp;
+ theContourTolerance : Real from Standard;
+ theCurvatureTolerance: Real from Standard = 0.001;
+ theDeflection : Real from Standard = 0.001)
+ ---Purpose: Constructor. Initializes the object with the face, the plane and
+ -- the tolerance for operation.
+ returns Surface from Unfolding;
+
+ SetFace (me: in out; theFace: Face from TopoDS);
+ ---Purpose: Sets the face.
+ ---C++: inline
+
+ GetFace (me)
+ ---Purpose: Returns the face.
+ ---C++: inline
+ ---C++: return const &
+ returns Face from TopoDS;
+
+ SetPlane (me: in out; thePlane: Pln from gp);
+ ---Purpose: Sets the plane.
+ ---C++: inline
+
+ GetPlane (me)
+ ---Purpose: Returns the plane.
+ ---C++: inline
+ ---C++: return const &
+ returns Pln from gp;
+
+ SetCurvatureTolerance (me: in out; theTolerance: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetCurvatureTolerance (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetContourTolerance (me: in out; theTolerance: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetContourTolerance (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ SetDeflection (me: in out; theDeflection: Real from Standard);
+ ---Purpose: Sets the tolerance for the operation.
+ ---C++: inline
+
+ GetDeflection (me)
+ ---Purpose: Returns the tolerance for the operation.
+ ---C++: inline
+ returns Real from Standard;
+
+ Perform (me: in out; theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools)
+ ---Purpose: Performs computation of the unfolded surface. It returns
+ -- Standard_True if the operation succeeds otherwise returns
+ -- Standard_False. It is possible to get the error status of
+ -- the performed operation using the method ErrorStatus().
+ -- theMapEdgeNbSamples is the map of edges as keys and
+ -- number of samples for this edge as item. It is required
+ -- for predefined sampling of edges of a face. If an edge is
+ -- absent in this map its sampling is automatically computed.
+ -- This feature is used to get same sampling for shared edges
+ -- on different faces.
+ returns Boolean from Standard;
+
+ ErrorStatus (me)
+ ---Purpose: Returns error status of the operation. The error status can have
+ -- one of the following values:
+ -- - Unfolding_Done: operation is succeeded;
+ -- - Unfolding_NotDone: the method Perform() is not called yet;
+ -- - Unfolding_Failure: the operation is failed;
+ -- - Unfolding_InvalidSurface: the surface cannot be unfolded
+ -- without distortion;
+ -- - Unfolding_InvalidInput: invalid input for the operation.
+ ---C++: inline
+ returns ErrorStatus from Unfolding;
+
+ GetDataContainer(me)
+ ---Purpose: Returns data container. That stores all results of the operation.
+ ---C++: inline
+ returns FaceDataContainer from Unfolding;
+
+ --protected
+ Reset(me: in out)
+ ---Purpose: Resets data to the initial state.
+ ---C++: inline
+ is protected;
+
+ --private
+ InitGrid(me: in out)
+ ---Purpose: Initializes the grid on surface. Computes a rectangular grid in
+ -- the parametric space of the face and computes the corresponding
+ -- 3d points on the surface.
+ returns Boolean from Standard
+ is private;
+
+ NbPoints(me; theUMin : Real from Standard;
+ theUMax : Real from Standard;
+ theVMin : Real from Standard;
+ theVMax : Real from Standard;
+ theNbPointsU: out Integer from Standard;
+ theNbPointsV: out Integer from Standard)
+ ---Purpose: Computes and returns the numbers of sampling points
+ -- for U and V directions.
+ is private;
+
+ Unfolding(me: in out)
+ ---Purpose: Performs unfolding of the grid of points onto the plane. Returns
+ -- Standard_True in case of success and Standard_False otherwise.
+ -- Initializes the error status of the operation.
+ returns Boolean from Standard
+ is private;
+
+ BuildPlanarFace(me: in out;
+ theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools)
+ ---Purpose: Constructs and returns a planar face.
+ returns Boolean from Standard
+ is private;
+
+ BuildPlanarWire(me: in out;
+ theWire : Wire from TopoDS;
+ theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools;
+ thePlanarWire : out Wire from TopoDS)
+ ---Purpose: Constructs and returns planar unfolded wire from original one.
+ returns Boolean from Standard
+ is private;
+
+ UnfoldEdge(me;
+ theEdge : Edge from TopoDS;
+ theStartVtx : Vertex from TopoDS;
+ theEndVtx : Vertex from TopoDS;
+ theMapEdgeNbSamples: DataMapOfShapeInteger from TopTools;
+ theStartPnt : in out XY from gp;
+ theEndPnt : out XY from gp;
+ thePlnEdges : out ListOfShape from TopTools)
+ ---Purpose: Constructs and returns a set of planar unfolded edges
+ -- from theEdge.
+ returns Boolean from Standard
+ is private;
+
+ ComputePointOnPlane(me; thePoint : XY from gp;
+ theEdgeTol : Real from Standard;
+ thePointOnPlane: out XY from gp)
+ ---Purpose: Computes and returns a point on plane that corresponds
+ -- to a point on a surface.
+ returns Boolean from Standard
+ is private;
+
+fields
+
+ myDataContainer : FaceDataContainer from Unfolding;
+ myPlane : Pln from gp;
+ myTolContour : Real from Standard;
+ myTolCurvature : Real from Standard;
+ myDeflection : Real from Standard;
+ myGrid : HArray2OfPoint from Unfolding;
+ myErrorStatus : ErrorStatus from Unfolding;
+
+end;
--- /dev/null
+// File: Unfolding_Surface.cxx
+// Created: Tue Jul 22 13:12:24 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+#include <Unfolding_Surface.hxx>
+#include <Unfolding.hxx>
+#include <Unfolding_HArray2OfPoint.hxx>
+#include <Unfolding_Point.hxx>
+#include <BRepBuilderAPI_MakeEdge.hxx>
+#include <BRepTools.hxx>
+#include <BRepTools_WireExplorer.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <ElCLib.hxx>
+#include <ElSLib.hxx>
+#include <GccAna_Circ2d3Tan.hxx>
+#include <Geom_BezierSurface.hxx>
+#include <Geom_BSplineSurface.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_ConicalSurface.hxx>
+#include <Geom_CylindricalSurface.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Plane.hxx>
+#include <Geom_RectangularTrimmedSurface.hxx>
+#include <Geom_SphericalSurface.hxx>
+#include <Geom_Surface.hxx>
+#include <Geom_SurfaceOfLinearExtrusion.hxx>
+#include <Geom_SurfaceOfRevolution.hxx>
+#include <Geom_ToroidalSurface.hxx>
+#include <Geom_TrimmedCurve.hxx>
+#include <Geom2d_Curve.hxx>
+#include <gp_Circ.hxx>
+#include <IntAna2d_AnaIntersection.hxx>
+#include <TColgp_Array2OfPnt.hxx>
+#include <TColgp_SequenceOfXY.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Wire.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+#include <TopTools_ListIteratorOfListOfShape.hxx>
+#include <TopTools_ListOfShape.hxx>
+
+
+static Standard_Integer aLimitNumber = 1000;
+
+static void AdjustToDeflection( Standard_Integer &theNbPointsU,
+ Standard_Integer &theNbPointsV,
+ const Handle(Geom_Surface) &theSurface,
+ const Standard_Real theUMin,
+ const Standard_Real theUMax,
+ const Standard_Real theVMin,
+ const Standard_Real theVMax,
+ const Standard_Real theDeflection);
+
+//=======================================================================
+//function : MakeCirc
+//purpose : This method constructs a circle that passes through 3 points.
+// theNorm is a normal to the plane that is formed by theP1, theP2
+// and theP3. Three points should not be on the same line and should
+// not coincide. All these conditions are not checked. Their respect
+// is under responsibility of the caller.
+//=======================================================================
+
+static Standard_Boolean MakeCirc(const gp_Pnt &theP1,
+ const gp_Pnt &theP2,
+ const gp_Pnt &theP3,
+ const gp_Dir &theNorm,
+ gp_Circ &theCircle)
+{
+ gp_Dir aX(theP3.XYZ().Subtracted(theP1.XYZ()));
+ gp_Ax3 aPlnAxis(theP1, theNorm, aX);
+ Standard_Real aU;
+ Standard_Real aV;
+ gp_Pnt2d aP1(0., 0.);
+
+ ElSLib::PlaneParameters(aPlnAxis, theP2, aU, aV);
+
+ gp_Pnt2d aP2(aU, aV);
+
+ ElSLib::PlaneParameters(aPlnAxis, theP3, aU, aV);
+
+ gp_Pnt2d aP3(aU, aV);
+
+ GccAna_Circ2d3Tan aCircTan(aP1, aP2, aP3, Precision::Confusion());
+
+ if (!aCircTan.IsDone() || aCircTan.NbSolutions() != 1)
+ return Standard_False;
+
+ gp_Circ2d aCirc2d = aCircTan.ThisSolution(1);
+
+ // Convert 2d circle to 3d.
+ const gp_Pnt2d &a2dLoc = aCirc2d.Location();
+ gp_Pnt a3dLoc = ElSLib::PlaneValue(a2dLoc.X(), a2dLoc.Y(), aPlnAxis);
+ gp_Dir a3dX(theP1.XYZ().Subtracted(a3dLoc.XYZ()));
+ gp_Ax2 aCircAxis(a3dLoc, theNorm, a3dX);
+ Standard_Real aRadius = aCirc2d.Radius();
+
+ theCircle.SetPosition(aCircAxis);
+ theCircle.SetRadius(aRadius);
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : CrvDistance
+//purpose : Returns the approximate curvelinear distance between two
+// points on surface. The distance is approximated by length of
+// the circular arc started at thePoint1 and ended at thePoint2
+// that is passed through the middle in UV space point.
+//=======================================================================
+
+static Standard_Real CrvDistance(const Unfolding_Point &thePoint1,
+ const Unfolding_Point &thePoint2,
+ const Handle(Geom_Surface) &theSurface,
+ const Standard_Real &theTolerance)
+{
+ const gp_XYZ &aP1 = thePoint1.GetPointOnSurface();
+ const gp_XYZ &aP2 = thePoint2.GetPointOnSurface();
+ gp_XYZ aP12 = aP2.Subtracted(aP1);
+ Standard_Real aLinDist = aP12.Modulus();
+
+ if (aLinDist <= theTolerance)
+ return aLinDist;
+
+ // Get middle point.
+ Standard_Real aUMid;
+ Standard_Real aVMid;
+ Standard_Real aU;
+ Standard_Real aV;
+ gp_Pnt aPntMid;
+
+ thePoint1.GetParameters(aUMid, aVMid);
+ thePoint2.GetParameters(aU, aV);
+
+ aUMid = 0.5*(aUMid + aU);
+ aVMid = 0.5*(aVMid + aV);
+
+ theSurface->D0(aUMid, aVMid, aPntMid);
+
+ const gp_XYZ &aPMid = aPntMid.XYZ();
+
+ // Compute distance from aPMid to aP12.
+ aP12.Divide(aLinDist);
+
+ gp_XYZ aDistCoord(aPMid.Subtracted(aP1));
+
+ aDistCoord.Cross(aP12);
+
+ Standard_Real aDist = aDistCoord.Modulus();
+
+ if (aDist < 0.01*theTolerance)
+ return aLinDist;
+
+ // Find a distance along an arc.
+ gp_Pnt aPnt1(aP1);
+ gp_Pnt aPnt2(aP2);
+ gp_Dir aNorm(aDistCoord);
+ gp_Circ aCirc;
+
+ if (!MakeCirc(aPnt1, aPntMid, aPnt2, aNorm, aCirc))
+ return 0.;
+
+ const gp_Ax2 &anAxis = aCirc.Position();
+ Standard_Real anAngle = ElCLib::CircleParameter(anAxis, aPnt2);
+ Standard_Real aCircParMid = ElCLib::CircleParameter(anAxis, aPntMid);
+ Standard_Real aRadius = aCirc.Radius();
+
+ if (anAngle < aCircParMid)
+ anAngle = 2.*M_PI - anAngle;
+
+ Standard_Real aCrvDist = anAngle*aRadius;
+
+ return aCrvDist;
+}
+
+//=======================================================================
+//function : GetCell
+//purpose : Returns the indices of a cell thePoint belongs to. The cell (i, j)
+// is defined between grid's points (i, j) - (i + 1, j) -
+// (i + 1, j + 1) - (i, j + 1). If the point is outside the grid,
+// its index is equal to 0 in case if corresponding index is lower
+// then the lower bound or NbPoints if it is greater then the upper
+// bound.
+//=======================================================================
+
+static void GetCell(const gp_XY &thePoint,
+ const Handle(Unfolding_HArray2OfPoint) &theGrid,
+ const Standard_Real &theTolerance,
+ Standard_Integer &theI,
+ Standard_Integer &theJ)
+{
+ Standard_Integer iStart = theGrid->LowerRow();
+ Standard_Integer jStart = theGrid->LowerCol();
+ Standard_Integer iEnd = theGrid->UpperRow();
+ Standard_Integer jEnd = theGrid->UpperCol();
+ const Unfolding_Point &aPff = theGrid->Value(iStart, jStart);
+ const Unfolding_Point &aPll = theGrid->Value(iEnd, jEnd);
+ Standard_Real aU = thePoint.X();
+
+ // Compute theI.
+ if (aU < aPff.GetU() - theTolerance)
+ theI = iStart - 1;
+ else if (aU >= aPll.GetU() - theTolerance)
+ theI = iEnd;
+ else {
+ Standard_Real aStep = (aPll.GetU() - aPff.GetU())/(iEnd - iStart + 1);
+
+ theI = Standard_Integer(Round((aU - aPff.GetU())/aStep)) + iStart;
+
+ if (theI < iStart)
+ theI = iStart;
+
+ if (theI > iEnd)
+ theI = iEnd;
+
+ while (theI >= iStart &&
+ aU < theGrid->Value(theI, jStart).GetU() - theTolerance)
+ theI--;
+
+ while (theI < iEnd &&
+ aU >= theGrid->Value(theI + 1, jStart).GetU() - theTolerance)
+ theI++;
+ }
+
+ // Compute theI.
+ Standard_Real aV = thePoint.Y();
+
+ if (aV < aPff.GetV() - theTolerance)
+ theJ = jStart - 1;
+ else if (aV >= aPll.GetV() - theTolerance)
+ theJ = jEnd;
+ else {
+ Standard_Real aStep = (aPll.GetV() - aPff.GetV())/(jEnd - jStart + 1);
+
+ theJ = Standard_Integer(Round((aV - aPff.GetV())/aStep)) + jStart;
+
+ if (theJ < jStart)
+ theJ = jStart;
+
+ if (theJ > jEnd)
+ theJ = jEnd;
+
+ while (theJ >= jStart &&
+ aV < theGrid->Value(iStart, theJ).GetV() - theTolerance)
+ theJ--;
+
+ while (theJ < jEnd &&
+ aV >= theGrid->Value(iStart, theJ + 1).GetV() - theTolerance)
+ theJ++;
+ }
+}
+
+//=======================================================================
+//function : Empty constructor
+//purpose : This method constructs and returns the curve that is passed
+// through three points. It can be either a line if these three
+// points lie on the same line or a circle. In case of failure
+// it returns a null handle.
+//=======================================================================
+
+static Handle(Geom_Curve) MakeCurve(const gp_Pnt &thePFirst,
+ const gp_Pnt &thePMid,
+ const gp_Pnt &thePLast,
+ const gp_Pln &thePlane,
+ const Standard_Real theTolerance)
+{
+ Handle(Geom_Curve) aCurve;
+ gp_Vec aDFL(thePLast.XYZ().Subtracted(thePFirst.XYZ()));
+ Standard_Real aLinDist = aDFL.Magnitude();
+
+ if (aLinDist > theTolerance) {
+ // compute distance between thePMid and the segment [thePFirst, thePLast].
+ gp_XYZ aDPMidFirst = thePMid.XYZ();
+
+ aDFL.Divide(aLinDist);
+ aDPMidFirst.Subtract(thePFirst.XYZ());
+ aDPMidFirst.Cross(aDFL.XYZ());
+
+ Standard_Real aDist = aDPMidFirst.Modulus();
+
+ // Line criteria like in the CrvDistance function.
+ if (aDist < 0.01*theTolerance) {
+ aCurve = new Geom_Line(thePFirst, gp_Dir(aDFL));
+ } else {
+ // Compute a circle
+ gp_Circ aCirc;
+
+ if (!MakeCirc(thePFirst, thePMid, thePLast,
+ thePlane.Position().Direction(), aCirc))
+ return aCurve;
+
+ aCurve = new Geom_Circle(aCirc);
+
+ // Trim the curve by the circle parameters.
+ const gp_Ax2 &anAxis = aCirc.Position();
+ Standard_Real aCircPar1 = 0.; // By construction
+ Standard_Real aCircPar2 = ElCLib::CircleParameter(anAxis, thePLast);
+ Standard_Real aCircParMid = ElCLib::CircleParameter(anAxis, thePMid);
+
+ if (aCircParMid > aCircPar2)
+ aCurve = new Geom_TrimmedCurve(aCurve, aCircPar1,
+ aCircPar2, Standard_False);
+ else
+ aCurve = new Geom_TrimmedCurve(aCurve, aCircPar1, aCircPar2);
+ }
+ }
+
+ return aCurve;
+}
+
+//=======================================================================
+// function : Analyse
+// purpose : Computes the numbers of samples along U and V direction using
+// the array of poles.
+//=======================================================================
+
+static void Analyse(const TColgp_Array2OfPnt &array2,
+ Standard_Integer &theNbSamplesU,
+ Standard_Integer &theNbSamplesV)
+{
+ gp_Vec Vi,Vip1;
+ Standard_Integer sh,nbch,i,j;
+ const Standard_Integer nbup = array2.UpperRow() - array2.LowerRow() + 1;
+ const Standard_Integer nbvp = array2.UpperCol() - array2.LowerCol() + 1;
+
+ sh = 1;
+ nbch = 0;
+ if(nbvp>2) {
+
+ for(i = array2.LowerRow(); i <= array2.UpperRow(); i++) {
+ const gp_Pnt& A=array2.Value(i,1);
+ const gp_Pnt& B=array2.Value(i,2);
+ const gp_Pnt& C=array2.Value(i,3);
+ Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
+ C.Y()-B.Y()-B.Y()+A.Y(),
+ C.Z()-B.Z()-B.Z()+A.Z());
+ Standard_Integer locnbch=0;
+
+ for(j = array2.LowerCol() + 2; j < array2.UpperCol();j++) { //-- essai
+ const gp_Pnt& Ax=array2.Value(i,j-1);
+ const gp_Pnt& Bx=array2.Value(i,j);
+ const gp_Pnt& Cx=array2.Value(i,j+1);
+ Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
+ Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
+ Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
+ Standard_Real pd = Vi.Dot(Vip1);
+ Vi=Vip1;
+ if(pd>1.0e-7 || pd<-1.0e-7) {
+ if(pd>0) { if(sh==-1) { sh=1; locnbch++; } }
+ else { if(sh==1) { sh=-1; locnbch++; } }
+ }
+ }
+ if(locnbch>nbch) {
+ nbch=locnbch;
+ }
+ }
+ }
+ theNbSamplesV = nbch+5;
+
+
+ nbch=0;
+ if(nbup > 2) {
+ for(j = array2.LowerCol(); j <= array2.UpperCol(); j++) {
+ const gp_Pnt& A=array2.Value(array2.LowerRow(), j);
+ const gp_Pnt& B=array2.Value(array2.LowerRow() + 1, j);
+ const gp_Pnt& C=array2.Value(array2.LowerRow() + 2, j);
+ Vi.SetCoord(C.X()-B.X()-B.X()+A.X(),
+ C.Y()-B.Y()-B.Y()+A.Y(),
+ C.Z()-B.Z()-B.Z()+A.Z());
+ Standard_Integer locnbch=0;
+
+ for(i = array2.LowerRow() + 2; i < array2.UpperRow(); i++) { //-- essai
+ const gp_Pnt& Ax=array2.Value(i-1,j);
+ const gp_Pnt& Bx=array2.Value(i,j);
+ const gp_Pnt& Cx=array2.Value(i+1,j);
+ Vip1.SetCoord(Cx.X()-Bx.X()-Bx.X()+Ax.X(),
+ Cx.Y()-Bx.Y()-Bx.Y()+Ax.Y(),
+ Cx.Z()-Bx.Z()-Bx.Z()+Ax.Z());
+ Standard_Real pd = Vi.Dot(Vip1);
+ Vi=Vip1;
+ if(pd>1.0e-7 || pd<-1.0e-7) {
+ if(pd>0) { if(sh==-1) { sh=1; locnbch++; } }
+ else { if(sh==1) { sh=-1; locnbch++; } }
+ }
+ }
+ if(locnbch>nbch) nbch=locnbch;
+ }
+ }
+ theNbSamplesU = nbch+5;
+}
+
+//=======================================================================
+//function : Empty constructor
+//purpose :
+//=======================================================================
+
+Unfolding_Surface::Unfolding_Surface()
+ : myTolContour(0.001),
+ myTolCurvature(0.001),
+ myDeflection(0.001)
+{
+ myDataContainer = new Unfolding_FaceDataContainer;
+ Reset();
+}
+
+//=======================================================================
+//function : Constructor
+//purpose :
+//=======================================================================
+
+Unfolding_Surface::Unfolding_Surface(const TopoDS_Face &theFace,
+ const gp_Pln &thePlane,
+ const Standard_Real theContourTolerance,
+ const Standard_Real theCurvatureTolerance,
+ const Standard_Real theDeflection)
+ : myPlane(thePlane),
+ myTolContour(theContourTolerance),
+ myTolCurvature(theCurvatureTolerance),
+ myDeflection(theDeflection)
+{
+ myDataContainer = new Unfolding_FaceDataContainer;
+ myDataContainer->SetFace(theFace);
+ Reset();
+}
+
+//=======================================================================
+//function : Perform
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::Perform
+ (const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples)
+{
+ // Check if the operation is already performed and there is nothing to do.
+ if (myErrorStatus != Unfolding_NotDone)
+ return (myErrorStatus == Unfolding_Done);
+
+ // Check input data validity.
+ if (myDataContainer->GetFace().IsNull() ||
+ ( myTolContour <= RealEpsilon() ) ||
+ ( myTolCurvature <= RealEpsilon() ) ||
+ ( myDeflection <= RealEpsilon() ) ) {
+ myErrorStatus = Unfolding_InvalidInput;
+ return Standard_False;
+ }
+
+ // Initialize the grid on the surface.
+ Standard_Boolean isOK = InitGrid();
+
+ if (isOK) {
+ // Perform unfolding
+ isOK = Unfolding();
+
+ if (isOK) {
+ // Construct a planar face.
+ isOK = BuildPlanarFace(theMapEdgeNbSamples);
+ }
+ }
+
+ return isOK;
+}
+
+//=======================================================================
+//function : InitGrid
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::InitGrid()
+{
+ // Get Bounding box of the face.
+ Standard_Real aUMin;
+ Standard_Real aUMax;
+ Standard_Real aVMin;
+ Standard_Real aVMax;
+ const TopoDS_Face &aFace = myDataContainer->GetFace();
+
+ BRepTools::UVBounds(aFace, aUMin, aUMax, aVMin, aVMax);
+
+ // Compute number of samples.
+ Standard_Integer aNbPntsU;
+ Standard_Integer aNbPntsV;
+
+ NbPoints(aUMin, aUMax, aVMin, aVMax, aNbPntsU, aNbPntsV);
+
+
+ // Construct a grid.
+ myGrid = new Unfolding_HArray2OfPoint(1, aNbPntsU, 1, aNbPntsV);
+
+ // Fill in the grid.
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
+ Standard_Real aUStep = (aUMax - aUMin)/(aNbPntsU - 1);
+ Standard_Real aVStep = (aVMax - aVMin)/(aNbPntsV - 1);
+ Standard_Real aUPar;
+ Standard_Real aVPar;
+ Standard_Integer i;
+ Standard_Integer j;
+ gp_Pnt aPnt;
+ gp_Vec aD1U;
+ gp_Vec aD1V;
+ gp_Vec aD2U;
+ gp_Vec aD2V;
+ gp_Vec aD2UV;
+ gp_Vec aNorm;
+ Standard_Real aL;
+ Standard_Real aM;
+ Standard_Real aN;
+ Standard_Real aMaxCurvature = 0.;
+
+ for (aUPar = aUMin, i = 1; i <= aNbPntsU; i++) {
+ for (aVPar = aVMin, j = 1; j <= aNbPntsV; j++) {
+ aSurface->D2(aUPar, aVPar, aPnt, aD1U, aD1V, aD2U, aD2V, aD2UV);
+
+ // Check Gauss curvature
+ aNorm = aD1U.Crossed(aD1V);
+ aNorm.Normalize();
+ aL = aD2U.Dot(aNorm);
+ aN = aD2V.Dot(aNorm);
+ aM = aD2UV.Dot(aNorm);
+ const Standard_Real aCurvature = Abs(aL*aN - aM*aM);
+ aMaxCurvature = ( aMaxCurvature < aCurvature ) ? aCurvature : aMaxCurvature;
+
+ if (aCurvature > myTolCurvature) {
+ myDataContainer->SetMaxGaussCurvature(aMaxCurvature);
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ // Initialize the point.
+ Unfolding_Point &aPoint = myGrid->ChangeValue(i, j);
+
+ aPoint.SetParameters(aUPar, aVPar);
+ aPoint.SetPointOnSurface(aPnt.XYZ());
+
+ aVPar = (j == aNbPntsV - 1) ? aVMax : aVPar + aVStep;
+ }
+
+ aUPar = (i == aNbPntsU - 1) ? aUMax : aUPar + aUStep;
+ }
+
+ myDataContainer->SetMaxGaussCurvature(aMaxCurvature);
+
+ // Initialize points by angles in DU and DV directions.
+ Standard_Real aTolConf = 0.01*Max(myTolContour,myDeflection);
+ gp_XYZ aDX;
+ gp_XYZ aDY;
+
+ for (i = 1; i <= aNbPntsU; i++) {
+ for (j = 1; j <= aNbPntsV; j++) {
+ Unfolding_Point &aP = myGrid->ChangeValue(i, j);
+
+ if (i == aNbPntsU || j == aNbPntsV) {
+ aP.SetAngle(0.);
+ } else {
+ const Unfolding_Point &aPX = myGrid->Value(i + 1, j);
+
+ aDX = aPX.GetPointOnSurface();
+ aDX.Subtract(aP.GetPointOnSurface());
+
+ if (aDX.Modulus() <= aTolConf) {
+ aP.SetAngle(0.);
+ } else {
+ const Unfolding_Point &aPY = myGrid->Value(i, j + 1);
+
+ aDY = aPY.GetPointOnSurface();
+ aDY.Subtract(aP.GetPointOnSurface());
+
+ if (aDY.Modulus() <= aTolConf) {
+ aP.SetAngle(0.);
+ } else {
+ aP.SetAngle(gp_Vec(aDX).Angle(gp_Vec(aDY)));
+ }
+ }
+ }
+ }
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : NbPoints
+//purpose :
+//=======================================================================
+
+void Unfolding_Surface::NbPoints(const Standard_Real theUMin,
+ const Standard_Real theUMax,
+ const Standard_Real theVMin,
+ const Standard_Real theVMax,
+ Standard_Integer &theNbPointsU,
+ Standard_Integer &theNbPointsV) const
+{
+ Handle(Geom_Surface) aSurface =
+ BRep_Tool::Surface(myDataContainer->GetFace());
+ Handle(Standard_Type) aType = aSurface->DynamicType();
+
+ while (aType == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
+ Handle(Geom_RectangularTrimmedSurface) aTrSurf =
+ Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface);
+ aSurface = aTrSurf->BasisSurface();
+ aType = aSurface->DynamicType();
+ }
+
+ if (aType == STANDARD_TYPE(Geom_Plane)) {
+ // PLANE
+ theNbPointsU = 11;
+ theNbPointsV = 11;
+ } else if (aType == STANDARD_TYPE(Geom_CylindricalSurface)) {
+ // CYLINDER
+ Handle(Geom_CylindricalSurface) aCyl =
+ Handle(Geom_CylindricalSurface)::DownCast(aSurface);
+ Standard_Real aRadius = aCyl->Radius();
+ Standard_Real aMaxAngle = M_PI *0.5;
+
+ if(aRadius > myDeflection) {
+ aMaxAngle = ACos(1. - myDeflection/aRadius)*2.;
+ }
+ if(aMaxAngle > Precision::Angular())
+ theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+ else
+ theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+ theNbPointsV = (Standard_Integer)(theVMax - theVMin);
+ theNbPointsV /= 10;
+
+ if (theNbPointsU < 3)
+ theNbPointsU = 3;
+
+ if (theNbPointsV < 3)
+ theNbPointsV = 3;
+ } else if (aType == STANDARD_TYPE(Geom_ConicalSurface)) {
+ // CONE
+ Handle(Geom_ConicalSurface) aConeSurf =
+ Handle(Geom_ConicalSurface)::DownCast(aSurface);
+ gp_Cone aCone = aConeSurf->Cone();
+ gp_Circ aCircle = ElSLib::ConeVIso(aCone.Position(),
+ aCone.RefRadius(),
+ aCone.SemiAngle(),
+ theVMin);
+ Standard_Real aRadius = aCircle.Radius();
+ aCircle = ElSLib::ConeVIso(aCone.Position(), aCone.RefRadius(),
+ aCone.SemiAngle(), theVMax);
+
+ if(aRadius < aCircle.Radius())
+ aRadius = aCircle.Radius();
+
+ Standard_Real aMaxAngle = M_PI*0.5;
+
+ if(aRadius > myDeflection)
+ aMaxAngle = ACos(1. - myDeflection/aRadius)*2.;
+
+ if(aMaxAngle > Precision::Angular())
+ theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+ else
+ theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+ theNbPointsV = (Standard_Integer)(theVMax - theVMin);
+ theNbPointsV /= 10;
+
+ if (theNbPointsU < 11)
+ theNbPointsU = 11;
+
+ if (theNbPointsV < 11)
+ theNbPointsV = 11;
+ } else if (aType == STANDARD_TYPE(Geom_SphericalSurface) ||
+ aType == STANDARD_TYPE(Geom_ToroidalSurface)) {
+ // SPHERE or TORUS
+ gp_Circ aCircle;
+ Standard_Real aRadius1;
+ Standard_Real aRadius2;
+
+ if (aType == STANDARD_TYPE(Geom_SphericalSurface)) {
+ // SPHERE
+ Handle(Geom_SphericalSurface) aSphSurf =
+ Handle(Geom_SphericalSurface)::DownCast(aSurface);
+ gp_Sphere aSphere = aSphSurf->Sphere();
+
+ aRadius1 = aSphere.Radius();
+ aRadius2 = aSphere.Radius();
+ } else {
+ Handle(Geom_ToroidalSurface) aTorusSurf =
+ Handle(Geom_ToroidalSurface)::DownCast(aSurface);
+ // TORUS
+ gp_Torus aTorus = aTorusSurf->Torus();
+
+ aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(),
+ aTorus.MinorRadius(), theUMin);
+ aRadius2 = aCircle.Radius();
+ aCircle = ElSLib::TorusUIso(aTorus.Position(), aTorus.MajorRadius(),
+ aTorus.MinorRadius(), theUMax);
+ aRadius2 = (aRadius2 < aCircle.Radius()) ? aCircle.Radius() : aRadius2;
+ aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(),
+ aTorus.MinorRadius(), theVMin);
+ aRadius1 = aCircle.Radius();
+ aCircle = ElSLib::TorusVIso(aTorus.Position(), aTorus.MajorRadius(),
+ aTorus.MinorRadius(), theVMax);
+ aRadius1 = (aRadius1 < aCircle.Radius()) ? aCircle.Radius() : aRadius1;
+ }
+
+ Standard_Real aMaxAngle = M_PI*0.5;
+
+ if(aRadius1 > myDeflection)
+ aMaxAngle = ACos(1. - myDeflection/aRadius1)*2.;
+
+ if(aMaxAngle > Precision::Angular())
+ theNbPointsU = Standard_Integer((theUMax - theUMin)/aMaxAngle);
+ else
+ theNbPointsU = (Standard_Integer)(theUMax - theUMin);
+
+ aMaxAngle = M_PI*0.5;
+
+ if(aRadius2 > myDeflection)
+ aMaxAngle = ACos(1. - myDeflection/aRadius2)*2.;
+
+ if(aMaxAngle > Precision::Angular())
+ theNbPointsV = Standard_Integer((theVMax - theVMin)/aMaxAngle);
+ else
+ theNbPointsV = (Standard_Integer)(theVMax - theVMin);
+
+ if (theNbPointsU < 11)
+ theNbPointsU = 11;
+
+ if (theNbPointsV < 11)
+ theNbPointsV = 11;
+ } else if (aType == STANDARD_TYPE(Geom_BezierSurface)) {
+ Handle(Geom_BezierSurface) aBezier =
+ Handle(Geom_BezierSurface)::DownCast(aSurface);
+ // BEZIER
+ theNbPointsU = 3 + aBezier->NbUPoles();
+ theNbPointsV = 3 + aBezier->NbVPoles();
+
+ if(theNbPointsU > 11 || theNbPointsV > 11) {
+ TColgp_Array2OfPnt array2(1, aBezier->NbUPoles(), 1, aBezier->NbVPoles());
+ aBezier->Poles(array2);
+ Analyse(array2, theNbPointsU, theNbPointsV);
+ }
+ AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface,
+ theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+ if(theNbPointsU < 11)
+ theNbPointsU = 11;
+
+ if(theNbPointsV < 11)
+ theNbPointsV = 11;
+ } else if (aType == STANDARD_TYPE(Geom_BSplineSurface)) {
+ // BSPLINE
+ Handle(Geom_BSplineSurface) aBSpline =
+ Handle(Geom_BSplineSurface)::DownCast(aSurface);
+
+ theNbPointsU = aBSpline->NbUKnots();
+ theNbPointsU *= aBSpline->UDegree();
+ theNbPointsV = aBSpline->NbVKnots();
+ theNbPointsV *= aBSpline->VDegree();
+
+ if(theNbPointsU > 11 || theNbPointsU > 11) {
+ TColgp_Array2OfPnt array2(1, aBSpline->NbUPoles(),
+ 1, aBSpline->NbVPoles());
+ aBSpline->Poles(array2);
+ Analyse(array2, theNbPointsU, theNbPointsV);
+ }
+ AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface,
+ theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+ if(theNbPointsU < 11)
+ theNbPointsU = 11;
+
+ if(theNbPointsV < 11)
+ theNbPointsV = 11;
+ } else if (aType == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)) {
+ // EXTRUSION
+ theNbPointsU = 15;
+ theNbPointsV = (Standard_Integer)(theVMax - theVMin);
+ theNbPointsV /= 10;
+
+ AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface,
+ theUMin, theUMax, theVMin, theVMax, myDeflection );
+
+ if(theNbPointsV < 15)
+ theNbPointsV = 15;
+ } else if (aType == STANDARD_TYPE(Geom_SurfaceOfRevolution)) {
+ // REVOLUTION
+ theNbPointsU = 15;
+ theNbPointsV = 15;
+
+ AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface,
+ theUMin, theUMax, theVMin, theVMax, myDeflection );
+ } else {
+ // OTHER
+ theNbPointsU = 11;
+ theNbPointsV = 11;
+ AdjustToDeflection( theNbPointsU, theNbPointsV, aSurface,
+ theUMin, theUMax, theVMin, theVMax, myDeflection );
+ }
+
+ // Check if the number of points exceeds the maximum number of points.
+ const Standard_Integer aMaxNbPoints = aLimitNumber;
+
+ if(theNbPointsU > aMaxNbPoints) {
+ if ( theNbPointsU < theNbPointsV ) {
+ theNbPointsU = aMaxNbPoints;
+ }
+ else {
+ Standard_Integer alim = aMaxNbPoints * aMaxNbPoints / theNbPointsV;
+ theNbPointsU = ( theNbPointsU > alim ) ? alim : theNbPointsU;
+ }
+ }
+
+ if(theNbPointsV > aMaxNbPoints) {
+ if ( theNbPointsV < theNbPointsU ) {
+ theNbPointsV = aMaxNbPoints;
+ }
+ else {
+ Standard_Integer alim = aMaxNbPoints * aMaxNbPoints / theNbPointsU;
+ theNbPointsV = ( theNbPointsV > alim ) ? alim : theNbPointsV;
+ }
+ }
+}
+
+//=======================================================================
+//function : Unfolding
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::Unfolding()
+{
+ Handle(Geom_Surface) aSurface = BRep_Tool::Surface(myDataContainer->GetFace());
+ Standard_Integer iStart = myGrid->LowerRow();
+ Standard_Integer jStart = myGrid->LowerCol();
+ Standard_Integer iEnd = myGrid->UpperRow();
+ Standard_Integer jEnd = myGrid->UpperCol();
+ Standard_Integer i;
+ Standard_Integer j;
+
+ // Initialize the array of 4 points on a plane. For a couple of indices (i, j)
+ // the points on a plane are initialized as follows:
+ // aPonPln[0] -> (i, j + 1)
+ // aPonPln[1] -> (i, j)
+ // aPonPln[2] -> (i + 1, j)
+ // aPonPln[3] -> (i + 1, j + 1)
+ gp_XY aPonPln[4];
+ Standard_Real aCrvDist;
+ Standard_Real aCrvDist2;
+ gp_XY aDirX;
+ gp_XY aDirY;
+ Standard_Real aTolConf = 0.01*Max(myTolContour, myDeflection);
+ Standard_Real aNorm;
+ Standard_Real aDistortionArea = 0.;
+
+ for (j = jStart; j < jEnd; j++) {
+ // Step 1: Get or compute aPonPln[1].
+ Unfolding_Point &aP1 = myGrid->ChangeValue(iStart, j);
+
+ // Add the first point aPonPln[1].
+ if (j == jStart)
+ aP1.SetPointOnPlane(gp_XY(0., 0.));
+
+ // Get aPonPln[1].
+ aPonPln[1] = aP1.GetPointOnPlane();
+
+ // Step 2: Compute aPonPln[0].
+ Unfolding_Point &aP2 = myGrid->ChangeValue(iStart, j + 1);
+
+ // Compute a curvelinear distance.
+ aCrvDist = CrvDistance(aP1, aP2, aSurface, myTolContour);
+
+ if (aCrvDist <= aTolConf) {
+ aPonPln[0] = aPonPln[1];
+ } else {
+ // Compute the Y direction.
+ if (j == jStart) {
+ aDirY.SetCoord(0., 1.);
+ } else {
+ Unfolding_Point &aP21 = myGrid->ChangeValue(iStart + 1, j);
+
+ aDirX = aP21.GetPointOnPlane().Subtracted(aPonPln[1]);
+ aNorm = aDirX.Modulus();
+
+ if (aNorm <= aTolConf) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ // Compute the Y direction.
+ aDirX.Divide(aNorm);
+
+ gp_Vec2d aVecX(aDirX);
+ aVecX.Rotate(aP1.GetAngle());
+ aDirY = aVecX.XY();
+ }
+
+ // Compute point on plane.
+ aPonPln[0] = aPonPln[1].Added(aDirY.Multiplied(aCrvDist));
+ }
+
+ aP2.SetPointOnPlane(aPonPln[0]);
+
+ for (i = iStart; i < iEnd; i++) {
+ Unfolding_Point &aP11 = myGrid->ChangeValue(i, j);
+ Unfolding_Point &aP21 = myGrid->ChangeValue(i + 1, j);
+ Unfolding_Point &aP22 = myGrid->ChangeValue(i + 1, j + 1);
+ Unfolding_Point &aP12 = myGrid->ChangeValue(i, j + 1);
+
+ // Step 3: Compute aPonPln[2].
+ aCrvDist = CrvDistance(aP11, aP21, aSurface, myTolContour);
+
+ if (aCrvDist <= aTolConf) {
+ if (j > jStart) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+ aPonPln[2] = aPonPln[1];
+ } else {
+ aDirY = aPonPln[0].Subtracted(aPonPln[1]);
+ aNorm = aDirY.Modulus();
+
+ if (aNorm <= aTolConf) {
+ if (i == iStart) {
+ aDirX.SetCoord(1., 0.);
+ } else {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+ } else {
+ // Compute the X direction.
+ aDirY.Divide(aNorm);
+
+ gp_Vec2d aVecY(aDirY);
+
+ aVecY.Rotate(-aP11.GetAngle());
+ aDirX = aVecY.XY();
+ }
+
+ aPonPln[2] = aPonPln[1].Added(aDirX.Multiplied(aCrvDist));
+ }
+
+ if (j == jStart) {
+ aP21.SetPointOnPlane(aPonPln[2]);
+ aCrvDist2 = CrvDistance(aP21, aP22, aSurface, myTolContour);
+ } else {
+ aCrvDist2 = CrvDistance(aP21, aP22, aSurface, myTolContour);
+ Standard_Real aDif = aPonPln[2].Subtracted(aP21.GetPointOnPlane()).Modulus();
+// aDistortionArea += aDif * aCrvDist * 0.5;
+ Standard_Real area = aDif * aCrvDist * 0.5;
+ if ( aCrvDist > gp::Resolution() ) {
+ Standard_Real aSinVal = 1. - (0.25*aDif*aDif / (aCrvDist*aCrvDist));
+ if ( aSinVal > 0. )
+ aSinVal = sqrt( aSinVal );
+ area *= aSinVal;
+ }
+ aDistortionArea += area;
+// if (!aPonPln[2].IsEqual(aP21.GetPointOnPlane(), myTolContour)) {
+ if ( aDif > ( aCrvDist2 + aCrvDist ) ) {
+ // The surface cannot be unfolded.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ // Keep old point
+ aPonPln[2] = aP21.GetPointOnPlane();
+ }
+
+ // Step 4: Compute aPonPln[3].
+ gp_XY aDiag = aPonPln[2].Subtracted(aPonPln[0]);
+ Standard_Real aDDiag = aDiag.Modulus();
+
+ if (aDDiag <= aTolConf) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ aCrvDist = CrvDistance(aP12, aP22, aSurface, myTolContour);
+
+ if (aCrvDist <= aTolConf) {
+ if (j < jEnd - 1) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+ aPonPln[3] = aPonPln[0];
+ } else {
+
+ if (aCrvDist2 <= aTolConf) {
+ if (i < iEnd - 1) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+ aPonPln[3] = aPonPln[2];
+ } else {
+ if (aCrvDist + aCrvDist2 <= aDDiag + aTolConf) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ // Construct two circles
+ gp_Dir2d aX(1., 0.);
+ gp_Ax22d aCirc1Axis = gp_Ax22d(gp_Pnt2d(aPonPln[0]), aX);
+ gp_Ax22d aCirc2Axis = gp_Ax22d(gp_Pnt2d(aPonPln[2]), aX);
+ gp_Circ2d aCirc1(aCirc1Axis, aCrvDist);
+ gp_Circ2d aCirc2(aCirc2Axis, aCrvDist2);
+
+ // Analytic intersection of two circles.
+ IntAna2d_AnaIntersection anInter(aCirc1, aCirc2);
+
+ if (!anInter.IsDone() || anInter.NbPoints() != 2) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+
+ gp_Pnt2d anIntP = anInter.Point(1).Value();
+ gp_XY aD30(anIntP.XY().Subtracted(aPonPln[0]));
+
+ if (aD30.Crossed(aDiag) > 0.) {
+ anIntP = anInter.Point(2).Value();
+ aD30 = anIntP.XY().Subtracted(aPonPln[0]);
+
+ if (aD30.Crossed(aDiag) > 0.) {
+ // Invalid case.
+ myErrorStatus = Unfolding_InvalidSurface;
+ return Standard_False;
+ }
+ }
+
+ aPonPln[3] = anIntP.XY();
+ }
+ }
+
+ aP22.SetPointOnPlane(aPonPln[3]);
+
+ // Prepare points for next iterations.
+ aPonPln[0] = aPonPln[3];
+ aPonPln[1] = aPonPln[2];
+ }
+ }
+
+ myDataContainer->SetDistortionArea(aDistortionArea);
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : BuildPlanarFace
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::BuildPlanarFace
+ (const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples)
+{
+ Handle(Geom_Surface) aPlane = new Geom_Plane(myPlane);
+ BRep_Builder aBuilder;
+ TopoDS_Face aPlanarFace;
+ Standard_Real aTopoTol = Precision::Confusion();
+
+ aBuilder.MakeFace(aPlanarFace, aPlane, aTopoTol);
+
+ // Build wires.
+ TopExp_Explorer anExp(myDataContainer->GetFace(), TopAbs_WIRE);
+ TopoDS_Wire aWire;
+
+ for (; anExp.More(); anExp.Next()) {
+ TopoDS_Wire aPlanarWire;
+
+ aWire = TopoDS::Wire(anExp.Current());
+
+ if (!BuildPlanarWire(aWire, theMapEdgeNbSamples, aPlanarWire)) {
+ myErrorStatus = Unfolding_Failure;
+
+ return Standard_False;
+ }
+
+ aBuilder.Add(aPlanarFace, aPlanarWire);
+ }
+
+ myDataContainer->SetUnfoldedFace(aPlanarFace);
+ myErrorStatus = Unfolding_Done;
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : BuildPlanarWire
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::BuildPlanarWire
+ (const TopoDS_Wire &theWire,
+ const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples,
+ TopoDS_Wire &thePlanarWire)
+{
+ BRep_Builder aBuilder;
+ BRepTools_WireExplorer aWExp(theWire, myDataContainer->GetFace());
+ TopoDS_Vertex aV[2];
+ TopoDS_Vertex aVEmpty;
+ TopoDS_Vertex aVFirst[2];
+ gp_XY aBndPnt[2] = { gp_XY(0., 0.), gp_XY(0., 0.) };
+ gp_XY aPntFirst;
+
+ aBuilder.MakeWire(thePlanarWire);
+
+ for (; aWExp.More();) {
+ TopoDS_Edge anEdge = aWExp.Current();
+
+ aWExp.Next();
+ // Skip degenerated edges as they cannot be unfolded.
+ if (BRep_Tool::Degenerated(anEdge))
+ continue;
+
+ aV[0] = TopExp::LastVertex(anEdge, Standard_True);
+
+ if (!aVFirst[0].IsNull() && !aWExp.More() && aVFirst[0].IsSame(aV[0])) {
+ // Close the edge
+ aVEmpty = aVFirst[1];
+ aBndPnt[1] = aPntFirst;
+ }
+
+ // Perform unfolding
+ TopTools_ListOfShape anEdges;
+
+ if (!UnfoldEdge(anEdge, aV[1], aVEmpty, theMapEdgeNbSamples,
+ aBndPnt[0], aBndPnt[1], anEdges))
+ return Standard_False;
+ myDataContainer->SetEdgesForEdge(anEdge, anEdges);
+
+ if (anEdges.IsEmpty())
+ return Standard_False;
+
+ // Build result.
+ TopTools_ListIteratorOfListOfShape anIter(anEdges);
+
+ for (; anIter.More(); anIter.Next()) {
+ const TopoDS_Shape &aPlnEdge = anIter.Value();
+
+ aBuilder.Add(thePlanarWire, aPlnEdge);
+ }
+
+ if (aVFirst[1].IsNull()) {
+ aVFirst[0] = TopExp::FirstVertex(anEdge, Standard_True);
+ aVFirst[1] = TopExp::FirstVertex(TopoDS::Edge(anEdges.First()));
+ aPntFirst = aBndPnt[0];
+ }
+
+ aV[1] = TopExp::LastVertex(TopoDS::Edge(anEdges.Last()));
+ aBndPnt[0] = aBndPnt[1];
+ }
+
+ thePlanarWire.Closed(Standard_True);
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : UnfoldEdge
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::UnfoldEdge
+ (const TopoDS_Edge &theEdge,
+ const TopoDS_Vertex &theStartVtx,
+ const TopoDS_Vertex &theEndVtx,
+ const TopTools_DataMapOfShapeInteger &theMapEdgeNbSamples,
+ gp_XY &theStartPnt,
+ gp_XY &theEndPnt,
+ TopTools_ListOfShape &thePlnEdges) const
+{
+ Standard_Boolean isReversed = theEdge.Orientation() == TopAbs_REVERSED;
+ Standard_Real aTol = BRep_Tool::Tolerance(theEdge);
+ Standard_Real aParam[2];
+ const TopoDS_Face &aFace = myDataContainer->GetFace();
+ Handle(Geom2d_Curve) a2dCurve = BRep_Tool::CurveOnSurface
+ (theEdge, aFace, aParam[0], aParam[1]);
+ Standard_Integer aNbPoints;
+
+ if (theMapEdgeNbSamples.IsBound(theEdge)) {
+ // Get already computed sampling.
+ aNbPoints = theMapEdgeNbSamples.Find(theEdge);
+ } else {
+ // Compute sampling
+ TopTools_ListOfShape aFaces;
+
+ aFaces.Append(aFace);
+ aNbPoints = Unfolding::NbSamples(theEdge, aFaces, myTolContour);
+ }
+
+ // Make sampling with middle points.
+ aNbPoints *= 2;
+ aNbPoints--;
+
+ Standard_Real aCurPar = aParam[0];
+ Standard_Real aStep = (aParam[1] - aParam[0])/(aNbPoints - 1);
+ Standard_Integer i = 1;
+ gp_Pnt2d aPUV;
+ gp_XY aPOnP;
+ TColgp_SequenceOfXY aSeqPnts;
+ Standard_Integer aNbIter = aNbPoints;
+
+ if (!theStartVtx.IsNull()) {
+ // Do not compute the first point.
+ if (isReversed)
+ aNbIter--;
+ else {
+ aCurPar += aStep;
+ i++;
+ }
+ }
+
+ if (!theEndVtx.IsNull()) {
+ // Do not compute the last point.
+ if (isReversed) {
+ aCurPar += aStep;
+ i++;
+ } else
+ aNbIter--;
+ }
+
+ for (; i <= aNbIter; i++) {
+ a2dCurve->D0(aCurPar, aPUV);
+
+ if (!ComputePointOnPlane(aPUV.XY(), aTol, aPOnP))
+ return Standard_False;
+
+ if (isReversed)
+ aSeqPnts.Prepend(aPOnP);
+ else
+ aSeqPnts.Append(aPOnP);
+
+ aCurPar = (i == aNbPoints - 1) ? aParam[1] : aCurPar + aStep;
+ }
+
+ // Prepend theStartPnt to the sequence of points if it was computed before.
+ if (!theStartVtx.IsNull())
+ aSeqPnts.Prepend(theStartPnt);
+ else
+ theStartPnt = aSeqPnts.First();
+
+ // Append theEndPoint to the sequence of points if it was computed before.
+ if (!theEndVtx.IsNull())
+ aSeqPnts.Append(theEndPnt);
+ else
+ theEndPnt = aSeqPnts.Last();
+
+ // Compute edges.
+ if (aSeqPnts.IsEmpty())
+ return Standard_False;
+
+ TopoDS_Vertex aV[2];
+ Standard_Boolean isClosed = Standard_False;
+
+ TopExp::Vertices(theEdge, aV[0], aV[1], Standard_True);
+
+ if (aV[0].IsSame(aV[1])) {
+ gp_Pnt2d aP2d[2];
+
+ a2dCurve->D0(aParam[0], aP2d[0]);
+ a2dCurve->D0(aParam[1], aP2d[1]);
+ isClosed = aP2d[0].IsEqual(aP2d[1], aTol);
+ }
+
+ // Check if the first point coincides with theStartVtx.
+ Handle(Geom_Surface) aPlane = new Geom_Plane(myPlane);
+ const gp_XY &aFirst = aSeqPnts.First();
+ const gp_XY &aLast = aSeqPnts.Last();
+ gp_Pnt aPFirst;
+ gp_Pnt aPLast;
+
+ aPlane->D0(aFirst.X(), aFirst.Y(), aPFirst);
+ aPlane->D0(aLast.X(), aLast.Y(), aPLast);
+
+ if (!theStartVtx.IsNull()) {
+ gp_Pnt aPStartVtx = BRep_Tool::Pnt(theStartVtx);
+ Standard_Real aVtxTol = BRep_Tool::Tolerance(theStartVtx);
+ Standard_Real aTolConf = Max(aVtxTol, myTolContour);
+
+ if (!aPFirst.IsEqual(aPStartVtx, aTolConf))
+ return Standard_False;
+
+ if (isClosed && !aPLast.IsEqual(aPStartVtx, aTolConf))
+ return Standard_False;
+ }
+
+ // Check if the last point coincides with theEndVtx.
+ if (!theEndVtx.IsNull()) {
+ gp_Pnt aPEndVtx = BRep_Tool::Pnt(theEndVtx);
+ Standard_Real aVtxTol = BRep_Tool::Tolerance(theEndVtx);
+ Standard_Real aTolConf = Max(aVtxTol, myTolContour);
+
+ if (!aPLast.IsEqual(aPEndVtx, aTolConf))
+ return Standard_False;
+ }
+
+ // Construct edges.
+ gp_Pnt aPOnPln[2];
+ gp_Pnt aPMid;
+ Standard_Real aTopoTol = Precision::Confusion();
+ BRep_Builder aBuilder;
+ Handle(Geom_Curve) aCurve;
+
+ for (i = 1; i <= aNbPoints; i += 2) {
+ const gp_XY &aP = aSeqPnts.Value(i);
+
+ aPlane->D0(aP.X(), aP.Y(), aPOnPln[1]);
+
+ // Get or compute aV[1].
+ if (i == 1 && !theStartVtx.IsNull()) {
+ aV[1] = theStartVtx;
+ } else if (i == aNbPoints) {
+ if (isClosed && !theStartVtx.IsNull())
+ aV[1] = theStartVtx;
+ else if(!theEndVtx.IsNull())
+ aV[1] = theEndVtx;
+ else
+ aBuilder.MakeVertex(aV[1], aPOnPln[1], aTopoTol);
+ } else
+ aBuilder.MakeVertex(aV[1], aPOnPln[1], aTopoTol);
+
+ if (i == 1) {
+ aV[0] = aV[1];
+ continue;
+ }
+
+ // Compute a curve
+ const gp_XY &aPm1 = aSeqPnts.Value(i - 1);
+
+ aPOnPln[0] = BRep_Tool::Pnt(aV[0]);
+ aPlane->D0(aPm1.X(), aPm1.Y(), aPMid);
+
+ aCurve = MakeCurve(aPOnPln[0], aPMid, aPOnPln[1], myPlane, myTolContour);
+
+ if (aCurve.IsNull())
+ return Standard_False;
+
+ // Construct the edge.
+ BRepBuilderAPI_MakeEdge aMkEdge(aCurve, aV[0], aV[1]);
+
+ if (!aMkEdge.IsDone())
+ return Standard_False;
+
+ const TopoDS_Edge &anEdge = aMkEdge.Edge();
+
+ thePlnEdges.Append(anEdge);
+ aV[0] = aV[1];
+ }
+
+ return Standard_True;
+}
+
+//=======================================================================
+//function : ComputePointOnPlane
+//purpose :
+//=======================================================================
+
+Standard_Boolean Unfolding_Surface::ComputePointOnPlane
+ (const gp_XY &thePoint,
+ const Standard_Real theEdgeTol,
+ gp_XY &thePointOnPlane) const
+{
+ Standard_Integer i;
+ Standard_Integer j;
+ Standard_Integer iStart = myGrid->LowerRow();
+ Standard_Integer jStart = myGrid->LowerCol();
+ Standard_Integer iEnd = myGrid->UpperRow();
+ Standard_Integer jEnd = myGrid->UpperCol();
+
+ GetCell(thePoint, myGrid, theEdgeTol, i, j);
+
+ if (i < iStart)
+ i++;
+
+ if (j < jStart)
+ j++;
+
+ const Unfolding_Point &aP11 = myGrid->Value(i, j);
+ gp_Pnt aPOnSurf;
+ gp_XYZ aDP;
+ Handle(Geom_Surface) aSurface =
+ BRep_Tool::Surface(myDataContainer->GetFace());
+
+ aSurface->D0(thePoint.X(), thePoint.Y(), aPOnSurf);
+ aDP = aPOnSurf.XYZ();
+ aDP.Subtract(aP11.GetPointOnSurface());
+
+ if (aDP.Modulus() < myTolContour) {
+ thePointOnPlane = aP11.GetPointOnPlane();
+ return Standard_True;
+ }
+
+ gp_XY aDP2d = thePoint.Subtracted(gp_XY(aP11.GetU(), aP11.GetV()));
+ gp_XYZ aDIso;
+ gp_XY aDIso2d;
+ gp_XY aDIsoSurf;
+
+ // Get direction along V.
+ if (j == jEnd) {
+ const Unfolding_Point &aP1M1 = myGrid->Value(i, j - 1);
+ aDIso = aP11.GetPointOnSurface() - aP1M1.GetPointOnSurface();
+ aDIso2d = aP11.GetPointOnPlane() - aP1M1.GetPointOnPlane();
+ aDIsoSurf.SetCoord(aP11.GetU() - aP1M1.GetU(), aP11.GetV() - aP1M1.GetV());
+ } else {
+ const Unfolding_Point &aP12 = myGrid->Value(i, j + 1);
+ aDIso = aP12.GetPointOnSurface() - aP11.GetPointOnSurface();
+ aDIso2d = aP12.GetPointOnPlane() - aP11.GetPointOnPlane();
+ aDIsoSurf.SetCoord(aP12.GetU() - aP11.GetU(), aP12.GetV() - aP11.GetV());
+ }
+
+ if (aDIso.Modulus() <= myTolContour) {
+ // Get direction along U.
+ if (i == iEnd) {
+ const Unfolding_Point &aPM11 = myGrid->Value(i - 1, j);
+ aDIso = aP11.GetPointOnSurface() - aPM11.GetPointOnSurface();
+ aDIso2d = aP11.GetPointOnPlane() - aPM11.GetPointOnPlane();
+ aDIsoSurf.SetCoord(aP11.GetU() - aPM11.GetU(), aP11.GetV() - aPM11.GetV());
+ } else {
+ const Unfolding_Point &aP21 = myGrid->Value(i + 1, j);
+ aDIso = aP21.GetPointOnSurface() - aP11.GetPointOnSurface();
+ aDIso2d = aP21.GetPointOnPlane() - aP11.GetPointOnPlane();
+ aDIsoSurf.SetCoord(aP21.GetU() - aP11.GetU(), aP21.GetV() - aP11.GetV());
+ }
+ }
+
+ if (aDIso.Modulus() <= myTolContour)
+ return Standard_False;
+
+ // Compute angle between aDP and aDIso
+ gp_Vec aVecIso(aDIso);
+ Standard_Real anAngle = aVecIso.Angle(gp_Vec(aDP));
+
+ if (aDP2d.Crossed(aDIsoSurf) < 0.)
+ anAngle = -anAngle;
+
+ // Rotate DIso2d by anAngle.
+ gp_Dir2d aPDir(aDIso2d);
+
+ aPDir.Rotate(-anAngle);
+
+ Unfolding_Point aPoint;
+ Standard_Real aCrvDist;
+
+ aPoint.SetPointOnSurface(aPOnSurf.XYZ());
+ aPoint.SetParameters(thePoint.X(), thePoint.Y());
+ aCrvDist = CrvDistance(aP11, aPoint, aSurface, myTolContour);
+
+ // Compute point on plane
+ thePointOnPlane = aP11.GetPointOnPlane();
+ thePointOnPlane += aPDir.XY().Multiplied(aCrvDist);
+
+ return Standard_True;
+}
+
+static void AdjustToDeflection( Standard_Integer &theNbPointsU,
+ Standard_Integer &theNbPointsV,
+ const Handle(Geom_Surface) &theSurface,
+ const Standard_Real theUMin,
+ const Standard_Real theUMax,
+ const Standard_Real theVMin,
+ const Standard_Real theVMax,
+ const Standard_Real theDeflection)
+{
+ if ( theNbPointsU < 2 )
+ theNbPointsU = 2;
+
+ if ( theNbPointsV < 2 )
+ theNbPointsV = 2;
+ Standard_Real aUStep = (theUMax - theUMin)/(theNbPointsU - 1);
+ Standard_Real aVStep = (theVMax - theVMin)/(theNbPointsV - 1);
+ Standard_Real aUPar;
+ Standard_Real aVPar;
+ Standard_Integer i;
+ Standard_Integer j;
+ TColgp_Array2OfPnt aMesh(1, theNbPointsU, 1, theNbPointsV);
+ gp_Pnt aPnt;
+
+
+ for (aUPar = theUMin, i = 1; i <= theNbPointsU; i++) {
+ for (aVPar = theVMin, j = 1; j <= theNbPointsV; j++) {
+ aPnt = theSurface->Value(aUPar, aVPar);
+ aMesh.SetValue(i, j, aPnt);
+ aVPar = (j == theNbPointsV - 1) ? theVMax : aVPar + aVStep;
+ }
+ aUPar = (i == theNbPointsU - 1) ? theUMax : aUPar + aUStep;
+ }
+ Standard_Real aMaxDist = 0.;
+ Standard_Real aMaxDifU = 0.;
+ Standard_Real aMaxDifV = 0.;
+
+ for (aUPar = theUMin + aUStep, i = 2; i <= theNbPointsU; i++) {
+ for (aVPar = theVMin + aVStep, j = 2; j <= theNbPointsV; j++) {
+ aPnt = theSurface->Value(aUPar-aUStep*0.5, aVPar-aVStep*0.5);
+ gp_XYZ xyz = aMesh.Value(i,j).XYZ();
+ xyz += aMesh.Value(i-1,j).XYZ();
+ xyz += aMesh.Value(i,j-1).XYZ();
+ xyz += aMesh.Value(i-1,j-1).XYZ();
+ xyz /= 4.;
+ Standard_Real aVal = aMesh.Value(i,j).SquareDistance(aMesh.Value(i-1,j));
+ if ( aMaxDifU < aVal )
+ aMaxDifU = aVal;
+
+ aVal = aMesh.Value(i,j-1).SquareDistance(aMesh.Value(i-1,j-1));
+ if ( aMaxDifU < aVal )
+ aMaxDifU = aVal;
+
+ aVal = aMesh.Value(i,j).SquareDistance(aMesh.Value(i,j-1));
+ if ( aMaxDifV < aVal )
+ aMaxDifV = aVal;
+
+ aVal = aMesh.Value(i-1,j).SquareDistance(aMesh.Value(i-1,j-1));
+ if ( aMaxDifV < aVal )
+ aMaxDifV = aVal;
+
+ Standard_Real aDist = aPnt.SquareDistance(gp_Pnt(xyz));
+ if ( aMaxDist < aDist )
+ aMaxDist = aDist;
+
+ aVPar = (j == theNbPointsV - 1) ? theVMax : aVPar + aVStep;
+ }
+ aUPar = (i == theNbPointsU - 1) ? theUMax : aUPar + aUStep;
+ }
+ aMaxDist = sqrt( aMaxDist );
+
+ if ( aMaxDist > theDeflection ) {
+ aMaxDifU = sqrt( aMaxDifU );
+ aMaxDifV = sqrt( aMaxDifV );
+
+ Standard_Real anewdifu = theDeflection * aMaxDifU / aMaxDist;
+ Standard_Real anewdifv = theDeflection * aMaxDifV / aMaxDist;
+
+ Standard_Real aVal = ( theUMax - theUMin ) / anewdifu;
+ if ( aVal > aLimitNumber )
+ aVal = aLimitNumber;
+ theNbPointsU = ( theNbPointsU < aVal ) ? Standard_Integer (aVal) : theNbPointsU;
+
+ aVal = ( theVMax - theVMin ) / anewdifv;
+ if ( aVal > aLimitNumber )
+ aVal = aLimitNumber;
+ theNbPointsV = ( theNbPointsV < aVal ) ? Standard_Integer (aVal) : theNbPointsV;
+ }
+}
--- /dev/null
+// File: Unfolding_Surface.lxx
+// Created: Tue Jul 22 16:13:39 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+#include <Unfolding_FaceDataContainer.hxx>
+
+
+//=======================================================================
+//function : SetFace
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Surface::SetFace (const TopoDS_Face &theFace)
+{
+ myDataContainer->SetFace(theFace);
+ Reset();
+}
+
+//=======================================================================
+//function : GetFace
+//purpose :
+//=======================================================================
+
+inline const TopoDS_Face &Unfolding_Surface::GetFace () const
+{
+ return myDataContainer->GetFace();
+}
+
+//=======================================================================
+//function : SetPlane
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Surface::SetPlane (const gp_Pln &thePlane)
+{
+ myPlane = thePlane;
+ Reset();
+}
+
+//=======================================================================
+//function : GetPlane
+//purpose :
+//=======================================================================
+
+inline const gp_Pln &Unfolding_Surface::GetPlane () const
+{
+ return myPlane;
+}
+
+//=======================================================================
+//function : SetTolerance
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Surface::SetContourTolerance (const Standard_Real theTolerance)
+{
+ myTolContour = theTolerance;
+ Reset();
+}
+
+//=======================================================================
+//function : GetTolerance
+//purpose :
+//=======================================================================
+
+inline Standard_Real Unfolding_Surface::GetContourTolerance () const
+{
+ return myTolContour;
+}
+
+
+inline void Unfolding_Surface::SetCurvatureTolerance(const Standard_Real theTolerance)
+{
+ myTolCurvature = theTolerance;
+ Reset();
+}
+
+
+inline Standard_Real Unfolding_Surface::GetCurvatureTolerance() const
+{
+ return myTolCurvature;
+}
+
+inline void Unfolding_Surface::SetDeflection(const Standard_Real theDeflection)
+{
+ myDeflection = theDeflection;
+ Reset();
+}
+
+
+inline Standard_Real Unfolding_Surface::GetDeflection() const
+{
+ return myDeflection;
+}
+
+
+//=======================================================================
+//function : ErrorStatus
+//purpose :
+//=======================================================================
+
+inline Unfolding_ErrorStatus Unfolding_Surface::ErrorStatus () const
+{
+ return myErrorStatus;
+}
+
+//=======================================================================
+//function : GetDataContainer
+//purpose :
+//=======================================================================
+
+inline Handle(Unfolding_FaceDataContainer)
+ Unfolding_Surface::GetDataContainer() const
+{
+ return myDataContainer;
+}
+
+//=======================================================================
+//function : Reset
+//purpose :
+//=======================================================================
+
+inline void Unfolding_Surface::Reset()
+{
+ myDataContainer->Reset();
+ myErrorStatus = Unfolding_NotDone;
+
+ if (!myGrid.IsNull())
+ myGrid.Nullify();
+}
--- /dev/null
+-- File: UnfoldingTest.cdl
+-- Created: Tue Jul 22 18:15:41 2008
+-- Author: Sergey KHROMOV
+-- <skv@dimox>
+---Copyright: Matra Datavision 2008
+
+
+package UnfoldingTest
+ ---Purpose: This package defines a set of Draw commands for testing of
+ -- functionality of the package Unfolding.
+
+uses
+
+ Draw
+
+is
+
+ Commands(theDI: in out Interpretor from Draw);
+ ---Purpose: Adds Draw commands to the draw interpretor.
+
+ Factory(theDI: out Interpretor from Draw);
+ ---Purpose: Plugin entry point function.
+
+end UnfoldingTest;
--- /dev/null
+// File: UnfoldingTest.cxx
+// Created: Tue Jul 22 18:35:23 2008
+// Author: Sergey KHROMOV
+// <skv@dimox>
+
+
+#include <UnfoldingTest.hxx>
+#include <Draw.hxx>
+#include <Draw_PluginMacro.hxx>
+#include <Draw_Interpretor.hxx>
+#include <TopoDS_Shape.hxx>
+#include <DBRep.hxx>
+#include <TopoDS_Shell.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS.hxx>
+#include <Geom_Surface.hxx>
+#include <DrawTrSurf.hxx>
+#include <Geom_Plane.hxx>
+#include <Unfolding_Surface.hxx>
+#include <Unfolding_Shell.hxx>
+#include <Unfolding.hxx>
+#include <TopTools_DataMapOfShapeInteger.hxx>
+
+
+//=======================================================================
+//function : dumpError
+//purpose :
+//=======================================================================
+
+static void dumpError (Draw_Interpretor &di,
+ const Standard_Integer theStatus)
+{
+ di << " Status: ";
+
+ switch (theStatus) {
+ case Unfolding_Done:
+ di << "Done";
+ break;
+ case Unfolding_NotDone:
+ di << "NotDone";
+ break;
+ case Unfolding_Failure:
+ di << "Failure";
+ break;
+ case Unfolding_InvalidSurface:
+ di << "InvalidSurface";
+ break;
+ case Unfolding_InvalidInput:
+ di << "InvalidInput";
+ break;
+ case Unfolding_InvalidShape:
+ di << "InvalidShape";
+ break;
+ case Unfolding_ComplexShape:
+ di << "ComplexShape";
+ break;
+ default:
+ di << "Unknown";
+ break;
+ }
+
+ di << " \n";
+}
+
+//=======================================================================
+//function : unfolding
+//purpose :
+//=======================================================================
+static Standard_Integer unfolding (Draw_Interpretor &di,
+ Standard_Integer n, const char** a)
+{
+ if (n < 4 || n > 7) {
+ di << "Usage: " << a[0] << " result face|shell plane [tol_contour] [tol_curvature] [deflection]" << "\n";
+ return 1;
+ }
+
+ // Get a shape from a[2].
+ TopoDS_Shape aShape = DBRep::Get(a[2]);
+
+ if (aShape.IsNull()) {
+ di << a[2] << " is not a shape!" << "\n";
+ return 1;
+ }
+
+ // Check if the shape is a face.
+ if (aShape.ShapeType() != TopAbs_FACE &&
+ aShape.ShapeType() != TopAbs_SHELL) {
+ di << a[2] << " is not a face or shell!" << "\n";
+ return 1;
+ }
+ TopoDS_Shell aShell;
+ TopoDS_Face aFace;
+ if (aShape.ShapeType() == TopAbs_FACE) {
+ aFace = TopoDS::Face( aShape );
+ if (aFace.IsNull()) {
+ di << a[2] << " is not a face!" << "\n";
+ return 1;
+ }
+ }
+ else {
+ aShell = TopoDS::Shell( aShape );
+ }
+
+ // Get a surface from a[3].
+ Handle(Geom_Surface) aSurface = DrawTrSurf::GetSurface(a[3]);
+
+ if (aSurface.IsNull()) {
+ di << a[3] << " is not a surface!" << "\n";
+ return 1;
+ }
+
+ // Cast the surface to a plane.
+ Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
+
+ if (aPlane.IsNull()) {
+ di << a[3] << " is not a plane!" << "\n";
+ return 1;
+ }
+
+ // Get the tolerance value.
+ Standard_Real aTolContour = 0.001;
+
+ if (n >= 5) {
+ aTolContour = Draw::Atof(a[4]);
+ } else {
+ di << "tolerance value is not provided. The default value " << aTolContour << " is used" << "\n";
+ }
+
+ // Get the curvature tolerance value.
+ Standard_Real aTolCurv = 0.001;
+
+ if (n >= 6) {
+ aTolCurv = Draw::Atof(a[5]);
+ } else {
+ di << "curvature value is not provided. The default value " << aTolCurv << " is used" << "\n";
+ }
+
+ // Get the curvature tolerance value.
+ Standard_Real aDefl = 0.001;
+
+ if (n == 7) {
+ aDefl = Draw::Atof(a[6]);
+ } else {
+ di << "deflection value is not provided. The default value " << aDefl << " is used" << "\n";
+ }
+
+
+ // Initialization of the unfolding algorithm
+ Standard_Boolean isOK = Standard_False;
+ TopoDS_Shape aResult;
+ Standard_Integer aErrorStatus = 0;
+
+ if ( !aFace.IsNull() ) {
+ TopTools_DataMapOfShapeInteger anEmptyMap;
+ Unfolding_Surface anUnfold(aFace, aPlane->Pln(), aTolContour, aTolCurv, aDefl);
+ isOK = anUnfold.Perform(anEmptyMap);
+
+ Handle(Unfolding_FaceDataContainer) aData = anUnfold.GetDataContainer();
+
+ di << "Gauss curvature =" << aData->GetMaxGaussCurvature() << "\n";
+ di << "Area of error =" << aData->GetDistortionArea() << "\n";
+ if ( isOK )
+ aResult = aData->GetUnfoldedFace();
+ aErrorStatus = anUnfold.ErrorStatus();
+ }
+ else if ( !aShell.IsNull() ) {
+ Unfolding_Shell anUnfold(aShell, aPlane->Pln(), aTolContour, aTolCurv, aDefl);
+ isOK = anUnfold.Perform();
+
+ di << "Gauss curvature =" << anUnfold.GetMaxGaussCurvature() << "\n";
+ di << "Area of error =" << anUnfold.GetAreaError() << "\n";
+ if ( isOK )
+ aResult = anUnfold.GetResult();
+ aErrorStatus = anUnfold.ErrorStatus();
+ }
+
+ if (isOK) {
+ DBRep::Set(a[1], aResult);
+ } else {
+ di << "Unfolding failure!" << "\n";
+ dumpError(di, aErrorStatus);
+
+ return 1;
+ }
+
+ return 0;
+}
+
+//=======================================================================
+//function : toshell
+//purpose :
+//=======================================================================
+
+static Standard_Integer toshell (Draw_Interpretor &di,
+ Standard_Integer n, const char** a)
+{
+ if (n != 3 && n != 4) {
+ di << "Usage: " << a[0] << " result shape [tolerance]" << "\n";;
+ return 1;
+ }
+
+ // Get a shape from a[2].
+ TopoDS_Shape aShape = DBRep::Get(a[2]);
+
+ if (aShape.IsNull()) {
+ di << a[2] << " is not a shape!" << "\n";
+ return 1;
+ }
+
+ // Get the tolerance value.
+ Standard_Real aTolerance = 1.e-6;
+
+ if (n == 4) {
+ aTolerance = Draw::Atof(a[3]);
+ } else {
+ di << "tolerance value is not provided. The default value " << aTolerance << " is used" << "\n";
+ }
+
+ Unfolding_ErrorStatus aStatus;
+ TopoDS_Shell aResult = Unfolding::ToShell(aShape, aTolerance, aStatus);
+
+ if (aResult.IsNull()) {
+ di << "toshell failure!" << "\n";
+ dumpError(di, aStatus);
+
+ return 1;
+ }
+
+ DBRep::Set(a[1], aResult);
+
+ return 0;
+}
+
+//=======================================================================
+//function : Commands
+//purpose :
+//=======================================================================
+
+void UnfoldingTest::Commands(Draw_Interpretor &theDI)
+{
+ static Standard_Boolean done = Standard_False;
+
+ if (done)
+ return;
+
+ done = Standard_True;
+
+ // Chapter's name
+ const char* group = "Unfolding commands";
+
+ theDI.Add("unfolding","unfolding result face|shell plane [tol_contour] [tol_curvature] [deflection]",
+ __FILE__, unfolding, group);
+
+ theDI.Add("toshell","toshell result shape [tolerance]",
+ __FILE__, toshell, group);
+}
+
+//=======================================================================
+//function : Factory
+//purpose :
+//=======================================================================
+
+void UnfoldingTest::Factory(Draw_Interpretor &theDI)
+{
+ UnfoldingTest::Commands(theDI);
+#ifdef DEB
+ theDI << "Draw Plugin : Unfolding commands are loaded" << "\n";
+#endif
+}
+
+// Declare entry point PLUGINFACTORY
+DPLUGIN(UnfoldingTest)
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
-
#include <OpenGl_GlCore20.hxx>
#include <AIS_Shape.hxx>
#include <AIS_InteractiveObject.hxx>
}
}
break;
-
- case WM_MOUSEWHEEL:
+#if _MSC_VER >= 1500
+ case WM_MOUSEWHEEL:
{
int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
if (wParam & MK_CONTROL)
}
}
}
- else
+ else
{
aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
}
break;
}
+#endif
case WM_MOUSEMOVE:
{