0028248: [Regression] HLR Algo result is retrieved from the last added shape only
[occt.git] / src / HLRBRep / HLRBRep_EdgeBuilder.cxx
1 // Created on: 1997-04-17
2 // Created by: Christophe MARION
3 // Copyright (c) 1997-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 #ifndef No_Exception
18 #define No_Exception
19 #endif
20
21
22 #include <HLRAlgo_Intersection.hxx>
23 #include <HLRBRep_AreaLimit.hxx>
24 #include <HLRBRep_EdgeBuilder.hxx>
25 #include <HLRBRep_VertexList.hxx>
26 #include <Standard_DomainError.hxx>
27 #include <Standard_NoMoreObject.hxx>
28 #include <Standard_NoSuchObject.hxx>
29 #include <TopAbs.hxx>
30
31 //=======================================================================
32 //function : HLRBRep_EdgeBuilder
33 //purpose  : 
34 //=======================================================================
35 HLRBRep_EdgeBuilder::HLRBRep_EdgeBuilder (HLRBRep_VertexList& VList)
36 {
37   // at creation the EdgeBuilder explore the VertexList
38   // and use it to build a list of "AreaLimit" on the edge.
39   // An area is a part of the curve between 
40   // two consecutive vertices
41   
42   Standard_DomainError_Raise_if(!VList.More(),
43                                 "EdgeBuilder  : Empty vertex list");
44
45   Handle(HLRBRep_AreaLimit) last,cur;
46   TopAbs_State before,after,ebefore,eafter;
47   HLRAlgo_Intersection V;
48
49   // loop on the Vertices
50   for (;VList.More();VList.Next()) {
51     before = after = ebefore = eafter = TopAbs_UNKNOWN;
52     // compute the states
53     if (VList.IsBoundary()) {
54       switch (VList.Orientation()) {
55
56       case TopAbs_FORWARD :
57         ebefore = TopAbs_OUT;
58         eafter  = TopAbs_IN;
59         break;
60
61       case TopAbs_REVERSED :
62         ebefore = TopAbs_IN;
63         eafter  = TopAbs_OUT;
64         break;
65
66       case TopAbs_INTERNAL :
67         ebefore = TopAbs_IN;
68         eafter  = TopAbs_IN;
69         break;
70
71       case TopAbs_EXTERNAL :
72         ebefore = TopAbs_OUT;
73         eafter  = TopAbs_OUT;
74         break;
75       }
76     }
77
78     if (VList.IsInterference()) {
79       switch (VList.Transition()) {
80
81       case TopAbs_FORWARD :
82         before = TopAbs_OUT;
83         after  = TopAbs_IN;
84         break;
85
86       case TopAbs_REVERSED :
87         before = TopAbs_IN;
88         after  = TopAbs_OUT;
89         break;
90
91       case TopAbs_INTERNAL :
92         before = TopAbs_IN;
93         after  = TopAbs_IN;
94         break;
95
96       case TopAbs_EXTERNAL :
97         before = TopAbs_OUT;
98         after  = TopAbs_OUT;
99         break;
100       }
101
102       switch (VList.BoundaryTransition()) {
103
104       case TopAbs_FORWARD :
105         after  = TopAbs_ON;
106         break;
107
108       case TopAbs_REVERSED :
109         before = TopAbs_ON;
110         break;
111
112       case TopAbs_INTERNAL :
113         before = TopAbs_ON;
114         after  = TopAbs_ON;
115         break;
116
117       case TopAbs_EXTERNAL :
118         break;
119       }
120     }
121
122     // create the Limit and connect to list
123     V = VList.Current();
124     cur = new HLRBRep_AreaLimit(V,
125                                  VList.IsBoundary(),
126                                  VList.IsInterference(),
127                                  before,after,
128                                  ebefore,eafter);
129     if (myLimits.IsNull()) {
130       myLimits = cur;
131       last     = cur;
132     }
133     else {
134       last->Next(cur);
135       cur->Previous(last);
136       last = cur;
137     }
138   }
139
140   // periodicity, make a circular list
141   if (VList.IsPeriodic()) {
142     last->Next(myLimits);
143     myLimits->Previous(last);
144   }
145
146   // process UNKNOWN areas
147   TopAbs_State  stat = TopAbs_UNKNOWN;
148   TopAbs_State estat = TopAbs_UNKNOWN;
149
150   cur = myLimits;
151   while (!cur.IsNull()) {
152     if (stat == TopAbs_UNKNOWN) {
153       stat = cur->StateBefore();
154       if (stat == TopAbs_UNKNOWN) {
155         stat = cur->StateAfter();
156       }
157     }
158     if (estat == TopAbs_UNKNOWN) {
159       estat = cur->EdgeBefore();
160       if (estat == TopAbs_UNKNOWN) {
161         estat = cur->EdgeAfter();
162       }
163     }
164     cur = cur->Next();
165     // test for periodicicity
166     if (cur == myLimits)
167       break;
168   }
169
170   // error if no interferences
171   Standard_DomainError_Raise_if(stat == TopAbs_UNKNOWN,
172                                 "EdgeBuilder : No interferences");
173   // if no boundary the edge covers the whole curve
174   if (estat == TopAbs_UNKNOWN)
175     estat = TopAbs_IN;
176   
177   // propagate states
178   cur = myLimits;
179   while (!cur.IsNull()) {
180     if (cur->StateBefore() == TopAbs_UNKNOWN)
181       cur->StateBefore(stat);
182     else
183       stat = cur->StateAfter();
184     if (cur->StateAfter() == TopAbs_UNKNOWN)
185       cur->StateAfter(stat);
186     if (cur->EdgeBefore() == TopAbs_UNKNOWN)
187       cur->EdgeBefore(estat);
188     else
189       estat = cur->EdgeAfter();
190     if (cur->EdgeAfter() == TopAbs_UNKNOWN)
191       cur->EdgeAfter(estat);
192
193     cur = cur->Next();
194     if (cur == myLimits)
195       break;
196   }
197
198   // initialise with IN parts
199   Builds(TopAbs_IN);
200 }
201
202 //=======================================================================
203 //function : InitAreas
204 //purpose  : set on the first area
205 //=======================================================================
206
207 void HLRBRep_EdgeBuilder::InitAreas()
208 {
209   left = myLimits->Previous();
210   right = myLimits;
211 }
212
213 //=======================================================================
214 //function : NextArea
215 //purpose  : 
216 //=======================================================================
217
218 void HLRBRep_EdgeBuilder::NextArea()
219 {
220   left = right;
221   if (!right.IsNull())
222     right = right->Next();
223 }
224
225 //=======================================================================
226 //function : PreviousArea
227 //purpose  : 
228 //=======================================================================
229
230 void HLRBRep_EdgeBuilder::PreviousArea()
231 {
232   right = left;
233   if (!left.IsNull())
234     left = left->Previous();
235 }
236
237 //=======================================================================
238 //function : HasArea
239 //purpose  : 
240 //=======================================================================
241
242 Standard_Boolean HLRBRep_EdgeBuilder::HasArea() const
243 {
244   if (left.IsNull())
245     if (right.IsNull()) return Standard_False;
246   if (right == myLimits) return Standard_False;
247   return Standard_True;
248 }
249
250 //=======================================================================
251 //function : AreaState
252 //purpose  : 
253 //=======================================================================
254
255 TopAbs_State HLRBRep_EdgeBuilder::AreaState() const
256 {
257   TopAbs_State stat = TopAbs_UNKNOWN;
258   if (!left.IsNull())
259     stat = left->StateAfter();
260   if (!right.IsNull())
261     stat = right->StateBefore();
262   return stat;
263 }
264
265 //=======================================================================
266 //function : AreaEdgeState
267 //purpose  : 
268 //=======================================================================
269
270 TopAbs_State HLRBRep_EdgeBuilder::AreaEdgeState() const
271 {
272   TopAbs_State stat = TopAbs_UNKNOWN;
273   if (!left.IsNull())
274     stat = left->EdgeAfter();
275   if (!right.IsNull())
276     stat = right->EdgeBefore();
277   return stat;
278 }
279
280 //=======================================================================
281 //function : LeftLimit
282 //purpose  : 
283 //=======================================================================
284
285 Handle(HLRBRep_AreaLimit) HLRBRep_EdgeBuilder::LeftLimit() const
286 {
287   return left;
288 }
289
290 //=======================================================================
291 //function : RightLimit
292 //purpose  : 
293 //=======================================================================
294
295 Handle(HLRBRep_AreaLimit) HLRBRep_EdgeBuilder::RightLimit() const
296 {
297   return right;
298 }
299
300 //=======================================================================
301 //function : Builds
302 //purpose  : 
303 //=======================================================================
304
305 void  HLRBRep_EdgeBuilder::Builds(const TopAbs_State ToBuild)
306 {
307   toBuild = ToBuild;
308   InitAreas();
309   do {
310     if ((AreaState() == toBuild) &&
311         (AreaEdgeState() == TopAbs_IN)) {
312       if (left.IsNull())
313         current = 2;
314       else
315         current = 1;
316       return;
317     }
318     NextArea();
319   }
320   while (HasArea());
321   current = 3;
322 }
323
324 //=======================================================================
325 //function : MoreEdges
326 //purpose  : 
327 //=======================================================================
328
329 Standard_Boolean  HLRBRep_EdgeBuilder::MoreEdges() const
330 {
331   return HasArea();
332 }
333
334 //=======================================================================
335 //function : NextEdge
336 //purpose  : 
337 //=======================================================================
338
339 void  HLRBRep_EdgeBuilder::NextEdge()
340 {
341   // clean the current edge
342   while (AreaState() == toBuild)
343     NextArea();
344   // go to the next edge
345   while (HasArea()) {
346     if ((AreaState() == toBuild) &&
347         (AreaEdgeState() == TopAbs_IN)) {
348       if (left.IsNull())
349         current = 2;
350       else
351         current = 1;
352       return;
353     }
354     NextArea();
355   }
356 }
357
358 //=======================================================================
359 //function : MoreVertices
360 //purpose  : 
361 //=======================================================================
362
363 Standard_Boolean  HLRBRep_EdgeBuilder::MoreVertices() const
364 {
365   return (current < 3);
366 }
367
368 //=======================================================================
369 //function : NextVertex
370 //purpose  : 
371 //=======================================================================
372
373 void  HLRBRep_EdgeBuilder::NextVertex()
374 {
375   if (current == 1) {
376     current = 2;
377     if (right.IsNull())
378       current = 3;
379   }
380   else if (current == 2) {
381     NextArea();
382     if ((AreaState() == toBuild) && (AreaEdgeState() == TopAbs_IN))
383       current = 2;
384     else
385       current = 3;
386   }
387   else
388     throw Standard_NoSuchObject("EdgeBuilder::NextVertex : No current edge");
389 }
390
391 //=======================================================================
392 //function : Current
393 //purpose  : 
394 //=======================================================================
395
396 const HLRAlgo_Intersection& HLRBRep_EdgeBuilder::Current() const
397 {
398   if (current == 1)
399     return left->Vertex();
400   else if (current == 2)
401     return right->Vertex();
402   else
403     throw Standard_NoSuchObject("EdgeBuilder::Current : No current vertex");
404 }
405
406 //=======================================================================
407 //function : IsBoundary
408 //purpose  : 
409 //=======================================================================
410
411 Standard_Boolean  HLRBRep_EdgeBuilder::IsBoundary() const
412 {
413   if (current == 1)
414     return left->IsBoundary();
415   else if (current == 2)
416     return right->IsBoundary();
417   else
418     throw Standard_NoSuchObject("EdgeBuilder::IsBoundary : No current vertex");
419 }
420
421 //=======================================================================
422 //function : IsInterference
423 //purpose  : 
424 //=======================================================================
425
426 Standard_Boolean  HLRBRep_EdgeBuilder::IsInterference() const
427 {
428   if (current == 1)
429     return left->IsInterference();
430   else if (current == 2)
431     return right->IsInterference();
432   else
433     throw Standard_NoSuchObject("EdgeBuilder::IsInterference : No current vertex");
434 }
435
436 //=======================================================================
437 //function : Orientation
438 //purpose  : 
439 //=======================================================================
440
441 TopAbs_Orientation  HLRBRep_EdgeBuilder::Orientation() const
442 {
443   if (current == 1) {
444     if ((left->StateBefore() == left->StateAfter()) &&
445         (left->EdgeBefore()  == left->EdgeAfter()))
446       return TopAbs_INTERNAL;
447     else
448       return TopAbs_FORWARD;
449   }
450   else if (current == 2) {
451     if ((right->StateBefore() == right->StateAfter()) &&
452         (right->EdgeBefore()  == right->EdgeAfter()))
453       return TopAbs_INTERNAL;
454     else
455       return TopAbs_REVERSED;
456   }
457   return TopAbs_EXTERNAL; // only for WNT.
458 }
459
460 //=======================================================================
461 //function : Destroy
462 //purpose  : 
463 //=======================================================================
464
465 void HLRBRep_EdgeBuilder::Destroy()
466 {
467   Handle(HLRBRep_AreaLimit) cur = myLimits;
468   while (!cur.IsNull()) {
469     Handle(HLRBRep_AreaLimit) n = cur->Next();
470     cur->Clear();
471     cur = n;
472   }
473   left.Nullify();
474   right.Nullify();
475   myLimits.Nullify();
476 }