33e431ec34b794c884ea4adfdffc5d16798b9f0d
[occt.git] / src / BOPAlgo / BOPAlgo_WireSplitter.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 #include <BOPAlgo_WireSplitter.ixx>
21
22 #include <TopoDS_Shape.hxx>
23 #include <TopoDS_Iterator.hxx>
24 #include <TopoDS_Edge.hxx>
25 #include <TopoDS.hxx>
26 #include <TopoDS_Wire.hxx>
27
28 #include <BRep_Tool.hxx>
29 #include <BRep_Builder.hxx>
30
31 #include <BOPCol_ListOfShape.hxx>
32 #include <BOPCol_IndexedMapOfShape.hxx>
33 #include <BOPCol_MapOfShape.hxx>
34 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
35 #include <BOPCol_TBB.hxx>
36 #include <BOPCol_NCVector.hxx>
37
38 #include <BOPTools.hxx>
39
40
41 //=======================================================================
42 //function : 
43 //purpose  : 
44 //=======================================================================
45 BOPAlgo_WireSplitter::BOPAlgo_WireSplitter()
46 :
47   BOPAlgo_Algo(),
48   myWES(NULL),
49   myLCB(myAllocator)
50 {
51 }
52 //=======================================================================
53 //function : 
54 //purpose  : 
55 //=======================================================================
56 BOPAlgo_WireSplitter::BOPAlgo_WireSplitter
57   (const Handle(NCollection_BaseAllocator)& theAllocator)
58 :
59   BOPAlgo_Algo(theAllocator),
60   myWES(NULL),
61   myLCB(myAllocator)
62 {
63 }
64 //=======================================================================
65 //function : ~
66 //purpose  : 
67 //=======================================================================
68 BOPAlgo_WireSplitter::~BOPAlgo_WireSplitter()
69 {
70 }
71 //=======================================================================
72 //function : SetWES
73 //purpose  : 
74 //=======================================================================
75 void BOPAlgo_WireSplitter::SetWES(const BOPAlgo_WireEdgeSet& theWES)
76 {
77   myWES=(BOPAlgo_WireEdgeSet*)&theWES;
78 }
79 //=======================================================================
80 //function : WES
81 //purpose  : 
82 //=======================================================================
83 BOPAlgo_WireEdgeSet& BOPAlgo_WireSplitter::WES()
84 {
85   return *myWES;
86 }
87 //=======================================================================
88 // function: CheckData
89 // purpose: 
90 //=======================================================================
91 void BOPAlgo_WireSplitter::CheckData()
92 {
93   myErrorStatus=0;
94   if (!myWES) {
95     myErrorStatus=10;
96     return;
97   }
98 }
99 //=======================================================================
100 //function : Perform
101 //purpose  : 
102 //=======================================================================
103 void BOPAlgo_WireSplitter::Perform()
104 {
105   myErrorStatus=0;
106   //
107   CheckData();
108   if (myErrorStatus) {
109     return;
110   }
111   //
112   MakeConnexityBlocks();
113   MakeWires();
114 }
115
116 //=======================================================================
117 //function : MakeConnexityBlocks
118 //purpose  : 
119 //=======================================================================
120 void BOPAlgo_WireSplitter::MakeConnexityBlocks()
121 {
122   Standard_Boolean bRegular, bClosed;
123   Standard_Integer i, j, aNbV, aNbVS, aNbVP, k;
124   TopoDS_Iterator aItE;
125   TopoDS_Shape aER;
126   BOPCol_ListIteratorOfListOfShape aIt;
127   BOPCol_MapIteratorOfMapOfShape aItM;
128   //
129   BOPCol_IndexedDataMapOfShapeListOfShape aMVE(100, myAllocator);
130   BOPCol_IndexedMapOfShape aMVP(100, myAllocator);
131   BOPCol_IndexedMapOfShape aMEC(100, myAllocator);
132   BOPCol_MapOfShape aMER(100, myAllocator);
133   BOPCol_MapOfShape aMEP(100, myAllocator);
134   BOPCol_IndexedMapOfShape aMVAdd(100, myAllocator);
135   BOPCol_MapOfShape aMVS(100, myAllocator);
136   //
137   myLCB.Clear();
138   //
139   const BOPCol_ListOfShape& aLSE=myWES->StartElements();
140   aIt.Initialize(aLSE);
141   for (; aIt.More(); aIt.Next()) {
142     const TopoDS_Shape& aE=aIt.Value();
143     if (aMEP.Add(aE)) {
144       BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
145     }
146     else {
147       aMER.Add(aE);
148     }
149   }
150   //
151   // 2
152   aNbV=aMVE.Extent();
153   for (i=1; i<=aNbV; ++i) {
154     aNbVS=aMVS.Extent();
155     if (aNbVS==aNbV) {
156       break;
157     }
158     //
159     const TopoDS_Shape& aV=aMVE.FindKey(i);
160     //
161     if (!aMVS.Add(aV)) {
162       continue;
163     }
164         // aMVS - globally processed vertices
165     //
166     //------------------------------------- goal: aMEC
167     aMEC.Clear();    // aMEC - edges of CB
168     aMVP.Clear();    // aMVP - vertices to process right now 
169     aMVAdd.Clear();  // aMVAdd vertices to process on next step of while(1)
170     //
171     aMVP.Add(aV);
172     //
173     for(;;) {
174       aNbVP=aMVP.Extent();
175       for (k=1; k<=aNbVP; ++k) {
176         const TopoDS_Shape& aVP=aMVP(k);
177         const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aVP);
178         aIt.Initialize(aLE);
179         for (; aIt.More(); aIt.Next()) {
180           const TopoDS_Shape& aE=aIt.Value();
181           if (aMEC.Add(aE)) {
182             aItE.Initialize(aE);
183             for (; aItE.More(); aItE.Next()) {
184               const TopoDS_Shape& aVE=aItE.Value();
185               if (aMVS.Add(aVE)) {
186                 aMVAdd.Add(aVE);
187               }
188             }
189           }
190         }
191       }//for (; aItM.More(); aItM.Next()) {
192       //
193       aNbVP=aMVAdd.Extent();
194       if (!aNbVP) {
195         break; // from while(1)
196       }
197       //
198       aMVP.Clear();
199       //
200       for (k=1; k<=aNbVP; ++k) {
201         const TopoDS_Shape& aVE=aMVAdd(k);
202         aMVP.Add(aVE);
203       }
204       aMVAdd.Clear();
205     }// while(1) {
206
207     //-------------------------------------
208     BOPTools_ConnexityBlock aCB(myAllocator);
209     BOPCol_ListOfShape& aLEC=aCB.ChangeShapes();
210     
211     BOPCol_IndexedDataMapOfShapeListOfShape aMVER(100, myAllocator);
212     //
213     bRegular=Standard_True;
214     Standard_Integer aNbCB = aMEC.Extent();
215     for (j = 1; j <= aNbCB; j++) {
216       aER = aMEC(j);
217       //
218       if (aMER.Contains(aER)) {
219         aER.Orientation(TopAbs_FORWARD);
220         aLEC.Append(aER);
221         aER.Orientation(TopAbs_REVERSED);
222         aLEC.Append(aER);
223         bRegular=Standard_False;
224       }
225       else {
226         aLEC.Append(aER);
227       }
228       //
229       if (bRegular) {
230         BOPTools::MapShapesAndAncestors(aER, TopAbs_VERTEX, TopAbs_EDGE, aMVER);
231       }
232     }
233     //
234     if (bRegular) {
235       Standard_Integer k, aNbVR, aNbER;
236       //
237       aNbVR=aMVER.Extent();
238       for (k=1; k<=aNbVR; ++k) {
239         const BOPCol_ListOfShape& aLER=aMVER(k);
240         aNbER=aLER.Extent();
241         if (aNbER==1) {
242           const TopoDS_Edge& aEx=TopoDS::Edge(aER);
243           bClosed=BRep_Tool::IsClosed(aEx, myWES->Face());
244           if (!bClosed) {
245             bRegular=!bRegular;
246             break;
247           }
248         }
249         if (aNbER>2) {
250           bRegular=!bRegular;
251           break;
252         }
253       }
254     }
255     //
256     aCB.SetRegular(bRegular);
257     myLCB.Append(aCB);
258   }
259 }
260 /////////////////////////////////////////////////////////////////////////
261
262 typedef BOPCol_NCVector<BOPTools_ConnexityBlock> \
263   BOPTools_VectorOfConnexityBlock;
264
265 //=======================================================================
266 //class    : WireSplitterFunctor
267 //purpose  : 
268 //=======================================================================
269 class BOPAlgo_WireSplitterFunctor {
270  protected:
271   TopoDS_Face myFace;
272   BOPTools_VectorOfConnexityBlock* myPVCB;
273   //
274  public:
275   //
276   BOPAlgo_WireSplitterFunctor(const TopoDS_Face& aF,
277                               BOPTools_VectorOfConnexityBlock& aVCB) 
278     : myFace(aF), myPVCB(&aVCB) {
279   }
280   //
281   void operator()( const flexible_range<Standard_Size>& aBR ) const{
282     Standard_Size i, iBeg, iEnd;
283     //
284     BOPTools_VectorOfConnexityBlock& aVCB=*myPVCB;
285     //
286     iBeg=aBR.begin();
287     iEnd=aBR.end();
288     for(i=iBeg; i!=iEnd; ++i) {
289       BOPTools_ConnexityBlock& aCB=aVCB((Standard_Integer)i);
290       //
291       BOPAlgo_WireSplitter::SplitBlock(myFace, aCB);
292     }
293   }
294 };
295 //=======================================================================
296 //class    : BOPAlgo_WireSplitterCnt
297 //purpose  : 
298 //=======================================================================
299 class BOPAlgo_WireSplitterCnt {
300  public:
301   //-------------------------------
302   // Perform
303   Standard_EXPORT 
304     static void Perform(const Standard_Boolean bRunParallel,
305                         const TopoDS_Face& aF, 
306                         BOPTools_VectorOfConnexityBlock& aVCB) {
307     //
308     BOPAlgo_WireSplitterFunctor aWSF(aF, aVCB);
309     Standard_Size aNbVCB=aVCB.Extent();
310     //
311     if (bRunParallel) {
312       flexible_for(flexible_range<Standard_Size>(0,aNbVCB), aWSF);
313     }
314     else {
315       aWSF.operator()(flexible_range<Standard_Size>(0,aNbVCB));
316     }
317   }
318   //
319 };
320 //=======================================================================
321 //function : MakeWires
322 //purpose  : 
323 //=======================================================================
324 void BOPAlgo_WireSplitter::MakeWires()
325 {
326   Standard_Boolean bIsRegular;
327   Standard_Integer aNbVCB, k;
328   TopoDS_Wire aW;
329   BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
330   BOPCol_ListIteratorOfListOfShape aIt;
331   BOPTools_VectorOfConnexityBlock aVCB;
332   //
333   aItCB.Initialize(myLCB);
334   for (; aItCB.More(); aItCB.Next()) {
335     BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
336     bIsRegular=aCB.IsRegular();
337     if (bIsRegular) {
338       BOPCol_ListOfShape& aLE=aCB.ChangeShapes();
339       BOPAlgo_WireSplitter::MakeWire(aLE, aW);
340       myWES->AddShape(aW);
341     }
342     else {
343       aVCB.Append(aCB);
344     }
345   }
346   //
347   aNbVCB=aVCB.Extent();
348   const TopoDS_Face& aF=myWES->Face();
349   //===================================================
350   BOPAlgo_WireSplitterCnt::Perform(myRunParallel, aF, aVCB);
351   //===================================================
352   for (k=0; k<aNbVCB; ++k) {
353     const BOPTools_ConnexityBlock& aCB=aVCB(k);
354     const BOPCol_ListOfShape& aLW=aCB.Loops();
355     aIt.Initialize(aLW);
356     for (; aIt.More(); aIt.Next()) {
357       const TopoDS_Shape& aWx=aIt.Value();
358       myWES->AddShape(aWx);
359     }
360   }
361 }