From: bugmaster Date: Tue, 9 Sep 2014 08:56:33 +0000 (+0400) Subject: Update TATA environment X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=41d83d6cc9eb717889157803f3f1d5488b7760b0;p=occt-copy.git Update TATA environment --- diff --git a/adm/UDLIST b/adm/UDLIST index 9da6e02420..de2c2d34e7 100644 --- a/adm/UDLIST +++ b/adm/UDLIST @@ -488,3 +488,11 @@ p BOPAlgo p BOPDS p BOPCol p BOPInt +p HelixBRep +p HelixGeom +p HelixTest +t TKHelix +p Unfolding +p UnfoldingTest +t TKUnfolding +t TKUnfoldingTest diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.cdl b/src/BOPAlgo/BOPAlgo_PaveFiller.cdl index 4c2199e81a..565fdad86d 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller.cdl +++ b/src/BOPAlgo/BOPAlgo_PaveFiller.cdl @@ -38,7 +38,8 @@ uses IndexedDataMapOfShapeInteger from BOPCol, DataMapOfIntegerListOfInteger from BOPCol, DataMapOfShapeListOfShape from BOPCol, - IndexedDataMapOfShapeListOfShape from BOPCol, + IndexedDataMapOfShapeListOfShape from BOPCol, + DataMapOfIntegerInteger from BOPCol, -- Context from BOPInt, -- @@ -174,19 +175,21 @@ is returns Boolean from Standard is protected; - PutPaveOnCurve(me:out; + PutPavesOnCurve(me:out; theMVOn:MapOfInteger from BOPCol; theTolR3D:Real from Standard; theNC:out Curve from BOPDS; nF1:Integer from Standard; nF2:Integer from Standard; + theMI : MapOfInteger from BOPCol; theMVEF:MapOfInteger from BOPCol) is protected; ExtendedTolerance(me:out; nV:Integer from Standard; aMI:MapOfInteger from BOPCol; - aTolVExt:out Real from Standard) + aTolVExt:out Real from Standard; + aType : Integer from Standard = 0) returns Boolean from Standard is protected; @@ -219,7 +222,8 @@ is PostTreatFF(me:out; theMSCPB:out IndexedDataMapOfShapeCoupleOfPaveBlocks from BOPDS; theMVI:out DataMapOfShapeInteger from BOPCol; - theDMExEd:out DataMapOfPaveBlockListOfPaveBlock from BOPDS; + theDMExEdges:out DataMapOfPaveBlockListOfPaveBlock from BOPDS; + theDMI:out DataMapOfIntegerInteger from BOPCol; theAllocator:out BaseAllocator from BOPCol) returns Integer from Standard is protected; @@ -252,15 +256,15 @@ is is protected; PutEFPavesOnCurve(me:out; - nF1 : Integer from Standard; - nF2 : Integer from Standard; theNC : out Curve from BOPDS; + theMI : MapOfInteger from BOPCol; theMVEF : MapOfInteger from BOPCol) is protected; PutStickPavesOnCurve(me:out; - nF1 : Integer from Standard; - nF2 : Integer from Standard; + aF1 : Face from TopoDS; + aF2 : Face from TopoDS; + theMI : MapOfInteger from BOPCol; theNC : out Curve from BOPDS; theMVStick : MapOfInteger from BOPCol) is protected; @@ -269,10 +273,11 @@ is nF1 : Integer from Standard; nF2 : Integer from Standard; theMVStick : out MapOfInteger from BOPCol; - theMVEFk : out MapOfInteger from BOPCol) + theMVEF : out MapOfInteger from BOPCol; + theMI : out MapOfInteger from BOPCol) is protected; - GetFullFaceMap(me:out; + GetFullShapeMap(me:out; nF : Integer from Standard; theMI : out MapOfInteger from BOPCol) is protected; @@ -286,8 +291,9 @@ is PutPaveOnCurve(me:out; nV : Integer from Standard; theTolR3D : Real from Standard; - theNC : Curve from BOPDS; - thePB : out PaveBlock from BOPDS) + theNC : out Curve from BOPDS; + theMI : MapOfInteger from BOPCol; + aType : Integer from Standard = 0) is protected; ProcessExistingPaveBlocks(me:out; @@ -340,7 +346,25 @@ is ---Purpose: ---Updates the information about faces - + SplitEdge(me:out; + nE : Integer from Standard; + nV1 : Integer from Standard; + aT1 : Real from Standard; + nV2 : Integer from Standard; + aT2 : Real from Standard) + returns Integer from Standard + is protected; + ---Purpose: + -- Creates new edge from the edge nE with vertices nV1 and nV2 + -- and returns the index of that new edge in the DS. + + UpdatePaveBlocks(me:out; + theDMI : DataMapOfIntegerInteger from BOPCol) + is protected; + ---Purpose: + -- Updates pave blocks which have the paves with indices contained + -- in the map . + fields myArguments : ListOfShape from BOPCol is protected; myDS : PDS from BOPDS is protected; diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx index dc28673b1f..ce288d9de9 100644 --- a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx +++ b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx @@ -257,13 +257,14 @@ static void ToleranceFF(const TopoDS_Face& aF1, BOPCol_ListOfInteger aLSE(aAllocator); BOPCol_MapOfInteger aMVOnIn(100, aAllocator), aMF(100, aAllocator), aMVStick(100,aAllocator), aMVEF(100, aAllocator), - aMVB(100, aAllocator); + aMVB(100, aAllocator), aMI(100, aAllocator); BOPDS_MapOfPaveBlock aMPBOnIn(100, aAllocator), aMPBAdd(100, aAllocator); BOPDS_ListOfPaveBlock aLPB(aAllocator); BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aMSCPB(100, aAllocator); BOPCol_DataMapOfShapeInteger aMVI(100, aAllocator); - BOPDS_DataMapOfPaveBlockListOfPaveBlock aDMExEdges; + BOPDS_DataMapOfPaveBlockListOfPaveBlock aDMExEdges(100, aAllocator); + BOPCol_DataMapOfIntegerInteger aDMI(100, aAllocator); // for (i=0; iSetEdge(iE); aLPBC.Append(aPB1); } // if (!aNbLPBx) { @@ -696,6 +700,11 @@ static void ToleranceFF(const TopoDS_Face& aF1, iV=aMVI.Find(aV); } } + const BOPDS_Pave& aP1 = !j ? aPB1->Pave1() : aPB1->Pave2(); + if (aP1.Parameter() == aPave[j].Parameter() && aP1.Index() != iV) { + aDMI.Bind(aP1.Index(), iV); + } + // aPave[j].SetIndex(iV); } // @@ -927,12 +936,12 @@ static void ToleranceFF(const TopoDS_Face& aF1, { Standard_Boolean bRet; Standard_Real aT1, aT2, aTm, aTx; - Standard_Integer nSp, iFlag, nV11, nV12, nV21, nV22; + Standard_Integer nSp, iFlag1, iFlag2, nV11, nV12, nV21, nV22; gp_Pnt aP1, aPm, aP2; Bnd_Box aBoxP1, aBoxPm, aBoxP2; BOPDS_MapIteratorOfMapOfPaveBlock aIt; // - bRet=Standard_True; + bRet=Standard_False; const IntTools_Curve& aIC=theNC.Curve(); // thePB->Range(aT1, aT2); @@ -957,25 +966,32 @@ static void ToleranceFF(const TopoDS_Face& aF1, aPB->Indices(nV21, nV22); nSp=aPB->Edge(); const BOPDS_ShapeInfo& aSISp=myDS->ChangeShapeInfo(nSp); + const TopoDS_Edge& aSp=(*(TopoDS_Edge *)(&aSISp.Shape())); const Bnd_Box& aBoxSp=aSISp.Box(); - if (!aBoxSp.IsOut(aBoxP1) && !aBoxSp.IsOut(aBoxPm) && !aBoxSp.IsOut(aBoxP2)) { - const TopoDS_Edge& aSp=(*(TopoDS_Edge *)(&aSISp.Shape())); - iFlag=(nV11 == nV21 || nV11 == nV22) ? 0 : - myContext->ComputePE(aP1, theTolR3D, aSp, aTx); - if (!iFlag) { - iFlag=(nV12 == nV21 || nV12 == nV22) ? 0 : - myContext->ComputePE(aP2, theTolR3D, aSp, aTx); - if (!iFlag) { - iFlag=myContext->ComputePE(aPm, theTolR3D, aSp, aTx); - if (!iFlag) { - aPBOut = aPB; - return bRet; - } - } + // + iFlag1 = (nV11 == nV21 || nV11 == nV22) ? 2 : (!aBoxSp.IsOut(aBoxP1) ? 1 : 0); + iFlag2 = (nV12 == nV21 || nV12 == nV22) ? 2 : (!aBoxSp.IsOut(aBoxP2) ? 1 : 0); + if (iFlag1 && iFlag2) { + if (aBoxSp.IsOut(aBoxPm) || myContext->ComputePE(aPm, theTolR3D, aSp, aTx)) { + continue; + } + // + if (iFlag1 == 1) { + iFlag1 = !myContext->ComputePE(aP1, theTolR3D, aSp, aTx); + } + // + if (iFlag2 == 1) { + iFlag2 = !myContext->ComputePE(aP2, theTolR3D, aSp, aTx); + } + // + if (iFlag1 && iFlag2) { + aPBOut = aPB; + bRet=Standard_True; + break; } } } - return !bRet; + return bRet; } //======================================================================= @@ -1082,79 +1098,57 @@ static void ToleranceFF(const TopoDS_Face& aF1, } //======================================================================= -//function : PutPaveOnCurve +//function : PutPavesOnCurve //purpose : //======================================================================= - void BOPAlgo_PaveFiller::PutPaveOnCurve(const BOPCol_MapOfInteger& aMVOnIn, - const Standard_Real aTolR3D, - BOPDS_Curve& aNC, - const Standard_Integer nF1, - const Standard_Integer nF2, - const BOPCol_MapOfInteger& aMVEF) + void BOPAlgo_PaveFiller::PutPavesOnCurve(const BOPCol_MapOfInteger& aMVOnIn, + const Standard_Real aTolR3D, + BOPDS_Curve& aNC, + const Standard_Integer nF1, + const Standard_Integer nF2, + const BOPCol_MapOfInteger& aMI, + const BOPCol_MapOfInteger& aMVEF) { - Standard_Boolean bIsVertexOnLine, bInBothFaces; + Standard_Boolean bInBothFaces; Standard_Integer nV; - Standard_Real aT; - BOPDS_Pave aPave; - // BOPCol_MapIteratorOfMapOfInteger aIt; // - Handle(BOPDS_PaveBlock)& aPB=aNC.ChangePaveBlock1(); - const IntTools_Curve& aIC=aNC.Curve(); const Bnd_Box& aBoxC=aNC.Box(); // + //Put EF vertices first + aIt.Initialize(aMVEF); + for (; aIt.More(); aIt.Next()) { + nV=aIt.Value(); + PutPaveOnCurve(nV, aTolR3D, aNC, aMI, 2); + } + //Put all other vertices aIt.Initialize(aMVOnIn); for (; aIt.More(); aIt.Next()) { nV=aIt.Value(); + if (aMVEF.Contains(nV)) { + continue; + } + // const BOPDS_ShapeInfo& aSIV=myDS->ShapeInfo(nV); - const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&aSIV.Shape())); + const Bnd_Box& aBoxV=aSIV.Box(); // - if (!aMVEF.Contains(nV)) { - const Bnd_Box& aBoxV=aSIV.Box(); + if (aBoxC.IsOut(aBoxV)){ + continue; + } + if (!myDS->IsNewShape(nV)) { + const BOPDS_FaceInfo& aFI1 = myDS->FaceInfo(nF1); + const BOPDS_FaceInfo& aFI2 = myDS->FaceInfo(nF2); // - if (aBoxC.IsOut(aBoxV)){ - continue; - } - if (!myDS->IsNewShape(nV)) { - const BOPDS_FaceInfo& aFI1 = myDS->FaceInfo(nF1); - const BOPDS_FaceInfo& aFI2 = myDS->FaceInfo(nF2); - // - bInBothFaces = (aFI1.VerticesOn().Contains(nV) || - aFI1.VerticesIn().Contains(nV))&& - (aFI2.VerticesOn().Contains(nV) || - aFI2.VerticesIn().Contains(nV)); - if (!bInBothFaces) { - continue; - } + bInBothFaces = (aFI1.VerticesOn().Contains(nV) || + aFI1.VerticesIn().Contains(nV))&& + (aFI2.VerticesOn().Contains(nV) || + aFI2.VerticesIn().Contains(nV)); + if (!bInBothFaces) { + continue; } } // - bIsVertexOnLine=myContext->IsVertexOnLine(aV, aIC, aTolR3D, aT); - if (!bIsVertexOnLine) { - Standard_Real aTolVExt; - BOPCol_MapOfInteger aMI; - // - aTolVExt = BRep_Tool::Tolerance(aV); - // - GetFullFaceMap(nF1, aMI); - GetFullFaceMap(nF2, aMI); - // - ExtendedTolerance(nV, aMI, aTolVExt); - bIsVertexOnLine=myContext->IsVertexOnLine(aV, aTolVExt, aIC, aTolR3D, aT); - } - // - if (bIsVertexOnLine) { - aPave.SetIndex(nV); - aPave.SetParameter(aT); - // - aPB->AppendExtPave(aPave); - // - BOPTools_AlgoTools::UpdateVertex (aIC, aT, aV); - // - BOPDS_ShapeInfo& aSIDS=myDS->ChangeShapeInfo(nV); - Bnd_Box& aBoxDS=aSIDS.ChangeBox(); - BRepBndLib::Add(aV, aBoxDS); - } + PutPaveOnCurve(nV, aTolR3D, aNC, aMI, 1); } } @@ -1162,35 +1156,44 @@ static void ToleranceFF(const TopoDS_Face& aF1, //function : ExtendedTolerance //purpose : //======================================================================= - Standard_Boolean BOPAlgo_PaveFiller::ExtendedTolerance(const Standard_Integer nV, - const BOPCol_MapOfInteger& aMI, - Standard_Real& aTolVExt) +Standard_Boolean BOPAlgo_PaveFiller::ExtendedTolerance(const Standard_Integer nV, + const BOPCol_MapOfInteger& aMI, + Standard_Real& aTolVExt, + const Standard_Integer aType) { Standard_Boolean bFound = Standard_False; if (!(myDS->IsNewShape(nV))) { return bFound; } - - Standard_Integer i, k, aNbLines; + // + Standard_Integer i, k, aNbLines, aNbInt; Standard_Real aT11, aT12, aD1, aD2, aD; TopoDS_Vertex aV; gp_Pnt aPV, aP11, aP12; - + // + k = 0; + aNbInt = 2; + if (aType == 1) { + aNbInt = 1; + } else if (aType == 2) { + k = 1; + } + // aV = (*(TopoDS_Vertex *)(&myDS->Shape(nV))); aPV=BRep_Tool::Pnt(aV); // BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE(); BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF(); - - for (k=0; k<2; ++k) { + // + for (; kIndexNew() == nV) { if (aMI.Contains(aInt->Index1()) && aMI.Contains(aInt->Index2())) { const IntTools_CommonPrt& aComPrt = !k ? aEEs(i).CommonPart() : - aEFs(i).CommonPart(); + aEFs(i).CommonPart(); // const TopoDS_Edge& aE1=aComPrt.Edge1(); aComPrt.Range1(aT11, aT12); @@ -1207,7 +1210,6 @@ static void ToleranceFF(const TopoDS_Face& aF1, }//if (aInt->IndexNew() == nV) { }//for (i = 0; i < aNbLines; ++i) { }//for (k=0; k<2; ++k) { - return bFound; } @@ -1221,24 +1223,21 @@ static void ToleranceFF(const TopoDS_Face& aF1, { Standard_Integer nE, nF, nFOpposite, aNbEFs, i; Standard_Real U1, U2, V1, V2, f, l; - BOPCol_MapOfInteger aMIF1, aMIF2; + BOPCol_MapOfInteger aMI; // //collect indexes of all shapes from nF1 and nF2. - GetFullFaceMap(nF1, aMIF1); - GetFullFaceMap(nF2, aMIF2); + GetFullShapeMap(nF1, aMI); + GetFullShapeMap(nF2, aMI); // BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF(); aNbEFs = aEFs.Extent(); // for(i = 0; i < aNbEFs; ++i) { const BOPDS_InterfEF& aEF = aEFs(i); - nE = aEF.Index1(); - nFOpposite = aEF.Index2(); - if(aMIF1.Contains(nE) && aMIF2.Contains(nFOpposite) || - aMIF1.Contains(nFOpposite) && aMIF2.Contains(nE)) { - // - IntTools_CommonPrt aCP = aEF.CommonPart(); - if(aCP.Type() == TopAbs_VERTEX) { + if (aEF.HasIndexNew()) { + aEF.Indices(nE, nFOpposite); + if(aMI.Contains(nE) && aMI.Contains(nFOpposite)) { + const IntTools_CommonPrt& aCP = aEF.CommonPart(); Standard_Real aPar = aCP.VertexParameter1(); const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&myDS->Shape(nE))); const TopoDS_Face& aFOpposite = (*(TopoDS_Face*)(&myDS->Shape(nFOpposite))); @@ -1291,10 +1290,9 @@ static void ToleranceFF(const TopoDS_Face& aF1, //function : ProcessUnUsedVertices //purpose : //======================================================================= - void BOPAlgo_PaveFiller::PutEFPavesOnCurve(const Standard_Integer nF1, - const Standard_Integer nF2, - BOPDS_Curve& aNC, - const BOPCol_MapOfInteger& aMVEF) +void BOPAlgo_PaveFiller::PutEFPavesOnCurve(BOPDS_Curve& aNC, + const BOPCol_MapOfInteger& aMI, + const BOPCol_MapOfInteger& aMVEF) { if (!aMVEF.Extent()) { return; @@ -1320,10 +1318,8 @@ static void ToleranceFF(const TopoDS_Face& aF1, BOPDS_Pave aPave; // const Handle(Geom_Curve)& aC3D=aIC.Curve(); - Handle(BOPDS_PaveBlock)& aPB = aNC.ChangePaveBlock1(); - GeomAPI_ProjectPointOnCurve& aProjPT = myContext->ProjPT(aC3D); - + // BOPCol_MapIteratorOfMapOfInteger aItMI; aItMI.Initialize(aMV); for (; aItMI.More(); aItMI.Next()) { @@ -1334,7 +1330,7 @@ static void ToleranceFF(const TopoDS_Face& aF1, Standard_Integer aNbPoints = aProjPT.NbPoints(); if (aNbPoints) { aDist = aProjPT.LowerDistance(); - PutPaveOnCurve(nV, aDist, aNC, aPB); + PutPaveOnCurve(nV, aDist, aNC, aMI); } } } @@ -1343,8 +1339,9 @@ static void ToleranceFF(const TopoDS_Face& aF1, //function : ProcessUnUsedVertices //purpose : //======================================================================= - void BOPAlgo_PaveFiller::PutStickPavesOnCurve(const Standard_Integer nF1, - const Standard_Integer nF2, + void BOPAlgo_PaveFiller::PutStickPavesOnCurve(const TopoDS_Face& aF1, + const TopoDS_Face& aF2, + const BOPCol_MapOfInteger& aMI, BOPDS_Curve& aNC, const BOPCol_MapOfInteger& aMVStick) { @@ -1357,40 +1354,36 @@ static void ToleranceFF(const TopoDS_Face& aF1, } // GeomAbs_SurfaceType aType1, aType2; - const TopoDS_Face& aF1 = (*(TopoDS_Face*)(&myDS->Shape(nF1))); - const TopoDS_Face& aF2 = (*(TopoDS_Face*)(&myDS->Shape(nF2))); Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1); Handle(Geom_Surface) aS2=BRep_Tool::Surface(aF2); GeomAdaptor_Surface aGAS1(aS1); GeomAdaptor_Surface aGAS2(aS2); - // aType1=aGAS1.GetType(); aType2=aGAS2.GetType(); // - if(aType1==GeomAbs_Torus || aType2==GeomAbs_Torus) { - Standard_Integer nV, m, n; - Standard_Real aTC[2], aD, aD2, u, v, aDT2, aScPr, aDScPr; + if (aType1==GeomAbs_Torus || aType2==GeomAbs_Torus) { GeomAbs_CurveType aTypeC; - gp_Pnt aPC[2], aPV; - gp_Dir aDN[2]; - gp_Pnt2d aP2D; - - Handle(Geom2d_Curve) aC2D[2]; - // - aDT2=2e-7; // the rich criteria - aDScPr=5.e-9; // the creasing criteria // const IntTools_Curve& aIC=aNC.Curve(); - //Handle(Geom_Curve) aC3D=aIC.Curve(); //DEB aTypeC=aIC.Type(); if (aTypeC==GeomAbs_BezierCurve || aTypeC==GeomAbs_BSplineCurve) { + Handle(Geom2d_Curve) aC2D[2]; // - aIC.Bounds(aTC[0], aTC[1], aPC[0], aPC[1]); aC2D[0]=aIC.FirstCurve2d(); aC2D[1]=aIC.SecondCurve2d(); if (!aC2D[0].IsNull() && !aC2D[1].IsNull()) { + Standard_Integer nV, m, n; + Standard_Real aTC[2], aD, aD2, u, v, aDT2, aScPr, aDScPr; + gp_Pnt aPC[2], aPV; + gp_Dir aDN[2]; + gp_Pnt2d aP2D; BOPCol_MapIteratorOfMapOfInteger aItMI, aItMI1; + // + aDT2=2e-7; // the rich criteria + aDScPr=5.e-9; // the creasing criteria + aIC.Bounds(aTC[0], aTC[1], aPC[0], aPC[1]); + // aItMI.Initialize(aMV); for (; aItMI.More(); aItMI.Next()) { nV = aItMI.Value(); @@ -1423,8 +1416,7 @@ static void ToleranceFF(const TopoDS_Face& aF1, // The intersection curve aIC is vanishing curve (the crease) aD=sqrt(aD2); // - Handle(BOPDS_PaveBlock)& aPB=aNC.ChangePaveBlock1(); - PutPaveOnCurve(nV, aD, aNC, aPB); + PutPaveOnCurve(nV, aD, aNC, aMI); } }//for (jVU=1; jVU=aNbVU; ++jVU) { } @@ -1439,10 +1431,10 @@ static void ToleranceFF(const TopoDS_Face& aF1, void BOPAlgo_PaveFiller::GetStickVertices(const Standard_Integer nF1, const Standard_Integer nF2, BOPCol_MapOfInteger& aMVStick, - BOPCol_MapOfInteger& aMVEF) + BOPCol_MapOfInteger& aMVEF, + BOPCol_MapOfInteger& aMI) { - BOPCol_MapOfInteger aMIF1, aMIF2; - Standard_Integer nV1, nV2, nE1, nE2, nV, nE, nF, nVNew, i; + Standard_Integer nS1, nS2, nVNew, aTypeInt, i; // BOPDS_VectorOfInterfVV& aVVs=myDS->InterfVV(); BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE(); @@ -1450,73 +1442,35 @@ static void ToleranceFF(const TopoDS_Face& aF1, BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF(); BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF(); // - Standard_Integer aNbVVs, aNbVEs, aNbEEs, aNbVFs, aNbEFs; - aNbVVs = aVVs.Extent(); - aNbVEs = aVEs.Extent(); - aNbEEs = aEEs.Extent(); - aNbVFs = aVFs.Extent(); - aNbEFs = aEFs.Extent(); - // - //collect indexes of all shapes from nF1 and nF2. - GetFullFaceMap(nF1, aMIF1); - GetFullFaceMap(nF2, aMIF2); - //collect VV interferences - for(i = 0; i < aNbVVs; ++i) { - const BOPDS_InterfVV& aVV = aVVs(i); - nV1 = aVV.Index1(); - nV2 = aVV.Index2(); - if(aMIF1.Contains(nV1) && aMIF2.Contains(nV2) || - aMIF1.Contains(nV2) && aMIF2.Contains(nV1)) { - if (aVV.HasIndexNew()) { - nVNew = aVV.IndexNew(); - aMVStick.Add(nVNew); - } - } - } - //collect VE interferences - for(i = 0; i < aNbVEs; ++i) { - const BOPDS_InterfVE& aVE = aVEs(i); - nV = aVE.Index1(); - nE = aVE.Index2(); - if(aMIF1.Contains(nV) && aMIF2.Contains(nE) || - aMIF1.Contains(nE) && aMIF2.Contains(nV)) { - aMVStick.Add(nV); - } - } - //collect EE interferences - for(i = 0; i < aNbEEs; ++i) { - const BOPDS_InterfEE& aEE = aEEs(i); - nE1 = aEE.Index1(); - nE2 = aEE.Index2(); - if(aMIF1.Contains(nE1) && aMIF2.Contains(nE2) || - aMIF1.Contains(nE2) && aMIF2.Contains(nE1)) { - IntTools_CommonPrt aCP = aEE.CommonPart(); - if(aCP.Type() == TopAbs_VERTEX) { - nVNew = aEE.IndexNew(); - aMVStick.Add(nVNew); + Standard_Integer aNbLines[5] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), + aVFs.Extent(), aEFs.Extent()}; + //collect indices of all shapes from nF1 and nF2. + aMI.Clear(); + GetFullShapeMap(nF1, aMI); + GetFullShapeMap(nF2, aMI); + // + //collect VV, VE, EE, VF interferences + for (aTypeInt = 0; aTypeInt < 4; ++aTypeInt) { + for (i = 0; i < aNbLines[aTypeInt]; ++i) { + BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) : + ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) : + ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) : (BOPDS_Interf*)(&aVFs(i)))); + if (aInt->HasIndexNew()) { + aInt->Indices(nS1, nS2); + if(aMI.Contains(nS1) && aMI.Contains(nS2)) { + nVNew = aInt->IndexNew(); + aMVStick.Add(nVNew); + } } } } - //collect VF interferences - for(i = 0; i < aNbVFs; ++i) { - const BOPDS_InterfVF& aVF = aVFs(i); - nV = aVF.Index1(); - nF = aVF.Index2(); - if(aMIF1.Contains(nV) && aMIF2.Contains(nF) || - aMIF1.Contains(nF) && aMIF2.Contains(nV)) { - aMVStick.Add(nV); - } - } //collect EF interferences - for(i = 0; i < aNbEFs; ++i) { - const BOPDS_InterfEF& aEF = aEFs(i); - nE = aEF.Index1(); - nF = aEF.Index2(); - if(aMIF1.Contains(nE) && aMIF2.Contains(nF) || - aMIF1.Contains(nF) && aMIF2.Contains(nE)) { - IntTools_CommonPrt aCP = aEF.CommonPart(); - if(aCP.Type() == TopAbs_VERTEX) { - nVNew = aEF.IndexNew(); + for (i = 0; i < aNbLines[4]; ++i) { + const BOPDS_InterfEF& aInt = aEFs(i); + if (aInt.HasIndexNew()) { + aInt.Indices(nS1, nS2); + if(aMI.Contains(nS1) && aMI.Contains(nS2)) { + nVNew = aInt.IndexNew(); aMVStick.Add(nVNew); aMVEF.Add(nVNew); } @@ -1525,34 +1479,25 @@ static void ToleranceFF(const TopoDS_Face& aF1, } //======================================================================= -// function: GetFullFaceMap +// function: GetFullShapeMap // purpose: //======================================================================= -void BOPAlgo_PaveFiller::GetFullFaceMap(const Standard_Integer nF, - BOPCol_MapOfInteger& aMI) +void BOPAlgo_PaveFiller::GetFullShapeMap(const Standard_Integer nF, + BOPCol_MapOfInteger& aMI) { - Standard_Integer nV, nE; - TopoDS_Edge aE; - TopoDS_Vertex aV; - //face + BOPCol_ListIteratorOfListOfInteger aIt; + Standard_Integer nS; + // + const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF); + const BOPCol_ListOfInteger& aLI = aSI.SubShapes(); + // aMI.Add(nF); - //edges - const TopoDS_Face& aF = (*(TopoDS_Face*)(&myDS->Shape(nF))); - TopExp_Explorer anExp(aF, TopAbs_EDGE); - for (; anExp.More(); anExp.Next()) { - aE = (*(TopoDS_Edge *)(&anExp.Current())); - nE = myDS->Index(aE); - aMI.Add(nE); - } - //vertices - TopExp_Explorer anExpV(aF, TopAbs_VERTEX); - for (; anExpV.More(); anExpV.Next()) { - aV = (*(TopoDS_Vertex *)(&anExpV.Current())); - nV = myDS->Index(aV); - aMI.Add(nV); + aIt.Initialize(aLI); + for (; aIt.More(); aIt.Next()) { + nS = aIt.Value(); + aMI.Add(nS); } } - //======================================================================= // function: RemoveUsedVertices // purpose: @@ -1583,17 +1528,26 @@ void BOPAlgo_PaveFiller::RemoveUsedVertices(BOPDS_Curve& aNC, //======================================================================= void BOPAlgo_PaveFiller::PutPaveOnCurve(const Standard_Integer nV, const Standard_Real aTolR3D, - const BOPDS_Curve& aNC, - Handle(BOPDS_PaveBlock)& aPB) + BOPDS_Curve& aNC, + const BOPCol_MapOfInteger& aMI, + const Standard_Integer iCheckExtend) { Standard_Boolean bIsVertexOnLine; - Standard_Real aT; + Standard_Real aT, aTol, aTolNew; BOPDS_Pave aPave; // const TopoDS_Vertex aV = (*(TopoDS_Vertex *)(&myDS->Shape(nV))); + Handle(BOPDS_PaveBlock)& aPB=aNC.ChangePaveBlock1(); const IntTools_Curve& aIC = aNC.Curve(); // bIsVertexOnLine=myContext->IsVertexOnLine(aV, aIC, aTolR3D, aT); + if (!bIsVertexOnLine && iCheckExtend) { + aTol = BRep_Tool::Tolerance(aV); + // + ExtendedTolerance(nV, aMI, aTol, iCheckExtend); + bIsVertexOnLine=myContext->IsVertexOnLine(aV, aTol, aIC, aTolR3D, aT); + } + // if (bIsVertexOnLine) { aPave.SetIndex(nV); aPave.SetParameter(aT); @@ -1905,6 +1859,73 @@ void BOPAlgo_PaveFiller::RemoveUsedVertices(BOPDS_Curve& aNC, aMVI.Bind(aV2, nV2); } +//======================================================================= +//function : UpdatePaveBlocks +//purpose : +//======================================================================= +void BOPAlgo_PaveFiller::UpdatePaveBlocks(const BOPCol_DataMapOfIntegerInteger& aDMI) +{ + if (aDMI.IsEmpty()) { + return; + } + // + Standard_Integer nSp, aNbPBP, nV[2], i, j; + Standard_Real aT[2]; + Standard_Boolean bCB, bRebuild; + BOPDS_ListIteratorOfListOfPaveBlock aItPB; + BOPDS_MapOfPaveBlock aMPB; + // + BOPDS_VectorOfListOfPaveBlock& aPBP=myDS->ChangePaveBlocksPool(); + aNbPBP = aPBP.Extent(); + for (i=0; iCommonBlock(); + bCB = !aCB.IsNull(); + if (bCB) { + aPB=aCB->PaveBlock1(); + } + // + if (aMPB.Add(aPB)) { + bRebuild = Standard_False; + aPB->Indices(nV[0], nV[1]); + aPB->Range(aT[0], aT[1]); + // + for (j = 0; j < 2; ++j) { + if (aDMI.IsBound(nV[j])) { + BOPDS_Pave aPave; + // + nV[j] = aDMI.Find(nV[j]); + aPave.SetIndex(nV[j]); + aPave.SetParameter(aT[j]); + // + bRebuild = Standard_True; + if (!j) { + aPB->SetPave1(aPave); + } else { + aPB->SetPave2(aPave); + } + } + } + // + if (bRebuild) { + nSp = SplitEdge(aPB->Edge(), nV[0], aT[0], nV[1], aT[1]); + if (bCB) { + aCB->SetEdge(nSp); + } + else { + aPB->SetEdge(nSp); + } + }// if (bRebuild) { + }// if (aMPB.Add(aPB)) { + }// for (; aItPB.More(); aItPB.Next()) { + }// for (i=0; iOriginalEdge(); + aPB->Indices(nV1, nV2); + aPB->Range(aT1, aT2); // - const BOPDS_Pave& aPave1=aPB->Pave1(); - aPave1.Contents(nV1, aT1); - // - const BOPDS_Pave& aPave2=aPB->Pave2(); - aPave2.Contents(nV2, aT2); - // - aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); - aE.Orientation(TopAbs_FORWARD); - // - aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1))); - aV1.Orientation(TopAbs_FORWARD); - // - aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2))); - aV2.Orientation(TopAbs_REVERSED); - // - BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp); - // - aSI.SetShape(aSp); - // - Bnd_Box& aBox=aSI.ChangeBox(); - BRepBndLib::Add(aSp, aBox); - // - nSp=myDS->Append(aSI); + nSp = SplitEdge(nE, nV1, aT1, nV2, aT2); // if (bCB) { aCB->SetEdge(nSp); @@ -169,6 +143,43 @@ static void UpdateVertices(const TopoDS_Edge& aE, aAllocator.Nullify(); } +//======================================================================= +// function: SplitEdge +// purpose: +//======================================================================= +Standard_Integer BOPAlgo_PaveFiller::SplitEdge(const Standard_Integer nE, + const Standard_Integer nV1, + const Standard_Real aT1, + const Standard_Integer nV2, + const Standard_Real aT2) +{ + Standard_Integer nSp; + TopoDS_Vertex aV1, aV2; + TopoDS_Edge aE, aSp; + BOPDS_ShapeInfo aSI; + // + aSI.SetShapeType(TopAbs_EDGE); + // + aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); + aE.Orientation(TopAbs_FORWARD); + // + aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1))); + aV1.Orientation(TopAbs_FORWARD); + // + aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2))); + aV2.Orientation(TopAbs_REVERSED); + // + BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp); + // + aSI.SetShape(aSp); + // + Bnd_Box& aBox=aSI.ChangeBox(); + BRepBndLib::Add(aSp, aBox); + // + nSp=myDS->Append(aSI); + return nSp; +} + //======================================================================= // function: MakePCurves // purpose: diff --git a/src/BRepFill/BRepFill.cdl b/src/BRepFill/BRepFill.cdl index c7268f422c..7202152007 100755 --- a/src/BRepFill/BRepFill.cdl +++ b/src/BRepFill/BRepFill.cdl @@ -72,6 +72,9 @@ is enumeration TransitionStyle is Modified, Right, Round end; + enumeration TypeOfContact + is NoContact, Contact, ContactOnBorder end; + -- private class FilledPair; ---Purpose: A pair of bound shapes with the result. diff --git a/src/BRepFill/BRepFill_PipeShell.cdl b/src/BRepFill/BRepFill_PipeShell.cdl index 50018107ed..1056d60edf 100755 --- a/src/BRepFill/BRepFill_PipeShell.cdl +++ b/src/BRepFill/BRepFill_PipeShell.cdl @@ -41,8 +41,8 @@ uses Section from BRepFill, Sweep from BRepFill, DataMapOfShapeListOfShape from TopTools, - SequenceOfSection from BRepFill - + SequenceOfSection from BRepFill, + TypeOfContact from BRepFill raises DomainError from Standard, @@ -96,7 +96,7 @@ is Set(me : mutable; AuxiliarySpine : Wire from TopoDS; CurvilinearEquivalence : Boolean = Standard_True; - KeepContact : Boolean = Standard_False ); + KeepContact : TypeOfContact from BRepFill = BRepFill_NoContact ); ---Purpose: Set an auxiliary spine to define the Normal -- For each Point of the Spine P, an Point Q is evalued @@ -269,7 +269,7 @@ is param : out Real from Standard) is private; ResetLoc(me : mutable) is private; - + BuildHistory(me: mutable; theSweep: Sweep from BRepFill) is private; @@ -289,6 +289,7 @@ fields myForceApproxC1 : Boolean; myLaw : Function from Law; + myIsAutomaticLaw : Boolean from Standard; myLocation : LocationLaw from BRepFill; mySection : SectionLaw from BRepFill; myFaces : HArray2OfShape from TopTools; diff --git a/src/BRepFill/BRepFill_PipeShell.cxx b/src/BRepFill/BRepFill_PipeShell.cxx index e6aadaf7b7..5a3a893107 100755 --- a/src/BRepFill/BRepFill_PipeShell.cxx +++ b/src/BRepFill/BRepFill_PipeShell.cxx @@ -75,6 +75,14 @@ #include +#include +#include +#include +#include +#include +#include +#include + #ifdef DRAW #include #include @@ -210,10 +218,11 @@ static Standard_Boolean IsSameOriented(const TopoDS_Shape& aFace, //======================================================================= BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) : mySpine(Spine), - myTrihedron(GeomFill_IsCorrectedFrenet), - myTransition(BRepFill_Modified), myForceApproxC1(Standard_False), - myStatus(GeomFill_PipeOk) + myTrihedron(GeomFill_IsCorrectedFrenet), + myTransition(BRepFill_Modified), + myIsAutomaticLaw(Standard_False), + myStatus(GeomFill_PipeOk) { myLocation.Nullify(); mySection.Nullify(); @@ -325,7 +334,7 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) //======================================================================= void BRepFill_PipeShell::Set(const TopoDS_Wire& AuxiliarySpine, const Standard_Boolean CurvilinearEquivalence, - const Standard_Boolean KeepContact) + const BRepFill_TypeOfContact KeepContact) { // Reorganization of the guide (pb of orientation and origin) TopoDS_Wire TheGuide; @@ -333,6 +342,9 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) Standard_Boolean SpClose = mySpine.Closed(), GuideClose = AuxiliarySpine.Closed(); + if (KeepContact == BRepFill_ContactOnBorder) + myIsAutomaticLaw = Standard_True; + if (!SpClose && !GuideClose) { // Case open reorientation of the guide TopoDS_Wire sp = mySpine; @@ -377,7 +389,8 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) Guide->ChangeCurve().SetPeriodic(Standard_True); if (CurvilinearEquivalence) { // trihedron by curvilinear reduced abscissa - if (KeepContact) + if (KeepContact == BRepFill_Contact || + KeepContact == BRepFill_ContactOnBorder) myTrihedron = GeomFill_IsGuideACWithContact; // with rotation else myTrihedron = GeomFill_IsGuideAC; // without rotation @@ -389,7 +402,8 @@ BRepFill_PipeShell::BRepFill_PipeShell(const TopoDS_Wire& Spine) myLocation = new (BRepFill_ACRLaw) (mySpine, Loc); } else {// trihedron by plane - if (KeepContact) + if (KeepContact == BRepFill_Contact || + KeepContact == BRepFill_ContactOnBorder) myTrihedron = GeomFill_IsGuidePlanWithContact; // with rotation else myTrihedron = GeomFill_IsGuidePlan; // without rotation @@ -438,10 +452,74 @@ void BRepFill_PipeShell::SetForceApproxC1(const Standard_Boolean ForceApproxC1) const Standard_Boolean WithCorrection) { Delete(Profile); // No duplication - BRepFill_Section S (Profile, Location, WithContact, WithCorrection); - mySeq.Append(S); - mySection.Nullify(); - ResetLoc(); + if (myIsAutomaticLaw) + { + mySeq.Clear(); + BRepFill_Section S (Profile, Location, WithContact, WithCorrection); + S.Set(Standard_True); + mySeq.Append(S); + mySection.Nullify(); + ResetLoc(); + + Handle(GeomFill_LocationGuide) Loc = Handle(GeomFill_LocationGuide)::DownCast(myLocation->Law(1)); + Handle(TColgp_HArray1OfPnt2d) ParAndRad; + GeomFill_PipeError theStatus = Loc->ComputeAutomaticLaw(ParAndRad); + + //Compuite initial width of section (this will be 1.) + GProp_GProps GlobalProps; + BRepGProp::LinearProperties(Profile, GlobalProps); + gp_Pnt BaryCenter = GlobalProps.CentreOfMass(); + + TopoDS_Face ProfileFace = BRepLib_MakeFace(TopoDS::Wire(Profile), Standard_True); //only plane + Handle(Geom_Surface) thePlane = BRep_Tool::Surface(ProfileFace); + Handle(GeomAdaptor_HSurface) GAHplane = new GeomAdaptor_HSurface(thePlane); + IntCurveSurface_HInter Intersector; + Handle(Adaptor3d_HCurve) aHCurve [2]; + aHCurve[0] = Loc->GetCurve(); + aHCurve[1] = Loc->Guide(); + gp_Pnt PointsOnSpines [2]; + Standard_Integer i, j; + + for (i = 0; i < 2; i++) + { + Intersector.Perform(aHCurve[i], GAHplane); + Standard_Real MinDist = RealLast(); + for (j = 1; j <= Intersector.NbPoints(); j++) + { + gp_Pnt aPint = Intersector.Point(j).Pnt(); + Standard_Real aDist = BaryCenter.Distance(aPint); + if (aDist < MinDist) + { + MinDist = aDist; + PointsOnSpines[i] = aPint; + } + } + } + + //Correct according to + Standard_Real InitialWidth = PointsOnSpines[0].Distance(PointsOnSpines[1]); + Standard_Integer NbParRad = ParAndRad->Upper(); + for (i = 1; i <= NbParRad; i++) + { + gp_Pnt2d aParRad = ParAndRad->Value(i); + aParRad.SetY( aParRad.Y() / InitialWidth ); + ParAndRad->SetValue(i, aParRad); + } + + myLaw = new Law_Interpol(); + + Standard_Boolean IsPeriodic = + (Abs(ParAndRad->Value(1).Y() - ParAndRad->Value(NbParRad).Y()) < Precision::Confusion()); + + (Handle(Law_Interpol)::DownCast(myLaw))->Set(ParAndRad->Array1(), IsPeriodic); + } + else + { + BRepFill_Section S (Profile, Location, WithContact, WithCorrection); + mySeq.Append(S); + mySection.Nullify(); + ResetLoc(); + } } //======================================================================= diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl index d53613f48c..2ec58d85de 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cdl @@ -53,7 +53,8 @@ uses Vertex from TopoDS, TransitionMode from BRepBuilderAPI, PipeError from BRepBuilderAPI, - PipeShell from BRepFill + PipeShell from BRepFill, + TypeOfContact from BRepFill raises DomainError from Standard, @@ -98,7 +99,7 @@ is SetMode(me : in out; AuxiliarySpine : Wire from TopoDS; CurvilinearEquivalence : Boolean; - KeepContact : Boolean = Standard_False ); + KeepContact : TypeOfContact from BRepFill = BRepFill_NoContact ); ---Purpose: Sets an auxiliary spine to define the Normal -- For each Point of the Spine P, an Point Q is evalued @@ -332,6 +333,7 @@ is is redefined; fields + myPipe : PipeShell from BRepFill; end MakePipeShell; diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx index 551488cde0..3c7edeb7a3 100755 --- a/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_MakePipeShell.cxx @@ -90,8 +90,8 @@ BRepOffsetAPI_MakePipeShell::BRepOffsetAPI_MakePipeShell(const TopoDS_Wire& Spin //purpose : //======================================================================= void BRepOffsetAPI_MakePipeShell::SetMode(const TopoDS_Wire& AuxiliarySpine, - const Standard_Boolean CurvilinearEquivalence, - const Standard_Boolean KeepContact) + const Standard_Boolean CurvilinearEquivalence, + const BRepFill_TypeOfContact KeepContact) { myPipe->Set(AuxiliarySpine, CurvilinearEquivalence, KeepContact); } diff --git a/src/BRepTest/BRepTest_SweepCommands.cxx b/src/BRepTest/BRepTest_SweepCommands.cxx index 0c42d08bcb..13597feb11 100755 --- a/src/BRepTest/BRepTest_SweepCommands.cxx +++ b/src/BRepTest/BRepTest_SweepCommands.cxx @@ -65,6 +65,7 @@ static BRepOffsetAPI_MakePipeShell* Sweep= 0; #include #include + //======================================================================= // prism //======================================================================= @@ -464,7 +465,7 @@ static Standard_Integer setsweep(Draw_Interpretor& di, di << " Surf have to be a shell or a face" <<"\n"; di << " -CN dx dy dz : BiNormal is given by dx dy dz" << "\n"; di << " -FX Tx Ty TZ [Nx Ny Nz] : Tangent and Normal are fixed" <<"\n"; - di << " -G guide 0|1(ACR|Plan) 0|1(contact|no contact) : with guide"<<"\n"; + di << " -G guide 0|1(Plan|ACR) 0|1|2(no contact|contact|contact on border) : with guide"<<"\n"; return 0; } @@ -534,7 +535,11 @@ static Standard_Integer setsweep(Draw_Interpretor& di, else { TopoDS_Shape Guide = DBRep::Get(a[2],TopAbs_WIRE); - Sweep->SetMode(TopoDS::Wire(Guide), Draw::Atoi(a[3]), Draw::Atoi(a[4])); + Standard_Integer CurvilinearEquivalence = Draw::Atoi(a[3]); + Standard_Integer KeepContact = Draw::Atoi(a[4]); + Sweep->SetMode(TopoDS::Wire(Guide), + CurvilinearEquivalence, + (BRepFill_TypeOfContact)KeepContact); } } @@ -623,9 +628,9 @@ static Standard_Integer addsweep(Draw_Interpretor& di, Standard_Integer ii, L= nbreal/2; TColgp_Array1OfPnt2d ParAndRad(1, L); for (ii=1; ii<=L; ii++, cur+=2) { - ParAndRad(ii).SetX(Draw::Atof(a[cur])); - ParAndRad(ii).SetY(Draw::Atof(a[cur+1])); - } + ParAndRad(ii).SetX(Draw::Atof(a[cur])); + ParAndRad(ii).SetY(Draw::Atof(a[cur+1])); + } thelaw = new (Law_Interpol) (); thelaw->Set(ParAndRad, Abs(ParAndRad(1).Y() - ParAndRad(L).Y()) < Precision::Confusion()); @@ -808,7 +813,7 @@ static Standard_Integer simulsweep(Draw_Interpretor& di, //======================================================================= // middlepath //======================================================================= -static Standard_Integer middlepath(Draw_Interpretor& di, +static Standard_Integer middlepath(Draw_Interpretor& /*di*/, Standard_Integer n, const char** a) { if (n < 5) return 1; diff --git a/src/DrawResources/DrawPlugin b/src/DrawResources/DrawPlugin index 2660d47d4a..e873fa5122 100755 --- a/src/DrawResources/DrawPlugin +++ b/src/DrawResources/DrawPlugin @@ -37,8 +37,10 @@ DATAEXCHANGEKERNEL : XSDRAW 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 @@ -48,3 +50,5 @@ XDEDRAW : TKXDEDRAW TOBJ : TKTObjDRAW DFBROWSER : TKDFBrowser QAcommands : TKQADraw +TestHelix : TKHelix +TestUnfolding : TKUnfoldingTest \ No newline at end of file diff --git a/src/GeomFill/GeomFill_GuideTrihedronAC.cxx b/src/GeomFill/GeomFill_GuideTrihedronAC.cxx index a18f88bb8d..7a4c61a60d 100755 --- a/src/GeomFill/GeomFill_GuideTrihedronAC.cxx +++ b/src/GeomFill/GeomFill_GuideTrihedronAC.cxx @@ -80,6 +80,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur gp_Vec To, B; myTrimmed->D1(Param, P, To);//point et derivee au parametre Param sur myCurve myTrimG->D0(tG, PG);// point au parametre tG sur myGuide + myCurPointOnGuide = PG; gp_Vec n (P, PG); // vecteur definissant la normale @@ -118,6 +119,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur myTrimmed->D2(Param, P, To, DTo); myTrimG->D1(tG, PG, TG); + myCurPointOnGuide = PG; gp_Vec n (P, PG), dn; Standard_Real Norm = n.Magnitude(); @@ -188,6 +190,7 @@ GeomFill_GuideTrihedronAC::GeomFill_GuideTrihedronAC(const Handle(Adaptor3d_HCur myTrimmed->D3(Param, P, To, DTo, D2To); myTrimG->D2(tG, PG, TG, DTG); + myCurPointOnGuide = PG; Standard_Real NTo = To.Magnitude(); Standard_Real N2To = To.SquareMagnitude(); @@ -394,7 +397,7 @@ void GeomFill_GuideTrihedronAC::SetInterval(const Standard_Real First, ABiNormal.SetCoord(0.,0.,0.); gp_Vec T, N, B; - for (ii=1, T; ii<=20; ii++) { + for (ii=1; ii<=20; ii++) { t = myCurve->FirstParameter() +(ii-1)*Delta; D0(t, T, N, B); ATangent +=T; diff --git a/src/GeomFill/GeomFill_LocationGuide.cdl b/src/GeomFill/GeomFill_LocationGuide.cdl index dd4386a8cc..e87c3afabb 100755 --- a/src/GeomFill/GeomFill_LocationGuide.cdl +++ b/src/GeomFill/GeomFill_LocationGuide.cdl @@ -278,6 +278,8 @@ is Param2 : Real) is static; + ComputeAutomaticLaw(me; ParAndRad : out HArray1OfPnt2d from TColgp) + returns PipeError from GeomFill; fields myLaw : TrihedronWithGuide from GeomFill; -- loi de triedre diff --git a/src/GeomFill/GeomFill_LocationGuide.cxx b/src/GeomFill/GeomFill_LocationGuide.cxx index 2a548c6806..fa0f40e794 100755 --- a/src/GeomFill/GeomFill_LocationGuide.cxx +++ b/src/GeomFill/GeomFill_LocationGuide.cxx @@ -44,7 +44,6 @@ #include #include -#include #include #include #include @@ -62,6 +61,9 @@ #include #include +#include +#include + #if DRAW static Standard_Integer Affich = 0; #include @@ -228,13 +230,12 @@ static void InGoodPeriod(const Standard_Real Prec, Standard_Integer ii, Deg; Standard_Boolean isconst, israt=Standard_False; Standard_Real t, v,w, OldAngle=0, Angle, DeltaG, DeltaU, Diff; - Standard_Real CurAngle = PrecAngle, a1, a2; + Standard_Real CurAngle = PrecAngle, a1/*, a2*/; gp_Pnt2d p1,p2; Handle(Geom_SurfaceOfRevolution) Revol; // surface de revolution Handle(GeomAdaptor_HSurface) Pl; // = Revol Handle(Geom_TrimmedCurve) S; IntCurveSurface_IntersectionPoint PInt; // intersection guide/Revol - IntCurveSurface_HInter Int; Handle(TColStd_HArray1OfInteger) Mult; Handle(TColStd_HArray1OfReal) Knots, Weights; Handle(TColgp_HArray1OfPnt) Poles; @@ -338,13 +339,18 @@ static void InGoodPeriod(const Standard_Real Prec, (Handle(Geom_Curve)::DownCast(mySection->Copy()), Uf, Ul); } S->Transform(Transfo); - + // Surface de revolution Revol = new(Geom_SurfaceOfRevolution) (S, Ax); - Pl = new (GeomAdaptor_HSurface)(Revol); - Int.Perform(myGuide, Pl); // intersection surf. revol / guide - if (Int.NbPoints() == 0) { + GeomAdaptor_Surface GArevol(Revol); + Extrema_ExtCS DistMini(myGuide->Curve(), GArevol, + Precision::Confusion(), Precision::Confusion()); + Extrema_POnCurv Pc; + Extrema_POnSurf Ps; + Standard_Real theU, theV; + + if (!DistMini.IsDone() || DistMini.NbExt() == 0) { #if DEB cout <<"LocationGuide : Pas d'intersection"<1) { Diff = w - myPoles2d->Value(1, ii-1).Y(); if (Abs(Diff) > DeltaG) { @@ -419,7 +435,8 @@ static void InGoodPeriod(const Standard_Real Prec, #endif } //Recadrage de l'angle. - Angle = PInt.U(); + Angle = theU; + if (ii > 1) { Diff = Angle - OldAngle; if (Abs(Diff) > M_PI) { @@ -435,7 +452,8 @@ static void InGoodPeriod(const Standard_Real Prec, //Recadrage du V - v = PInt.V(); + v = theV; + if (ii > 1) { if (uperiodic) { InGoodPeriod (myPoles2d->Value(2, ii-1).Y(), UPeriod, v); @@ -1442,3 +1460,40 @@ void GeomFill_LocationGuide::SetOrigine(const Standard_Real Param1, OrigParam2 = Param2; } +//================================================================== +//Function : ComputeAutomaticLaw +//Purpose : +//================================================================== +GeomFill_PipeError GeomFill_LocationGuide::ComputeAutomaticLaw(Handle(TColgp_HArray1OfPnt2d)& ParAndRad) const +{ + gp_Pnt P; + gp_Vec T,N,B; + Standard_Integer ii; + Standard_Real t; + + GeomFill_PipeError theStatus = GeomFill_PipeOk; + + Standard_Real f = myCurve->FirstParameter(); + Standard_Real l = myCurve->LastParameter(); + + ParAndRad = new TColgp_HArray1OfPnt2d(1, myNbPts); + for (ii = 1; ii <= myNbPts; ii++) + { + t = Standard_Real(myNbPts - ii)*f + Standard_Real(ii - 1)*l; + t /= (myNbPts-1); + myCurve->D0(t, P); + Standard_Boolean Ok = myLaw->D0(t, T, N, B); + if (!Ok) + { + theStatus = myLaw->ErrorStatus(); + return theStatus; + } + gp_Pnt PointOnGuide = myLaw->CurrentPointOnGuide(); + Standard_Real CurWidth = P.Distance(PointOnGuide); + + gp_Pnt2d aParamWithRadius(t, CurWidth); + ParAndRad->SetValue(ii, aParamWithRadius); + } + + return theStatus; +} diff --git a/src/GeomFill/GeomFill_TrihedronWithGuide.cdl b/src/GeomFill/GeomFill_TrihedronWithGuide.cdl index 42315f9239..6b8d20d2dd 100755 --- a/src/GeomFill/GeomFill_TrihedronWithGuide.cdl +++ b/src/GeomFill/GeomFill_TrihedronWithGuide.cdl @@ -29,7 +29,8 @@ inherits TrihedronLaw from GeomFill uses HCurve from Adaptor3d, - Real from Standard + Real from Standard, + Pnt from gp raises OutOfRange, NotImplemented @@ -45,9 +46,15 @@ is Param2 : Real) is deferred; + CurrentPointOnGuide(me) + ---Purpose: Returns the current point on guide + -- found by D0, D1 or D2. + returns Pnt from gp; + fields myGuide : HCurve from Adaptor3d is protected; myTrimG : HCurve from Adaptor3d is protected; + myCurPointOnGuide : Pnt from gp is protected; end TrihedronWithGuide; diff --git a/src/GeomFill/GeomFill_TrihedronWithGuide.cxx b/src/GeomFill/GeomFill_TrihedronWithGuide.cxx index 12deaf14b2..74b36f72fb 100755 --- a/src/GeomFill/GeomFill_TrihedronWithGuide.cxx +++ b/src/GeomFill/GeomFill_TrihedronWithGuide.cxx @@ -28,4 +28,12 @@ Handle(Adaptor3d_HCurve) GeomFill_TrihedronWithGuide::Guide()const return myGuide; } +//======================================================================= +//function : CurrentPointOnGuide +//purpose : +//======================================================================= +gp_Pnt GeomFill_TrihedronWithGuide::CurrentPointOnGuide() const +{ + return myCurPointOnGuide; +} diff --git a/src/HLRBRep/HLRBRep.cxx b/src/HLRBRep/HLRBRep.cxx index e84a9668e2..e307c64201 100755 --- a/src/HLRBRep/HLRBRep.cxx +++ b/src/HLRBRep/HLRBRep.cxx @@ -18,12 +18,12 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - #include #include #include #include #include +#include #include #include #include @@ -93,6 +93,8 @@ TopoDS_Edge HLRBRep::MakeEdge (const HLRBRep_Curve& ec, TopoDS_Edge anEdge = ec.GetCurve().Edge(); Standard_Real fpar, lpar; Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar); + if (aCurve->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve)) + aCurve = (Handle(Geom_TrimmedCurve)::DownCast(aCurve))->BasisCurve(); const Handle(Geom_BSplineCurve)& BSplCurve = Handle(Geom_BSplineCurve)::DownCast(aCurve); Handle(Geom_BSplineCurve) theCurve = Handle(Geom_BSplineCurve)::DownCast(BSplCurve->Copy()); if (theCurve->IsPeriodic() && !GAcurve.IsClosed()) diff --git a/src/HLRBRep/HLRBRep_Curve.cxx b/src/HLRBRep/HLRBRep_Curve.cxx index 3cba5e81c0..37472de798 100755 --- a/src/HLRBRep/HLRBRep_Curve.cxx +++ b/src/HLRBRep/HLRBRep_Curve.cxx @@ -18,7 +18,6 @@ // purpose or non-infringement. Please see the License for the specific terms // and conditions governing the rights and limitations under the License. - #include #include #include @@ -101,7 +100,7 @@ HLRBRep_Curve::Parameter3d (const Standard_Real P2d) const const Standard_Real FmOZ = myOF - myOZ; return P2d * FmOZ * FmOZ / (FmOZ * (myOF * myVX + P2d * myVZ) + myOF * myOX * myVZ); } - return P2d / myVX; + return ((myVX <= gp::Resolution())? P2d : (P2d / myVX)); } else if (myType == GeomAbs_Ellipse) { diff --git a/src/HelixBRep/HelixBRep.cdl b/src/HelixBRep/HelixBRep.cdl new file mode 100644 index 0000000000..07617d0926 --- /dev/null +++ b/src/HelixBRep/HelixBRep.cdl @@ -0,0 +1,21 @@ +-- File: HelixBRep.cdl + + +package HelixBRep + + ---Purpose: + +uses + gp, + TopoDS, + GeomAbs, + TColStd, + TopTools, + HelixGeom + +is + class BuilderHelix; + + +end HelixBRep; + diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.cdl b/src/HelixBRep/HelixBRep_BuilderHelix.cdl new file mode 100644 index 0000000000..54df5d26ca --- /dev/null +++ b/src/HelixBRep/HelixBRep_BuilderHelix.cdl @@ -0,0 +1,145 @@ +-- 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; + diff --git a/src/HelixBRep/HelixBRep_BuilderHelix.cxx b/src/HelixBRep/HelixBRep_BuilderHelix.cxx new file mode 100644 index 0000000000..2c7128d5eb --- /dev/null +++ b/src/HelixBRep/HelixBRep_BuilderHelix.cxx @@ -0,0 +1,631 @@ +// File: HelixBRep_BuilderHelix.cxx + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//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; + Standard_Real aTaperAngle; + // + aTolPrec=myTolerance; + Standard_Real aTolAng = 1.e-7; + // + + if (theTaperAngle > M_PI/2. - aTolAng) { + myErrorStatus=13; // invalid TaperAngle value + return; + } + if (theHeight 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, aTaperAngle, 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); +} diff --git a/src/HelixGeom/HelixGeom.cdl b/src/HelixGeom/HelixGeom.cdl new file mode 100644 index 0000000000..62d0ac4480 --- /dev/null +++ b/src/HelixGeom/HelixGeom.cdl @@ -0,0 +1,35 @@ +-- 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; + diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl new file mode 100644 index 0000000000..b2292eedee --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cdl @@ -0,0 +1,72 @@ +-- 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; diff --git a/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx new file mode 100644 index 0000000000..925d4d6512 --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderApproxCurve.cxx @@ -0,0 +1,100 @@ +// File: HelixGeom_BuilderApproxCurve.cxx + +#include + +//======================================================================= +//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; +} diff --git a/src/HelixGeom/HelixGeom_BuilderHelix.cdl b/src/HelixGeom/HelixGeom_BuilderHelix.cdl new file mode 100644 index 0000000000..1ea1958af7 --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelix.cdl @@ -0,0 +1,38 @@ +-- 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; + diff --git a/src/HelixGeom/HelixGeom_BuilderHelix.cxx b/src/HelixGeom/HelixGeom_BuilderHelix.cxx new file mode 100644 index 0000000000..d60416b4ac --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelix.cxx @@ -0,0 +1,165 @@ +// File: HelixGeom_BuilderHelix.cxx + + +#include +#include +#include +#include +#include +#include + + +//======================================================================= +//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=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)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); + } + // +} + diff --git a/src/HelixGeom/HelixGeom_BuilderHelixCoil.cdl b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cdl new file mode 100644 index 0000000000..175dbed1da --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cdl @@ -0,0 +1,24 @@ +-- 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; + + diff --git a/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx new file mode 100644 index 0000000000..2021fc4061 --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelixCoil.cxx @@ -0,0 +1,63 @@ +// File: HelixGeom_BuilderHelixCoil.cxx + + +#include +#include +#include +#include +#include + +//======================================================================= +//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); + } +} + + + diff --git a/src/HelixGeom/HelixGeom_BuilderHelixGen.cdl b/src/HelixGeom/HelixGeom_BuilderHelixGen.cdl new file mode 100644 index 0000000000..e5f82b9941 --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelixGen.cdl @@ -0,0 +1,45 @@ +-- 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; + diff --git a/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx b/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx new file mode 100644 index 0000000000..fd0117ceda --- /dev/null +++ b/src/HelixGeom/HelixGeom_BuilderHelixGen.cxx @@ -0,0 +1,58 @@ +// File: HelixGeom_BuilderHelixGen.cxx + +#include + +//======================================================================= +//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; +} + + diff --git a/src/HelixGeom/HelixGeom_HHelixCurve.cdl b/src/HelixGeom/HelixGeom_HHelixCurve.cdl new file mode 100644 index 0000000000..7817f6ef95 --- /dev/null +++ b/src/HelixGeom/HelixGeom_HHelixCurve.cdl @@ -0,0 +1,35 @@ +-- 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 mutable HHelixCurve from HelixGeom; + + Create(aC: HelixCurve from HelixGeom) + ---Purpose: Constructor by corresponding adaptor curve + returns mutable 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 mutable HHelixCurve from HelixGeom; + +--fields + +end HHelixCurve; + + diff --git a/src/HelixGeom/HelixGeom_HHelixCurve.cxx b/src/HelixGeom/HelixGeom_HHelixCurve.cxx new file mode 100644 index 0000000000..afb2dc3530 --- /dev/null +++ b/src/HelixGeom/HelixGeom_HHelixCurve.cxx @@ -0,0 +1,39 @@ +// File: HelixGeom_HHelixCurve.cxx + +#include + +//======================================================================= +//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); +} + + diff --git a/src/HelixGeom/HelixGeom_HelixCurve.cdl b/src/HelixGeom/HelixGeom_HelixCurve.cdl new file mode 100644 index 0000000000..69c7700bb6 --- /dev/null +++ b/src/HelixGeom/HelixGeom_HelixCurve.cdl @@ -0,0 +1,140 @@ +-- 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:out; + S : Shape from GeomAbs) + ---Purpose: Gets number of intervals + returns Integer from Standard + is redefined; + + Intervals(me:out; + 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; + + diff --git a/src/HelixGeom/HelixGeom_HelixCurve.cxx b/src/HelixGeom/HelixGeom_HelixCurve.cxx new file mode 100644 index 0000000000..919db91352 --- /dev/null +++ b/src/HelixGeom/HelixGeom_HelixCurve.cxx @@ -0,0 +1,288 @@ +// File: HelixGeom_HelixCurve.cxx + +#include +#include +#include +#include +#include +#include + +//======================================================================= +//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 ) +{ + return 1; +} +//======================================================================= +//function : Intervals +//purpose : +//======================================================================= +void HelixGeom_HelixCurve::Intervals(TColStd_Array1OfReal& T, + const GeomAbs_Shape) +{ + 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); +} + + diff --git a/src/HelixGeom/HelixGeom_Tools.cdl b/src/HelixGeom/HelixGeom_Tools.cdl new file mode 100644 index 0000000000..6c0aed68fa --- /dev/null +++ b/src/HelixGeom/HelixGeom_Tools.cdl @@ -0,0 +1,42 @@ +-- 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; + + diff --git a/src/HelixGeom/HelixGeom_Tools.cxx b/src/HelixGeom/HelixGeom_Tools.cxx new file mode 100644 index 0000000000..c0d655cca2 --- /dev/null +++ b/src/HelixGeom/HelixGeom_Tools.cxx @@ -0,0 +1,168 @@ +// File: HelixGeom_Tools.cxx + + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//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; +} + diff --git a/src/HelixTest/FILES b/src/HelixTest/FILES new file mode 100644 index 0000000000..855ee4beca --- /dev/null +++ b/src/HelixTest/FILES @@ -0,0 +1,2 @@ +HelixTest.cxx +HelixTest_HelixCommands.cxx diff --git a/src/HelixTest/HelixTest.cdl b/src/HelixTest/HelixTest.cdl new file mode 100644 index 0000000000..667a8559f1 --- /dev/null +++ b/src/HelixTest/HelixTest.cdl @@ -0,0 +1,19 @@ +-- 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; + diff --git a/src/HelixTest/HelixTest.cxx b/src/HelixTest/HelixTest.cxx new file mode 100644 index 0000000000..680607a9c8 --- /dev/null +++ b/src/HelixTest/HelixTest.cxx @@ -0,0 +1,35 @@ +// File: HelixTest.cxx + +#include +#include + +//======================================================================= +//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 +DPLUGIN(HelixTest) + + diff --git a/src/HelixTest/HelixTest_HelixCommands.cxx b/src/HelixTest/HelixTest_HelixCommands.cxx new file mode 100644 index 0000000000..670e1924eb --- /dev/null +++ b/src/HelixTest/HelixTest_HelixCommands.cxx @@ -0,0 +1,559 @@ +// File: HelixTest_HelixCommands.cxx + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// +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] = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aHeights(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + bIsPitches(i) = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aHeights(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + bIsPitches(i) = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aHeights(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + bIsPitches(i) = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aNbTurns(i) = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aNbTurns(i) = 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 = 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) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aPitches(i) = atof(a[ic]); + ++ic; + } + + for(i = 1; i <= aNb; ++i) { + aNbTurns(i) = 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; +} diff --git a/src/OS/FILES b/src/OS/FILES index 5ad90edc61..7d767e7426 100755 --- a/src/OS/FILES +++ b/src/OS/FILES @@ -6,3 +6,5 @@ srcinc:::ModelingData.tcl srcinc:::Visualization.tcl srcinc:::ApplicationFramework.tcl srcinc:::DataExchange.tcl +srcinc:::Helix.tcl +srcinc:::Unfolding.tcl diff --git a/src/OS/Helix.tcl b/src/OS/Helix.tcl new file mode 100644 index 0000000000..2a48257f38 --- /dev/null +++ b/src/OS/Helix.tcl @@ -0,0 +1,36 @@ +# 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] +} diff --git a/src/OS/Modules.tcl b/src/OS/Modules.tcl index 153ee8dda9..f50d8f8798 100755 --- a/src/OS/Modules.tcl +++ b/src/OS/Modules.tcl @@ -26,6 +26,8 @@ proc OS:Modules { {plat ""} } { ApplicationFramework \ DataExchange \ Draw \ + Helix \ + Unfolding \ ] return $ret } diff --git a/src/OS/Unfolding.tcl b/src/OS/Unfolding.tcl new file mode 100644 index 0000000000..41ef7ee10f --- /dev/null +++ b/src/OS/Unfolding.tcl @@ -0,0 +1,36 @@ +# 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] +} diff --git a/src/TKHelix/EXTERNLIB b/src/TKHelix/EXTERNLIB new file mode 100644 index 0000000000..f48ab6c4bc --- /dev/null +++ b/src/TKHelix/EXTERNLIB @@ -0,0 +1,7 @@ +TKBRep +TKMath +TKernel +TKG2d +TKG3d +TKDraw +TKTopAlgo diff --git a/src/TKHelix/FILES b/src/TKHelix/FILES new file mode 100644 index 0000000000..ee6f7057f7 --- /dev/null +++ b/src/TKHelix/FILES @@ -0,0 +1 @@ +EXTERNLIB diff --git a/src/TKHelix/PACKAGES b/src/TKHelix/PACKAGES new file mode 100644 index 0000000000..2be7474caa --- /dev/null +++ b/src/TKHelix/PACKAGES @@ -0,0 +1,3 @@ +HelixGeom +HelixBRep +HelixTest diff --git a/src/TKUnfolding/EXTERNLIB b/src/TKUnfolding/EXTERNLIB new file mode 100644 index 0000000000..aede3a708b --- /dev/null +++ b/src/TKUnfolding/EXTERNLIB @@ -0,0 +1,10 @@ +TKBRep +TKMath +TKernel +TKG2d +TKG3d +TKDraw +TKTopAlgo +TKGeomAlgo +TKShHealing +TKGeomBase diff --git a/src/TKUnfolding/FILES b/src/TKUnfolding/FILES new file mode 100644 index 0000000000..ee6f7057f7 --- /dev/null +++ b/src/TKUnfolding/FILES @@ -0,0 +1 @@ +EXTERNLIB diff --git a/src/TKUnfolding/PACKAGES b/src/TKUnfolding/PACKAGES new file mode 100644 index 0000000000..66fa871b7c --- /dev/null +++ b/src/TKUnfolding/PACKAGES @@ -0,0 +1 @@ +Unfolding diff --git a/src/TKUnfoldingTest/EXTERNLIB b/src/TKUnfoldingTest/EXTERNLIB new file mode 100644 index 0000000000..683e029f62 --- /dev/null +++ b/src/TKUnfoldingTest/EXTERNLIB @@ -0,0 +1,6 @@ +TKBRep +TKMath +TKernel +TKG3d +TKDraw +TKUnfolding \ No newline at end of file diff --git a/src/TKUnfoldingTest/FILES b/src/TKUnfoldingTest/FILES new file mode 100644 index 0000000000..ee6f7057f7 --- /dev/null +++ b/src/TKUnfoldingTest/FILES @@ -0,0 +1 @@ +EXTERNLIB diff --git a/src/TKUnfoldingTest/PACKAGES b/src/TKUnfoldingTest/PACKAGES new file mode 100644 index 0000000000..1626becca8 --- /dev/null +++ b/src/TKUnfoldingTest/PACKAGES @@ -0,0 +1 @@ +UnfoldingTest diff --git a/src/Unfolding/Unfolding.cdl b/src/Unfolding/Unfolding.cdl new file mode 100644 index 0000000000..aa130b1b88 --- /dev/null +++ b/src/Unfolding/Unfolding.cdl @@ -0,0 +1,90 @@ +-- File: Unfolding.cdl +-- Created: Tue Jul 22 12:48:05 2008 +-- Author: Sergey KHROMOV +-- +---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; diff --git a/src/Unfolding/Unfolding.cxx b/src/Unfolding/Unfolding.cxx new file mode 100644 index 0000000000..2e036d705a --- /dev/null +++ b/src/Unfolding/Unfolding.cxx @@ -0,0 +1,162 @@ +// File: Unfolding.cxx +// Created: Wed Sep 17 09:16:05 2008 +// Author: Sergey KHROMOV +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//======================================================================= +//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; +} diff --git a/src/Unfolding/Unfolding.lxx b/src/Unfolding/Unfolding.lxx new file mode 100644 index 0000000000..9116d7ba8a --- /dev/null +++ b/src/Unfolding/Unfolding.lxx @@ -0,0 +1,12 @@ +// File: Unfolding.lxx +// Created: Tue Jul 22 13:12:24 2008 +// Author: Sergey KHROMOV +// + + +inline Standard_Integer Unfolding::GetMaxNbSamples() +{ + static Standard_Integer aMaxNbSamples = 1000; + + return aMaxNbSamples; +} diff --git a/src/Unfolding/Unfolding_FaceDataContainer.cdl b/src/Unfolding/Unfolding_FaceDataContainer.cdl new file mode 100644 index 0000000000..075705b7fa --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataContainer.cdl @@ -0,0 +1,89 @@ +-- File: Unfolding_FaceDataContainer.cdl +-- Created: Fri Sep 19 16:52:05 2008 +-- Author: Sergey KHROMOV +-- +---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; diff --git a/src/Unfolding/Unfolding_FaceDataContainer.cxx b/src/Unfolding/Unfolding_FaceDataContainer.cxx new file mode 100644 index 0000000000..b1d147dd30 --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataContainer.cxx @@ -0,0 +1,111 @@ +// File: Unfolding_FaceDataContainer.cxx +// Created: Tue Jul 22 13:12:24 2008 +// Author: Sergey KHROMOV +// + + +#include +#include +#include +#include +#include +#include + + +//======================================================================= +//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; +} diff --git a/src/Unfolding/Unfolding_FaceDataContainer.lxx b/src/Unfolding/Unfolding_FaceDataContainer.lxx new file mode 100644 index 0000000000..86f770251c --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataContainer.lxx @@ -0,0 +1,101 @@ +// File: Unfolding_FaceDataContainer.lxx +// Created: Tue Jul 22 13:12:24 2008 +// Author: Sergey KHROMOV +// + + +//======================================================================= +//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.; +} diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.cdl b/src/Unfolding/Unfolding_FaceDataMapHasher.cdl new file mode 100644 index 0000000000..7ee72b47f4 --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataMapHasher.cdl @@ -0,0 +1,32 @@ +-- File: Unfolding_FaceDataMapHasher.cdl +-- Created: Fri Sep 19 16:52:05 2008 +-- Author: Sergey KHROMOV +-- +---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 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; diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.cxx b/src/Unfolding/Unfolding_FaceDataMapHasher.cxx new file mode 100644 index 0000000000..8357ff58cd --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataMapHasher.cxx @@ -0,0 +1,7 @@ +// File: Unfolding_FaceDataMapHasher.cxx +// Created: Mon Sep 22 09:01:04 2008 +// Author: Sergey KHROMOV +// + + +#include diff --git a/src/Unfolding/Unfolding_FaceDataMapHasher.lxx b/src/Unfolding/Unfolding_FaceDataMapHasher.lxx new file mode 100644 index 0000000000..fd132b7892 --- /dev/null +++ b/src/Unfolding/Unfolding_FaceDataMapHasher.lxx @@ -0,0 +1,30 @@ +// File: Unfolding_FaceDataMapHasher.lxx +// Created: Mon Sep 22 08:54:51 2008 +// Author: Sergey KHROMOV +// + + +//======================================================================= +//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()); +} diff --git a/src/Unfolding/Unfolding_FunctionWithDerivative.cdl b/src/Unfolding/Unfolding_FunctionWithDerivative.cdl new file mode 100644 index 0000000000..6ca0c19bfd --- /dev/null +++ b/src/Unfolding/Unfolding_FunctionWithDerivative.cdl @@ -0,0 +1,60 @@ +-- File: Unfolding_FunctionWithDerivative.cdl +-- Created: Fri Sep 5 17:44:29 2008 +-- Author: Mikhail KLOKOV +-- +---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 of the function for the variable . + -- 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 of the function + -- for the variable . + -- 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 and the derivative of the + -- function for the variable . + -- 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; diff --git a/src/Unfolding/Unfolding_FunctionWithDerivative.cxx b/src/Unfolding/Unfolding_FunctionWithDerivative.cxx new file mode 100644 index 0000000000..fca468b391 --- /dev/null +++ b/src/Unfolding/Unfolding_FunctionWithDerivative.cxx @@ -0,0 +1,247 @@ +// File: Unfolding_FunctionWithDerivative.cxx +// Created: Fri Sep 5 17:51:58 2008 +// Author: Mikhail KLOKOV +// + + +#include + + +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; +} diff --git a/src/Unfolding/Unfolding_Point.cdl b/src/Unfolding/Unfolding_Point.cdl new file mode 100644 index 0000000000..8c62588e8e --- /dev/null +++ b/src/Unfolding/Unfolding_Point.cdl @@ -0,0 +1,82 @@ +-- File: Unfolding_Point.cdl +-- Created: Mon Jul 28 14:56:12 2008 +-- Author: Sergey KHROMOV +-- +---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; diff --git a/src/Unfolding/Unfolding_Point.cxx b/src/Unfolding/Unfolding_Point.cxx new file mode 100644 index 0000000000..d5f08731a8 --- /dev/null +++ b/src/Unfolding/Unfolding_Point.cxx @@ -0,0 +1,8 @@ +// File: Unfolding_Point.cxx +// Created: Mon Jul 28 15:27:34 2008 +// Author: Sergey KHROMOV +// + + +#include + diff --git a/src/Unfolding/Unfolding_Point.lxx b/src/Unfolding/Unfolding_Point.lxx new file mode 100644 index 0000000000..566b2a0437 --- /dev/null +++ b/src/Unfolding/Unfolding_Point.lxx @@ -0,0 +1,116 @@ +// File: Unfolding_Point.lxx +// Created: Mon Jul 28 15:18:15 2008 +// Author: Sergey KHROMOV +// + + +//======================================================================= +//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; +} diff --git a/src/Unfolding/Unfolding_Shell.cdl b/src/Unfolding/Unfolding_Shell.cdl new file mode 100644 index 0000000000..403ecf1a2d --- /dev/null +++ b/src/Unfolding/Unfolding_Shell.cdl @@ -0,0 +1,167 @@ +-- File: Unfolding_Shell.cdl +-- Created: Tue Sep 9 16:56:09 2008 +-- Author: Mikhail KLOKOV +-- +---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; diff --git a/src/Unfolding/Unfolding_Shell.cxx b/src/Unfolding/Unfolding_Shell.cxx new file mode 100644 index 0000000000..4c570e4d8d --- /dev/null +++ b/src/Unfolding/Unfolding_Shell.cxx @@ -0,0 +1,777 @@ +// File: Unfolding_Shell.cxx +// Created: Tue Sep 9 17:14:33 2008 +// Author: Mikhail KLOKOV +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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; + + while (Standard_True) { + 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; +} diff --git a/src/Unfolding/Unfolding_Shell.lxx b/src/Unfolding/Unfolding_Shell.lxx new file mode 100644 index 0000000000..5a3cc7a69e --- /dev/null +++ b/src/Unfolding/Unfolding_Shell.lxx @@ -0,0 +1,99 @@ +// File: Unfolding_Shell.lxx +// Created: Tue Sep 9 17:14:56 2008 +// Author: Mikhail KLOKOV +// + + +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(); +} diff --git a/src/Unfolding/Unfolding_Surface.cdl b/src/Unfolding/Unfolding_Surface.cdl new file mode 100644 index 0000000000..dfc5a25930 --- /dev/null +++ b/src/Unfolding/Unfolding_Surface.cdl @@ -0,0 +1,200 @@ +-- File: Unfolding_Surface.cdl +-- Created: Tue Jul 22 12:50:10 2008 +-- Author: Sergey KHROMOV +-- +---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; diff --git a/src/Unfolding/Unfolding_Surface.cxx b/src/Unfolding/Unfolding_Surface.cxx new file mode 100644 index 0000000000..2de862ab1d --- /dev/null +++ b/src/Unfolding/Unfolding_Surface.cxx @@ -0,0 +1,1543 @@ +// File: Unfolding_Surface.cxx +// Created: Tue Jul 22 13:12:24 2008 +// Author: Sergey KHROMOV +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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; + } +} diff --git a/src/Unfolding/Unfolding_Surface.lxx b/src/Unfolding/Unfolding_Surface.lxx new file mode 100644 index 0000000000..ff7ff984d4 --- /dev/null +++ b/src/Unfolding/Unfolding_Surface.lxx @@ -0,0 +1,132 @@ +// File: Unfolding_Surface.lxx +// Created: Tue Jul 22 16:13:39 2008 +// Author: Sergey KHROMOV +// + + +#include + + +//======================================================================= +//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(); +} diff --git a/src/UnfoldingTest/UnfoldingTest.cdl b/src/UnfoldingTest/UnfoldingTest.cdl new file mode 100644 index 0000000000..23d72fa827 --- /dev/null +++ b/src/UnfoldingTest/UnfoldingTest.cdl @@ -0,0 +1,24 @@ +-- File: UnfoldingTest.cdl +-- Created: Tue Jul 22 18:15:41 2008 +-- Author: Sergey KHROMOV +-- +---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; diff --git a/src/UnfoldingTest/UnfoldingTest.cxx b/src/UnfoldingTest/UnfoldingTest.cxx new file mode 100644 index 0000000000..1227afabf8 --- /dev/null +++ b/src/UnfoldingTest/UnfoldingTest.cxx @@ -0,0 +1,272 @@ +// File: UnfoldingTest.cxx +// Created: Tue Jul 22 18:35:23 2008 +// Author: Sergey KHROMOV +// + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +//======================================================================= +//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 = 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 = 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 = 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 = 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)