4906bbaffff8c18e305aadcd6cc0142b52b62e0a
[occt.git] / src / BOP / BOP_AreaBuilder.cxx
1 // File:        BOP_AreaBuilder.cxx
2 // Created:     Thu Dec 21 17:07:40 1995
3 // Author:      Jean Yves LEBEY
4 //              <jyl@meteox>
5 //Copyright:     Matra Datavision 1995
6
7 // " Voyager, c'est bien utile, ca fait travailler l'imagination.
8 //   Tout le reste n'est que deceptions et fatigues. Notre voyage 
9 //   a nous est entierement imaginaire. Voila sa force. "
10 //                         Celine
11 //                         Voyage au bout de la nuit
12
13 #include <BOP_AreaBuilder.ixx>
14
15 #include <Standard_DomainError.hxx>
16 #include <TopAbs.hxx>
17
18 //=======================================================================
19 //function : BOP_AreaBuilder::BOP_AreaBuilder
20 //purpose  : 
21 //=======================================================================
22   BOP_AreaBuilder::BOP_AreaBuilder() 
23 :
24   myUNKNOWNRaise(Standard_False) 
25 {
26 }
27
28 //=======================================================================
29 //function : TopOpeBRepBuild_AreaBuilder
30 //purpose  : 
31 //=======================================================================
32   BOP_AreaBuilder::BOP_AreaBuilder (BOP_LoopSet&        LS,
33                                     BOP_LoopClassifier& LC,
34                                     const Standard_Boolean ForceClass)
35 :
36   myUNKNOWNRaise(Standard_False) 
37 {
38   InitAreaBuilder(LS, LC, ForceClass);
39 }
40 //=======================================================================
41 //function : Delete
42 //purpose  : 
43 //=======================================================================
44   void BOP_AreaBuilder::Delete()
45 {}
46
47 //=======================================================================
48 //function : CompareLoopWithListOfLoop
49 //purpose  : Compare position of the Loop <L> with the Area <LOL>
50 //           using the Loop Classifier <LC>.
51 //           According to <whattotest>, Loops of <LOL> are selected or not
52 //           during <LOL> exploration.
53 //result   : TopAbs_OUT if <LOL> is empty
54 //           TopAbs_UNKNOWN if position undefined
55 //           TopAbs_IN  if <L> is inside all the selected Loops of <LOL>
56 //           TopAbs_OUT if <L> is outside one of the selected Loops of <LOL>
57 //           TopAbs_ON  if <L> is on one of the selected Loops of <LOL>
58 //=======================================================================
59   TopAbs_State BOP_AreaBuilder::CompareLoopWithListOfLoop (BOP_LoopClassifier &LC,
60                                                            const Handle(BOP_Loop)& L,
61                                                            const BOP_ListOfLoop &LOL,
62                                                            const BOP_LoopEnum   what) const
63 {
64   TopAbs_State                 state = TopAbs_UNKNOWN;
65   Standard_Boolean             totest; // L must or not be tested
66   BOP_ListIteratorOfListOfLoop LoopIter;  
67   
68   if ( LOL.IsEmpty() ) {
69     return TopAbs_OUT;
70   }
71
72   LoopIter.Initialize(LOL);
73   for (; LoopIter.More(); LoopIter.Next() ) {
74     const Handle(BOP_Loop)& curL = LoopIter.Value();
75     switch ( what ) { 
76     case BOP_ANYLOOP  : 
77       totest = Standard_True;
78       break;
79     case BOP_BOUNDARY : 
80       totest =  curL->IsShape();
81       break;
82     case BOP_BLOCK    : 
83       totest = !curL->IsShape();
84       break;
85     default:
86       totest = Standard_False;
87       break;
88     }
89     if ( totest ) {
90       state = LC.Compare(L,curL);
91       if (state == TopAbs_OUT) 
92         // <L> is out of at least one Loop 
93         //of <LOL> : stop to explore
94         break;  
95     }
96   }
97   return state;
98 }
99
100 //=======================================================================
101 //function : Atomize
102 //purpose  : 
103 //=======================================================================
104   void BOP_AreaBuilder::Atomize(TopAbs_State& state, 
105                                 const TopAbs_State newstate) const
106 {
107   if (myUNKNOWNRaise) {
108     Standard_DomainError_Raise_if((state == TopAbs_UNKNOWN),
109                                   "AreaBuilder : Position Unknown");
110   }
111   else {
112     state = newstate;
113   }
114 }
115
116
117 //=======================================================================
118 //function : InitAreaBuilder
119 //purpose  : 
120 //=======================================================================
121   void BOP_AreaBuilder::InitAreaBuilder(BOP_LoopSet& LS,
122                                         BOP_LoopClassifier& LC,
123                                         const Standard_Boolean ForceClass)
124 {
125   TopAbs_State     state;
126   Standard_Boolean Loopinside;
127   Standard_Boolean loopoutside;
128   
129   BOP_ListIteratorOfListOfListOfLoop AreaIter;
130   BOP_ListIteratorOfListOfLoop       LoopIter;
131   // boundaryloops : list of boundary loops out of the areas.
132   BOP_ListOfLoop                     boundaryloops; 
133   
134   myArea.Clear();          // Clear the list of Area to be built
135   
136   for (LS.InitLoop(); LS.MoreLoop(); LS.NextLoop()) {
137     
138     // process a new loop : L is the new current Loop
139     const Handle(BOP_Loop)& L = LS.Loop();
140     Standard_Boolean boundaryL = L->IsShape();
141     
142     // L = Shape et ForceClass  : on traite L comme un block
143     // L = Shape et !ForceClass : on traite L comme un pur Shape
144     // L = !Shape               : on traite L comme un block
145     Standard_Boolean traitercommeblock = (!boundaryL) || ForceClass;
146     if ( ! traitercommeblock ) {
147
148       // the loop L is a boundary loop : 
149       // - try to insert it in an existing area, such as L is inside all 
150       //   the block loops. Only block loops of the area are compared. 
151       // - if L could not be inserted, store it in list of boundary loops.
152
153       Loopinside = Standard_False; 
154       for (AreaIter.Initialize(myArea); AreaIter.More(); AreaIter.Next()) {
155         BOP_ListOfLoop& aArea = AreaIter.Value();
156         if ( aArea.IsEmpty() ) continue;
157         state = CompareLoopWithListOfLoop(LC,L,aArea,BOP_BLOCK );
158         if (state == TopAbs_UNKNOWN) {
159           Atomize(state,TopAbs_IN);
160         }       
161         Loopinside = ( state == TopAbs_IN);
162         if ( Loopinside ) {
163           break;
164         }
165       } // end of Area scan
166
167       if ( Loopinside ) {
168         BOP_ListOfLoop& aArea = AreaIter.Value();
169         ADD_Loop_TO_LISTOFLoop(L,aArea);
170       }
171       else if ( ! Loopinside ) {
172         ADD_Loop_TO_LISTOFLoop(L,boundaryloops);
173       }
174     } // end of boundary loop
175     
176     else { 
177       // the loop L is a block loop
178       // if L is IN theArea :
179       //   - stop area scan, insert L in theArea.
180       //   - remove from the area all the loops outside L
181       //   - make a new area with them, unless they are all boundary
182       //   - if they are all boundary put them back in boundaryLoops
183       // else :
184       //   - create a new area with L.
185       //   - insert boundary loops that are IN the new area
186       //     (and remove them from 'boundaryloops')
187       
188       Loopinside = Standard_False;
189
190       for (AreaIter.Initialize(myArea); AreaIter.More(); AreaIter.Next() ) {
191         BOP_ListOfLoop& aArea = AreaIter.Value();
192         if ( aArea.IsEmpty() ) {
193           continue;
194         }       
195         state = CompareLoopWithListOfLoop(LC,L,aArea,BOP_ANYLOOP);
196         if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN);
197         Loopinside = (state == TopAbs_IN);
198         if ( Loopinside ) {
199           break;
200         }
201       } // end of Area scan
202       
203       if ( Loopinside) {
204         BOP_ListOfLoop& aArea = AreaIter.Value();
205         Standard_Boolean allShape = Standard_True;
206         BOP_ListOfLoop removedLoops;
207         
208         LoopIter.Initialize(aArea);
209         while (LoopIter.More()) {
210           state = LC.Compare(LoopIter.Value(),L);
211           if (state == TopAbs_UNKNOWN){
212             Atomize(state,TopAbs_IN); // not OUT
213           }
214           
215           loopoutside = ( state == TopAbs_OUT );
216           
217           if ( loopoutside ) {
218             const Handle(BOP_Loop)& curL = LoopIter.Value();
219             // remove the loop from the area
220             ADD_Loop_TO_LISTOFLoop (curL,removedLoops);
221             
222             allShape = allShape && curL->IsShape();
223             REM_Loop_FROM_LISTOFLoop(LoopIter,AreaIter.Value());
224           }
225           else {
226             LoopIter.Next();
227           }
228         }
229         // insert the loop in the area
230         ADD_Loop_TO_LISTOFLoop(L,aArea);
231         if ( ! removedLoops.IsEmpty() ) {
232           if ( allShape ) {
233             ADD_LISTOFLoop_TO_LISTOFLoop(removedLoops,boundaryloops);
234           }
235           else {
236             // make a new area with the removed loops
237             BOP_ListOfLoop thelistofloop;
238             myArea.Append(thelistofloop);
239             ADD_LISTOFLoop_TO_LISTOFLoop (removedLoops,myArea.Last());
240           }
241         }
242       } // Loopinside == True
243       
244       else {
245         Standard_Integer ashapeinside,ablockinside;
246         BOP_ListOfLoop thelistofloop1;
247         myArea.Append(thelistofloop1);
248         BOP_ListOfLoop& newArea0 = myArea.Last();
249         ADD_Loop_TO_LISTOFLoop(L, newArea0);
250         
251         LoopIter.Initialize(boundaryloops);
252         while ( LoopIter.More() ) {
253           ashapeinside = ablockinside = Standard_False;
254           state = LC.Compare(LoopIter.Value(),L);
255           if (state == TopAbs_UNKNOWN) {
256             Atomize(state,TopAbs_IN);
257           }
258          
259           ashapeinside = (state == TopAbs_IN);
260           if (ashapeinside) {
261             state = LC.Compare(L,LoopIter.Value());
262             if (state == TopAbs_UNKNOWN){
263               Atomize(state,TopAbs_IN);
264             }       
265             ablockinside = (state == TopAbs_IN);
266           }
267
268           if ( ashapeinside && ablockinside ) {
269             const Handle(BOP_Loop)& curL = LoopIter.Value();
270             ADD_Loop_TO_LISTOFLoop(curL, newArea0);
271
272             REM_Loop_FROM_LISTOFLoop(LoopIter,boundaryloops);
273           }
274           else { 
275             LoopIter.Next();
276           }
277         } // end of boundaryloops scan
278       } // Loopinside == False
279     } // end of block loop
280   } // end of LoopSet LS scan
281   
282   InitArea();
283 }
284
285 //=======================================================================
286 //function : InitArea
287 //purpose  : 
288 //=======================================================================
289   Standard_Integer BOP_AreaBuilder::InitArea()
290 {
291   myAreaIterator.Initialize(myArea);
292   InitLoop();
293   Standard_Integer n = myArea.Extent();
294   return n;
295 }
296
297 //=======================================================================
298 //function : MoreArea
299 //purpose  : 
300 //=======================================================================
301   Standard_Boolean BOP_AreaBuilder::MoreArea() const
302 {
303   Standard_Boolean b = myAreaIterator.More();
304   return b;
305 }
306
307 //=======================================================================
308 //Function : NextArea
309 //Purpose  : 
310 //=======================================================================
311   void BOP_AreaBuilder::NextArea()
312 {
313   myAreaIterator.Next();
314   InitLoop();
315 }
316
317 //=======================================================================
318 //function : InitLoop
319 //purpose  : 
320 //=======================================================================
321   Standard_Integer BOP_AreaBuilder::InitLoop()
322 {
323   Standard_Integer n = 0;
324   if (myAreaIterator.More()) {
325     const BOP_ListOfLoop& LAL = myAreaIterator.Value();
326     myLoopIterator.Initialize(LAL);
327     n = LAL.Extent();
328   }
329   else { // Create an empty ListIteratorOfListOfLoop
330     myLoopIterator = BOP_ListIteratorOfListOfLoop();  
331   }
332   return n;
333 }
334
335 //=======================================================================
336 //function : MoreLoop
337 //purpose  : 
338 //=======================================================================
339   Standard_Boolean BOP_AreaBuilder::MoreLoop() const
340 {
341   Standard_Boolean b = myLoopIterator.More();
342   return b;
343 }
344
345 //=======================================================================
346 //function : NextLoop
347 //purpose  : 
348 //=======================================================================
349   void BOP_AreaBuilder::NextLoop()
350 {
351   myLoopIterator.Next();
352 }
353
354 //=======================================================================
355 //function : Loop
356 //purpose  : 
357 //=======================================================================
358   const Handle(BOP_Loop)& BOP_AreaBuilder::Loop() const
359 {
360   const Handle(BOP_Loop)& L = myLoopIterator.Value();
361   return L;
362 }
363
364 //=======================================================================
365 //function : ADD_Loop_TO_LISTOFLoop
366 //purpose  : 
367 //=======================================================================
368   void BOP_AreaBuilder::ADD_Loop_TO_LISTOFLoop(const Handle(BOP_Loop)& L,
369                                                BOP_ListOfLoop& LOL) const
370 {
371   LOL.Append(L);
372 }
373
374 //=======================================================================
375 //function : REM_Loop_FROM_LISTOFLoop
376 //purpose  : 
377 //=======================================================================
378   void BOP_AreaBuilder::REM_Loop_FROM_LISTOFLoop(BOP_ListIteratorOfListOfLoop& ITA,
379                                                  BOP_ListOfLoop& A) const
380 {
381   A.Remove(ITA);
382 }
383
384 //=======================================================================
385 //function : ADD_LISTOFLoop_TO_LISTOFLoop
386 //purpose  : 
387 //=======================================================================
388   void BOP_AreaBuilder::ADD_LISTOFLoop_TO_LISTOFLoop(BOP_ListOfLoop& A1,
389                                                      BOP_ListOfLoop& A2) const
390                                                      
391 {
392   A2.Append(A1);
393 }