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