0021762: Integration of new Boolean Operation algorithm to OCCT.
[occt.git] / src / BOPTest / BOPTest_CheckCommands.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 #include <BOPTest.ixx>
21 #include <TCollection_AsciiString.hxx>
22
23 #include <gp_Pnt.hxx>
24
25 #include <TopoDS_Shape.hxx>
26 #include <TopoDS_Compound.hxx>
27 #include <BRep_Builder.hxx>
28
29 #include <DBRep.hxx>
30
31 #include <Geom_Geometry.hxx>
32 #include <Geom_CartesianPoint.hxx>
33
34 #include <Draw.hxx>
35 #include <DrawTrSurf.hxx>
36 #include <BOPAlgo_CheckerSI.hxx>
37 #include <BOPDS_VectorOfInterfVV.hxx>
38 #include <BOPDS_VectorOfInterfVE.hxx>
39 #include <BOPDS_VectorOfInterfEE.hxx>
40 #include <BOPDS_VectorOfInterfVF.hxx>
41 #include <BOPDS_VectorOfInterfEF.hxx>
42 #include <BOPDS_VectorOfInterfFF.hxx>
43 #include <BOPDS_DS.hxx>
44
45 #include <BOPCol_ListOfShape.hxx>
46 #include <BOPAlgo_ArgumentAnalyzer.hxx>
47 #include <BOPAlgo_CheckResult.hxx>
48 #include <BRepBuilderAPI_Copy.hxx>
49
50 static 
51   Standard_Integer bopcheck (Draw_Interpretor&, Standard_Integer, const char** );
52
53 static 
54   Standard_Integer bopargcheck (Draw_Interpretor&, Standard_Integer, const char** );
55 //
56
57 //=======================================================================
58 //function : CheckCommands
59 //purpose  : 
60 //=======================================================================
61   void  BOPTest::CheckCommands(Draw_Interpretor& theCommands)
62 {
63   static Standard_Boolean done = Standard_False;
64   if (done) 
65     return;
66
67   done = Standard_True;
68   // Chapter's name
69   const char* g = "CCR commands";
70   //
71   theCommands.Add("bopcheck" ,  "Use >bopcheck Shape",  __FILE__, bopcheck, g);
72   theCommands.Add("bopargcheck" ,  "Use bopargcheck without parameters to get ",  __FILE__, bopargcheck, g);
73 }
74
75 //=======================================================================
76 //function : bopcheck
77 //purpose  : 
78 //=======================================================================
79 Standard_Integer bopcheck (Draw_Interpretor& di, Standard_Integer n,  const char** a )
80 {
81   
82   if (n<2) {
83     di << " Use >bopcheck Shape" << "\n";
84     return 1;
85   }
86
87   TopoDS_Shape aS1 = DBRep::Get(a[1]);
88   if (aS1.IsNull()) {
89     di << "null shapes are not allowed here!";
90     return 1;
91   }
92   TopoDS_Shape aS = BRepBuilderAPI_Copy(aS1).Shape();
93   //
94   Standard_Integer iErr, aTypeInt, i, ind, j;
95   Standard_Integer nI1, nI2;
96   Standard_Boolean bSelfInt, bFFInt;
97   char buf[256];
98   
99   BOPAlgo_CheckerSI aChecker;
100   BOPCol_ListOfShape anArgs;
101   anArgs.Append(aS);
102   aChecker.SetArguments(anArgs);
103   //
104   aChecker.Perform();
105   iErr = aChecker.ErrorStatus();
106   //
107   const BOPDS_PDS& theDS = aChecker.PDS();
108   BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV();
109   BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE();
110   BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE();
111   BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF();
112   BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF();
113   BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF();
114   //
115   Standard_Integer aNb[6] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), 
116                              aVFs.Extent(), aEFs.Extent(), aFFs.Extent()};
117   char type[6][5] = {"V/V:", "V/E:", "E/E:","V/F:", "E/F:", "F/F:"};
118
119   //
120   bSelfInt = Standard_False;
121   ind = 0;
122   for (aTypeInt = 0; aTypeInt < 6; ++aTypeInt) {
123     for (i = 0; i < aNb[aTypeInt]; ++i) {
124       BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) : 
125                           ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) :
126                           ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) : 
127                           ((aTypeInt==3) ? (BOPDS_Interf*)(&aVFs(i)) :
128                           ((aTypeInt==4) ? (BOPDS_Interf*)(&aEFs(i)) : (BOPDS_Interf*)(&aFFs(i))))));
129       //
130       nI1 = aInt->Index1();
131       nI2 = aInt->Index2();
132       if (nI1 == nI2) {
133         continue;
134       }
135       //
136       const TopoDS_Shape& aS1 = theDS->Shape(nI1);
137       const TopoDS_Shape& aS2 = theDS->Shape(nI2);
138       //
139       if (aTypeInt == 5) {
140         bFFInt = Standard_False;
141         BOPDS_InterfFF& aFF = aFFs(i);
142         BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
143         Standard_Integer aNbP=aVP.Extent();
144         BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
145         Standard_Integer aNbC=aVC.Extent();
146         if (!aNbP && !aNbC) {
147           continue;
148         }
149         for (j=0; j<aNbC; ++j) {
150           BOPDS_Curve& aNC=aVC(j);
151           BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
152           if (aLPBC.Extent()) {
153             bFFInt = Standard_True;
154             break;
155           }
156         }
157         if (!bFFInt) {
158           continue;
159         }
160       }
161       //
162       di << type[aTypeInt];
163       //
164       TCollection_AsciiString aBaseName("x");
165       TCollection_AsciiString anumbername(ind);
166       TCollection_AsciiString aXName = aBaseName + anumbername;
167       Standard_CString aname=aXName.ToCString();
168       DBRep::Set (aname, aS1);
169       ++ind;
170       TCollection_AsciiString anumbername1(ind);
171       TCollection_AsciiString aXName1 = aBaseName + anumbername1;
172       Standard_CString aname1=aXName1.ToCString();
173       DBRep::Set (aname1, aS2);
174       ++ind;
175       //
176       Sprintf(buf, "%s, %s \n", aname, aname1);
177       di << buf;
178       bSelfInt = Standard_True;
179     }
180   }
181   
182   if (iErr) {
183     di << "There were errors during the operation, so the list may be incomplete." << "\n";
184   }
185   
186   if (!bSelfInt) {
187     di << " This shape seems to be OK." << "\n";
188   }
189   
190   return 0;
191 }
192
193 static void MakeShapeForFullOutput(const TCollection_AsciiString & aBaseName,
194                                    const Standard_Integer          aIndex,
195                                    const BOPCol_ListOfShape &    aList,
196                                    Standard_Integer&               aCount,
197                                    Draw_Interpretor&               di)
198 {
199   TCollection_AsciiString aNum(aIndex);
200   TCollection_AsciiString aName = aBaseName + aNum;
201   Standard_CString name = aName.ToCString();
202
203   TopoDS_Compound cmp;
204   BRep_Builder BB;
205   BB.MakeCompound(cmp);
206
207   BOPCol_ListIteratorOfListOfShape anIt(aList);
208   for(; anIt.More(); anIt.Next()) {
209     const TopoDS_Shape & aS = anIt.Value();
210     BB.Add(cmp, aS);
211     aCount++;
212   }
213   di << "Made faulty shape: " << name << "\n";
214   DBRep::Set(name, cmp);
215 }
216
217
218 Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const char** a )
219 {
220   if (n<2) {
221     di << "\n";
222     di << " Use >bopargcheck Shape1 [[Shape2] [-F/O/C/T/S/U] [/R|F|T|V|E|I|P]] [#BF]" << "\n" << "\n";
223     di << " -<Boolean Operation>" << "\n";
224     di << " F (fuse)" << "\n";
225     di << " O (common)" << "\n";
226     di << " C (cut)" << "\n";
227     di << " T (cut21)" << "\n";
228     di << " S (section)" << "\n";
229     di << " U (unknown)" << "\n";
230     di << " For example: \"bopargcheck s1 s2 -F\" enables checking for Fuse operation" << "\n";
231     di << " default - section" << "\n" << "\n";
232     di << " /<Test Options>" << "\n";
233     di << " R (disable small edges (shrank range) test)" << "\n";
234     di << " F (disable faces verification test)" << "\n";
235     di << " T (disable tangent faces searching test)" << "\n";
236     di << " V (disable test possibility to merge vertices)" << "\n";
237     di << " E (disable test possibility to merge edges)" << "\n";
238     di << " I (disable self-interference test)" << "\n";
239     di << " P (disable shape type test)" << "\n";
240     di << " For example: \"bopargcheck s1 s2 /RI\" disables small edge detection and self-intersection detection" << "\n";
241     di << " default - all options are enabled" << "\n" << "\n";
242     di << " #<Additional Test Options>" << "\n";
243     di << " B (stop test on first faulty found); default OFF" << "\n";
244     di << " F (full output for faulty shapes); default - output in a short format" << "\n" << "\n";
245     di << " NOTE: <Boolean Operation> and <Test Options> are used only for couple" << "\n";
246     di << "       of argument shapes, except I and P options that are always used for" << "\n";
247     di << "       couple of shapes as well as for single shape test." << "\n";
248     return 1;
249   }
250
251   TopoDS_Shape aS11 = DBRep::Get(a[1]);
252
253   if(aS11.IsNull()) {
254     di << "Error: null shape not allowed!" << "\n";
255     di << "Type bopargcheck without arguments for more information" << "\n";
256     return 1;
257   }
258   TopoDS_Shape aS1 = BRepBuilderAPI_Copy(aS11).Shape();
259   
260
261   Standard_Boolean isBO = Standard_False;
262   Standard_Integer indxBO = 0;
263   Standard_Boolean isOP = Standard_False;
264   Standard_Integer indxOP = 0;
265   Standard_Boolean isAD = Standard_False;
266   Standard_Integer indxAD = 0;
267   Standard_Boolean isS2 = Standard_False;
268   Standard_Integer indxS2 = 0;
269
270   if(n >= 3) {
271     Standard_Integer iIndex = 0;
272     for(iIndex = 2; iIndex < n; iIndex++) {
273       if(a[iIndex][0] == '-')
274       {
275         isBO = Standard_True;
276         indxBO = iIndex;
277       }
278       //else if(a[iIndex][0] == '+')
279       else if(a[iIndex][0] == '/')
280       {
281         isOP = Standard_True;
282         indxOP = iIndex;
283       }
284       else if(a[iIndex][0] == '#')
285       {
286         isAD = Standard_True;
287         indxAD = iIndex;
288       }
289       else {
290         isS2 = Standard_True;
291         indxS2 = iIndex;
292       }
293     }
294   }
295
296   // set & test second shape
297   TopoDS_Shape aS22, aS2;
298   if(isS2) {
299     if(indxS2 != 2) {
300       di << "Error: second shape should follow the first one!" << "\n";
301       di << "Type bopargcheck without arguments for more information" << "\n";
302       return 1;
303     }
304     else {
305       aS22 = DBRep::Get(a[2]);
306       if(aS22.IsNull()) {
307         di << "Error: second shape is null!" << "\n";
308         di << "Type bopargcheck without arguments for more information" << "\n";
309         return 1;
310       }
311     }
312   }
313
314   // init checker
315   BOPAlgo_ArgumentAnalyzer aChecker;
316   aChecker.SetShape1(aS1);
317
318   // set default options (always tested!) for single and couple shapes
319   aChecker.ArgumentTypeMode() = Standard_True;
320   aChecker.SelfInterMode()    = Standard_True;
321
322   // test & set options and operation for two shapes
323   if(!aS22.IsNull()) {
324     aS2 = BRepBuilderAPI_Copy(aS22).Shape();
325     aChecker.SetShape2(aS2);
326     // set operation (default - Section)
327     if(isBO) {
328       if(a[indxBO][1] == 'F' || a[indxBO][1] == 'f') {
329         aChecker.OperationType() = BOPAlgo_FUSE;
330       }
331       else if(a[indxBO][1] == 'O' || a[indxBO][1] == 'o') {
332         aChecker.OperationType() = BOPAlgo_COMMON;
333       }
334       else if(a[indxBO][1] == 'C' || a[indxBO][1] == 'c') {
335         aChecker.OperationType() = BOPAlgo_CUT;
336       }
337       else if(a[indxBO][1] == 'T' || a[indxBO][1] == 't') {
338          aChecker.OperationType() = BOPAlgo_CUT21;
339       }
340       else if(a[indxBO][1] == 'S' || a[indxBO][1] == 's') {
341          aChecker.OperationType() = BOPAlgo_SECTION;
342       }
343       else if(a[indxBO][1] == 'U' || a[indxBO][1] == 'u') {
344         aChecker.OperationType() = BOPAlgo_UNKNOWN;
345       }
346       else {
347         di << "Error: invalid boolean operation type!" << "\n";
348         di << "Type bopargcheck without arguments for more information" << "\n";
349         return 1;
350       }
351     }
352     else
353       aChecker.OperationType() = BOPAlgo_SECTION;
354
355     aChecker.SmallEdgeMode()   = Standard_True;
356     aChecker.RebuildFaceMode() = Standard_True;
357     aChecker.TangentMode()     = Standard_True;
358     aChecker.MergeVertexMode() = Standard_True;
359     aChecker.MergeEdgeMode()   = Standard_True;
360
361     // set options (default - all ON)
362     if(isOP) {
363       Standard_Integer ind = 1;
364       while(a[indxOP][ind] != 0) {
365         if(a[indxOP][ind] == 'R' || a[indxOP][ind] == 'r') {
366           //aChecker.SmallEdgeMode() = Standard_True;
367           aChecker.SmallEdgeMode() = Standard_False;
368         }
369         else if(a[indxOP][ind] == 'F' || a[indxOP][ind] == 'f') {
370           //aChecker.RebuildFaceMode() = Standard_True;
371           aChecker.RebuildFaceMode() = Standard_False;
372         }
373         else if(a[indxOP][ind] == 'T' || a[indxOP][ind] == 't') {
374           //aChecker.TangentMode() = Standard_True;
375           aChecker.TangentMode() = Standard_False;
376         }
377         else if(a[indxOP][ind] == 'V' || a[indxOP][ind] == 'v') {
378           //aChecker.MergeVertexMode() = Standard_True;
379           aChecker.MergeVertexMode() = Standard_False;
380         }
381         else if(a[indxOP][ind] == 'E' || a[indxOP][ind] == 'e') {
382           //aChecker.MergeEdgeMode() = Standard_True;
383           aChecker.MergeEdgeMode() = Standard_False;
384         }
385         else if(a[indxOP][ind] == 'I' || a[indxOP][ind] == 'i') {
386           aChecker.SelfInterMode() = Standard_False;
387         }
388         else if(a[indxOP][ind] == 'P' || a[indxOP][ind] == 'p') {
389           aChecker.ArgumentTypeMode() = Standard_False;
390         }
391         else {
392           di << "Error: invalid test option(s)!" << "\n";
393           di << "Type bopargcheck without arguments for more information" << "\n";
394           return 1;
395         }
396         ind++;
397       }
398     }
399     else {
400       // default test mode (all - ON)
401       aChecker.SmallEdgeMode()   = Standard_True;
402       aChecker.RebuildFaceMode() = Standard_True;
403       aChecker.TangentMode()     = Standard_True;
404       aChecker.MergeVertexMode() = Standard_True;
405       aChecker.MergeEdgeMode()   = Standard_True;
406     }
407   }
408   else {
409     // check type and self-interference mode for single shape test
410     // also check small edges and check faces
411       aChecker.SmallEdgeMode()   = Standard_True;
412       aChecker.RebuildFaceMode() = Standard_True;
413
414      if(isOP) {
415       Standard_Integer ind = 1;
416       while(a[indxOP][ind] != 0) {
417         if(a[indxOP][ind] == 'R' || a[indxOP][ind] == 'r') {
418         }
419         else if(a[indxOP][ind] == 'F' || a[indxOP][ind] == 'f') {
420         }
421         else if(a[indxOP][ind] == 'T' || a[indxOP][ind] == 't') {
422         }
423         else if(a[indxOP][ind] == 'V' || a[indxOP][ind] == 'v') {
424         }
425         else if(a[indxOP][ind] == 'E' || a[indxOP][ind] == 'e') {
426         }
427         else if(a[indxOP][ind] == 'I' || a[indxOP][ind] == 'i') {
428           aChecker.SelfInterMode() = Standard_False;
429         }
430         else if(a[indxOP][ind] == 'P' || a[indxOP][ind] == 'p') {
431           aChecker.ArgumentTypeMode() = Standard_False;
432         }
433         else {
434           di << "Error: invalid test option(s)!" << "\n";
435           di << "Type bopargcheck without arguments for more information" << "\n";
436           return 1;
437         }
438         ind++;
439       }
440     }
441   }
442
443   // set additional options
444   Standard_Boolean fullOutput = Standard_False;
445   if(isAD) {
446     Standard_Integer ind = 1;
447     while(a[indxAD][ind] != 0) {
448       if(a[indxAD][ind] == 'B' || a[indxAD][ind] == 'b') {
449         aChecker.StopOnFirstFaulty() = Standard_True;
450       }
451       else if(a[indxAD][ind] == 'F' || a[indxAD][ind] == 'f') {
452         fullOutput = Standard_True;
453       }
454       else {
455         di << "Error: invalid additional test option(s)!" << "\n";
456         di << "Type bopargcheck without arguments for more information" << "\n";
457         return 1;
458       }
459       ind++;
460     }
461   }
462
463   // run checker
464   aChecker.Perform();
465
466   // process result of checking
467   if(!aChecker.HasFaulty()) {
468     di << "Shape(s) seem(s) to be valid for BOP."  << "\n";
469   }
470   else {
471     if(!fullOutput) {
472       di << "Faulties, that can not be treated by BOP, are detected." << "\n"; 
473     }
474     else {
475       const BOPAlgo_ListOfCheckResult& aResultList = aChecker.GetCheckResult();
476       BOPAlgo_ListIteratorOfListOfCheckResult anIt(aResultList);
477
478       Standard_Integer S1_BadType = 0, S1_SelfInt = 0, S1_SmalE = 0, S1_BadF = 0, S1_BadV = 0, S1_BadE = 0;
479       Standard_Integer S1_SelfIntAll = 0, S1_SmalEAll = 0, S1_BadFAll = 0, S1_BadVAll = 0, S1_BadEAll = 0;
480       Standard_Integer S2_BadType = 0, S2_SelfInt = 0, S2_SmalE = 0, S2_BadF = 0, S2_BadV = 0, S2_BadE = 0;
481       Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0;
482       Standard_Integer S1_OpAb = 0, S2_OpAb = 0;
483       Standard_Boolean hasUnknown = Standard_False;
484
485       TCollection_AsciiString aS1SIBaseName("s1si_");
486       TCollection_AsciiString aS1SEBaseName("s1se_");
487       TCollection_AsciiString aS1BFBaseName("s1bf_");
488       TCollection_AsciiString aS1BVBaseName("s1bv_");
489       TCollection_AsciiString aS1BEBaseName("s1be_");
490       TCollection_AsciiString aS2SIBaseName("s2si_");
491       TCollection_AsciiString aS2SEBaseName("s2se_");
492       TCollection_AsciiString aS2BFBaseName("s2bf_");
493       TCollection_AsciiString aS2BVBaseName("s2bv_");
494       TCollection_AsciiString aS2BEBaseName("s2be_");
495
496       for(; anIt.More(); anIt.Next()) {
497         const BOPAlgo_CheckResult& aResult = anIt.Value();
498         const TopoDS_Shape & aSS1 = aResult.GetShape1();
499         const TopoDS_Shape & aSS2 = aResult.GetShape2();
500         const BOPCol_ListOfShape & aLS1 = aResult.GetFaultyShapes1();
501         const BOPCol_ListOfShape & aLS2 = aResult.GetFaultyShapes2();
502         Standard_Boolean isL1 = !aLS1.IsEmpty();
503         Standard_Boolean isL2 = !aLS2.IsEmpty();
504
505         switch(aResult.GetCheckStatus()) {
506         case BOPAlgo_BadType: {
507           if(!aSS1.IsNull()) S1_BadType++;
508           if(!aSS2.IsNull()) S2_BadType++;
509         }
510           break;
511         case BOPAlgo_SelfIntersect: {
512           if(!aSS1.IsNull()) {
513             S1_SelfInt++;
514             if(isL1)
515               MakeShapeForFullOutput(aS1SIBaseName, S1_SelfInt, aLS1, S1_SelfIntAll, di);
516           }
517           if(!aSS2.IsNull()) {
518             S2_SelfInt++;
519             if(isL2)
520               MakeShapeForFullOutput(aS2SIBaseName, S2_SelfInt, aLS2, S2_SelfIntAll, di);
521           }
522         }
523           break;
524         case BOPAlgo_TooSmallEdge: {
525           if(!aSS1.IsNull()) {
526             S1_SmalE++;
527             if(isL1)
528               MakeShapeForFullOutput(aS1SEBaseName, S1_SmalE, aLS1, S1_SmalEAll, di);
529           }
530           if(!aSS2.IsNull()) {
531             S2_SmalE++;
532             if(isL2)
533               MakeShapeForFullOutput(aS2SEBaseName, S2_SmalE, aLS2, S2_SmalEAll, di);
534           }
535         }
536           break;
537         case BOPAlgo_NonRecoverableFace: {
538           if(!aSS1.IsNull()) {
539             S1_BadF++;
540             if(isL1)
541               MakeShapeForFullOutput(aS1BFBaseName, S1_BadF, aLS1, S1_BadFAll, di);
542           }
543           if(!aSS2.IsNull()) {
544             S2_BadF++;
545             if(isL2)
546               MakeShapeForFullOutput(aS2BFBaseName, S2_BadF, aLS2, S2_BadFAll, di);
547           }
548         }
549           break;
550         case BOPAlgo_IncompatibilityOfVertex: {
551           if(!aSS1.IsNull()) {
552             S1_BadV++;
553             if(isL1) {
554               MakeShapeForFullOutput(aS1BVBaseName, S1_BadV, aLS1, S1_BadVAll, di);
555             }
556           }
557           if(!aSS2.IsNull()) {
558             S2_BadV++;
559             if(isL2){
560               MakeShapeForFullOutput(aS2BVBaseName, S2_BadV, aLS2, S2_BadVAll, di);
561             }
562           }
563         }
564           break;
565         case BOPAlgo_IncompatibilityOfEdge: {
566           if(!aSS1.IsNull()) {
567             S1_BadE++;
568             if(isL1) {
569               MakeShapeForFullOutput(aS1BEBaseName, S1_BadE, aLS1, S1_BadEAll, di);
570             }
571           }
572           if(!aSS2.IsNull()) {
573             S2_BadE++;
574             if(isL2) {
575               MakeShapeForFullOutput(aS2BEBaseName, S2_BadE, aLS2, S2_BadEAll, di);
576             }
577           }
578         }
579           break;
580         case BOPAlgo_IncompatibilityOfFace: {
581           // not yet implemented
582         }
583           break;
584         case BOPAlgo_OperationAborted: {
585           if(!aSS1.IsNull()) S1_OpAb++;
586           if(!aSS2.IsNull()) S2_OpAb++;
587         }
588           break;
589         case BOPAlgo_CheckUnknown:
590         default: {
591           hasUnknown = Standard_True;
592         }
593           break;
594         } // switch
595       }// faulties
596
597       Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb;
598       FS1 += (S1_BadType != 0) ? 1 : 0;
599       Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb;
600       FS2 += (S2_BadType != 0) ? 1 : 0;
601       
602       // output for first shape
603       di << "Faulties for FIRST  shape found : " << FS1 << "\n";
604       if(FS1 != 0) {
605         di << "---------------------------------" << "\n";
606         Standard_CString CString1;
607         if (S1_BadType != 0)
608           CString1="YES";
609         else
610           CString1="NO";
611         di << "Shapes are not suppotrted by BOP: " << CString1 << "\n";
612         Standard_CString CString2;
613         if (S1_SelfInt != 0)
614           CString2="YES";
615         else
616           CString2="NO";
617         di << "Self-Intersections              : " << CString2;
618         if(S1_SelfInt != 0)
619           di << "  Cases(" << S1_SelfInt << ")  Total shapes(" << S1_SelfIntAll << ")" << "\n";
620         else
621           di << "\n";
622         Standard_CString CString13;
623         if (S1_OpAb != 0)
624           CString13="YES";
625         else
626           CString13="NO";
627         di << "Check for SI has been aborted   : " << CString13 << "\n";
628         Standard_CString CString3;
629         if (S1_SmalE != 0)
630           CString3="YES";
631         else
632           CString3="NO";
633         di << "Too small edges                 : " << CString3;
634         if(S1_SmalE != 0)
635           di << "  Cases(" << S1_SmalE << ")  Total shapes(" << S1_SmalEAll << ")" << "\n";
636         else
637           di << "\n";
638         Standard_CString CString4;
639         if (S1_BadF != 0)
640           CString4="YES";
641         else
642           CString4="NO";
643         di << "Bad faces                       : " << CString4;
644         if(S1_BadF != 0)
645           di << "  Cases(" << S1_BadF << ")  Total shapes(" << S1_BadFAll << ")" << "\n";
646         else
647           di << "\n";
648         Standard_CString CString5;
649         if (S1_BadV != 0)
650           CString5="YES";
651         else
652           CString5="NO";
653         di << "Too close vertices              : " << CString5;
654         if(S1_BadV != 0)
655           di << "  Cases(" << S1_BadV << ")  Total shapes(" << S1_BadVAll << ")" << "\n";
656         else
657           di << "\n";
658         Standard_CString CString6;
659         if (S1_BadE != 0)
660           CString6="YES";
661         else
662           CString6="NO";
663         di << "Too close edges                 : " << CString6;
664         if(S1_BadE != 0)
665           di << "  Cases(" << S1_BadE << ")  Total shapes(" << S1_BadEAll << ")" << "\n";
666         else
667           di << "\n";
668       }
669
670       // output for second shape
671       di << "\n";
672       di << "Faulties for SECOND  shape found : " << FS2 << "\n";
673       if(FS2 != 0) {
674         di << "---------------------------------" << "\n";
675         Standard_CString CString7;
676         if (S2_BadType != 0)
677           CString7="YES";
678         else
679           CString7="NO";
680         di << "Shapes are not suppotrted by BOP: " << CString7 << "\n";
681         Standard_CString CString8;
682         if (S2_SelfInt != 0)
683           CString8="YES";
684         else
685           CString8="NO";
686         di << "Self-Intersections              : " << CString8;
687         if(S2_SelfInt != 0)
688           di << "  Cases(" << S2_SelfInt << ")  Total shapes(" << S2_SelfIntAll << ")" << "\n";
689         else
690           di << "\n";
691
692         Standard_CString CString14;
693         if (S2_OpAb != 0)
694           CString14="YES";
695         else
696           CString14="NO";
697         di << "Check for SI has been aborted   : " << CString14 << "\n";
698         Standard_CString CString9;
699         if (S2_SmalE != 0)
700           CString9="YES";
701         else
702           CString9="NO";
703         di << "Too small edges                 : " << CString9;
704         if(S2_SmalE != 0)
705           di << "  Cases(" << S2_SmalE << ")  Total shapes(" << S2_SmalEAll << ")" << "\n";
706         else
707           di << "\n";
708         Standard_CString CString10;
709         if (S2_BadF != 0)
710           CString10="YES";
711         else
712           CString10="NO";
713         di << "Bad faces                       : " << CString10;
714         if(S2_BadF != 0)
715           di << "  Cases(" << S2_BadF << ")  Total shapes(" << S2_BadFAll << ")" << "\n";
716         else
717           di << "\n";
718         Standard_CString CString11;
719         if (S2_BadV != 0)
720           CString11="YES";
721         else
722           CString11="NO";
723         di << "Too close vertices              : " << CString11;
724         if(S2_BadV != 0)
725           di << "  Cases(" << S2_BadV << ")  Total shapes(" << S2_BadVAll << ")" << "\n";
726         else
727           di << "\n";
728         Standard_CString CString12;
729         if (S2_BadE != 0)
730           CString12="YES";
731         else
732           CString12="NO";
733         di << "Too close edges                 : " << CString12;
734         if(S2_BadE != 0)
735           di << "  Cases(" << S2_BadE << ")  Total shapes(" << S2_BadEAll << ")" << "\n";
736         else
737           di << "\n";
738
739         // warning
740         di << "\n";
741         if(hasUnknown)
742           di << "WARNING: The unexpected test break occurs!" << "\n";
743       }
744     } // full output
745   } // has faulties
746
747   return 0;
748 }