0024933: Inconsistent results of self-interferences checker in SALOME and DRAW Applic...
[occt.git] / src / BOPTest / BOPTest_CheckCommands.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPTest.ixx>
16
17 #include <vector>
18 #include <algorithm>
19 #include <functional>
20
21 #include <TCollection_AsciiString.hxx>
22
23 #include <TopoDS_Shape.hxx>
24 #include <TopoDS_Compound.hxx>
25 #include <BRep_Builder.hxx>
26 #include <BRepBuilderAPI_Copy.hxx>
27
28 #include <DBRep.hxx>
29 #include <Draw.hxx>
30
31 #include <BOPCol_ListOfShape.hxx>
32
33 #include <BOPDS_DS.hxx>
34 #include <BOPDS_MapOfPassKey.hxx>
35
36 #include <BOPAlgo_CheckerSI.hxx>
37 #include <BOPAlgo_ArgumentAnalyzer.hxx>
38 #include <BOPAlgo_CheckResult.hxx>
39
40 #include <BOPTest_Chronometer.hxx>
41 //
42 static 
43   void MakeShapeForFullOutput (const TCollection_AsciiString&,
44                                const Standard_Integer,
45                                const BOPCol_ListOfShape&,
46                                Standard_Integer& ,
47                                Draw_Interpretor&);
48 //
49 static Standard_Integer bopcheck   (Draw_Interpretor&, Standard_Integer, const char** );
50 static Standard_Integer bopargcheck(Draw_Interpretor&, Standard_Integer, const char** );
51
52 //=======================================================================
53 //function : CheckCommands
54 //purpose  : 
55 //=======================================================================
56 void  BOPTest::CheckCommands(Draw_Interpretor& theCommands)
57 {
58   static Standard_Boolean done = Standard_False;
59   if (done) 
60     return;
61
62   done = Standard_True;
63   // Chapter's name
64   const char* g = "CCR commands";
65   //
66   theCommands.Add("bopcheck",  
67                   "Use >bopcheck Shape [level of check: 0(V/V) - 5(all)]",
68                   __FILE__, bopcheck, g);
69   theCommands.Add("bopargcheck" , 
70                   "Use bopargcheck without parameters to get ",  
71                   __FILE__, bopargcheck, g);
72 }
73 //=======================================================================
74 //class    : BOPTest_Interf
75 //purpose  : Auxiliary class
76 //=======================================================================
77 class BOPTest_Interf {
78  public:
79   BOPTest_Interf() : myIndex1(-1), myIndex2(-1), myType(-1) {
80   }
81   //
82   ~BOPTest_Interf() {
83   }
84   //
85   void SetIndices(const Standard_Integer theIndex1,
86                   const Standard_Integer theIndex2) {
87     myIndex1=theIndex1; 
88     myIndex2=theIndex2; 
89   }
90   //
91   void Indices(Standard_Integer& theIndex1,
92                Standard_Integer& theIndex2) const {
93     theIndex1=myIndex1; 
94     theIndex2=myIndex2; 
95   }
96   //
97   void SetType(const Standard_Integer theType) {
98     myType=theType;
99   }
100   //
101   Standard_Integer Type() const {
102     return myType;
103   }
104   //
105   bool operator < (const  BOPTest_Interf& aOther) const {
106     bool bFlag;
107     //
108     if (myType==aOther.myType) {
109       if (myIndex1 == aOther.myIndex1) {
110         bFlag=(myIndex2 < aOther.myIndex2);
111       }
112       else {
113         bFlag=(myIndex1 < aOther.myIndex1);
114       }
115     }
116     else {
117       bFlag=(myType < aOther.myType);
118     }
119     //
120     return bFlag;
121   }
122   //
123  protected:
124   Standard_Integer myIndex1;
125   Standard_Integer myIndex2;
126   Standard_Integer myType;
127 };
128 //=======================================================================
129 //function : bopcheck
130 //purpose  : 
131 //=======================================================================
132 Standard_Integer bopcheck (Draw_Interpretor& di, 
133                            Standard_Integer n,  
134                            const char** a )
135 {
136   if (n<2) {
137     di << " Use > bopcheck Shape [level of check: 0 - 9] [-t -s]" << "\n";
138     di << " The level of check defines "; 
139     di << " which interferences will be checked:\n";
140     di << " 0 - V/V only\n"; 
141     di << " 1 - V/V, V/E\n";
142     di << " 2 - V/V, V/E, E/E\n"; 
143     di << " 3 - V/V, V/E, E/E , V/F\n"; 
144     di << " 4 - V/V, V/E, E/E, V/F , E/F\n"; 
145     di << " 5 - V/V, V/E, E/E, V/F, E/F, F/F;\n";
146     di << " 6 - V/V, V/E, E/E, V/F, E/F, F/F, V/Z\n";
147     di << " 7 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z\n";
148     di << " 8 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z\n";
149     di << " 9 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z, Z/Z\n";
150     di << " Default level is 9\n";
151     return 1;
152   }
153   //
154   TopoDS_Shape aS = DBRep::Get(a[1]);
155   if (aS.IsNull()) {
156     di << "null shapes are not allowed here!";
157     return 1;
158   }
159   //
160   Standard_Boolean bRunParallel, bShowTime;
161   Standard_Integer i, aLevel, aNbInterfTypes;
162   //
163   aNbInterfTypes=BOPDS_DS::NbInterfTypes();
164   //
165   aLevel=aNbInterfTypes-1;
166   //
167   if (n>2) {
168     aLevel=Draw::Atoi(a[2]); 
169   }
170   //
171   if (aLevel < 0 || aLevel > aNbInterfTypes-1) {
172     di << "Invalid level";
173     return 1;
174   }
175   //
176   bShowTime=Standard_False;
177   bRunParallel=Standard_True;
178   for (i=3; i<n; ++i) {
179     if (!strcmp(a[i], "-s")) {
180       bRunParallel=Standard_False;
181     }
182     else if (!strcmp(a[i], "-t")) {
183       bShowTime=Standard_True;
184     }
185   }
186   //
187   //aLevel = (n==3) ? Draw::Atoi(a[2]) : aNbInterfTypes-1;
188   //-------------------------------------------------------------------
189   char buf[256], aName1[32], aName2[32];
190   char aInterfTypes[10][4] = {
191     "V/V", "V/E", "E/E","V/F", "E/F", "F/F", "V/Z", "E/Z", "F/Z", "Z/Z"
192   };
193   //
194   Standard_Integer iErr, iCnt, n1, n2, iT;
195   TopAbs_ShapeEnum aType1, aType2;
196   BOPAlgo_CheckerSI aChecker;
197   BOPCol_ListOfShape aLS;
198   BOPDS_MapIteratorMapOfPassKey aItMPK;
199   BOPTime_Chronometer aChrono;
200   //
201   if (aLevel < (aNbInterfTypes-1)) {
202     di << "Info:\nThe level of check is set to " 
203       << aInterfTypes[aLevel] << ", i.e. intersection(s)\n";
204     
205     for (i=aLevel+1; i<aNbInterfTypes; ++i) {
206       di << aInterfTypes[i];
207       if (i<aNbInterfTypes-1) {
208         di << ", ";
209       }
210     }
211     di << " will not be checked.\n\n";
212   }
213   //
214   aLS.Append(aS);
215   aChecker.SetArguments(aLS);
216   aChecker.SetLevelOfCheck(aLevel);
217   aChecker.SetRunParallel(bRunParallel);
218   //
219   aChrono.Start();
220   //
221   aChecker.Perform();
222   //
223   aChrono.Stop();
224   //
225   iErr=aChecker.ErrorStatus();
226   //
227   const BOPDS_DS& aDS=*(aChecker.PDS());
228   //
229   const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
230   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
231   using namespace std;
232   vector <BOPTest_Interf> aVec;
233   vector <BOPTest_Interf>::iterator aIt;
234   BOPTest_Interf aBInterf;
235   //
236   aItMPK.Initialize(aMPK);
237   for (; aItMPK.More(); aItMPK.Next()) {
238     const BOPDS_PassKey& aPK=aItMPK.Value();
239     aPK.Ids(n1, n2);
240     if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
241       continue;
242     }
243     //
244     const BOPDS_ShapeInfo& aSI1=aDS.ShapeInfo(n1);
245     const BOPDS_ShapeInfo& aSI2=aDS.ShapeInfo(n2);
246     aType1=aSI1.ShapeType();
247     aType2=aSI2.ShapeType();
248     //
249     iT=BOPDS_Tools::TypeToInteger(aType1, aType2);
250     //
251     aBInterf.SetIndices(n1, n2);
252     aBInterf.SetType(iT);
253     //
254     aVec.push_back(aBInterf);
255   }
256   //
257   sort( aVec.begin(), aVec.end(), less<BOPTest_Interf>());
258   //
259   iCnt=0;
260   for (aIt=aVec.begin(); aIt!=aVec.end(); aIt++) {
261     const BOPTest_Interf& aBI=*aIt;
262     //
263     aBI.Indices(n1, n2);
264     if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
265       continue;
266     }
267     //
268     const TopoDS_Shape& aS1=aDS.Shape(n1);
269     const TopoDS_Shape& aS2=aDS.Shape(n2);
270     //
271     iT=aBI.Type(); 
272     di << aInterfTypes[iT] << ": ";
273     //
274     sprintf(aName1, "x%d", n1);
275     //sprintf(aName1, "x%d", iCnt);
276     DBRep::Set (aName1, aS1);
277     //
278     ++iCnt;
279     sprintf(aName2, "x%d", n2);
280     //sprintf(aName2, "x%d", iCnt);
281     DBRep::Set (aName2, aS2);
282     ++iCnt;
283     //
284     sprintf(buf, "%s %s \n", aName1, aName2);
285     di << buf;
286   }
287   //
288   if (iErr) {
289     di << "There were errors during the operation, ";
290     di << "so the list may be incomplete." << "\n";
291   }
292   //
293   if (!iCnt) {
294     di << " This shape seems to be OK." << "\n";
295   }
296   if (bShowTime) {
297     Standard_Real aTime;
298     //
299     aTime=aChrono.Time();
300     Sprintf(buf, "  Tps: %7.2lf\n", aTime);
301     di << buf;
302   }
303   return 0;
304 }
305 //=======================================================================
306 //function : bopargcheck
307 //purpose  : 
308 //=======================================================================
309 Standard_Integer bopargcheck (Draw_Interpretor& di, 
310                               Standard_Integer n,  
311                               const char** a )
312 {
313   if (n<2) {
314     di << "\n";
315     di << " Use >bopargcheck Shape1 [[Shape2] ";
316     di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P]] [#BF]" << "\n" << "\n";
317     di << " -<Boolean Operation>" << "\n";
318     di << " F (fuse)" << "\n";
319     di << " O (common)" << "\n";
320     di << " C (cut)" << "\n";
321     di << " T (cut21)" << "\n";
322     di << " S (section)" << "\n";
323     di << " U (unknown)" << "\n";
324     di << " For example: \"bopargcheck s1 s2 -F\" enables" ;
325     di << " checking for Fuse operation" << "\n";
326     di << " default - section" << "\n" << "\n";
327     di << " /<Test Options>" << "\n";
328     di << " R (disable small edges (shrank range) test)" << "\n";
329     di << " F (disable faces verification test)" << "\n";
330     di << " T (disable tangent faces searching test)" << "\n";
331     di << " V (disable test possibility to merge vertices)" << "\n";
332     di << " E (disable test possibility to merge edges)" << "\n";
333     di << " I (disable self-interference test)" << "\n";
334     di << " P (disable shape type test)" << "\n";
335     di << " C (disable test for shape continuity)" << "\n";
336     di << " For example: \"bopargcheck s1 s2 /RI\" disables ";
337     di << "small edge detection and self-intersection detection" << "\n";
338     di << " default - all options are enabled" << "\n" << "\n";
339     di << " #<Additional Test Options>" << "\n";
340     di << " B (stop test on first faulty found); default OFF" << "\n";
341     di << " F (full output for faulty shapes); default - output ";
342     di << "in a short format" << "\n" << "\n";
343     di << " NOTE: <Boolean Operation> and <Test Options> are ";
344     di <<  "used only for couple" << "\n";
345     di << "       of argument shapes, except I and P options ";
346     di << "that are always used for" << "\n";
347     di << "       couple of shapes as well as for ";
348     di <<"single shape test." << "\n";
349     return 1;
350   }
351
352   TopoDS_Shape aS1 = DBRep::Get(a[1]);
353
354   if(aS1.IsNull()) {
355     di << "Error: null shape not allowed!" << "\n";
356     di << "Type bopargcheck without arguments for more ";
357     di <<"information" << "\n";
358     return 1;
359   }
360
361   Standard_Boolean isBO = Standard_False;
362   Standard_Integer indxBO = 0;
363   Standard_Boolean isOP = Standard_False;
364   Standard_Integer indxOP = 0;
365   Standard_Boolean isAD = Standard_False;
366   Standard_Integer indxAD = 0;
367   Standard_Boolean isS2 = Standard_False;
368   Standard_Integer indxS2 = 0;
369
370   if(n >= 3) {
371     Standard_Integer iIndex = 0;
372     for(iIndex = 2; iIndex < n; iIndex++) {
373       if(a[iIndex][0] == '-')
374       {
375         isBO = Standard_True;
376         indxBO = iIndex;
377       }
378       //else if(a[iIndex][0] == '+')
379       else if(a[iIndex][0] == '/')
380       {
381         isOP = Standard_True;
382         indxOP = iIndex;
383       }
384       else if(a[iIndex][0] == '#')
385       {
386         isAD = Standard_True;
387         indxAD = iIndex;
388       }
389       else {
390         isS2 = Standard_True;
391         indxS2 = iIndex;
392       }
393     }
394   }
395
396   // set & test second shape
397   TopoDS_Shape aS22, aS2;
398   if(isS2) {
399     if(indxS2 != 2) {
400       di << "Error: second shape should follow the first one!" << "\n";
401       di << "Type bopargcheck without arguments for more information" << "\n";
402       return 1;
403     }
404     else {
405       aS22 = DBRep::Get(a[2]);
406       if(aS22.IsNull()) {
407         di << "Error: second shape is null!" << "\n";
408         di << "Type bopargcheck without arguments for more information" << "\n";
409         return 1;
410       }
411     }
412   }
413
414   // init checker
415   BOPAlgo_ArgumentAnalyzer aChecker;
416   aChecker.SetShape1(aS1);
417
418   // set default options (always tested!) for single and couple shapes
419   aChecker.ArgumentTypeMode() = Standard_True;
420   aChecker.SelfInterMode()    = Standard_True;
421   aChecker.SmallEdgeMode()    = Standard_True;
422   aChecker.RebuildFaceMode()  = Standard_True;
423   aChecker.ContinuityMode()   = Standard_True;
424
425   // test & set options and operation for two shapes
426   if(!aS22.IsNull()) {
427     aS2 = BRepBuilderAPI_Copy(aS22).Shape();
428     aChecker.SetShape2(aS2);
429     // set operation (default - Section)
430     if(isBO) {
431       if(a[indxBO][1] == 'F' || a[indxBO][1] == 'f') {
432         aChecker.OperationType() = BOPAlgo_FUSE;
433       }
434       else if(a[indxBO][1] == 'O' || a[indxBO][1] == 'o') {
435         aChecker.OperationType() = BOPAlgo_COMMON;
436       }
437       else if(a[indxBO][1] == 'C' || a[indxBO][1] == 'c') {
438         aChecker.OperationType() = BOPAlgo_CUT;
439       }
440       else if(a[indxBO][1] == 'T' || a[indxBO][1] == 't') {
441          aChecker.OperationType() = BOPAlgo_CUT21;
442       }
443       else if(a[indxBO][1] == 'S' || a[indxBO][1] == 's') {
444          aChecker.OperationType() = BOPAlgo_SECTION;
445       }
446       else if(a[indxBO][1] == 'U' || a[indxBO][1] == 'u') {
447         aChecker.OperationType() = BOPAlgo_UNKNOWN;
448       }
449       else {
450         di << "Error: invalid boolean operation type!" << "\n";
451         di << "Type bopargcheck without arguments for more information" << "\n";
452         return 1;
453       }
454     }
455     else
456       aChecker.OperationType() = BOPAlgo_SECTION;
457
458     aChecker.TangentMode()     = Standard_True;
459     aChecker.MergeVertexMode() = Standard_True;
460     aChecker.MergeEdgeMode()   = Standard_True;
461   }
462   
463   // set options (default - all ON)
464   if(isOP) {
465     Standard_Integer ind = 1;
466     while(a[indxOP][ind] != 0) {
467       if(a[indxOP][ind] == 'R' || a[indxOP][ind] == 'r') {
468         aChecker.SmallEdgeMode() = Standard_False;
469       }
470       else if(a[indxOP][ind] == 'F' || a[indxOP][ind] == 'f') {
471         aChecker.RebuildFaceMode() = Standard_False;
472       }
473       else if(a[indxOP][ind] == 'T' || a[indxOP][ind] == 't') {
474         aChecker.TangentMode() = Standard_False;
475       }
476       else if(a[indxOP][ind] == 'V' || a[indxOP][ind] == 'v') {
477         aChecker.MergeVertexMode() = Standard_False;
478       }
479       else if(a[indxOP][ind] == 'E' || a[indxOP][ind] == 'e') {
480         aChecker.MergeEdgeMode() = Standard_False;
481       }
482       else if(a[indxOP][ind] == 'I' || a[indxOP][ind] == 'i') {
483         aChecker.SelfInterMode() = Standard_False;
484       }
485       else if(a[indxOP][ind] == 'P' || a[indxOP][ind] == 'p') {
486         aChecker.ArgumentTypeMode() = Standard_False;
487       }
488       else if(a[indxOP][ind] == 'C' || a[indxOP][ind] == 'c') {
489         aChecker.ContinuityMode() = Standard_False;
490       }
491       else {
492         di << "Error: invalid test option(s)!" << "\n";
493         di << "Type bopargcheck without arguments for more information" << "\n";
494         return 1;
495       }
496       ind++;
497     }
498   }
499
500   // set additional options
501   Standard_Boolean fullOutput = Standard_False;
502   if(isAD) {
503     Standard_Integer ind = 1;
504     while(a[indxAD][ind] != 0) {
505       if(a[indxAD][ind] == 'B' || a[indxAD][ind] == 'b') {
506         aChecker.StopOnFirstFaulty() = Standard_True;
507       }
508       else if(a[indxAD][ind] == 'F' || a[indxAD][ind] == 'f') {
509         fullOutput = Standard_True;
510       }
511       else {
512         di << "Error: invalid additional test option(s)!" << "\n";
513         di << "Type bopargcheck without arguments for more information" << "\n";
514         return 1;
515       }
516       ind++;
517     }
518   }
519
520   // run checker
521   aChecker.Perform();
522
523   // process result of checking
524   if(!aChecker.HasFaulty()) {
525     di << "Shape(s) seem(s) to be valid for BOP."  << "\n";
526   }
527   else {
528     if(!fullOutput) {
529       di << "Faulties, that can not be treated by BOP, are detected." << "\n"; 
530     }
531     else {
532       const BOPAlgo_ListOfCheckResult& aResultList = aChecker.GetCheckResult();
533       BOPAlgo_ListIteratorOfListOfCheckResult anIt(aResultList);
534
535       Standard_Integer S1_BadType = 0, S1_SelfInt = 0, S1_SmalE = 0, S1_BadF = 0, S1_BadV = 0, S1_BadE = 0;
536       Standard_Integer S1_SelfIntAll = 0, S1_SmalEAll = 0, S1_BadFAll = 0, S1_BadVAll = 0, S1_BadEAll = 0;
537       Standard_Integer S2_BadType = 0, S2_SelfInt = 0, S2_SmalE = 0, S2_BadF = 0, S2_BadV = 0, S2_BadE = 0;
538       Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0;
539       Standard_Integer S1_OpAb = 0, S2_OpAb = 0;
540       Standard_Integer S1_C0 = 0, S2_C0 = 0, S1_C0All = 0, S2_C0All = 0;
541       Standard_Boolean hasUnknown = Standard_False;
542
543       TCollection_AsciiString aS1SIBaseName("s1si_");
544       TCollection_AsciiString aS1SEBaseName("s1se_");
545       TCollection_AsciiString aS1BFBaseName("s1bf_");
546       TCollection_AsciiString aS1BVBaseName("s1bv_");
547       TCollection_AsciiString aS1BEBaseName("s1be_");
548       TCollection_AsciiString aS1C0BaseName("s1C0_");
549       TCollection_AsciiString aS2SIBaseName("s2si_");
550       TCollection_AsciiString aS2SEBaseName("s2se_");
551       TCollection_AsciiString aS2BFBaseName("s2bf_");
552       TCollection_AsciiString aS2BVBaseName("s2bv_");
553       TCollection_AsciiString aS2BEBaseName("s2be_");
554       TCollection_AsciiString aS2C0BaseName("s2C0_");
555
556       for(; anIt.More(); anIt.Next()) {
557         const BOPAlgo_CheckResult& aResult = anIt.Value();
558         const TopoDS_Shape & aSS1 = aResult.GetShape1();
559         const TopoDS_Shape & aSS2 = aResult.GetShape2();
560         const BOPCol_ListOfShape & aLS1 = aResult.GetFaultyShapes1();
561         const BOPCol_ListOfShape & aLS2 = aResult.GetFaultyShapes2();
562         Standard_Boolean isL1 = !aLS1.IsEmpty();
563         Standard_Boolean isL2 = !aLS2.IsEmpty();
564
565         switch(aResult.GetCheckStatus()) {
566         case BOPAlgo_BadType: {
567           if(!aSS1.IsNull()) S1_BadType++;
568           if(!aSS2.IsNull()) S2_BadType++;
569         }
570           break;
571         case BOPAlgo_SelfIntersect: {
572           if(!aSS1.IsNull()) {
573             S1_SelfInt++;
574             if(isL1)
575               MakeShapeForFullOutput(aS1SIBaseName, S1_SelfInt, aLS1, S1_SelfIntAll, di);
576           }
577           if(!aSS2.IsNull()) {
578             S2_SelfInt++;
579             if(isL2)
580               MakeShapeForFullOutput(aS2SIBaseName, S2_SelfInt, aLS2, S2_SelfIntAll, di);
581           }
582         }
583           break;
584         case BOPAlgo_TooSmallEdge: {
585           if(!aSS1.IsNull()) {
586             S1_SmalE++;
587             if(isL1)
588               MakeShapeForFullOutput(aS1SEBaseName, S1_SmalE, aLS1, S1_SmalEAll, di);
589           }
590           if(!aSS2.IsNull()) {
591             S2_SmalE++;
592             if(isL2)
593               MakeShapeForFullOutput(aS2SEBaseName, S2_SmalE, aLS2, S2_SmalEAll, di);
594           }
595         }
596           break;
597         case BOPAlgo_NonRecoverableFace: {
598           if(!aSS1.IsNull()) {
599             S1_BadF++;
600             if(isL1)
601               MakeShapeForFullOutput(aS1BFBaseName, S1_BadF, aLS1, S1_BadFAll, di);
602           }
603           if(!aSS2.IsNull()) {
604             S2_BadF++;
605             if(isL2)
606               MakeShapeForFullOutput(aS2BFBaseName, S2_BadF, aLS2, S2_BadFAll, di);
607           }
608         }
609           break;
610         case BOPAlgo_IncompatibilityOfVertex: {
611           if(!aSS1.IsNull()) {
612             S1_BadV++;
613             if(isL1) {
614               MakeShapeForFullOutput(aS1BVBaseName, S1_BadV, aLS1, S1_BadVAll, di);
615             }
616           }
617           if(!aSS2.IsNull()) {
618             S2_BadV++;
619             if(isL2){
620               MakeShapeForFullOutput(aS2BVBaseName, S2_BadV, aLS2, S2_BadVAll, di);
621             }
622           }
623         }
624           break;
625         case BOPAlgo_IncompatibilityOfEdge: {
626           if(!aSS1.IsNull()) {
627             S1_BadE++;
628             if(isL1) {
629               MakeShapeForFullOutput(aS1BEBaseName, S1_BadE, aLS1, S1_BadEAll, di);
630             }
631           }
632           if(!aSS2.IsNull()) {
633             S2_BadE++;
634             if(isL2) {
635               MakeShapeForFullOutput(aS2BEBaseName, S2_BadE, aLS2, S2_BadEAll, di);
636             }
637           }
638         }
639           break;
640         case BOPAlgo_IncompatibilityOfFace: {
641           // not yet implemented
642         }
643           break;
644         case BOPAlgo_GeomAbs_C0: {
645           if(!aSS1.IsNull()) {
646             S1_C0++;
647             if(isL1) {
648               MakeShapeForFullOutput(aS1C0BaseName, S1_C0, aLS1, S1_C0All, di);
649             }
650           }
651           if(!aSS2.IsNull()) {
652             S2_C0++;
653             if(isL2) {
654               MakeShapeForFullOutput(aS2C0BaseName, S2_C0, aLS2, S2_C0All, di);
655             }
656           }
657         }
658           break;
659         case BOPAlgo_OperationAborted: {
660           if(!aSS1.IsNull()) S1_OpAb++;
661           if(!aSS2.IsNull()) S2_OpAb++;
662         }
663           break;
664         case BOPAlgo_CheckUnknown:
665         default: {
666           hasUnknown = Standard_True;
667         }
668           break;
669         } // switch
670       }// faulties
671
672       Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0;
673       FS1 += (S1_BadType != 0) ? 1 : 0;
674       Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0;
675       FS2 += (S2_BadType != 0) ? 1 : 0;
676       
677       // output for first shape
678       di << "Faulties for FIRST  shape found : " << FS1 << "\n";
679       if(FS1 != 0) {
680         di << "---------------------------------" << "\n";
681         Standard_CString CString1;
682         if (S1_BadType != 0)
683           CString1="YES";
684         else
685           CString1="NO";
686         di << "Shapes are not suppotrted by BOP: " << CString1 << "\n";
687         Standard_CString CString2;
688         if (S1_SelfInt != 0)
689           CString2="YES";
690         else
691           CString2="NO";
692         di << "Self-Intersections              : " << CString2;
693         if(S1_SelfInt != 0)
694           di << "  Cases(" << S1_SelfInt << ")  Total shapes(" << S1_SelfIntAll << ")" << "\n";
695         else
696           di << "\n";
697         Standard_CString CString13;
698         if (S1_OpAb != 0)
699           CString13="YES";
700         else
701           CString13="NO";
702         di << "Check for SI has been aborted   : " << CString13 << "\n";
703         Standard_CString CString3;
704         if (S1_SmalE != 0)
705           CString3="YES";
706         else
707           CString3="NO";
708         di << "Too small edges                 : " << CString3;
709         if(S1_SmalE != 0)
710           di << "  Cases(" << S1_SmalE << ")  Total shapes(" << S1_SmalEAll << ")" << "\n";
711         else
712           di << "\n";
713         Standard_CString CString4;
714         if (S1_BadF != 0)
715           CString4="YES";
716         else
717           CString4="NO";
718         di << "Bad faces                       : " << CString4;
719         if(S1_BadF != 0)
720           di << "  Cases(" << S1_BadF << ")  Total shapes(" << S1_BadFAll << ")" << "\n";
721         else
722           di << "\n";
723         Standard_CString CString5;
724         if (S1_BadV != 0)
725           CString5="YES";
726         else
727           CString5="NO";
728         di << "Too close vertices              : " << CString5;
729         if(S1_BadV != 0)
730           di << "  Cases(" << S1_BadV << ")  Total shapes(" << S1_BadVAll << ")" << "\n";
731         else
732           di << "\n";
733         Standard_CString CString6;
734         if (S1_BadE != 0)
735           CString6="YES";
736         else
737           CString6="NO";
738         di << "Too close edges                 : " << CString6;
739         if(S1_BadE != 0)
740           di << "  Cases(" << S1_BadE << ")  Total shapes(" << S1_BadEAll << ")" << "\n";
741         else
742           di << "\n";
743         Standard_CString CString15;
744         if (S1_C0 != 0)
745           CString15="YES";
746         else
747           CString15="NO";
748         di << "Shapes with Continuity C0       : " << CString15;
749         if(S1_C0 != 0)
750           di << "  Cases(" << S1_C0 << ")  Total shapes(" << S1_C0All << ")" << "\n";
751         else
752           di << "\n";
753       }
754
755       // output for second shape
756       di << "\n";
757       di << "Faulties for SECOND  shape found : " << FS2 << "\n";
758       if(FS2 != 0) {
759         di << "---------------------------------" << "\n";
760         Standard_CString CString7;
761         if (S2_BadType != 0)
762           CString7="YES";
763         else
764           CString7="NO";
765         di << "Shapes are not suppotrted by BOP: " << CString7 << "\n";
766         Standard_CString CString8;
767         if (S2_SelfInt != 0)
768           CString8="YES";
769         else
770           CString8="NO";
771         di << "Self-Intersections              : " << CString8;
772         if(S2_SelfInt != 0)
773           di << "  Cases(" << S2_SelfInt << ")  Total shapes(" << S2_SelfIntAll << ")" << "\n";
774         else
775           di << "\n";
776
777         Standard_CString CString14;
778         if (S2_OpAb != 0)
779           CString14="YES";
780         else
781           CString14="NO";
782         di << "Check for SI has been aborted   : " << CString14 << "\n";
783         Standard_CString CString9;
784         if (S2_SmalE != 0)
785           CString9="YES";
786         else
787           CString9="NO";
788         di << "Too small edges                 : " << CString9;
789         if(S2_SmalE != 0)
790           di << "  Cases(" << S2_SmalE << ")  Total shapes(" << S2_SmalEAll << ")" << "\n";
791         else
792           di << "\n";
793         Standard_CString CString10;
794         if (S2_BadF != 0)
795           CString10="YES";
796         else
797           CString10="NO";
798         di << "Bad faces                       : " << CString10;
799         if(S2_BadF != 0)
800           di << "  Cases(" << S2_BadF << ")  Total shapes(" << S2_BadFAll << ")" << "\n";
801         else
802           di << "\n";
803         Standard_CString CString11;
804         if (S2_BadV != 0)
805           CString11="YES";
806         else
807           CString11="NO";
808         di << "Too close vertices              : " << CString11;
809         if(S2_BadV != 0)
810           di << "  Cases(" << S2_BadV << ")  Total shapes(" << S2_BadVAll << ")" << "\n";
811         else
812           di << "\n";
813         Standard_CString CString12;
814         if (S2_BadE != 0)
815           CString12="YES";
816         else
817           CString12="NO";
818         di << "Too close edges                 : " << CString12;
819         if(S2_BadE != 0)
820           di << "  Cases(" << S2_BadE << ")  Total shapes(" << S2_BadEAll << ")" << "\n";
821         else
822           di << "\n";
823         Standard_CString CString16;
824         if (S2_C0 != 0)
825           CString16="YES";
826         else
827           CString16="NO";
828         di << "Shapes with Continuity C0       : " << CString16;
829         if(S2_C0 != 0)
830           di << "  Cases(" << S2_C0 << ")  Total shapes(" << S2_C0All << ")" << "\n";
831         else
832           di << "\n";
833
834         // warning
835         di << "\n";
836         if(hasUnknown)
837           di << "WARNING: The unexpected test break occurs!" << "\n";
838       }
839     } // full output
840   } // has faulties
841
842   return 0;
843 }
844 //=======================================================================
845 //function : MakeShapeForFullOutput
846 //purpose  : 
847 //=======================================================================
848 void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName,
849                              const Standard_Integer          aIndex,
850                              const BOPCol_ListOfShape &    aList,
851                              Standard_Integer&               aCount,
852                              Draw_Interpretor&               di)
853 {
854   TCollection_AsciiString aNum(aIndex);
855   TCollection_AsciiString aName = aBaseName + aNum;
856   Standard_CString name = aName.ToCString();
857
858   TopoDS_Compound cmp;
859   BRep_Builder BB;
860   BB.MakeCompound(cmp);
861
862   BOPCol_ListIteratorOfListOfShape anIt(aList);
863   for(; anIt.More(); anIt.Next()) {
864     const TopoDS_Shape & aS = anIt.Value();
865     BB.Add(cmp, aS);
866     aCount++;
867   }
868   di << "Made faulty shape: " << name << "\n";
869   DBRep::Set(name, cmp);
870 }