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