// Created by: Peter KURNEV
-// Copyright (c) 2010-2012 OPEN CASCADE SAS
+// Copyright (c) 2010-2014 OPEN CASCADE SAS
// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
//
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
//
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
-#include <BOPAlgo_Builder.ixx>
-#include <NCollection_IncAllocator.hxx>
-
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Face.hxx>
-#include <TopoDS_Edge.hxx>
-#include <TopoDS_Vertex.hxx>
-#include <TopoDS_Compound.hxx>
-
-#include <BRep_Tool.hxx>
-#include <BRep_Builder.hxx>
-
-#include <TopExp_Explorer.hxx>
-
-#include <BOPCol_ListOfShape.hxx>
-#include <BOPCol_ListOfInteger.hxx>
-#include <BOPCol_MapOfInteger.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_BuilderFace.hxx>
+#include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Tools.hxx>
#include <BOPCol_DataMapOfIntegerListOfShape.hxx>
#include <BOPCol_DataMapOfShapeShape.hxx>
-
-#include <BOPInt_Context.hxx>
-
-#include <BOPDS_PaveBlock.hxx>
-#include <BOPDS_ShapeInfo.hxx>
+#include <BOPCol_ListOfInteger.hxx>
+#include <BOPCol_ListOfShape.hxx>
+#include <BOPCol_MapOfInteger.hxx>
+#include <BOPCol_NCVector.hxx>
+#include <BOPCol_Parallel.hxx>
#include <BOPDS_DS.hxx>
#include <BOPDS_FaceInfo.hxx>
-#include <BOPDS_MapOfPaveBlock.hxx>
-#include <BOPDS_VectorOfInterfFF.hxx>
#include <BOPDS_Interf.hxx>
+#include <BOPDS_MapOfPaveBlock.hxx>
+#include <BOPDS_PaveBlock.hxx>
+#include <BOPDS_ShapeInfo.hxx>
#include <BOPDS_VectorOfCurve.hxx>
+#include <BOPDS_VectorOfInterfFF.hxx>
#include <BOPDS_VectorOfPoint.hxx>
-
#include <BOPTools.hxx>
#include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_AlgoTools3D.hxx>
-#include <BOPAlgo_BuilderFace.hxx>
#include <BOPTools_CoupleOfShape.hxx>
+#include <BOPTools_DataMapOfShapeSet.hxx>
#include <BOPTools_ListOfCoupleOfShape.hxx>
#include <BOPTools_MapOfSet.hxx>
-#include <BOPTools_DataMapOfShapeSet.hxx>
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+#include <GeomAdaptor_Surface.hxx>
+#include <GeomLib.hxx>
+#include <Precision.hxx>
+#include <IntTools_Context.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Vertex.hxx>
+//
static
Standard_Boolean HasPaveBlocksOnIn(const BOPDS_FaceInfo& aFI1,
const BOPDS_FaceInfo& aFI2);
+//
static
- void FillMap(const TopoDS_Shape& aS1,
- const TopoDS_Shape& aS2,
- BOPCol_IndexedDataMapOfShapeListOfShape& aDMSLS,
- Handle(NCollection_IncAllocator)& aAllocator);
-static
- void MakeBlocksCnx(const BOPCol_IndexedDataMapOfShapeListOfShape& aMILI,
- BOPCol_DataMapOfIntegerListOfShape& aMBlocks,
- Handle(NCollection_IncAllocator)& aAllocator);
+ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+ const BOPCol_DataMapOfShapeListOfShape& theImages,
+ Handle(IntTools_Context)& theCtx);
+//
+typedef BOPCol_NCVector<TopoDS_Shape> BOPAlgo_VectorOfShape;
+//
+typedef BOPCol_NCVector<BOPAlgo_VectorOfShape> \
+ BOPAlgo_VectorOfVectorOfShape;
+//
+typedef NCollection_IndexedDataMap\
+ <BOPTools_Set, Standard_Integer, BOPTools_SetMapHasher> \
+ BOPAlgo_IndexedDataMapOfSetInteger;
+//
+//=======================================================================
+//class : BOPAlgo_PairOfShapeBoolean
+//purpose :
+//=======================================================================
+class BOPAlgo_PairOfShapeBoolean : public BOPAlgo_Algo {
+
+ public:
+ DEFINE_STANDARD_ALLOC
+ BOPAlgo_PairOfShapeBoolean() :
+ BOPAlgo_Algo(),
+ myFlag(Standard_False) {
+ }
+ //
+ virtual ~BOPAlgo_PairOfShapeBoolean() {
+ }
+ //
+ TopoDS_Shape& Shape1() {
+ return myShape1;
+ }
+ //
+ TopoDS_Shape& Shape2() {
+ return myShape2;
+ }
+ //
+ Standard_Boolean& Flag() {
+ return myFlag;
+ }
+ //
+ void SetContext(const Handle(IntTools_Context)& aContext) {
+ myContext=aContext;
+ }
+ //
+ const Handle(IntTools_Context)& Context()const {
+ return myContext;
+ }
+ //
+ virtual void Perform() {
+ BOPAlgo_Algo::UserBreak();
+ //
+ const TopoDS_Face& aFj=*((TopoDS_Face*)&myShape1);
+ const TopoDS_Face& aFk=*((TopoDS_Face*)&myShape2);
+ myFlag=BOPTools_AlgoTools::AreFacesSameDomain(aFj, aFk, myContext, myFuzzyValue);
+ }
+ //
+ protected:
+ Standard_Boolean myFlag;
+ TopoDS_Shape myShape1;
+ TopoDS_Shape myShape2;
+ Handle(IntTools_Context) myContext;
+};
+//
+typedef BOPCol_NCVector<BOPAlgo_PairOfShapeBoolean> \
+ BOPAlgo_VectorOfPairOfShapeBoolean;
+//
+typedef BOPCol_ContextFunctor
+ <BOPAlgo_PairOfShapeBoolean,
+ BOPAlgo_VectorOfPairOfShapeBoolean,
+ Handle(IntTools_Context),
+ IntTools_Context> BOPCol_BuilderSDFaceFunctor;
+//
+typedef BOPCol_ContextCnt
+ <BOPCol_BuilderSDFaceFunctor,
+ BOPAlgo_VectorOfPairOfShapeBoolean,
+ Handle(IntTools_Context)> BOPAlgo_BuilderSDFaceCnt;
+//
+//=======================================================================
+// BuilderFace
+//
+typedef BOPCol_NCVector<BOPAlgo_BuilderFace> BOPAlgo_VectorOfBuilderFace;
+//
+typedef BOPCol_Functor
+ <BOPAlgo_BuilderFace,
+ BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceFunctor;
+//
+typedef BOPCol_Cnt
+ <BOPAlgo_BuilderFaceFunctor,
+ BOPAlgo_VectorOfBuilderFace> BOPAlgo_BuilderFaceCnt;
+//
+//=======================================================================
+//class : BOPAlgo_VFI
+//purpose :
+//=======================================================================
+class BOPAlgo_VFI : public BOPAlgo_Algo {
+
+ public:
+ DEFINE_STANDARD_ALLOC
+
+ BOPAlgo_VFI() :
+ BOPAlgo_Algo(),
+ myFlag(-1) {
+ }
+ //
+ virtual ~BOPAlgo_VFI(){
+ }
+ //
+ void SetVertex(const TopoDS_Vertex& aV) {
+ myV=aV;
+ }
+ //
+ TopoDS_Vertex& Vertex() {
+ return myV;
+ }
+ //
+ void SetFace(const TopoDS_Face& aF) {
+ myF=aF;
+ }
+ //
+ TopoDS_Face& Face() {
+ return myF;
+ }
+ //
+ Standard_Integer Flag()const {
+ return myFlag;
+ }
+ //
+ void SetContext(const Handle(IntTools_Context)& aContext) {
+ myContext=aContext;
+ }
+ //
+ const Handle(IntTools_Context)& Context()const {
+ return myContext;
+ }
+ //
+ virtual void Perform() {
+ Standard_Real aT1, aT2, dummy;
+ //
+ BOPAlgo_Algo::UserBreak();
+ myFlag = myContext->ComputeVF(myV, myF, aT1, aT2, dummy, myFuzzyValue);
+ }
+ //
+ protected:
+ Standard_Integer myFlag;
+ TopoDS_Vertex myV;
+ TopoDS_Face myF;
+ Handle(IntTools_Context) myContext;
+};
+//
+typedef BOPCol_NCVector<BOPAlgo_VFI> BOPAlgo_VectorOfVFI;
+//
+typedef BOPCol_ContextFunctor
+ <BOPAlgo_VFI,
+ BOPAlgo_VectorOfVFI,
+ Handle(IntTools_Context),
+ IntTools_Context> BOPAlgo_VFIFunctor;
+//
+typedef BOPCol_ContextCnt
+ <BOPAlgo_VFIFunctor,
+ BOPAlgo_VectorOfVFI,
+ Handle(IntTools_Context)> BOPAlgo_VFICnt;
+//
//=======================================================================
//function : FillImagesFaces
//purpose :
//=======================================================================
- void BOPAlgo_Builder::FillImagesFaces()
+void BOPAlgo_Builder::FillImagesFaces()
{
- myErrorStatus=0;
- //
BuildSplitFaces();
FillSameDomainFaces();
FillImagesFaces1();
//function : BuildSplitFaces
//purpose :
//=======================================================================
- void BOPAlgo_Builder::BuildSplitFaces()
+void BOPAlgo_Builder::BuildSplitFaces()
{
Standard_Boolean bHasFaceInfo, bIsClosed, bIsDegenerated, bToReverse;
- Standard_Integer i, j, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
+ Standard_Integer i, j, k, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
TopoDS_Face aFF, aFSD;
TopoDS_Edge aSp, aEE;
TopAbs_Orientation anOriF, anOriE;
BOPCol_ListIteratorOfListOfShape aIt;
BOPCol_ListOfInteger aLIAV;
BOPCol_MapOfShape aMFence;
- Handle(NCollection_IncAllocator) aAllocator;
- BOPCol_ListOfShape aLFIm(myAllocator);
- BOPCol_MapIteratorOfMapOfShape aItMS;
- //
- myErrorStatus=0;
+ Handle(NCollection_BaseAllocator) aAllocator;
+ BOPAlgo_VectorOfBuilderFace aVBF;
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope f
- aAllocator=new NCollection_IncAllocator();
+ aAllocator=
+ NCollection_BaseAllocator::CommonBaseAllocator();
//
BOPCol_ListOfShape aLE(aAllocator);
BOPCol_MapOfShape aMDE(100, aAllocator);
//
+ // Build temporary map of faces images to avoid rebuilding
+ // of the faces without any IN or section edges
+ NCollection_IndexedDataMap<Standard_Integer, BOPCol_ListOfShape> aFacesIm;
+ //
aNbS=myDS->NbSourceShapes();
+ //
for (i=0; i<aNbS; ++i) {
const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
if (aSI.ShapeType()!=TopAbs_FACE) {
}
//
const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
+ Standard_Boolean isUClosed = Standard_False,
+ isVClosed = Standard_False,
+ isChecked = Standard_False;
//
bHasFaceInfo=myDS->HasFaceInfo(i);
if(!bHasFaceInfo) {
continue;
}
//
- // aLFIm will contain images of aF
- aLFIm.Clear();
- //
const BOPDS_FaceInfo& aFI=myDS->FaceInfo(i);
//
const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
if (!aNbPBIn && !aNbPBOn && !aNbPBSc && !aNbAV) { // not compete
continue;
}
- //
+
+ if (!aNbPBIn && !aNbPBSc)
+ {
+ // No internal parts for the face, so just build the draft face
+ // and keep it to pass directly into result.
+ // If the original face has any internal edges, the draft face
+ // will be null, as the internal edges may split the face on parts
+ // (as in the case "bugs modalg_5 bug25245_1").
+ // The BuilderFace algorithm will be called in this case.
+ TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext);
+ if (!aFD.IsNull())
+ {
+ aFacesIm(aFacesIm.Add(i, BOPCol_ListOfShape())).Append(aFD);
+ continue;
+ }
+ }
+
aMFence.Clear();
//
anOriF=aF.Orientation();
aFF=aF;
aFF.Orientation(TopAbs_FORWARD);
//
-
- //
- // 1. Fill the egdes set for the face aFF -> LE
+ // 1. Fill the edges set for the face aFF -> LE
aLE.Clear();
- //
- //
+
// 1.1 Bounding edges
aExp.Init(aFF, TopAbs_EDGE);
for (; aExp.More(); aExp.Next()) {
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
anOriE=aE.Orientation();
- bIsDegenerated=BRep_Tool::Degenerated(aE);
- bIsClosed=BRep_Tool::IsClosed(aE, aF);
//
if (!myImages.IsBound(aE)) {
if (anOriE==TopAbs_INTERNAL) {
else {
aLE.Append(aE);
}
+
+ continue;
}
- else {//else 1
- const BOPCol_ListOfShape& aLIE=myImages.Find(aE);
- aIt.Initialize(aLIE);
- for (; aIt.More(); aIt.Next()) {
- aSp=(*(TopoDS_Edge*)(&aIt.Value()));
- if (bIsDegenerated) {
- aSp.Orientation(anOriE);
- aLE.Append(aSp);
- continue;
- }
+
+ if(!isChecked)
+ {
+ const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
+ GeomLib::IsClosed(aSurf, BRep_Tool::Tolerance(aE),
+ isUClosed, isVClosed);
+
+ isChecked = Standard_True;
+ }
+
+ bIsClosed = Standard_False;
+
+ if((isUClosed || isVClosed) && BRep_Tool::IsClosed(aE, aF))
+ {
+
+ Standard_Boolean isUIso = Standard_False, isVIso = Standard_False;
+ BOPTools_AlgoTools2D::IsEdgeIsoline(aE, aF, isUIso, isVIso);
+
+ bIsClosed = ((isUClosed && isUIso) || (isVClosed && isVIso));
+ }
+
+ bIsDegenerated=BRep_Tool::Degenerated(aE);
+
+ const BOPCol_ListOfShape& aLIE=myImages.Find(aE);
+ aIt.Initialize(aLIE);
+ for (; aIt.More(); aIt.Next()) {
+ aSp=(*(TopoDS_Edge*)(&aIt.Value()));
+ if (bIsDegenerated) {
+ aSp.Orientation(anOriE);
+ aLE.Append(aSp);
+ continue;
+ }
+ //
+ if (anOriE==TopAbs_INTERNAL) {
+ aSp.Orientation(TopAbs_FORWARD);
+ aLE.Append(aSp);
+ aSp.Orientation(TopAbs_REVERSED);
+ aLE.Append(aSp);
+ continue;
+ }
//
- if (anOriE==TopAbs_INTERNAL) {
+ if (bIsClosed) {
+ if (aMFence.Add(aSp)) {
+ if (!BRep_Tool::IsClosed(aSp, aF)){
+ BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
+ }
+ //
aSp.Orientation(TopAbs_FORWARD);
aLE.Append(aSp);
aSp.Orientation(TopAbs_REVERSED);
aLE.Append(aSp);
- continue;
- }
- //
- if (bIsClosed) {
- if (aMFence.Add(aSp)) {
- if (!BRep_Tool::IsClosed(aSp, aF)){
- BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aF);
- }
- //
- aSp.Orientation(TopAbs_FORWARD);
- aLE.Append(aSp);
- aSp.Orientation(TopAbs_REVERSED);
- aLE.Append(aSp);
- }// if (aMFence.Add(aSp))
- continue;
- }// if (bIsClosed){
- //
- aSp.Orientation(anOriE);
- bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
- if (bToReverse) {
- aSp.Reverse();
- }
- aLE.Append(aSp);
- }// for (; aIt.More(); aIt.Next()) {
- }// else 1
+ }// if (aMFence.Add(aSp))
+ continue;
+ }// if (bIsClosed){
+ //
+ aSp.Orientation(anOriE);
+ bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
+ if (bToReverse) {
+ aSp.Reverse();
+ }
+ aLE.Append(aSp);
+ }// for (; aIt.More(); aIt.Next()) {
}// for (; aExp.More(); aExp.Next()) {
//
//
aLE.Append(aSp);
}
//
+ if (!myPaveFiller->NonDestructive()) {
+ // speed up for planar faces
+ BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane (aLE, aFF);
+ }
// 3 Build split faces
- BOPAlgo_BuilderFace aBF(aAllocator);
- //
- aBF.SetFace(aFF);
- //aBF.SetContext(myContext);
- //
- // <-DEB ft
- //
+ BOPAlgo_BuilderFace& aBF=aVBF.Append1();
+ aBF.SetFace(aF);
aBF.SetShapes(aLE);
+ aBF.SetRunParallel(myRunParallel);
+ aBF.SetProgressIndicator(myProgressIndicator);
//
- aBF.Perform();
- //
- const BOPCol_ListOfShape& aLFR=aBF.Areas();
+ }// for (i=0; i<aNbS; ++i) {
+ //
+ //===================================================
+ BOPAlgo_BuilderFaceCnt::Perform(myRunParallel, aVBF);
+ //===================================================
+ //
+ Standard_Integer aNbBF = aVBF.Extent();
+ for (k = 0; k < aNbBF; ++k)
+ {
+ BOPAlgo_BuilderFace& aBF = aVBF(k);
+ aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
+ }
+
+ aNbBF = aFacesIm.Extent();
+ for (k = 1; k <= aNbBF; ++k)
+ {
+ const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(aFacesIm.FindKey(k)));
+ anOriF = aF.Orientation();
+ const BOPCol_ListOfShape& aLFR = aFacesIm(k);
+ //
+ BOPCol_ListOfShape* pLFIm = mySplits.Bound(aF, BOPCol_ListOfShape());
aIt.Initialize(aLFR);
for (; aIt.More(); aIt.Next()) {
TopoDS_Shape& aFR=aIt.ChangeValue();
- if (anOriF==TopAbs_REVERSED) {
+ if (anOriF==TopAbs_REVERSED)
aFR.Orientation(TopAbs_REVERSED);
- }
- //aFR.Orientation(anOriF);
- aLFIm.Append(aFR);
+ pLFIm->Append(aFR);
}
- //
- mySplits.Bind(aF, aLFIm);
- }// for (i=0; i<aNbS; ++i) {
+ }
//
- aAllocator.Nullify();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope t
}
//=======================================================================
//function : FillSameDomainFaces
//purpose :
//=======================================================================
- void BOPAlgo_Builder::FillSameDomainFaces()
+void BOPAlgo_Builder::FillSameDomainFaces()
{
Standard_Boolean bFlag;
- Standard_Integer i, aNbFFs, aNbCurves, aNbPoints, nF1, nF2, aNbS;
- Standard_Integer j;
- Handle(NCollection_IncAllocator) aAllocator;
- BOPCol_ListIteratorOfListOfShape aItF1, aItF2;
- BOPTools_ListOfCoupleOfShape aLCS;
- BOPCol_ListIteratorOfListOfShape aItLS;
- BOPCol_MapOfShape aMF;
- BOPCol_MapIteratorOfMapOfShape aItMF;
- //
- myErrorStatus=0;
+ Standard_Integer i, j, k, aNbFFs, nF1, nF2;
+ Handle(NCollection_BaseAllocator) aAllocator;
+ BOPCol_ListIteratorOfListOfShape aItF;
+ BOPCol_MapOfShape aMFence;
+ BOPAlgo_IndexedDataMapOfSetInteger aIDMSS;
+ BOPAlgo_VectorOfVectorOfShape aVVS;
//
const BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
//
if (!aNbFFs) {
return;
}
- //-----------------------------------------------------scope f
- aAllocator=new NCollection_IncAllocator();
- BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS(100, aAllocator);
- BOPCol_DataMapOfIntegerListOfShape aMBlocks(100, aAllocator);
- BOPTools_DataMapOfShapeSet aMSST(100, aAllocator);
- //
- BOPCol_ListOfShape aLFIm;
//
for (i=0; i<aNbFFs; ++i) {
const BOPDS_InterfFF& aFF=aFFs(i);
aFF.Indices(nF1, nF2);
//
- const BOPDS_VectorOfCurve& aCurves=aFF.Curves();
- aNbCurves=aCurves.Extent();
- if (aNbCurves) {
- //
- bFlag=Standard_False;
- for (j=0; j<aNbCurves; ++j) {
- const BOPDS_Curve& aNC=aCurves.Value(j);
- bFlag=aNC.HasEdge();
- if (bFlag) {
- break;
- }
- }
- if (bFlag) {
- continue;
- }
- //continue;
- }
- //
- const BOPDS_VectorOfPoint& aPoints=aFF.Points();
- aNbPoints=aPoints.Extent();
- if (aNbPoints) {
- continue;
- }
- //
if (!myDS->HasFaceInfo(nF1) || !myDS->HasFaceInfo(nF2) ) {
continue;
}
//
const BOPDS_FaceInfo& aFI1=myDS->FaceInfo(nF1);
const BOPDS_FaceInfo& aFI2=myDS->FaceInfo(nF2);
- bFlag=HasPaveBlocksOnIn(aFI1, aFI2);
//
- const TopoDS_Face& aF1=(*(TopoDS_Face*)(&myDS->Shape(nF1)));
- const TopoDS_Face& aF2=(*(TopoDS_Face*)(&myDS->Shape(nF2)));
+ const TopoDS_Shape& aF1=myDS->Shape(nF1);
+ const TopoDS_Shape& aF2=myDS->Shape(nF2);
+ //
+ bFlag=HasPaveBlocksOnIn(aFI1, aFI2);
bFlag=bFlag && (mySplits.IsBound(aF1) && mySplits.IsBound(aF2));
//
- if (!bFlag) {
- //case when the faces have shared bounds
- if (!aMSST.IsBound(aF1)) {
- BOPTools_Set aST1(aAllocator);
- aMSST.Bind(aF1, aST1);
- BOPTools_Set& aST=aMSST.ChangeFind(aF1);
- aST.AddEdges(aF1);
+ if (bFlag) {
+ for (k=0; k<2; ++k) {
+ const TopoDS_Shape& aF=(!k) ? aF1 : aF2;
+ const BOPCol_ListOfShape& aLF=mySplits.Find(aF);
+ //
+ aItF.Initialize(aLF);
+ for (; aItF.More(); aItF.Next()) {
+ const TopoDS_Shape& aFx=aItF.Value();
+ //
+ if (aMFence.Add(aFx)) {
+ BOPTools_Set aSTx;
+ //
+ aSTx.Add(aFx, TopAbs_EDGE);
+ //
+ if (!aIDMSS.Contains(aSTx)) {
+ BOPAlgo_VectorOfShape& aVS=aVVS.Append1();
+ aVS.Append(aFx);
+ //
+ j=aVVS.Extent()-1;
+ aIDMSS.Add (aSTx, j);
+ }
+ else {
+ j=aIDMSS.ChangeFromKey(aSTx);
+ BOPAlgo_VectorOfShape& aVS=aVVS(j);
+ aVS.Append(aFx);
+ }
+ }
+ }
}
+ }// if (bFlag) {
+ else {// if (!bFlag)
+ BOPTools_Set aST1, aST2;
//
- if (!aMSST.IsBound(aF2)) {
- BOPTools_Set aST2(aAllocator);
- aMSST.Bind(aF2, aST2);
- BOPTools_Set& aST=aMSST.ChangeFind(aF2);
- aST.AddEdges(aF2);
- }
+ aST1.Add(aF1, TopAbs_EDGE);
+ aST2.Add(aF2, TopAbs_EDGE);
//
- const BOPTools_Set& aST1=aMSST.Find(aF1);
- const BOPTools_Set& aST2=aMSST.Find(aF2);
if (aST1.IsEqual(aST2)) {
- bFlag=BOPTools_AlgoTools::AreFacesSameDomain(aF1, aF2, myContext);
- if (bFlag) {
- FillMap(aF1, aF2, aDMSLS, aAllocator);
- aMF.Add(aF1);
- aMF.Add(aF2);
- }
- }
- continue;
- }
- //
- const BOPCol_ListOfShape& aLF1=mySplits.Find(aF1);
- const BOPCol_ListOfShape& aLF2=mySplits.Find(aF2);
- //
- aItF1.Initialize(aLF1);
- for (; aItF1.More(); aItF1.Next()) {
- const TopoDS_Face& aF1x=(*(TopoDS_Face*)(&aItF1.Value()));
- if (!aMSST.IsBound(aF1x)) {
- BOPTools_Set aST1(aAllocator);
- //
- aMSST.Bind(aF1x, aST1);
- BOPTools_Set& aST=aMSST.ChangeFind(aF1x);
- aST.AddEdges(aF1x);
- }
- //
- aItF2.Initialize(aLF2);
- for (; aItF2.More(); aItF2.Next()) {
- const TopoDS_Face& aF2y=(*(TopoDS_Face*)(&aItF2.Value()));
- if (!aMSST.IsBound(aF2y)) {
- BOPTools_Set aST2(aAllocator);
+ if (!aIDMSS.Contains(aST1)) {
+ BOPAlgo_VectorOfShape& aVS=aVVS.Append1();
+ if (aMFence.Add(aF1)) {
+ aVS.Append(aF1);
+ }
+ if (aMFence.Add(aF2)) {
+ aVS.Append(aF2);
+ }
//
- aMSST.Bind(aF2y, aST2);
- BOPTools_Set& aST=aMSST.ChangeFind(aF2y);
- aST.AddEdges(aF2y);
+ k=aVVS.Extent()-1;
+ aIDMSS.Add (aST1, k);
}
- //
- const BOPTools_Set& aST1=aMSST.Find(aF1x);
- const BOPTools_Set& aST2=aMSST.Find(aF2y);
- //
- if (aST1.IsEqual(aST2)) {
- bFlag=BOPTools_AlgoTools::AreFacesSameDomain(aF1x, aF2y, myContext);
- if (bFlag) {
- FillMap(aF1x, aF2y, aDMSLS, aAllocator);
+ else {
+ k=aIDMSS.ChangeFromKey(aST1);
+ BOPAlgo_VectorOfShape& aVS=aVVS(k);
+ if (aMFence.Add(aF1)) {
+ aVS.Append(aF1);
+ }
+ if (aMFence.Add(aF2)) {
+ aVS.Append(aF2);
}
}
- }
- }
- } // for (i=0; i<aNbFFs; ++i) {
+ }//if (aST1.IsEqual(aST2)) {
+ }// else {// if (!bFlag)
+ //
+ }// for (i=0; i<aNbFFs; ++i) {
//
- // 2. Make blocks
- MakeBlocksCnx(aDMSLS, aMBlocks, aAllocator);
+ aIDMSS.Clear();
//
- // 3. Fill same domain faces map -> aMSDF
- aNbS = aMBlocks.Extent();
- for (i=0; i<aNbS; ++i) {
- const BOPCol_ListOfShape& aLSD=aMBlocks.Find(i);
- if (aLSD.Extent()) {
- const TopoDS_Shape& aFSD1=aLSD.First();
- aItLS.Initialize(aLSD);
- for (; aItLS.More(); aItLS.Next()) {
- const TopoDS_Shape& aFSD=aItLS.Value();
- myShapesSD.Bind(aFSD, aFSD1);
+ Standard_Boolean bFlagSD;
+ Standard_Integer aNbVPSB, aNbVVS, aNbF, aNbF1;
+ BOPAlgo_VectorOfPairOfShapeBoolean aVPSB;
+ //
+ aNbVVS=aVVS.Extent();
+ for (i=0; i<aNbVVS; ++i) {
+ const BOPAlgo_VectorOfShape& aVS=aVVS(i);
+ aNbF=aVS.Extent();
+ if (aNbF<2) {
+ continue;
+ }
+ //
+ aNbF1=aNbF-1;
+ for (j=0; j<aNbF1; ++j) {
+ const TopoDS_Shape& aFj=aVS(j);
+ for (k=j+1; k<aNbF; ++k) {
+ const TopoDS_Shape& aFk=aVS(k);
+ BOPAlgo_PairOfShapeBoolean& aPSB=aVPSB.Append1();
+ aPSB.Shape1()=aFj;
+ aPSB.Shape2()=aFk;
+ aPSB.SetFuzzyValue(myFuzzyValue);
+ aPSB.SetProgressIndicator(myProgressIndicator);
}
}
}
+ //================================================================
+ BOPAlgo_BuilderSDFaceCnt::Perform(myRunParallel, aVPSB, myContext);
+ //================================================================
+ aAllocator=
+ NCollection_BaseAllocator::CommonBaseAllocator();
+ BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS(100, aAllocator);
+ NCollection_List<BOPCol_ListOfShape> aMBlocks(aAllocator);
+ //
+ aNbVPSB=aVPSB.Extent();
+ for (i=0; i<aNbVPSB; ++i) {
+ BOPAlgo_PairOfShapeBoolean& aPSB=aVPSB(i);
+ bFlagSD=aPSB.Flag();
+ if (bFlagSD) {
+ const TopoDS_Shape& aFj=aPSB.Shape1();
+ const TopoDS_Shape& aFk=aPSB.Shape2();
+ BOPAlgo_Tools::FillMap<TopoDS_Shape, TopTools_ShapeMapHasher>(aFj, aFk, aDMSLS, aAllocator);
+ }
+ }
+ aVPSB.Clear();
//
- aItMF.Initialize(aMF);
- for (; aItMF.More(); aItMF.Next()){
- const TopoDS_Shape& aF = aItMF.Value();
+ // 2. Make blocks
+ BOPAlgo_Tools::MakeBlocks<TopoDS_Shape, TopTools_ShapeMapHasher>(aDMSLS, aMBlocks, aAllocator);
+ //
+ // 3. Fill same domain faces map -> aMSDF
+ NCollection_List<BOPCol_ListOfShape>::Iterator aItB(aMBlocks);
+ for (; aItB.More(); aItB.Next()) {
+ const BOPCol_ListOfShape& aLSD = aItB.Value();
//
- BOPCol_ListOfShape aLS;
- aLS.Append(aF);
- mySplits.Bind(aF, aLS);
+ const TopoDS_Shape& aFSD1=aLSD.First();
+ aItF.Initialize(aLSD);
+ for (; aItF.More(); aItF.Next()) {
+ const TopoDS_Shape& aFSD=aItF.Value();
+ myShapesSD.Bind(aFSD, aFSD1);
+ //
+ // If the face has no splits but are SD face,
+ // it is considered as splitted face
+ if (!mySplits.IsBound(aFSD)) {
+ BOPCol_ListOfShape aLS;
+ aLS.Append(aFSD);
+ mySplits.Bind(aFSD, aLS);
+ }
+ }
}
- //-----------------------------------------------------scope t
- aMSST.Clear();
aMBlocks.Clear();
aDMSLS.Clear();
- aAllocator.Nullify();
}
//=======================================================================
// function: FillImagesFaces1
// purpose:
//=======================================================================
- void BOPAlgo_Builder::FillImagesFaces1()
+void BOPAlgo_Builder::FillImagesFaces1()
{
- Standard_Integer i, aNbS, iSense;
+ Standard_Integer i, aNbS, iSense, nVx, aNbVFI, iFlag;
TopoDS_Face aFSD;
+ TopoDS_Vertex aVx;
+ BRep_Builder aBB;
BOPCol_ListOfInteger aLIAV;
BOPCol_ListOfShape aLFIm;
- BOPCol_ListIteratorOfListOfShape aItLS;
+ BOPCol_ListIteratorOfListOfInteger aItV;
+ BOPCol_ListIteratorOfListOfShape aItLS, aItF;
+ BOPAlgo_VectorOfVFI aVVFI;
//
aNbS=myDS->NbSourceShapes();
for (i=0; i<aNbS; ++i) {
if (!mySplits.IsBound(aF)) {
continue;
}
- //
+ //
+ // 1.
aLIAV.Clear();
myDS->AloneVertices(i, aLIAV);
aLFIm.Clear();
}
else {
aFSD=(*(TopoDS_Face*)(&myShapesSD.Find(aFSp)));
- iSense=BOPTools_AlgoTools::Sense(aFSp, aFSD);
+ iSense=BOPTools_AlgoTools::Sense(aFSp, aFSD, myContext);
if (iSense<0) {
aFSD.Reverse();
}
}
}
//
- FillInternalVertices(aLFIm, aLIAV);
+ //FillInternalVertices(aLFIm, aLIAV);
//
myImages.Bind(aF, aLFIm);
//
- //fill myOrigins
+ // 2. fill myOrigins
aItLS.Initialize(aLFIm);
for (; aItLS.More(); aItLS.Next()) {
const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&aItLS.Value()));
- myOrigins.Bind(aFSp, aF);
- }
- }// for (i=0; i<aNbS; ++i) {
-}
-//=======================================================================
-// function: FillInternalVertices
-// purpose:
-//=======================================================================
- void BOPAlgo_Builder::FillInternalVertices(BOPCol_ListOfShape& aLFIm,
- BOPCol_ListOfInteger& aLIAV)
-{
- Standard_Integer nV, iFlag;
- Standard_Real aU1, aU2;
- TopoDS_Vertex aV;
- BRep_Builder aBB;
- BOPCol_ListIteratorOfListOfInteger aItV;
- BOPCol_ListIteratorOfListOfShape aItF;
- //
- aItV.Initialize(aLIAV);
- for (; aItV.More(); aItV.Next()) {
- nV=aItV.Value();
- aV=(*(TopoDS_Vertex*)(&myDS->Shape(nV)));
- aV.Orientation(TopAbs_INTERNAL);
- //
- aItF.Initialize(aLFIm);
- for (; aItF.More(); aItF.Next()) {
- TopoDS_Face& aF=(*(TopoDS_Face*)(&aItF.Value()));
- iFlag=myContext->ComputeVF(aV, aF, aU1, aU2);
- if (!iFlag) {
- aBB.Add(aF, aV);
- break;
+ //
+ BOPCol_ListOfShape* pLOr = myOrigins.ChangeSeek(aFSp);
+ if (!pLOr) {
+ pLOr = myOrigins.Bound(aFSp, BOPCol_ListOfShape());
}
+ pLOr->Append(aF);
}
- }
-}
-//=======================================================================
-//function : MakeBlocksCnx
-//purpose :
-//=======================================================================
-void MakeBlocksCnx(const BOPCol_IndexedDataMapOfShapeListOfShape& aMILI,
- BOPCol_DataMapOfIntegerListOfShape& aMBlocks,
- Handle(NCollection_IncAllocator)& aAllocator)
-{
- Standard_Integer aNbV, aNbVS, aNbVP, aNbEC, k, i, j;
- BOPCol_ListIteratorOfListOfShape aItLI;
- //
- BOPCol_MapOfShape aMVS(100, aAllocator);
- BOPCol_IndexedMapOfShape aMEC(100, aAllocator);
- BOPCol_IndexedMapOfShape aMVP(100, aAllocator);
- BOPCol_IndexedMapOfShape aMVAdd(100, aAllocator);
- //
- aNbV=aMILI.Extent();
- //
- for (k=0,i=1; i<=aNbV; ++i) {
- aNbVS=aMVS.Extent();
- if (aNbVS==aNbV) {
- break;
- }
- //
- const TopoDS_Shape& nV=aMILI.FindKey(i);
- if (aMVS.Contains(nV)){
- continue;
- }
- aMVS.Add(nV);
- //
- aMEC.Clear();
- aMVP.Clear();
- aMVAdd.Clear();
//
- aMVP.Add(nV);
- while(1) {
- aNbVP=aMVP.Extent();
- for (j=1; j<=aNbVP; ++j) {
- const TopoDS_Shape& nVP=aMVP(j);
- const BOPCol_ListOfShape& aLV=aMILI.FindFromKey(nVP);
- aItLI.Initialize(aLV);
- for (; aItLI.More(); aItLI.Next()) {
- const TopoDS_Shape& nVx=aItLI.Value();
- if (aMEC.Contains(nVx)) {
- continue;
- }
- //
- aMVS.Add(nVx);
- aMEC.Add(nVx);
- aMVAdd.Add(nVx);
- }
- }
- //
- aNbVP=aMVAdd.Extent();
- if (!aNbVP) {
- break; // from while(1)
- }
+ // 3.
+ aItV.Initialize(aLIAV);
+ for (; aItV.More(); aItV.Next()) {
+ nVx=aItV.Value();
+ aVx=(*(TopoDS_Vertex*)(&myDS->Shape(nVx)));
+ aVx.Orientation(TopAbs_INTERNAL);
//
- aMVP.Clear();
- for (j=1; j<=aNbVP; ++j) {
- aMVP.Add(aMVAdd(j));
+ aItF.Initialize(aLFIm);
+ for (; aItF.More(); aItF.Next()) {
+ TopoDS_Face& aFy=(*(TopoDS_Face*)(&aItF.Value()));
+ //
+ BOPAlgo_VFI& aVFI=aVVFI.Append1();
+ aVFI.SetVertex(aVx);
+ aVFI.SetFace(aFy);
+ aVFI.SetFuzzyValue(myFuzzyValue);
+ aVFI.SetProgressIndicator(myProgressIndicator);
}
- aMVAdd.Clear();
- }//while(1) {
- //
- BOPCol_ListOfShape aLIx(aAllocator);
- //
- aNbEC = aMEC.Extent();
- for (j=1; j<=aNbEC; ++j) {
- const TopoDS_Shape& nVx=aMEC(j);
- aLIx.Append(nVx);
}
- //
- aMBlocks.Bind(k, aLIx);
- ++k;
- }//for (k=0,i=1; i<=aNbV; ++i)
- aMVAdd.Clear();
- aMVP.Clear();
- aMEC.Clear();
- aMVS.Clear();
-}
-
-//=======================================================================
-//function : FillMap
-//purpose :
-//=======================================================================
-void FillMap(const TopoDS_Shape& aS1,
- const TopoDS_Shape& aS2,
- BOPCol_IndexedDataMapOfShapeListOfShape& aDMSLS,
- Handle(NCollection_IncAllocator)& aAllocator)
-{
- if (aDMSLS.Contains(aS1)) {
- BOPCol_ListOfShape& aLS=aDMSLS.ChangeFromKey(aS1);
- aLS.Append(aS2);
- }
- else {
- BOPCol_ListOfShape aLS(aAllocator);
- aLS.Append(aS2);
- aDMSLS.Add(aS1, aLS);
- }
+ }// for (i=0; i<aNbS; ++i) {
//
- if (aDMSLS.Contains(aS2)) {
- BOPCol_ListOfShape& aLS=aDMSLS.ChangeFromKey(aS2);
- aLS.Append(aS1);
- }
- else {
- BOPCol_ListOfShape aLS(aAllocator);
- aLS.Append(aS1);
- aDMSLS.Add(aS2, aLS);
+ // 4.
+ aNbVFI=aVVFI.Extent();
+ //================================================================
+ BOPAlgo_VFICnt::Perform(myRunParallel, aVVFI, myContext);
+ //================================================================
+ //
+ for (i=0; i < aNbVFI; ++i) {
+ BOPAlgo_VFI& aVFI=aVVFI(i);
+ //
+ iFlag=aVFI.Flag();
+ if (!iFlag) {
+ TopoDS_Vertex& aVertex=aVFI.Vertex();
+ TopoDS_Face& aFy=aVFI.Face();
+ aBB.Add(aFy, aVertex);
+ }
}
}
//=======================================================================
const BOPDS_FaceInfo& aFI2)
{
Standard_Boolean bRet;
- BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
+ Standard_Integer i, aNbPB;
//
bRet=Standard_False;
- const BOPDS_IndexedMapOfPaveBlock& aMPBOn1=aFI1.PaveBlocksOn();
- const BOPDS_IndexedMapOfPaveBlock& aMPBIn1=aFI1.PaveBlocksIn();
- //
- const BOPDS_IndexedMapOfPaveBlock& aMPBOn2=aFI2.PaveBlocksOn();
- aItMPB.Initialize(aMPBOn2);
- for (; aItMPB.More(); aItMPB.Next()) {
- const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
- bRet=aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
+ const BOPDS_IndexedMapOfPaveBlock& aMPBOn1 = aFI1.PaveBlocksOn();
+ const BOPDS_IndexedMapOfPaveBlock& aMPBIn1 = aFI1.PaveBlocksIn();
+ //
+ const BOPDS_IndexedMapOfPaveBlock& aMPBOn2 = aFI2.PaveBlocksOn();
+ aNbPB = aMPBOn2.Extent();
+ for (i = 1; i <= aNbPB; ++i) {
+ const Handle(BOPDS_PaveBlock)& aPB = aMPBOn2(i);
+ bRet = aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
if (bRet) {
return bRet;
}
}
//
- const BOPDS_IndexedMapOfPaveBlock& aMPBIn2=aFI2.PaveBlocksIn();
- aItMPB.Initialize(aMPBIn2);
- for (; aItMPB.More(); aItMPB.Next()) {
- const Handle(BOPDS_PaveBlock)& aPB=aItMPB.Value();
- bRet=aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
+ const BOPDS_IndexedMapOfPaveBlock& aMPBIn2 = aFI2.PaveBlocksIn();
+ aNbPB = aMPBIn2.Extent();
+ for (i = 1; i <= aNbPB; ++i) {
+ const Handle(BOPDS_PaveBlock)& aPB = aMPBIn2(i);
+ bRet = aMPBOn1.Contains(aPB) || aMPBIn1.Contains(aPB);
if (bRet) {
return bRet;
}
return bRet;
}
-/*
-//DEBf
+//=======================================================================
+//function : BuildDraftFace
+//purpose : Build draft faces, updating the bounding edges,
+// according to the information stored into the <theImages> map
+//=======================================================================
+TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+ const BOPCol_DataMapOfShapeListOfShape& theImages,
+ Handle(IntTools_Context)& theCtx)
+{
+ BRep_Builder aBB;
+ // Take the information from the original face
+ TopLoc_Location aLoc;
+ const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
+ const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
+ // Make the new face, without any wires
+ TopoDS_Face aDraftFace;
+ aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
+
+ // Update wires of the original face and add them to draft face
+ TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
+ for (; aItW.More(); aItW.Next())
+ {
+ const TopoDS_Shape& aW = aItW.Value();
+ if (aW.ShapeType() != TopAbs_WIRE)
+ continue;
+
+ // Rebuild wire using images of edges
+ TopoDS_Iterator aItE(aW.Oriented(TopAbs_FORWARD));
+ if (!aItE.More())
+ continue;
+
+ TopoDS_Wire aNewWire;
+ aBB.MakeWire(aNewWire);
+
+ for (; aItE.More(); aItE.Next())
{
- TopoDS_Compound aCx;
- BRep_Builder aBBx;
- BOPCol_ListIteratorOfListOfShape aItx;
- //
- aBBx.MakeCompound(aCx);
- aBBx.Add(aCx, aFF);
- aItx.Initialize(aLE);
- for (; aItx.More(); aItx.Next()) {
- const TopoDS_Shape& aEx=aItx.Value();
- aBBx.Add(aCx, aEx);
+ const TopoDS_Edge& aE = TopoDS::Edge(aItE.Value());
+
+ TopAbs_Orientation anOriE = aE.Orientation();
+ if (anOriE == TopAbs_INTERNAL)
+ {
+ // The internal edges could split the original face on halves.
+ // Thus, use the BuilderFace algorithm to build the new face.
+ TopoDS_Face aNull;
+ return aNull;
+ }
+
+ const BOPCol_ListOfShape* pLEIm = theImages.Seek(aE);
+ if (!pLEIm)
+ {
+ aBB.Add(aNewWire, aE);
+ continue;
+ }
+
+ // Check if the original edge is degenerated
+ Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
+ // Check if the original edge is closed on the face
+ Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
+
+ BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm);
+ for (; aItLEIm.More(); aItLEIm.Next())
+ {
+ TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
+
+ aSp.Orientation(anOriE);
+ if (bIsDegenerated)
+ {
+ aBB.Add(aNewWire, aSp);
+ continue;
+ }
+
+ // Check closeness of the split edge and if it is not
+ // make the second PCurve
+ if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
+ BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
+
+ // Check if the split should be reversed
+ if (BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, theCtx))
+ aSp.Reverse();
+
+ aBB.Add(aNewWire, aSp);
}
- int a=0;
}
- //DEBt
-*/
+
+ aNewWire.Orientation(aW.Orientation());
+ aNewWire.Closed(BRep_Tool::IsClosed(aNewWire));
+ aBB.Add(aDraftFace, aNewWire);
+ }
+
+ if (theFace.Orientation() == TopAbs_REVERSED)
+ aDraftFace.Reverse();
+
+ return aDraftFace;
+}