0025801: Some of the commands in BOPTest packages show the execution time without...
[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 <TopExp_Explorer.hxx>
24
25 #include <TopTools_MapOfShape.hxx>
26 #include <TopTools_ShapeMapHasher.hxx>
27
28 #include <TopoDS_Shape.hxx>
29 #include <TopoDS_Compound.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRepBuilderAPI_Copy.hxx>
32
33 #include <DBRep.hxx>
34 #include <Draw.hxx>
35
36 #include <BOPCol_ListOfShape.hxx>
37
38 #include <BOPDS_DS.hxx>
39 #include <BOPDS_MapOfPassKey.hxx>
40
41 #include <BOPAlgo_CheckerSI.hxx>
42 #include <BOPAlgo_ArgumentAnalyzer.hxx>
43 #include <BOPAlgo_CheckResult.hxx>
44 #include <BOPTools_AlgoTools.hxx>
45
46 #include <OSD_Timer.hxx>
47 #include <BOPTest_Objects.hxx>
48
49 //
50 static 
51   void MakeShapeForFullOutput (const TCollection_AsciiString&,
52                                const Standard_Integer,
53                                const BOPCol_ListOfShape&,
54                                Standard_Integer& ,
55                                Draw_Interpretor&,
56                                Standard_Boolean bCurveOnSurf = Standard_False,
57                                Standard_Real aMaxDist = 0.,
58                                Standard_Real aMaxParameter = 0.);
59 //
60 static Standard_Integer bopcheck   (Draw_Interpretor&, Standard_Integer, const char** );
61 static Standard_Integer bopargcheck(Draw_Interpretor&, Standard_Integer, const char** );
62 static Standard_Integer xdistef(Draw_Interpretor&, Standard_Integer, const char** );
63 static Standard_Integer checkcurveonsurf (Draw_Interpretor&, Standard_Integer, const char**);
64
65 //=======================================================================
66 //function : CheckCommands
67 //purpose  : 
68 //=======================================================================
69 void  BOPTest::CheckCommands(Draw_Interpretor& theCommands)
70 {
71   static Standard_Boolean done = Standard_False;
72   if (done) 
73     return;
74
75   done = Standard_True;
76   // Chapter's name
77   const char* g = "BOPTest commands";
78   //
79   theCommands.Add("bopcheck",  
80                   "use bopcheck Shape [level of check: 0 - 9] [-t]",
81                   __FILE__, bopcheck, g);
82   theCommands.Add("bopargcheck" , 
83                   "use bopargcheck without parameters to get ",  
84                   __FILE__, bopargcheck, g);
85   theCommands.Add ("xdistef" ,
86                    "use xdistef edge face",
87                    __FILE__, xdistef, g);
88   theCommands.Add("checkcurveonsurf",
89                   "use checkcurveonsurf shape",
90                   __FILE__, checkcurveonsurf, g);
91 }
92 //=======================================================================
93 //class    : BOPTest_Interf
94 //purpose  : Auxiliary class
95 //=======================================================================
96 class BOPTest_Interf {
97  public:
98   BOPTest_Interf() : myIndex1(-1), myIndex2(-1), myType(-1) {
99   }
100   //
101   ~BOPTest_Interf() {
102   }
103   //
104   void SetIndices(const Standard_Integer theIndex1,
105                   const Standard_Integer theIndex2) {
106     myIndex1=theIndex1; 
107     myIndex2=theIndex2; 
108   }
109   //
110   void Indices(Standard_Integer& theIndex1,
111                Standard_Integer& theIndex2) const {
112     theIndex1=myIndex1; 
113     theIndex2=myIndex2; 
114   }
115   //
116   void SetType(const Standard_Integer theType) {
117     myType=theType;
118   }
119   //
120   Standard_Integer Type() const {
121     return myType;
122   }
123   //
124   bool operator < (const  BOPTest_Interf& aOther) const {
125     bool bFlag;
126     //
127     if (myType==aOther.myType) {
128       if (myIndex1 == aOther.myIndex1) {
129         bFlag=(myIndex2 < aOther.myIndex2);
130       }
131       else {
132         bFlag=(myIndex1 < aOther.myIndex1);
133       }
134     }
135     else {
136       bFlag=(myType < aOther.myType);
137     }
138     //
139     return bFlag;
140   }
141   //
142  protected:
143   Standard_Integer myIndex1;
144   Standard_Integer myIndex2;
145   Standard_Integer myType;
146 };
147 //=======================================================================
148 //function : bopcheck
149 //purpose  : 
150 //=======================================================================
151 Standard_Integer bopcheck (Draw_Interpretor& di, 
152                            Standard_Integer n,  
153                            const char** a )
154 {
155   if (n<2) {
156     di << " use bopcheck Shape [level of check: 0 - 9] [-t]\n";
157     di << " The level of check defines "; 
158     di << " which interferences will be checked:\n";
159     di << " 0 - V/V only\n"; 
160     di << " 1 - V/V, V/E\n";
161     di << " 2 - V/V, V/E, E/E\n"; 
162     di << " 3 - V/V, V/E, E/E , V/F\n"; 
163     di << " 4 - V/V, V/E, E/E, V/F , E/F\n"; 
164     di << " 5 - V/V, V/E, E/E, V/F, E/F, F/F;\n";
165     di << " 6 - V/V, V/E, E/E, V/F, E/F, F/F, V/Z\n";
166     di << " 7 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z\n";
167     di << " 8 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z\n";
168     di << " 9 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z, Z/Z\n";
169     di << " Default level is 9\n";
170     return 1;
171   }
172   //
173   TopoDS_Shape aS = DBRep::Get(a[1]);
174   if (aS.IsNull()) {
175     di << "null shapes are not allowed here!";
176     return 1;
177   }
178   //
179   Standard_Boolean bRunParallel, bShowTime;
180   Standard_Integer i, aLevel, aNbInterfTypes;
181   Standard_Real aTol;
182   //
183   aNbInterfTypes=BOPDS_DS::NbInterfTypes();
184   //
185   aLevel=aNbInterfTypes-1;
186   //
187   if (n>2) {
188     if (a[2][0] != '-') {
189       aLevel=Draw::Atoi(a[2]); 
190     }
191   }
192   //
193   if (aLevel < 0 || aLevel > aNbInterfTypes-1) {
194     di << "Invalid level";
195     return 1;
196   }
197   //
198   bShowTime=Standard_False;
199   aTol=BOPTest_Objects::FuzzyValue();
200   bRunParallel=BOPTest_Objects::RunParallel(); 
201   //
202   for (i=2; i<n; ++i) {
203     if (!strcmp(a[i], "-t")) {
204       bShowTime=Standard_True;
205     }
206       }
207   //
208   //aLevel = (n==3) ? Draw::Atoi(a[2]) : aNbInterfTypes-1;
209   //-------------------------------------------------------------------
210   char buf[256], aName1[32], aName2[32];
211   char aInterfTypes[10][4] = {
212     "V/V", "V/E", "E/E","V/F", "E/F", "F/F", "V/Z", "E/Z", "F/Z", "Z/Z"
213   };
214   //
215   Standard_Integer iErr, iCnt, n1, n2, iT;
216   TopAbs_ShapeEnum aType1, aType2;
217   BOPAlgo_CheckerSI aChecker;
218   BOPCol_ListOfShape aLS;
219   BOPDS_MapIteratorMapOfPassKey aItMPK;
220   //
221   if (aLevel < (aNbInterfTypes-1)) {
222     di << "Info:\nThe level of check is set to " 
223       << aInterfTypes[aLevel] << ", i.e. intersection(s)\n";
224     
225     for (i=aLevel+1; i<aNbInterfTypes; ++i) {
226       di << aInterfTypes[i];
227       if (i<aNbInterfTypes-1) {
228         di << ", ";
229       }
230     }
231     di << " will not be checked.\n\n";
232   }
233   //
234   aLS.Append(aS);
235   aChecker.SetArguments(aLS);
236   aChecker.SetLevelOfCheck(aLevel);
237   aChecker.SetRunParallel(bRunParallel);
238   aChecker.SetFuzzyValue(aTol);
239   //
240   OSD_Timer aTimer;
241   aTimer.Start();
242   //
243   aChecker.Perform();
244   //
245   aTimer.Stop();
246   //
247   iErr=aChecker.ErrorStatus();
248   //
249   const BOPDS_DS& aDS=*(aChecker.PDS());
250   //
251   const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
252   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
253   using namespace std;
254   vector <BOPTest_Interf> aVec;
255   vector <BOPTest_Interf>::iterator aIt;
256   BOPTest_Interf aBInterf;
257   //
258   aItMPK.Initialize(aMPK);
259   for (; aItMPK.More(); aItMPK.Next()) {
260     const BOPDS_PassKey& aPK=aItMPK.Value();
261     aPK.Ids(n1, n2);
262     if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
263       continue;
264     }
265     //
266     const BOPDS_ShapeInfo& aSI1=aDS.ShapeInfo(n1);
267     const BOPDS_ShapeInfo& aSI2=aDS.ShapeInfo(n2);
268     aType1=aSI1.ShapeType();
269     aType2=aSI2.ShapeType();
270     //
271     iT=BOPDS_Tools::TypeToInteger(aType1, aType2);
272     //
273     aBInterf.SetIndices(n1, n2);
274     aBInterf.SetType(iT);
275     //
276     aVec.push_back(aBInterf);
277   }
278   //
279   sort( aVec.begin(), aVec.end(), less<BOPTest_Interf>());
280   //
281   iCnt=0;
282   for (aIt=aVec.begin(); aIt!=aVec.end(); aIt++) {
283     const BOPTest_Interf& aBI=*aIt;
284     //
285     aBI.Indices(n1, n2);
286     if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
287       continue;
288     }
289     //
290     const TopoDS_Shape& aS1=aDS.Shape(n1);
291     const TopoDS_Shape& aS2=aDS.Shape(n2);
292     //
293     iT=aBI.Type(); 
294     di << aInterfTypes[iT] << ": ";
295     //
296     sprintf(aName1, "x%d", n1);
297     //sprintf(aName1, "x%d", iCnt);
298     DBRep::Set (aName1, aS1);
299     //
300     ++iCnt;
301     sprintf(aName2, "x%d", n2);
302     //sprintf(aName2, "x%d", iCnt);
303     DBRep::Set (aName2, aS2);
304     ++iCnt;
305     //
306     sprintf(buf, "%s %s \n", aName1, aName2);
307     di << buf;
308   }
309   //
310   if (iErr) {
311     di << "There were errors during the operation, ";
312     di << "so the list may be incomplete." << "\n";
313   }
314   //
315   if (!iCnt) {
316     di << " This shape seems to be OK." << "\n";
317   }
318   if (bShowTime)
319   {
320     Sprintf(buf, "  Tps: %7.2lf\n", aTimer.ElapsedTime());
321     di << buf;
322   }
323   return 0;
324 }
325 //=======================================================================
326 //function : bopargcheck
327 //purpose  : 
328 //=======================================================================
329 Standard_Integer bopargcheck (Draw_Interpretor& di,
330                               Standard_Integer n,
331                               const char** a )
332 {
333   if (n<2) {
334     di << "\n";
335     di << " Use >bopargcheck Shape1 [[Shape2] ";
336     di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P|C|S]] [#BF]\n\n";
337     di << " -<Boolean Operation>" << "\n";
338     di << " F (fuse)" << "\n";
339     di << " O (common)" << "\n";
340     di << " C (cut)" << "\n";
341     di << " T (cut21)" << "\n";
342     di << " S (section)" << "\n";
343     di << " U (unknown)" << "\n";
344     di << " For example: \"bopargcheck s1 s2 -F\" enables" ;
345     di << " checking for Fuse operation" << "\n";
346     di << " default - section" << "\n" << "\n";
347     di << " /<Test Options>" << "\n";
348     di << " R (disable small edges (shrank range) test)" << "\n";
349     di << " F (disable faces verification test)" << "\n";
350     di << " T (disable tangent faces searching test)" << "\n";
351     di << " V (disable test possibility to merge vertices)" << "\n";
352     di << " E (disable test possibility to merge edges)" << "\n";
353     di << " I (disable self-interference test)" << "\n";
354     di << " P (disable shape type test)" << "\n";
355     di << " C (disable test for shape continuity)" << "\n";
356     di << " S (disable curve on surface check)" << "\n";
357     di << " For example: \"bopargcheck s1 s2 /RI\" disables ";
358     di << "small edge detection and self-intersection detection" << "\n";
359     di << " default - all options are enabled" << "\n" << "\n";
360     di << " #<Additional Test Options>" << "\n";
361     di << " B (stop test on first faulty found); default OFF" << "\n";
362     di << " F (full output for faulty shapes); default - output ";
363     di << "in a short format" << "\n" << "\n";
364     di << " NOTE: <Boolean Operation> and <Test Options> are ";
365     di <<  "used only for couple" << "\n";
366     di << "       of argument shapes, except I and P options ";
367     di << "that are always used for" << "\n";
368     di << "       couple of shapes as well as for ";
369     di <<"single shape test." << "\n";
370     return 1;
371   }
372
373   TopoDS_Shape aS1 = DBRep::Get(a[1]);
374
375   if(aS1.IsNull()) {
376     di << "Error: null shape not allowed!" << "\n";
377     di << "Type bopargcheck without arguments for more ";
378     di <<"information" << "\n";
379     return 1;
380   }
381
382   Standard_Boolean isBO = Standard_False;
383   Standard_Integer indxBO = 0;
384   Standard_Boolean isOP = Standard_False;
385   Standard_Integer indxOP = 0;
386   Standard_Boolean isAD = Standard_False;
387   Standard_Integer indxAD = 0;
388   Standard_Boolean isS2 = Standard_False;
389   Standard_Integer indxS2 = 0;
390   Standard_Real aTolerance = 0;
391
392   aTolerance=BOPTest_Objects::FuzzyValue();
393   
394   if(n >= 3) {
395     Standard_Integer iIndex = 0;
396     for(iIndex = 2; iIndex < n; iIndex++) {
397       if(a[iIndex][0] == '-')   {
398         isBO = Standard_True;
399         indxBO = iIndex;
400       }
401       else if(a[iIndex][0] == '/') {
402         isOP = Standard_True;
403         indxOP = iIndex;
404       }
405       else if(a[iIndex][0] == '#') {
406         isAD = Standard_True;
407         indxAD = iIndex;
408       }
409       else {
410         isS2 = Standard_True;
411         indxS2 = iIndex;
412       }
413     }
414   }
415   
416   // set & test second shape
417   TopoDS_Shape aS22, aS2;
418   if(isS2) {
419     if(indxS2 != 2) {
420       di << "Error: second shape should follow the first one!" << "\n";
421       di << "Type bopargcheck without arguments for more information" << "\n";
422       return 1;
423     }
424     else {
425       aS22 = DBRep::Get(a[2]);
426       if(aS22.IsNull()) {
427         di << "Error: second shape is null!" << "\n";
428         di << "Type bopargcheck without arguments for more information" << "\n";
429         return 1;
430       }
431     }
432   }
433   
434   // init checker
435   BOPAlgo_ArgumentAnalyzer aChecker;
436   aChecker.SetFuzzyValue(aTolerance);
437   aChecker.SetShape1(aS1);
438
439   // set default options (always tested!) for single and couple shapes
440   aChecker.ArgumentTypeMode()   = Standard_True;
441   aChecker.SelfInterMode()      = Standard_True;
442   aChecker.SmallEdgeMode()      = Standard_True;
443   aChecker.RebuildFaceMode()    = Standard_True;
444   aChecker.ContinuityMode()     = Standard_True;
445   aChecker.CurveOnSurfaceMode() = Standard_True;
446
447   // test & set options and operation for two shapes
448   if(!aS22.IsNull()) {
449     aS2 = BRepBuilderAPI_Copy(aS22).Shape();
450     aChecker.SetShape2(aS2);
451     // set operation (default - Section)
452     if(isBO) {
453       if(a[indxBO][1] == 'F' || a[indxBO][1] == 'f') {
454         aChecker.OperationType() = BOPAlgo_FUSE;
455       }
456       else if(a[indxBO][1] == 'O' || a[indxBO][1] == 'o') {
457         aChecker.OperationType() = BOPAlgo_COMMON;
458       }
459       else if(a[indxBO][1] == 'C' || a[indxBO][1] == 'c') {
460         aChecker.OperationType() = BOPAlgo_CUT;
461       }
462       else if(a[indxBO][1] == 'T' || a[indxBO][1] == 't') {
463          aChecker.OperationType() = BOPAlgo_CUT21;
464       }
465       else if(a[indxBO][1] == 'S' || a[indxBO][1] == 's') {
466          aChecker.OperationType() = BOPAlgo_SECTION;
467       }
468       else if(a[indxBO][1] == 'U' || a[indxBO][1] == 'u') {
469         aChecker.OperationType() = BOPAlgo_UNKNOWN;
470       }
471       else {
472         di << "Error: invalid boolean operation type!" << "\n";
473         di << "Type bopargcheck without arguments for more information" << "\n";
474         return 1;
475       }
476     }
477     else
478       aChecker.OperationType() = BOPAlgo_SECTION;
479
480     aChecker.TangentMode()     = Standard_True;
481     aChecker.MergeVertexMode() = Standard_True;
482     aChecker.MergeEdgeMode()   = Standard_True;
483   }
484   
485   // set options (default - all ON)
486   if(isOP) {
487     Standard_Integer ind = 1;
488     while(a[indxOP][ind] != 0) {
489       if(a[indxOP][ind] == 'R' || a[indxOP][ind] == 'r') {
490         aChecker.SmallEdgeMode() = Standard_False;
491       }
492       else if(a[indxOP][ind] == 'F' || a[indxOP][ind] == 'f') {
493         aChecker.RebuildFaceMode() = Standard_False;
494       }
495       else if(a[indxOP][ind] == 'T' || a[indxOP][ind] == 't') {
496         aChecker.TangentMode() = Standard_False;
497       }
498       else if(a[indxOP][ind] == 'V' || a[indxOP][ind] == 'v') {
499         aChecker.MergeVertexMode() = Standard_False;
500       }
501       else if(a[indxOP][ind] == 'E' || a[indxOP][ind] == 'e') {
502         aChecker.MergeEdgeMode() = Standard_False;
503       }
504       else if(a[indxOP][ind] == 'I' || a[indxOP][ind] == 'i') {
505         aChecker.SelfInterMode() = Standard_False;
506       }
507       else if(a[indxOP][ind] == 'P' || a[indxOP][ind] == 'p') {
508         aChecker.ArgumentTypeMode() = Standard_False;
509       }
510       else if(a[indxOP][ind] == 'C' || a[indxOP][ind] == 'c') {
511         aChecker.ContinuityMode() = Standard_False;
512       }
513       else if(a[indxOP][ind] == 'S' || a[indxOP][ind] == 's') {
514         aChecker.CurveOnSurfaceMode() = Standard_False;
515       }
516       else {
517         di << "Error: invalid test option(s)!" << "\n";
518         di << "Type bopargcheck without arguments for more information" << "\n";
519         return 1;
520       }
521       ind++;
522     }
523   }
524
525   // set additional options
526   Standard_Boolean fullOutput = Standard_False;
527   if(isAD) {
528     Standard_Integer ind = 1;
529     while(a[indxAD][ind] != 0) {
530       if(a[indxAD][ind] == 'B' || a[indxAD][ind] == 'b') {
531         aChecker.StopOnFirstFaulty() = Standard_True;
532       }
533       else if(a[indxAD][ind] == 'F' || a[indxAD][ind] == 'f') {
534         fullOutput = Standard_True;
535       }
536       else {
537         di << "Error: invalid additional test option(s)!" << "\n";
538         di << "Type bopargcheck without arguments for more information" << "\n";
539         return 1;
540       }
541       ind++;
542     }
543   }
544
545   // run checker
546   aChecker.Perform();
547
548   // process result of checking
549   if(!aChecker.HasFaulty()) {
550     di << "Shape(s) seem(s) to be valid for BOP."  << "\n";
551   }
552   else {
553     if(!fullOutput) {
554       di << "Faulties, that can not be treated by BOP, are detected." << "\n"; 
555     }
556     else {
557       const BOPAlgo_ListOfCheckResult& aResultList = aChecker.GetCheckResult();
558       BOPAlgo_ListIteratorOfListOfCheckResult anIt(aResultList);
559
560       Standard_Integer S1_BadType = 0, S1_SelfInt = 0, S1_SmalE = 0, S1_BadF = 0, S1_BadV = 0, S1_BadE = 0;
561       Standard_Integer S1_SelfIntAll = 0, S1_SmalEAll = 0, S1_BadFAll = 0, S1_BadVAll = 0, S1_BadEAll = 0;
562       Standard_Integer S2_BadType = 0, S2_SelfInt = 0, S2_SmalE = 0, S2_BadF = 0, S2_BadV = 0, S2_BadE = 0;
563       Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0;
564       Standard_Integer S1_OpAb = 0, S2_OpAb = 0;
565       Standard_Integer S1_C0 = 0, S2_C0 = 0, S1_C0All = 0, S2_C0All = 0;
566       Standard_Integer S1_COnS = 0, S2_COnS = 0, S1_COnSAll = 0, S2_COnSAll = 0;
567       Standard_Boolean hasUnknown = Standard_False;
568
569       TCollection_AsciiString aS1SIBaseName("s1si_");
570       TCollection_AsciiString aS1SEBaseName("s1se_");
571       TCollection_AsciiString aS1BFBaseName("s1bf_");
572       TCollection_AsciiString aS1BVBaseName("s1bv_");
573       TCollection_AsciiString aS1BEBaseName("s1be_");
574       TCollection_AsciiString aS1C0BaseName("s1C0_");
575       TCollection_AsciiString aS1COnSBaseName("s1COnS_");
576       TCollection_AsciiString aS2SIBaseName("s2si_");
577       TCollection_AsciiString aS2SEBaseName("s2se_");
578       TCollection_AsciiString aS2BFBaseName("s2bf_");
579       TCollection_AsciiString aS2BVBaseName("s2bv_");
580       TCollection_AsciiString aS2BEBaseName("s2be_");
581       TCollection_AsciiString aS2C0BaseName("s2C0_");
582       TCollection_AsciiString aS2COnSBaseName("s2COnS_");
583
584       for(; anIt.More(); anIt.Next()) {
585         const BOPAlgo_CheckResult& aResult = anIt.Value();
586         const TopoDS_Shape & aSS1 = aResult.GetShape1();
587         const TopoDS_Shape & aSS2 = aResult.GetShape2();
588         const BOPCol_ListOfShape & aLS1 = aResult.GetFaultyShapes1();
589         const BOPCol_ListOfShape & aLS2 = aResult.GetFaultyShapes2();
590         Standard_Boolean isL1 = !aLS1.IsEmpty();
591         Standard_Boolean isL2 = !aLS2.IsEmpty();
592
593         switch(aResult.GetCheckStatus()) {
594         case BOPAlgo_BadType: {
595           if(!aSS1.IsNull()) S1_BadType++;
596           if(!aSS2.IsNull()) S2_BadType++;
597         }
598           break;
599         case BOPAlgo_SelfIntersect: {
600           if(!aSS1.IsNull()) {
601             S1_SelfInt++;
602             if(isL1)
603               MakeShapeForFullOutput(aS1SIBaseName, S1_SelfInt, aLS1, S1_SelfIntAll, di);
604           }
605           if(!aSS2.IsNull()) {
606             S2_SelfInt++;
607             if(isL2)
608               MakeShapeForFullOutput(aS2SIBaseName, S2_SelfInt, aLS2, S2_SelfIntAll, di);
609           }
610         }
611           break;
612         case BOPAlgo_TooSmallEdge: {
613           if(!aSS1.IsNull()) {
614             S1_SmalE++;
615             if(isL1)
616               MakeShapeForFullOutput(aS1SEBaseName, S1_SmalE, aLS1, S1_SmalEAll, di);
617           }
618           if(!aSS2.IsNull()) {
619             S2_SmalE++;
620             if(isL2)
621               MakeShapeForFullOutput(aS2SEBaseName, S2_SmalE, aLS2, S2_SmalEAll, di);
622           }
623         }
624           break;
625         case BOPAlgo_NonRecoverableFace: {
626           if(!aSS1.IsNull()) {
627             S1_BadF++;
628             if(isL1)
629               MakeShapeForFullOutput(aS1BFBaseName, S1_BadF, aLS1, S1_BadFAll, di);
630           }
631           if(!aSS2.IsNull()) {
632             S2_BadF++;
633             if(isL2)
634               MakeShapeForFullOutput(aS2BFBaseName, S2_BadF, aLS2, S2_BadFAll, di);
635           }
636         }
637           break;
638         case BOPAlgo_IncompatibilityOfVertex: {
639           if(!aSS1.IsNull()) {
640             S1_BadV++;
641             if(isL1) {
642               MakeShapeForFullOutput(aS1BVBaseName, S1_BadV, aLS1, S1_BadVAll, di);
643             }
644           }
645           if(!aSS2.IsNull()) {
646             S2_BadV++;
647             if(isL2){
648               MakeShapeForFullOutput(aS2BVBaseName, S2_BadV, aLS2, S2_BadVAll, di);
649             }
650           }
651         }
652           break;
653         case BOPAlgo_IncompatibilityOfEdge: {
654           if(!aSS1.IsNull()) {
655             S1_BadE++;
656             if(isL1) {
657               MakeShapeForFullOutput(aS1BEBaseName, S1_BadE, aLS1, S1_BadEAll, di);
658             }
659           }
660           if(!aSS2.IsNull()) {
661             S2_BadE++;
662             if(isL2) {
663               MakeShapeForFullOutput(aS2BEBaseName, S2_BadE, aLS2, S2_BadEAll, di);
664             }
665           }
666         }
667           break;
668         case BOPAlgo_IncompatibilityOfFace: {
669           // not yet implemented
670         }
671           break;
672         case BOPAlgo_GeomAbs_C0: {
673           if(!aSS1.IsNull()) {
674             S1_C0++;
675             if(isL1) {
676               MakeShapeForFullOutput(aS1C0BaseName, S1_C0, aLS1, S1_C0All, di);
677             }
678           }
679           if(!aSS2.IsNull()) {
680             S2_C0++;
681             if(isL2) {
682               MakeShapeForFullOutput(aS2C0BaseName, S2_C0, aLS2, S2_C0All, di);
683             }
684           }
685         }
686           break;
687         case BOPAlgo_InvalidCurveOnSurface: {
688           if(!aSS1.IsNull()) {
689             S1_COnS++;
690             if(isL1) {
691               Standard_Real aMaxDist = aResult.GetMaxDistance1();
692               Standard_Real aMaxParameter = aResult.GetMaxParameter1();
693               MakeShapeForFullOutput(aS1COnSBaseName, S1_COnS, aLS1, S1_COnSAll, di,
694                                      Standard_True, aMaxDist, aMaxParameter);
695             }
696           }
697           if(!aSS2.IsNull()) {
698             S2_COnS++;
699             if(isL2) {
700               Standard_Real aMaxDist = aResult.GetMaxDistance2();
701               Standard_Real aMaxParameter = aResult.GetMaxParameter2();
702               MakeShapeForFullOutput(aS2COnSBaseName, S2_COnS, aLS2, S2_COnSAll, di,
703                                      Standard_True, aMaxDist, aMaxParameter);
704             }
705           }
706         }
707           break;
708         case BOPAlgo_OperationAborted: {
709           if(!aSS1.IsNull()) S1_OpAb++;
710           if(!aSS2.IsNull()) S2_OpAb++;
711         }
712           break;
713         case BOPAlgo_CheckUnknown:
714         default: {
715           hasUnknown = Standard_True;
716         }
717           break;
718         } // switch
719       }// faulties
720
721       Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0 + S1_COnS;
722       FS1 += (S1_BadType != 0) ? 1 : 0;
723       Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0 + S2_COnS;
724       FS2 += (S2_BadType != 0) ? 1 : 0;
725       
726       // output for first shape
727       di << "Faulties for FIRST  shape found : " << FS1 << "\n";
728       if(FS1 != 0) {
729         di << "---------------------------------" << "\n";
730         Standard_CString CString1;
731         if (S1_BadType != 0)
732           CString1="YES";
733         else
734           CString1=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
735         di << "Shapes are not suppotrted by BOP: " << CString1 << "\n";
736         Standard_CString CString2;
737         if (S1_SelfInt != 0)
738           CString2="YES";
739         else
740           CString2=aChecker.SelfInterMode() ? "NO" : "DISABLED";
741         di << "Self-Intersections              : " << CString2;
742         if(S1_SelfInt != 0)
743           di << "  Cases(" << S1_SelfInt << ")  Total shapes(" << S1_SelfIntAll << ")" << "\n";
744         else
745           di << "\n";
746         Standard_CString CString13;
747         if (S1_OpAb != 0)
748           CString13="YES";
749         else
750           CString13=aChecker.SelfInterMode() ? "NO" : "DISABLED";
751         di << "Check for SI has been aborted   : " << CString13 << "\n";
752         Standard_CString CString3;
753         if (S1_SmalE != 0)
754           CString3="YES";
755         else
756           CString3=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
757         di << "Too small edges                 : " << CString3;
758         if(S1_SmalE != 0)
759           di << "  Cases(" << S1_SmalE << ")  Total shapes(" << S1_SmalEAll << ")" << "\n";
760         else
761           di << "\n";
762         Standard_CString CString4;
763         if (S1_BadF != 0)
764           CString4="YES";
765         else
766           CString4=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
767         di << "Bad faces                       : " << CString4;
768         if(S1_BadF != 0)
769           di << "  Cases(" << S1_BadF << ")  Total shapes(" << S1_BadFAll << ")" << "\n";
770         else
771           di << "\n";
772         Standard_CString CString5;
773         if (S1_BadV != 0)
774           CString5="YES";
775         else
776           CString5=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
777         di << "Too close vertices              : " << CString5;
778         if(S1_BadV != 0)
779           di << "  Cases(" << S1_BadV << ")  Total shapes(" << S1_BadVAll << ")" << "\n";
780         else
781           di << "\n";
782         Standard_CString CString6;
783         if (S1_BadE != 0)
784           CString6="YES";
785         else
786           CString6=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
787         di << "Too close edges                 : " << CString6;
788         if(S1_BadE != 0)
789           di << "  Cases(" << S1_BadE << ")  Total shapes(" << S1_BadEAll << ")" << "\n";
790         else
791           di << "\n";
792         Standard_CString CString15;
793         if (S1_C0 != 0)
794           CString15="YES";
795         else
796           CString15=aChecker.ContinuityMode() ? "NO" : "DISABLED";
797         di << "Shapes with Continuity C0       : " << CString15;
798         if(S1_C0 != 0)
799           di << "  Cases(" << S1_C0 << ")  Total shapes(" << S1_C0All << ")" << "\n";
800         else
801           di << "\n";
802
803         Standard_CString CString17;
804         if (S1_COnS != 0)
805           CString17="YES";
806         else
807           CString17=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
808         di << "Invalid Curve on Surface        : " << CString17;
809         if(S1_COnS != 0)
810           di << "  Cases(" << S1_COnS << ")  Total shapes(" << S1_COnSAll << ")" << "\n";
811         else
812           di << "\n";
813       }
814
815       // output for second shape
816       di << "\n";
817       di << "Faulties for SECOND  shape found : " << FS2 << "\n";
818       if(FS2 != 0) {
819         di << "---------------------------------" << "\n";
820         Standard_CString CString7;
821         if (S2_BadType != 0)
822           CString7="YES";
823         else
824           CString7=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
825         di << "Shapes are not suppotrted by BOP: " << CString7 << "\n";
826         Standard_CString CString8;
827         if (S2_SelfInt != 0)
828           CString8="YES";
829         else
830           CString8=aChecker.SelfInterMode() ? "NO" : "DISABLED";
831         di << "Self-Intersections              : " << CString8;
832         if(S2_SelfInt != 0)
833           di << "  Cases(" << S2_SelfInt << ")  Total shapes(" << S2_SelfIntAll << ")" << "\n";
834         else
835           di << "\n";
836
837         Standard_CString CString14;
838         if (S2_OpAb != 0)
839           CString14="YES";
840         else
841           CString14=aChecker.SelfInterMode() ? "NO" : "DISABLED";
842         di << "Check for SI has been aborted   : " << CString14 << "\n";
843         Standard_CString CString9;
844         if (S2_SmalE != 0)
845           CString9="YES";
846         else
847           CString9=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
848         di << "Too small edges                 : " << CString9;
849         if(S2_SmalE != 0)
850           di << "  Cases(" << S2_SmalE << ")  Total shapes(" << S2_SmalEAll << ")" << "\n";
851         else
852           di << "\n";
853         Standard_CString CString10;
854         if (S2_BadF != 0)
855           CString10="YES";
856         else
857           CString10=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
858         di << "Bad faces                       : " << CString10;
859         if(S2_BadF != 0)
860           di << "  Cases(" << S2_BadF << ")  Total shapes(" << S2_BadFAll << ")" << "\n";
861         else
862           di << "\n";
863         Standard_CString CString11;
864         if (S2_BadV != 0)
865           CString11="YES";
866         else
867           CString11=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
868         di << "Too close vertices              : " << CString11;
869         if(S2_BadV != 0)
870           di << "  Cases(" << S2_BadV << ")  Total shapes(" << S2_BadVAll << ")" << "\n";
871         else
872           di << "\n";
873         Standard_CString CString12;
874         if (S2_BadE != 0)
875           CString12="YES";
876         else
877           CString12=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
878         di << "Too close edges                 : " << CString12;
879         if(S2_BadE != 0)
880           di << "  Cases(" << S2_BadE << ")  Total shapes(" << S2_BadEAll << ")" << "\n";
881         else
882           di << "\n";
883         Standard_CString CString16;
884         if (S2_C0 != 0)
885           CString16="YES";
886         else
887           CString16=aChecker.ContinuityMode() ? "NO" : "DISABLED";
888         di << "Shapes with Continuity C0       : " << CString16;
889         if(S2_C0 != 0)
890           di << "  Cases(" << S2_C0 << ")  Total shapes(" << S2_C0All << ")" << "\n";
891         else
892           di << "\n";
893
894         Standard_CString CString18;
895         if (S2_COnS != 0)
896           CString18="YES";
897         else
898           CString18=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
899         di << "Invalid Curve on Surface        : " << CString18;
900         if(S2_COnS != 0)
901           di << "  Cases(" << S2_COnS << ")  Total shapes(" << S2_COnSAll << ")" << "\n";
902         else
903           di << "\n";
904       }
905       // warning
906       if(hasUnknown) {
907         di << "\n";
908         di << "WARNING: The unexpected test break occurs!" << "\n";
909       }
910     } // full output
911   } // has faulties
912
913   return 0;
914 }
915
916 //=======================================================================
917 //function : xdistef
918 //purpose  : 
919 //=======================================================================
920 Standard_Integer xdistef(Draw_Interpretor& di,
921                          Standard_Integer n,
922                          const char** a)
923 {
924   if(n < 3) {
925     di << "use xdistef edge face\n";
926     return 1;
927   }
928   //
929   const TopoDS_Shape aS1 = DBRep::Get(a[1]);
930   const TopoDS_Shape aS2 = DBRep::Get(a[2]);
931   //
932   if (aS1.IsNull() || aS2.IsNull()) {
933     di << "null shapes\n";
934     return 1;
935   }
936   //
937   if (aS1.ShapeType() != TopAbs_EDGE || 
938       aS2.ShapeType() != TopAbs_FACE) {
939     di << "type mismatch\n";
940     return 1;
941   }
942   //
943   Standard_Real aMaxDist = 0.0, aMaxPar = 0.0;
944   //
945   const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&aS1;
946   const TopoDS_Face& aFace  = *(TopoDS_Face*)&aS2;
947   //
948   if(!BOPTools_AlgoTools::ComputeTolerance
949      (aFace, anEdge, aMaxDist, aMaxPar)) {
950     di << "Tolerance cannot be computed\n";
951     return 1;
952   }
953   //
954   di << "Max Distance = " << aMaxDist 
955      << "; Parameter on curve = " << aMaxPar << "\n";
956   //
957   return 0;
958 }
959
960 //=======================================================================
961 //function : checkcurveonsurf
962 //purpose  : 
963 //=======================================================================
964 Standard_Integer checkcurveonsurf(Draw_Interpretor& di,
965                                   Standard_Integer n, 
966                                   const char** a)
967 {
968   if (n != 2) {
969     di << "use checkcurveonsurf shape\n";
970     return 1;
971   }
972   //
973   TopoDS_Shape aS =  DBRep::Get(a[1]);
974   if (aS.IsNull()) {
975     di << "null shape\n";
976     return 1;
977   }
978   //
979   Standard_Integer nE, nF, anECounter, aFCounter;
980   Standard_Real aT, aTolE, aDMax;
981   TopExp_Explorer aExpF, aExpE;
982   char buf[200], aFName[10], anEName[10];
983   NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> aDMETol;
984   BOPCol_DataMapOfShapeInteger aMSI;
985   //
986   anECounter = 0;
987   aFCounter  = 0;
988   //
989   aExpF.Init(aS, TopAbs_FACE);
990   for (; aExpF.More(); aExpF.Next()) {
991     const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
992     //
993     aExpE.Init(aF, TopAbs_EDGE);
994     for (; aExpE.More(); aExpE.Next()) {
995       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
996       //
997       if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) {
998         continue;
999       }
1000       //
1001       aTolE = BRep_Tool::Tolerance(aE);
1002       if (aDMax < aTolE) {
1003         continue;
1004       }
1005       //
1006       if (aDMETol.IsBound(aE)) {
1007         Standard_Real& aD = aDMETol.ChangeFind(aE);
1008         if (aDMax > aD) {
1009           aD = aDMax;
1010         }
1011       }
1012       else {
1013         aDMETol.Bind(aE, aDMax);
1014       }
1015       //
1016       if (anECounter == 0) {
1017         di << "Invalid curves on surface:\n";
1018       }
1019       //
1020       if (aMSI.IsBound(aE)) {
1021         nE = aMSI.Find(aE);
1022       }
1023       else {
1024         nE = anECounter;
1025         aMSI.Bind(aE, nE);
1026         ++anECounter;
1027       }
1028       //
1029       if (aMSI.IsBound(aF)) {
1030         nF = aMSI.Find(aF);
1031       } else {
1032         nF = aFCounter;
1033         aMSI.Bind(aF, nF);
1034         ++aFCounter;
1035       }
1036       //
1037       sprintf(anEName, "e_%d", nE);
1038       sprintf(aFName , "f_%d", nF);
1039       sprintf(buf, "edge %s on face %s (max dist: %3.16f, parameter on curve: %3.16f)\n",
1040               anEName, aFName, aDMax, aT);
1041       di << buf;
1042       //
1043       DBRep::Set(anEName, aE);
1044       DBRep::Set(aFName , aF);
1045     }
1046   }
1047   //
1048   if (anECounter > 0) {
1049     di << "\n\nSugestions to fix the shape:\n";
1050     di << "explode " << a[1] << " e;\n";
1051     //
1052     TopTools_MapOfShape M;
1053     aExpE.Init(aS, TopAbs_EDGE);
1054     for (anECounter = 0; aExpE.More(); aExpE.Next()) {
1055       const TopoDS_Shape& aE = aExpE.Current();
1056       if (!M.Add(aE)) {
1057         continue;
1058       }
1059       ++anECounter;
1060       //
1061       if (!aDMETol.IsBound(aE)) {
1062         continue;
1063       }
1064       //
1065       aTolE = aDMETol.Find(aE);
1066       aTolE *= 1.001;
1067       sprintf(buf, "settolerance %s_%d %3.16f;\n", a[1], anECounter, aTolE);
1068       di << buf;
1069     }
1070   }
1071   else {
1072     di << "This shape seems to be OK.\n";
1073   }
1074   //
1075   return 0;
1076 }
1077
1078 //=======================================================================
1079 //function : MakeShapeForFullOutput
1080 //purpose  : 
1081 //=======================================================================
1082 void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName,
1083                              const Standard_Integer          aIndex,
1084                              const BOPCol_ListOfShape &      aList,
1085                              Standard_Integer&               aCount,
1086                              Draw_Interpretor&               di,
1087                              Standard_Boolean                bCurveOnSurf,
1088                              Standard_Real                   aMaxDist,
1089                              Standard_Real                   aMaxParameter)
1090 {
1091   TCollection_AsciiString aNum(aIndex);
1092   TCollection_AsciiString aName = aBaseName + aNum;
1093   Standard_CString name = aName.ToCString();
1094
1095   TopoDS_Compound cmp;
1096   BRep_Builder BB;
1097   BB.MakeCompound(cmp);
1098
1099   BOPCol_ListIteratorOfListOfShape anIt(aList);
1100   for(; anIt.More(); anIt.Next()) {
1101     const TopoDS_Shape & aS = anIt.Value();
1102     BB.Add(cmp, aS);
1103     aCount++;
1104   }
1105   di << "Made faulty shape: " << name;
1106   //
1107   if (bCurveOnSurf) {
1108     di << " (MaxDist = " << aMaxDist 
1109        << ", MaxPar = " << aMaxParameter << ")";
1110   }
1111   //
1112   di << "\n";
1113   //
1114   DBRep::Set(name, cmp);
1115 }