44b8338305a3f88c8a27846d36a9a950153b1298
[occt.git] / src / HLRBRep / HLRBRep_Hider.cxx
1 // Created on: 1997-04-17
2 // Created by: Christophe MARION
3 // Copyright (c) 1997-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 #define No_Standard_OutOfRange
23
24 #include <HLRBRep_Hider.ixx>
25
26 #include <HLRAlgo_Coincidence.hxx>
27 #include <HLRAlgo_Interference.hxx>
28 #include <HLRAlgo_InterferenceList.hxx>
29 #include <HLRAlgo_ListIteratorOfInterferenceList.hxx>
30 #include <HLRAlgo_Intersection.hxx>
31 #include <HLRBRep_EdgeIList.hxx>
32 #include <HLRBRep_EdgeBuilder.hxx>
33 #include <HLRBRep_VertexList.hxx>
34 #include <HLRBRep_EdgeInterferenceTool.hxx>
35 #include <Standard_ErrorHandler.hxx>
36
37 //=======================================================================
38 //function : HLRBRep_Hider
39 //purpose  : 
40 //=======================================================================
41
42 HLRBRep_Hider::
43 HLRBRep_Hider (const Handle(HLRBRep_Data)& DS) :
44   myDS(DS) 
45 {}
46
47 //=======================================================================
48 //function : OwnHiding
49 //purpose  : 
50 //=======================================================================
51
52 void HLRBRep_Hider::OwnHiding(const Standard_Integer)
53 {
54 }
55
56 //=======================================================================
57 //function : Hide
58 //purpose  : 
59 //=======================================================================
60
61 void HLRBRep_Hider::Hide(const Standard_Integer FI,
62                          BRepTopAdaptor_MapOfShapeTool& MST)
63 {
64   // *****************************************************************
65   //
66   // This algorithm hides a set of edges stored in the data structure <myDS>
67   // with the hiding face number FI in <myDS>.
68   //
69   // Outline of the algorithm
70   //
71   //   1. Loop on the Edges (not hidden and not rejected by the face minmax)
72   //   
73   //       The rejections depending of the face are 
74   //          - Edge above the face
75   //          - Edge belonging to the face
76   //          - Edge rejected by a wire minmax
77   //
78   //       Compute interferences with the not rejected edges of the face.
79   //           Store IN and ON interferences in two sorted lists
80   //               ILHidden and ILOn
81   //       If ILOn is not empty
82   //           Resolve ComplexTransitions in ILOn
83   //           Resolve ON Intersections in ILOn
84   //             An On interference may become
85   //               IN  : Move it from ILOn to ILHidden
86   //               OUT : Remove it from ILOn
87   //       If ILHidden and ILOn are empty
88   //           intersect the edge with the face and classify the Edge.
89   //               - if inside and under the face hide it.
90   //       Else
91   //         If ILHidden is not empty
92   //           Resolve ComplexTransitions in ILHidden
93   //           Build Hidden parts of the edge
94   //               - Hide them
95   //           Build visible parts of the edge
96   //           Build Parts of the edge under the boundary of the face
97   //               - Hide them as Boundary
98   //         If ILOn is not empty
99   //           Build ON parts of the edge
100   //               - Hide them as ON parts
101   //           Build Parts of the edge on the boundary of the face
102   //               - Hide them as ON parts on Boundary
103   // 
104   //
105   // *****************************************************************
106
107   myDS->InitEdge(FI,MST);
108   if (!myDS->MoreEdge())                        // there is nothing to do
109      return;                                    // **********************
110   HLRBRep_EdgeInterferenceTool EIT(myDS); // List of Intersections
111   HLRBRep_Array1OfEData& myEData = myDS->EDataArray();
112
113   for (; myDS->MoreEdge(); myDS->NextEdge()) {       // loop on the Edges
114     Standard_Integer E = myDS->Edge();               // *****************
115
116     try {
117       OCC_CATCH_SIGNALS
118       Standard_Boolean hasOut = Standard_False;
119       HLRAlgo_InterferenceList ILHidden;
120       HLRAlgo_InterferenceList ILOn;
121       EIT.LoadEdge();
122       
123       for (myDS->InitInterference();     // intersections with face-edges
124            myDS->MoreInterference();     // *****************************
125            myDS->NextInterference()) {
126         if (myDS->RejectedInterference()) {
127           if (myDS->AboveInterference() &&
128               myDS->SimpleHidingFace ()) { 
129             hasOut = Standard_True;
130           }
131         }
132         else {
133           HLRAlgo_Interference& Int = myDS->Interference();
134           switch (Int.Intersection().State()) {
135           case TopAbs_IN      :
136             HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT); break;
137           case TopAbs_ON      :
138             HLRBRep_EdgeIList::AddInterference(ILOn    ,Int,EIT); break;
139           case TopAbs_OUT     : 
140           case TopAbs_UNKNOWN :                                   break;
141           }
142         }
143       }
144       
145       //-- ============================================================
146       Standard_Boolean Modif;
147       do { 
148         Modif = Standard_False; 
149         HLRAlgo_ListIteratorOfInterferenceList ItSegHidden1(ILHidden);
150         while(ItSegHidden1.More() && Modif==Standard_False) { 
151           HLRAlgo_Interference& Int1 = ItSegHidden1.Value();
152           Standard_Integer numseg1=Int1.Intersection().SegIndex();
153           if(numseg1!=0) { 
154             HLRAlgo_ListIteratorOfInterferenceList ItSegHidden2(ILHidden);
155             while(ItSegHidden2.More()  && Modif==Standard_False) {
156               HLRAlgo_Interference& Int2 = ItSegHidden2.Value();
157               Standard_Integer numseg2=Int2.Intersection().SegIndex();
158               if(numseg1+numseg2 == 0) { 
159                 //--printf("\nHidden Traitement du segment %d  %d\n",numseg1,numseg2); fflush(stdout);
160                 TopAbs_State stbef1,staft1,stbef2,staft2;
161                 Int1.Boundary().State3D(stbef1,staft1);  
162                 Int2.Boundary().State3D(stbef2,staft2);
163                 if(Int1.Orientation() == Int2.Orientation()) {
164                   if(Int1.Transition() == Int2.Transition()) {
165                     if(stbef1==stbef2 && staft1==staft2 && stbef1!=TopAbs_ON && staft1!=TopAbs_ON ) { 
166                       //-- printf("\n Index1 = %d  Index2 = %d\n",Int1.Intersection().Index(),Int2.Intersection().Index());
167                       Standard_Integer nind=-1;
168                       if(Int1.Intersection().Index()!=0) { 
169                         nind=Int1.Intersection().Index();
170                       }
171                       if(Int2.Intersection().Index()!=0) {
172                         if(nind!=-1) {
173                           if(Int1.Intersection().Index() != Int2.Intersection().Index()) { 
174                             nind=-1;
175                           }
176                         }
177                         else { 
178                           nind=Int2.Intersection().Index();
179                         }
180                       }
181                       if(Int1.Intersection().Index()==0 && Int2.Intersection().Index()==0) nind=0;
182                      
183                       if(nind!=-1) { 
184                         //-- printf("\n Segment Supprime\n"); fflush(stdout);
185                         HLRAlgo_Intersection& inter = Int1.ChangeIntersection();
186                         inter.SegIndex(nind);
187                         Standard_Real p1 = Int1.Intersection().Parameter();
188                         Standard_Real p2 = Int2.Intersection().Parameter();
189                         inter.Parameter((p1+p2)*0.5);
190                         Int1.BoundaryTransition(TopAbs_EXTERNAL);
191
192                         ILHidden.Remove(ItSegHidden2);
193                         Modif=Standard_True;
194                       }
195                     }
196                   }
197                 }
198               }
199               if(Modif==Standard_False) { 
200                 ItSegHidden2.Next();
201               }
202             }
203           }
204           if(Modif==Standard_False) { 
205             ItSegHidden1.Next();
206           }
207         }
208       }
209       while(Modif);
210         
211
212       //-- ============================================================
213
214
215       if (!ILOn.IsEmpty()) {         // process the interferences on ILOn
216                                      // *********************************
217       
218         HLRBRep_EdgeIList::ProcessComplex   // complex transition on ILOn
219           (ILOn,EIT);                       // **************************
220
221         HLRAlgo_ListIteratorOfInterferenceList It(ILOn); 
222         
223         while(It.More()) {           // process Intersections on the Face
224                                      // *********************************
225           
226           HLRAlgo_Interference& Int = It.Value();
227           TopAbs_State stbef, staft;                // read the 3d states
228           Int.Boundary().State3D(stbef,staft);      // ******************
229
230           switch (Int.Transition()) {
231           case TopAbs_FORWARD  :
232             switch (staft) {
233             case TopAbs_OUT     :
234               ILOn.Remove(It);                            break;
235             case TopAbs_IN      :
236               HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT);
237               ILOn.Remove(It);                            break;
238             case TopAbs_UNKNOWN : cout << "UNKNOWN state staft" << endl;
239             case TopAbs_ON      :
240               It.Next();                                  break;
241             }                                             break;
242           case TopAbs_REVERSED :
243             switch (stbef) {
244             case TopAbs_OUT     :
245               ILOn.Remove(It);                            break;
246             case TopAbs_IN      :
247               HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT);
248               ILOn.Remove(It);                            break;
249             case TopAbs_UNKNOWN : cout << "UNKNOWN state stbef" << endl;
250             case TopAbs_ON      :
251               It.Next();                                  break;
252             }                                             break;
253           case TopAbs_EXTERNAL :
254             ILOn.Remove(It);                              break;
255           case TopAbs_INTERNAL :
256             switch (stbef) {
257             case TopAbs_IN        :
258               switch (staft) {
259               case TopAbs_IN      :
260                 HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT);
261                 ILOn.Remove(It);                          break;
262               case TopAbs_ON      :
263                 Int.Transition(TopAbs_FORWARD );      // FORWARD  in ILOn,
264                 HLRBRep_EdgeIList::AddInterference    // REVERSED in ILHidden
265                   (ILHidden,HLRAlgo_Interference   
266                    (Int.Intersection(),
267                     Int.Boundary(),
268                     Int.Orientation(),
269                     TopAbs_REVERSED,
270                     Int.BoundaryTransition()),EIT);
271                 It.Next();                                break;
272               case TopAbs_OUT     :
273                 Int.Transition(TopAbs_REVERSED);      // set REVERSED
274                 HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT);
275                 ILOn.Remove(It);                          break;
276               case TopAbs_UNKNOWN :
277                 cout << "UNKNOWN state after" << endl;
278                 It.Next();                                break;
279               }                                           break;
280             case TopAbs_ON :
281               switch (staft) {
282               case TopAbs_IN      :
283                 Int.Transition(TopAbs_REVERSED);      // REVERSED in ILOn,
284                 HLRBRep_EdgeIList::AddInterference    // REVERSED in ILHidden
285                   (ILHidden,HLRAlgo_Interference   
286                    (Int.Intersection(),
287                     Int.Boundary(),
288                     Int.Orientation(),
289                     TopAbs_FORWARD,
290                     Int.BoundaryTransition()),EIT);       break;
291               case TopAbs_ON      :                       break;
292               case TopAbs_OUT     :
293                 Int.Transition(TopAbs_REVERSED);          break;
294               case TopAbs_UNKNOWN :
295                 cout << "UNKNOWN state after" << endl;    break;
296               }     
297               It.Next();                                  break;
298             case TopAbs_OUT :
299               switch (staft) {
300               case TopAbs_IN      :
301                 Int.Transition(TopAbs_FORWARD);       // set FORWARD
302                 HLRBRep_EdgeIList::AddInterference(ILHidden,Int,EIT);
303                 ILOn.Remove(It);                          break;
304               case TopAbs_ON      :
305                 Int.Transition(TopAbs_FORWARD );      // FORWARD  in ILOn
306                 It.Next();                                break;
307               case TopAbs_OUT     :
308                 ILOn.Remove(It);                          break;
309               case TopAbs_UNKNOWN :
310                 cout << "UNKNOWN state after" << endl;
311                 It.Next();                                break;
312               }                                           break;
313             case TopAbs_UNKNOWN :
314               cout << "UNKNOWN state stbef" << endl;      break;
315             }
316           }
317         }
318       }
319       
320       if (ILHidden.IsEmpty() && ILOn.IsEmpty() && !hasOut) {
321         HLRBRep_EdgeData& ed = myEData(E);
322         TopAbs_State st = myDS->Compare(E,ed);              // Classification
323         if (st == TopAbs_IN || st == TopAbs_ON)             // **************
324           ed.Status().HideAll();
325       }
326       else {
327         Standard_Real p1 = 0.,p2 = 0.;
328         Standard_ShortReal tol1 = 0., tol2 = 0.;
329
330         HLRBRep_EdgeData& ed = myEData(E);
331         HLRAlgo_EdgeStatus& ES = ed.Status();
332
333         Standard_Boolean foundHidden = Standard_False;
334         
335         Standard_Integer aStartLevel;
336         if (!ILHidden.IsEmpty()) {    
337
338           HLRBRep_EdgeIList::ProcessComplex // complex transition on ILHidden
339             (ILHidden,EIT);                 // ******************************
340           Standard_Integer level = 0;
341           if (!myDS->SimpleHidingFace())                    // Level at Start
342             level = myDS->HidingStartLevel(E,ed,ILHidden);  // **************
343                   HLRAlgo_ListIteratorOfInterferenceList It(ILHidden); 
344           
345           aStartLevel = level;
346           while(It.More()) {           // suppress multi-inside Intersections
347                                        // ***********************************
348           
349             HLRAlgo_Interference& Int = It.Value();
350             switch (Int.Transition()) {
351               
352             case TopAbs_FORWARD  :
353               {
354                 Standard_Integer decal = Int.Intersection().Level();
355                 if (level > 0) ILHidden.Remove(It);
356                 else           It.Next();
357                 level = level + decal;
358               }
359               break;
360             case TopAbs_REVERSED : 
361               { 
362                 level = level - Int.Intersection().Level();
363                 if (level > 0) ILHidden.Remove(It);
364                 else           It.Next();
365               }
366               break;
367             case TopAbs_EXTERNAL :
368               It.Next();
369               break;
370             case TopAbs_INTERNAL :
371               It.Next();
372               break;
373             default :
374               It.Next();
375               break;
376             }
377           }
378           if (ILHidden.IsEmpty())                             // Edge hidden
379             ES.HideAll();                                     // ***********
380           else
381             foundHidden = Standard_True;
382         }
383
384
385         if (!ILHidden.IsEmpty()) {
386           //IFV
387
388           TopAbs_State aBuildIN = TopAbs_IN;
389           Standard_Boolean IsSuspision = Standard_True;
390           
391           Standard_Real pmax, pmin;
392           Standard_Boolean allInt = Standard_False;
393           Standard_Boolean allFor = Standard_False;
394           Standard_Boolean allRev = Standard_False;
395           pmin = RealLast();
396           pmax = -pmin;
397
398           if(ILHidden.Extent() > 1 ) {
399             allInt = Standard_True;
400             allFor = Standard_True;
401             allRev = Standard_True;
402             HLRAlgo_ListIteratorOfInterferenceList It(ILHidden);
403             for(;It.More(); It.Next()) {
404               Standard_Real p = It.Value().Intersection().Parameter();
405               allFor = allFor && ( It.Value().Transition() == TopAbs_FORWARD);
406               allRev = allRev && ( It.Value().Transition() == TopAbs_REVERSED);
407               allInt = allInt && ( It.Value().Transition() == TopAbs_INTERNAL);
408               if(p < pmin) pmin = p;
409               if(p > pmax) pmax = p;
410             }
411
412           }
413           
414           HLRAlgo_ListIteratorOfInterferenceList Itl(ILHidden);
415           HLRBRep_VertexList IL(EIT,Itl);
416
417
418           HLRBRep_EdgeBuilder EB(IL);
419           
420           EB.Builds(aBuildIN);                         // build hidden parts
421                                                        // ******************
422           while (EB.MoreEdges()) {
423             while (EB.MoreVertices()) {
424               switch (EB.Orientation()) {
425               case TopAbs_FORWARD  : 
426                 p1   =  EB.Current().Parameter(); 
427                 tol1 =  EB.Current().Tolerance();
428                 break;
429               case TopAbs_REVERSED :
430                 p2   =  EB.Current().Parameter(); 
431                 tol2 =  EB.Current().Tolerance();
432                 break;
433               case TopAbs_INTERNAL :
434               case TopAbs_EXTERNAL :
435                 break;
436               }
437               EB.NextVertex();
438             }
439
440             if(Abs(p1 - p2) <= 1.e-7) {
441               EB.NextEdge();
442               continue;
443             }
444
445             if(allInt) {
446               if(p1 < pmin) p1 = pmin;
447               if(p2 > pmax) p2 = pmax;
448               //HLRBRep_EdgeData& ed = myEData(E);
449               //TopAbs_State st = myDS->Compare(E,ed);              // Classification
450             }
451             
452             TopAbs_State aTestState = TopAbs_IN;
453             if(IsSuspision) {
454               Standard_Integer aNbp = 1;
455               aTestState = myDS->SimplClassify(E, ed, aNbp, p1, p2);
456             }
457
458             if(aTestState != TopAbs_OUT) {
459               ES.Hide(p1,tol1,p2,tol2,
460                       Standard_False,   // under  the Face
461                       Standard_False);  // inside the Face
462             }
463             
464             EB.NextEdge();
465           }
466           
467           EB.Builds(TopAbs_ON);             // build parts under the boundary
468                                             // ******************************
469           while (EB.MoreEdges()) {
470             while (EB.MoreVertices()) {
471               switch (EB.Orientation()) {
472               case TopAbs_FORWARD  :
473                 p1   = EB.Current().Parameter(); 
474                 tol1 = EB.Current().Tolerance();
475                 break;
476               case TopAbs_REVERSED :
477                 p2   = EB.Current().Parameter(); 
478                 tol2 = EB.Current().Tolerance();
479                 break;
480               case TopAbs_INTERNAL :
481               case TopAbs_EXTERNAL :
482                 break;
483               }
484               EB.NextVertex();
485             }
486             ES.Hide(p1,tol1,p2,tol2,
487                     Standard_False,   // under the Face
488                     Standard_True);   // on the boundary
489             EB.NextEdge();
490           }
491         }      
492         
493         if (!ILOn.IsEmpty()) {
494           Standard_Integer level = 0;
495           if (!myDS->SimpleHidingFace())                    // Level at Start
496             level = myDS->HidingStartLevel(E,ed,ILOn);      // **************
497           if (level > 0) {
498             HLRAlgo_ListIteratorOfInterferenceList It(ILOn); 
499             
500             while(It.More()) {         // suppress multi-inside Intersections
501                                        // ***********************************
502               
503               HLRAlgo_Interference& Int = It.Value();
504               switch (Int.Transition()) {
505                 
506               case TopAbs_FORWARD  :
507                 {
508                   Standard_Integer decal = Int.Intersection().Level();
509                   if (level > 0) ILOn.Remove(It);
510                   else           It.Next();
511                   level = level + decal;
512                 }
513                 break;
514               case TopAbs_REVERSED :
515                 level = level - Int.Intersection().Level();
516                 if (level > 0) ILOn.Remove(It);
517                 else           It.Next();
518                 break;
519               case TopAbs_EXTERNAL :
520               case TopAbs_INTERNAL :
521                 default :
522                 It.Next();
523                 break;
524               }
525             }
526             if (ILOn.IsEmpty() && !foundHidden)               // Edge hidden
527               ES.HideAll();                                   // ***********
528           }
529         }
530         
531         if (!ILOn.IsEmpty()) {
532           HLRBRep_VertexList IL(EIT,ILOn);
533           HLRBRep_EdgeBuilder EB(IL);
534           
535           EB.Builds (TopAbs_IN);                   // build parts on the Face
536                                                    // ***********************
537           while (EB.MoreEdges()) {
538             while (EB.MoreVertices()) {
539               switch (EB.Orientation()) {
540               case TopAbs_FORWARD  : 
541                 p1   = EB.Current().Parameter(); 
542                 tol1 = EB.Current().Tolerance();
543                 break;
544               case TopAbs_REVERSED :
545                 p2   = EB.Current().Parameter(); 
546                 tol2 = EB.Current().Tolerance();
547                 break;
548               case TopAbs_INTERNAL :
549               case TopAbs_EXTERNAL :   
550                 break;
551               }
552               EB.NextVertex();
553             }
554             ES.Hide(p1,tol1,p2,tol2,
555                     Standard_True,    // on     the Face
556                     Standard_False);  // inside the Face
557             EB.NextEdge();
558           }
559           
560           EB.Builds(TopAbs_ON);      // build hidden parts under the boundary
561                                      // *************************************
562           while (EB.MoreEdges()) {
563             while (EB.MoreVertices()) {
564               switch (EB.Orientation()) {
565               case TopAbs_FORWARD  :
566                 p1   = EB.Current().Parameter(); 
567                 tol1 = EB.Current().Tolerance();
568                 break;
569               case TopAbs_REVERSED :
570                 p2   = EB.Current().Parameter(); 
571                 tol2 = EB.Current().Tolerance();
572                 break;
573               case TopAbs_INTERNAL :
574               case TopAbs_EXTERNAL :
575                 break;
576               }
577               EB.NextVertex();
578             }
579             ES.Hide(p1,tol1,p2,tol2,
580                     Standard_True,    // on the Face
581                     Standard_True);   // on the boundary
582             EB.NextEdge();
583           }
584         }
585       }
586
587     }
588
589     catch(Standard_Failure) {
590 #ifdef DEB
591       cout << "An exception was catched when hiding edge " << E;
592       cout << " by the face " << FI << endl;
593       Handle(Standard_Failure) fail = Standard_Failure::Caught();
594       cout << fail << endl;
595 #endif
596     }
597   }
598 }