0028786: Refactoring of the Warning/Error reporting system of Boolean Operations...
[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
17 #include <BOPAlgo_WireEdgeSet.hxx>
18 #include <BOPAlgo_WireSplitter.hxx>
19 #include <BOPAlgo_Alerts.hxx>
20 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
21 #include <BOPCol_IndexedMapOfShape.hxx>
22 #include <BOPCol_ListOfShape.hxx>
23 #include <BOPCol_MapOfShape.hxx>
24 #include <BOPCol_NCVector.hxx>
25 #include <BOPCol_Parallel.hxx>
26 #include <BOPTools.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRep_Tool.hxx>
29 #include <TopoDS.hxx>
30 #include <TopoDS_Edge.hxx>
31 #include <TopoDS_Face.hxx>
32 #include <TopoDS_Iterator.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopoDS_Wire.hxx>
35
36 //=======================================================================
37 //function : 
38 //purpose  : 
39 //=======================================================================
40 BOPAlgo_WireSplitter::BOPAlgo_WireSplitter()
41 :
42   BOPAlgo_Algo(),
43   myWES(NULL),
44   myLCB(myAllocator)
45 {
46 }
47 //=======================================================================
48 //function : 
49 //purpose  : 
50 //=======================================================================
51 BOPAlgo_WireSplitter::BOPAlgo_WireSplitter
52   (const Handle(NCollection_BaseAllocator)& theAllocator)
53 :
54   BOPAlgo_Algo(theAllocator),
55   myWES(NULL),
56   myLCB(myAllocator)
57 {
58 }
59 //=======================================================================
60 //function : ~
61 //purpose  : 
62 //=======================================================================
63 BOPAlgo_WireSplitter::~BOPAlgo_WireSplitter()
64 {
65 }
66 //=======================================================================
67 //function : SetWES
68 //purpose  : 
69 //=======================================================================
70 void BOPAlgo_WireSplitter::SetWES(const BOPAlgo_WireEdgeSet& theWES)
71 {
72   myWES=(BOPAlgo_WireEdgeSet*)&theWES;
73 }
74 //=======================================================================
75 //function : WES
76 //purpose  : 
77 //=======================================================================
78 BOPAlgo_WireEdgeSet& BOPAlgo_WireSplitter::WES()
79 {
80   return *myWES;
81 }
82 //=======================================================================
83 //function : SetContext
84 //purpose  : 
85 //=======================================================================
86 void BOPAlgo_WireSplitter::SetContext(const Handle(IntTools_Context)& theContext)
87 {
88   myContext = theContext;
89 }
90 //=======================================================================
91 //function : Context
92 //purpose  : 
93 //=======================================================================
94 const Handle(IntTools_Context)& BOPAlgo_WireSplitter::Context()
95 {
96   return myContext;
97 }
98 //=======================================================================
99 // function: CheckData
100 // purpose: 
101 //=======================================================================
102 void BOPAlgo_WireSplitter::CheckData()
103 {
104   if (!myWES) {
105     AddError (new BOPAlgo_AlertNullInputShapes);
106     return;
107   }
108 }
109 //=======================================================================
110 //function : Perform
111 //purpose  : 
112 //=======================================================================
113 void BOPAlgo_WireSplitter::Perform()
114 {
115   GetReport()->Clear();
116   //
117   CheckData();
118   if (HasErrors()) {
119     return;
120   }
121   //
122   // create a context
123   if (myContext.IsNull()) {
124     myContext = new IntTools_Context;
125   }
126   //
127   MakeConnexityBlocks();
128   MakeWires();
129 }
130
131 //=======================================================================
132 //function : MakeConnexityBlocks
133 //purpose  : 
134 //=======================================================================
135 void BOPAlgo_WireSplitter::MakeConnexityBlocks()
136 {
137   Standard_Boolean bRegular, bClosed;
138   Standard_Integer i, j, aNbV, aNbVS, aNbVP, k;
139   TopoDS_Iterator aItE;
140   TopoDS_Shape aER;
141   BOPCol_ListIteratorOfListOfShape aIt;
142   //
143   BOPCol_IndexedDataMapOfShapeListOfShape aMVE(100, myAllocator);
144   BOPCol_IndexedMapOfShape aMVP(100, myAllocator);
145   BOPCol_IndexedMapOfShape aMEC(100, myAllocator);
146   BOPCol_MapOfShape aMER(100, myAllocator);
147   BOPCol_MapOfShape aMEP(100, myAllocator);
148   BOPCol_IndexedMapOfShape aMVAdd(100, myAllocator);
149   BOPCol_MapOfShape aMVS(100, myAllocator);
150   //
151   myLCB.Clear();
152   //
153   const BOPCol_ListOfShape& aLSE=myWES->StartElements();
154   aIt.Initialize(aLSE);
155   for (; aIt.More(); aIt.Next()) {
156     const TopoDS_Shape& aE=aIt.Value();
157     if (aMEP.Add(aE)) {
158       BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
159     }
160     else {
161       aMER.Add(aE);
162     }
163   }
164   //
165   // 2
166   aNbV=aMVE.Extent();
167   for (i=1; i<=aNbV; ++i) {
168     aNbVS=aMVS.Extent();
169     if (aNbVS==aNbV) {
170       break;
171     }
172     //
173     const TopoDS_Shape& aV=aMVE.FindKey(i);
174     //
175     if (!aMVS.Add(aV)) {
176       continue;
177     }
178         // aMVS - globally processed vertices
179     //
180     //------------------------------------- goal: aMEC
181     aMEC.Clear();    // aMEC - edges of CB
182     aMVP.Clear();    // aMVP - vertices to process right now 
183     aMVAdd.Clear();  // aMVAdd vertices to process on next step of while(1)
184     //
185     aMVP.Add(aV);
186     //
187     for(;;) {
188       aNbVP=aMVP.Extent();
189       for (k=1; k<=aNbVP; ++k) {
190         const TopoDS_Shape& aVP=aMVP(k);
191         const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aVP);
192         aIt.Initialize(aLE);
193         for (; aIt.More(); aIt.Next()) {
194           const TopoDS_Shape& aE=aIt.Value();
195           if (aMEC.Add(aE)) {
196             aItE.Initialize(aE);
197             for (; aItE.More(); aItE.Next()) {
198               const TopoDS_Shape& aVE=aItE.Value();
199               if (aMVS.Add(aVE)) {
200                 aMVAdd.Add(aVE);
201               }
202             }
203           }
204         }
205       }//for (k=1; k<=aNbVP; ++k) {
206       //
207       aNbVP=aMVAdd.Extent();
208       if (!aNbVP) {
209         break; // from while(1)
210       }
211       //
212       aMVP.Clear();
213       //
214       for (k=1; k<=aNbVP; ++k) {
215         const TopoDS_Shape& aVE=aMVAdd(k);
216         aMVP.Add(aVE);
217       }
218       aMVAdd.Clear();
219     }// while(1) {
220
221     //-------------------------------------
222     BOPTools_ConnexityBlock aCB(myAllocator);
223     BOPCol_ListOfShape& aLEC=aCB.ChangeShapes();
224     
225     BOPCol_IndexedDataMapOfShapeListOfShape aMVER(100, myAllocator);
226     //
227     bRegular=Standard_True;
228     Standard_Integer aNbCB = aMEC.Extent();
229     for (j = 1; j <= aNbCB; j++) {
230       aER = aMEC(j);
231       //
232       if (aMER.Contains(aER)) {
233         aER.Orientation(TopAbs_FORWARD);
234         aLEC.Append(aER);
235         aER.Orientation(TopAbs_REVERSED);
236         aLEC.Append(aER);
237         bRegular=Standard_False;
238       }
239       else {
240         aLEC.Append(aER);
241       }
242       //
243       if (bRegular) {
244         BOPTools::MapShapesAndAncestors(aER, TopAbs_VERTEX, TopAbs_EDGE, aMVER);
245       }
246     }
247     //
248     if (bRegular) {
249       Standard_Integer aNbVR, aNbER;
250       //
251       aNbVR=aMVER.Extent();
252       for (k=1; k<=aNbVR; ++k) {
253         const BOPCol_ListOfShape& aLER=aMVER(k);
254         aNbER=aLER.Extent();
255         if (aNbER==1) {
256           const TopoDS_Edge& aEx=TopoDS::Edge(aER);
257           bClosed=BRep_Tool::IsClosed(aEx, myWES->Face());
258           if (!bClosed) {
259             bRegular=!bRegular;
260             break;
261           }
262         }
263         if (aNbER>2) {
264           bRegular=!bRegular;
265           break;
266         }
267       }
268     }
269     //
270     aCB.SetRegular(bRegular);
271     myLCB.Append(aCB);
272   }
273 }
274 /////////////////////////////////////////////////////////////////////////
275 class BOPAlgo_WS_ConnexityBlock {
276 public:
277   BOPAlgo_WS_ConnexityBlock() {};
278   ~BOPAlgo_WS_ConnexityBlock() {};
279
280   void SetFace(const TopoDS_Face& theF) {
281     myFace = theF;
282   }
283
284   const TopoDS_Face& Face() const {
285     return myFace;
286   }
287
288   void SetConnexityBlock(const BOPTools_ConnexityBlock& theCB) {
289     myCB = theCB;
290   }
291
292   const BOPTools_ConnexityBlock& ConnexityBlock() const {
293     return myCB;
294   }
295
296   void SetContext(const Handle(IntTools_Context)& aContext) {
297     myContext = aContext;
298   }
299   //
300   const Handle(IntTools_Context)& Context()const {
301     return myContext;
302   }
303
304   void Perform() {
305     BOPAlgo_WireSplitter::SplitBlock(myFace, myCB, myContext);
306   }
307
308 protected:
309   TopoDS_Face myFace;
310   BOPTools_ConnexityBlock myCB;
311   Handle(IntTools_Context) myContext;
312 };
313
314 typedef BOPCol_NCVector<BOPAlgo_WS_ConnexityBlock> \
315   BOPAlgo_VectorOfConnexityBlock;
316 //
317 typedef BOPCol_ContextFunctor
318   <BOPAlgo_WS_ConnexityBlock,
319   BOPAlgo_VectorOfConnexityBlock,
320   Handle(IntTools_Context),
321   IntTools_Context> BOPAlgo_SplitBlockFunctor;
322 //
323 typedef BOPCol_ContextCnt
324   <BOPAlgo_SplitBlockFunctor,
325   BOPAlgo_VectorOfConnexityBlock,
326   Handle(IntTools_Context)> BOPAlgo_SplitBlockCnt;
327
328 //=======================================================================
329 //function : MakeWires
330 //purpose  : 
331 //=======================================================================
332 void BOPAlgo_WireSplitter::MakeWires()
333 {
334   Standard_Boolean bIsRegular;
335   Standard_Integer aNbVCB, k;
336   TopoDS_Wire aW;
337   BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
338   BOPCol_ListIteratorOfListOfShape aIt;
339   BOPAlgo_VectorOfConnexityBlock aVCB;
340   //
341   const TopoDS_Face& aF=myWES->Face();
342   //
343   aItCB.Initialize(myLCB);
344   for (; aItCB.More(); aItCB.Next()) {
345     BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
346     bIsRegular=aCB.IsRegular();
347     if (bIsRegular) {
348       BOPCol_ListOfShape& aLE=aCB.ChangeShapes();
349       BOPAlgo_WireSplitter::MakeWire(aLE, aW);
350       myWES->AddShape(aW);
351     }
352     else {
353       BOPAlgo_WS_ConnexityBlock& aWSCB = aVCB.Append1();
354       aWSCB.SetFace(aF);
355       aWSCB.SetConnexityBlock(aCB);
356     }
357   }
358   //===================================================
359   BOPAlgo_SplitBlockCnt::Perform(myRunParallel, aVCB, myContext);
360   //===================================================
361   aNbVCB=aVCB.Extent();
362   for (k=0; k<aNbVCB; ++k) {
363     const BOPAlgo_WS_ConnexityBlock& aCB=aVCB(k);
364     const BOPCol_ListOfShape& aLW=aCB.ConnexityBlock().Loops();
365     aIt.Initialize(aLW);
366     for (; aIt.More(); aIt.Next()) {
367       const TopoDS_Shape& aWx=aIt.Value();
368       myWES->AddShape(aWx);
369     }
370   }
371 }