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