0027067: Avoid use of virtual methods for implementation of destructors in legacy...
[occt.git] / src / TopOpeBRepBuild / TopOpeBRepBuild_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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // " Voyager, c'est bien utile, ca fait travailler l'imagination.
18 //   Tout le reste n'est que deceptions et fatigues. Notre voyage 
19 //   a nous est entierement imaginaire. Voila sa force. "
20 //                         Celine
21 //                         Voyage au bout de la nuit
22
23 #include <Standard_DomainError.hxx>
24 #include <TopAbs.hxx>
25 #include <TopOpeBRepBuild_AreaBuilder.hxx>
26 #include <TopOpeBRepBuild_Loop.hxx>
27 #include <TopOpeBRepBuild_LoopClassifier.hxx>
28 #include <TopOpeBRepBuild_LoopSet.hxx>
29
30 #ifdef OCCT_DEBUG
31 extern Standard_Boolean TopOpeBRepDS_GettraceSTRANGE();
32 #endif
33
34 //=======================================================================
35 //function : TopOpeBRepBuild_AreaBuilder
36 //purpose  : 
37 //=======================================================================
38
39 TopOpeBRepBuild_AreaBuilder::TopOpeBRepBuild_AreaBuilder() :
40 myUNKNOWNRaise(Standard_False) // no raise if UNKNOWN state found
41 {
42 }
43
44 //=======================================================================
45 //function : TopOpeBRepBuild_AreaBuilder
46 //purpose  : 
47 //=======================================================================
48
49 TopOpeBRepBuild_AreaBuilder::TopOpeBRepBuild_AreaBuilder
50 (TopOpeBRepBuild_LoopSet&        LS,
51  TopOpeBRepBuild_LoopClassifier& LC,
52  const Standard_Boolean ForceClass) :
53 myUNKNOWNRaise(Standard_False) // no raise if UNKNOWN state found
54 {
55   InitAreaBuilder(LS,LC,ForceClass);
56 }
57
58 TopOpeBRepBuild_AreaBuilder::~TopOpeBRepBuild_AreaBuilder()
59 {}
60
61 //=======================================================================
62 //function : CompareLoopWithListOfLoop
63 //purpose  : Compare position of the Loop <L> with the Area <LOL>
64 //           using the Loop Classifier <LC>.
65 //           According to <whattotest>, Loops of <LOL> are selected or not
66 //           during <LOL> exploration.
67 //result   : TopAbs_OUT if <LOL> is empty
68 //           TopAbs_UNKNOWN if position undefined
69 //           TopAbs_IN  if <L> is inside all the selected Loops of <LOL>
70 //           TopAbs_OUT if <L> is outside one of the selected Loops of <LOL>
71 //           TopAbs_ON  if <L> is on one of the selected Loops of <LOL>
72 //=======================================================================
73 TopAbs_State TopOpeBRepBuild_AreaBuilder::CompareLoopWithListOfLoop
74 (TopOpeBRepBuild_LoopClassifier   &LC,
75  const Handle(TopOpeBRepBuild_Loop)& L,
76  const TopOpeBRepBuild_ListOfLoop &LOL,
77  const TopOpeBRepBuild_LoopEnum   what) const
78 {
79   TopAbs_State                 state = TopAbs_UNKNOWN;
80   Standard_Boolean             totest; // L must or not be tested
81   TopOpeBRepBuild_ListIteratorOfListOfLoop LoopIter;  
82   
83   if ( LOL.IsEmpty() ) return TopAbs_OUT;
84   
85   for ( LoopIter.Initialize(LOL); LoopIter.More(); LoopIter.Next() ) {
86     const Handle(TopOpeBRepBuild_Loop)& curL = LoopIter.Value();
87     switch ( what ) { 
88     case TopOpeBRepBuild_ANYLOOP  : totest = Standard_True;break;
89     case TopOpeBRepBuild_BOUNDARY : totest =  curL->IsShape();break;
90     case TopOpeBRepBuild_BLOCK    : totest = !curL->IsShape();break;
91     default                       : totest = Standard_False;
92     }
93     if ( totest ) {
94       state = LC.Compare(L,curL);
95       if (state == TopAbs_OUT) 
96         // <L> is out of at least one Loop of <LOL> : stop to explore
97         break;  
98     }
99   }
100   
101   return state;
102 }
103
104 //=======================================================================
105 //function : Atomize
106 //purpose  : myUNKNOWNRaise = True --> raise if <state> = UNKNOWN
107 //           myUNKNOWNRaise = False--> assign a new value <newstate> to <state>
108 //=======================================================================
109
110 void TopOpeBRepBuild_AreaBuilder::Atomize(TopAbs_State& state, 
111                                           const TopAbs_State newstate) const
112 {
113   if (myUNKNOWNRaise) {
114     Standard_DomainError_Raise_if((state == TopAbs_UNKNOWN),
115                                   "AreaBuilder : Position Unknown");
116   }
117   else {
118 #ifdef OCCT_DEBUG
119     if ( TopOpeBRepDS_GettraceSTRANGE() ) { 
120       cout<<"AreaBuilder : state "; TopAbs::Print(state,cout);
121       cout<<" taken as "; TopAbs::Print(newstate,cout); cout<<endl;
122     }
123 #endif
124     state = newstate;
125   }
126 }
127
128
129 //=======================================================================
130 //function : InitAreaBuilder
131 //purpose  : 
132 //=======================================================================
133
134 void TopOpeBRepBuild_AreaBuilder::InitAreaBuilder
135 (TopOpeBRepBuild_LoopSet&        LS,
136  TopOpeBRepBuild_LoopClassifier& LC,
137  const Standard_Boolean ForceClass)
138 {
139   TopAbs_State     state;
140   Standard_Boolean Loopinside;
141   Standard_Boolean loopoutside;
142   
143   TopOpeBRepBuild_ListIteratorOfListOfListOfLoop AreaIter;
144   TopOpeBRepBuild_ListIteratorOfListOfLoop       LoopIter;
145   // boundaryloops : list of boundary loops out of the areas.
146   TopOpeBRepBuild_ListOfLoop                     boundaryloops; 
147   
148   myArea.Clear();          // Clear the list of Area to be built
149   
150   for (LS.InitLoop(); LS.MoreLoop(); LS.NextLoop()) {
151     
152     // process a new loop : L is the new current Loop
153     const Handle(TopOpeBRepBuild_Loop)& L = LS.Loop();
154     Standard_Boolean boundaryL = L->IsShape();
155     
156     // L = Shape et ForceClass  : on traite L comme un block
157     // L = Shape et !ForceClass : on traite L comme un pur Shape
158     // L = !Shape               : on traite L comme un block
159     Standard_Boolean traitercommeblock = (!boundaryL) || ForceClass;
160     if ( ! traitercommeblock ) {
161
162       // the loop L is a boundary loop : 
163       // - try to insert it in an existing area, such as L is inside all 
164       //   the block loops. Only block loops of the area are compared. 
165       // - if L could not be inserted, store it in list of boundary loops.
166
167       Loopinside = Standard_False; 
168       for (AreaIter.Initialize(myArea); AreaIter.More(); AreaIter.Next()) {
169         TopOpeBRepBuild_ListOfLoop& aArea = AreaIter.Value();
170         if ( aArea.IsEmpty() ) continue;
171         state = CompareLoopWithListOfLoop(LC,L,aArea,TopOpeBRepBuild_BLOCK );
172         if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN);
173         Loopinside = ( state == TopAbs_IN);
174         if ( Loopinside ) break;
175       } // end of Area scan
176
177       if ( Loopinside ) {
178         TopOpeBRepBuild_ListOfLoop& aArea = AreaIter.Value();
179         ADD_Loop_TO_LISTOFLoop(L,aArea,(void*)("IN, to current area"));
180       }
181       else if ( ! Loopinside ) {
182         ADD_Loop_TO_LISTOFLoop(L,boundaryloops,(void*)("! IN, to boundaryloops"));
183       }
184
185     } // end of boundary loop
186     
187     else { 
188       // the loop L is a block loop
189       // if L is IN theArea :
190       //   - stop area scan, insert L in theArea.
191       //   - remove from the area all the loops outside L
192       //   - make a new area with them, unless they are all boundary
193       //   - if they are all boundary put them back in boundaryLoops
194       // else :
195       //   - create a new area with L.
196       //   - insert boundary loops that are IN the new area
197       //     (and remove them from 'boundaryloops')
198       
199       Loopinside = Standard_False;
200       for (AreaIter.Initialize(myArea); AreaIter.More(); AreaIter.Next() ) {
201         TopOpeBRepBuild_ListOfLoop& aArea = AreaIter.Value();
202         if ( aArea.IsEmpty() ) continue;
203         state = CompareLoopWithListOfLoop(LC,L,aArea,TopOpeBRepBuild_ANYLOOP);
204         if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN);
205         Loopinside = (state == TopAbs_IN);
206         if ( Loopinside ) break;
207       } // end of Area scan
208       
209       if ( Loopinside) {
210         TopOpeBRepBuild_ListOfLoop& aArea = AreaIter.Value();
211         Standard_Boolean allShape = Standard_True;
212         TopOpeBRepBuild_ListOfLoop removedLoops;
213         LoopIter.Initialize(aArea);
214         while (LoopIter.More()) {
215           state = LC.Compare(LoopIter.Value(),L);
216           if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN); // not OUT
217           loopoutside = ( state == TopAbs_OUT );
218           if ( loopoutside ) {
219             const Handle(TopOpeBRepBuild_Loop)& curL = LoopIter.Value();
220             // remove the loop from the area
221             ADD_Loop_TO_LISTOFLoop
222               (curL,removedLoops,(void*)("loopoutside = 1, area = removedLoops"));
223             
224             allShape = allShape && curL->IsShape();
225             REM_Loop_FROM_LISTOFLoop
226               (LoopIter,AreaIter.Value(),(void*)("loop of cur. area, cur. area"));
227           }
228           else {
229             LoopIter.Next();
230           }
231         }
232         // insert the loop in the area
233         ADD_Loop_TO_LISTOFLoop(L,aArea,(void*)("area = current"));
234         if ( ! removedLoops.IsEmpty() ) {
235           if ( allShape ) {
236             ADD_LISTOFLoop_TO_LISTOFLoop
237               (removedLoops,boundaryloops,
238                (void*)("allShape = 1"),(void*)("removedLoops"),(void*)("boundaryloops"));
239           }
240           else {
241             // make a new area with the removed loops
242             TopOpeBRepBuild_ListOfLoop thelist;
243             myArea.Append(thelist);
244             ADD_LISTOFLoop_TO_LISTOFLoop
245               (removedLoops,myArea.Last(),
246                (void*)("allShape = 0"),(void*)("removedLoops"),(void*)("new area"));
247           }
248         }
249       } // Loopinside == True
250       
251       else {
252         Standard_Integer ashapeinside,ablockinside;
253         TopOpeBRepBuild_ListOfLoop thelist1;
254         myArea.Append(thelist1);
255         TopOpeBRepBuild_ListOfLoop& newArea0 = myArea.Last();
256         ADD_Loop_TO_LISTOFLoop(L,newArea0,(void*)("new area"));
257         
258         LoopIter.Initialize(boundaryloops);
259         while ( LoopIter.More() ) {
260           ashapeinside = ablockinside = Standard_False;
261           state = LC.Compare(LoopIter.Value(),L);
262           if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN);
263           ashapeinside = (state == TopAbs_IN);
264           if (ashapeinside) {
265             state = LC.Compare(L,LoopIter.Value());
266             if (state == TopAbs_UNKNOWN) Atomize(state,TopAbs_IN);
267             ablockinside = (state == TopAbs_IN);
268           }
269           if ( ashapeinside && ablockinside ) {
270             const Handle(TopOpeBRepBuild_Loop)& curL = LoopIter.Value();
271             ADD_Loop_TO_LISTOFLoop
272               (curL,newArea0,(void*)("ashapeinside && ablockinside, new area"));
273
274             REM_Loop_FROM_LISTOFLoop
275               (LoopIter,boundaryloops,(void*)("loop of boundaryloops, boundaryloops"));
276           }
277           else { 
278             LoopIter.Next();
279           }
280         } // end of boundaryloops scan
281       } // Loopinside == False
282     } // end of block loop
283   } // end of LoopSet LS scan
284   
285   InitArea();
286 }
287
288 //=======================================================================
289 //function : InitArea
290 //purpose  : 
291 //=======================================================================
292
293 Standard_Integer TopOpeBRepBuild_AreaBuilder::InitArea()
294 {
295   myAreaIterator.Initialize(myArea);
296   InitLoop();
297   Standard_Integer n = myArea.Extent();
298   return n;
299 }
300
301 //=======================================================================
302 //function : MoreArea
303 //purpose  : 
304 //=======================================================================
305
306 Standard_Boolean TopOpeBRepBuild_AreaBuilder::MoreArea() const
307 {
308   Standard_Boolean b = myAreaIterator.More();
309   return b;
310 }
311
312 //=======================================================================
313 //Function : NextArea
314 //Purpose  : 
315 //=======================================================================
316
317 void TopOpeBRepBuild_AreaBuilder::NextArea()
318 {
319   myAreaIterator.Next();
320   InitLoop();
321 }
322
323 //=======================================================================
324 //function : InitLoop
325 //purpose  : 
326 //=======================================================================
327
328 Standard_Integer TopOpeBRepBuild_AreaBuilder::InitLoop()
329 {
330   Standard_Integer n = 0;
331   if (myAreaIterator.More()) {
332     const TopOpeBRepBuild_ListOfLoop& LAL = myAreaIterator.Value();
333     myLoopIterator.Initialize(LAL);
334     n = LAL.Extent();
335   }
336   else { // Create an empty ListIteratorOfListOfLoop
337     myLoopIterator = TopOpeBRepBuild_ListIteratorOfListOfLoop();  
338   }
339   return n;
340 }
341
342 //=======================================================================
343 //function : MoreLoop
344 //purpose  : 
345 //=======================================================================
346
347 Standard_Boolean TopOpeBRepBuild_AreaBuilder::MoreLoop() const
348 {
349   Standard_Boolean b = myLoopIterator.More();
350   return b;
351 }
352
353 //=======================================================================
354 //function : NextLoop
355 //purpose  : 
356 //=======================================================================
357
358 void TopOpeBRepBuild_AreaBuilder::NextLoop()
359 {
360   myLoopIterator.Next();
361 }
362
363 //=======================================================================
364 //function : Loop
365 //purpose  : 
366 //=======================================================================
367
368 const Handle(TopOpeBRepBuild_Loop)& TopOpeBRepBuild_AreaBuilder::Loop() const
369 {
370   const Handle(TopOpeBRepBuild_Loop)& L = myLoopIterator.Value();
371   return L;
372 }
373
374 //=======================================================================
375 //function : ADD_Loop_TO_LISTOFLoop
376 //purpose  : 
377 //=======================================================================
378
379 void TopOpeBRepBuild_AreaBuilder::ADD_Loop_TO_LISTOFLoop
380   (const Handle(TopOpeBRepBuild_Loop)& L,
381    TopOpeBRepBuild_ListOfLoop& LOL,
382    const Standard_Address /*ss*/) const
383 {
384   LOL.Append(L);
385 }
386
387 //=======================================================================
388 //function : REM_Loop_FROM_LISTOFLoop
389 //purpose  : 
390 //=======================================================================
391
392 void TopOpeBRepBuild_AreaBuilder::REM_Loop_FROM_LISTOFLoop
393   (TopOpeBRepBuild_ListIteratorOfListOfLoop& ITA,
394    TopOpeBRepBuild_ListOfLoop& A,
395    const Standard_Address /*ss*/) const
396 {
397   A.Remove(ITA);
398 }
399
400 //=======================================================================
401 //function : ADD_LISTOFLoop_TO_LISTOFLoop
402 //purpose  : 
403 //=======================================================================
404
405 void TopOpeBRepBuild_AreaBuilder::ADD_LISTOFLoop_TO_LISTOFLoop
406   (TopOpeBRepBuild_ListOfLoop& A1,
407    TopOpeBRepBuild_ListOfLoop& A2,
408    const Standard_Address /*ss*/,
409    const Standard_Address /*ss1*/,
410    const Standard_Address /*ss2*/) const
411 {
412   A2.Append(A1);
413 }