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