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