0024002: Overall code and build procedure refactoring -- automatic
[occt.git] / src / BOPTest / BOPTest_CheckCommands.cxx
index 6219ab9..3076341 100644 (file)
@@ -3,8 +3,8 @@
 //
 // This file is part of Open CASCADE Technology software library.
 //
-// This library is free software; you can redistribute it and / or modify it
-// under the terms of the GNU Lesser General Public version 2.1 as published
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
 // by the Free Software Foundation, with special exception defined in the file
 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
 // distribution for complete text of the license and disclaimer of any warranty.
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <BOPTest.ixx>
-#include <TCollection_AsciiString.hxx>
-
-#include <gp_Pnt.hxx>
-
-#include <TopoDS_Shape.hxx>
-#include <TopoDS_Compound.hxx>
-#include <BRep_Builder.hxx>
-
-#include <DBRep.hxx>
 
-#include <Geom_Geometry.hxx>
-#include <Geom_CartesianPoint.hxx>
-
-#include <Draw.hxx>
-#include <DrawTrSurf.hxx>
-#include <BOPAlgo_CheckerSI.hxx>
-#include <BOPDS_VectorOfInterfVV.hxx>
-#include <BOPDS_VectorOfInterfVE.hxx>
-#include <BOPDS_VectorOfInterfEE.hxx>
-#include <BOPDS_VectorOfInterfVF.hxx>
-#include <BOPDS_VectorOfInterfEF.hxx>
-#include <BOPDS_VectorOfInterfFF.hxx>
-#include <BOPDS_DS.hxx>
-
-#include <BOPCol_ListOfShape.hxx>
 #include <BOPAlgo_ArgumentAnalyzer.hxx>
+#include <BOPAlgo_CheckerSI.hxx>
 #include <BOPAlgo_CheckResult.hxx>
+#include <BOPCol_ListOfShape.hxx>
+#include <BOPDS_DS.hxx>
+#include <BOPDS_MapOfPassKey.hxx>
+#include <BOPTest.hxx>
+#include <BOPTest_Objects.hxx>
+#include <BOPTools_AlgoTools.hxx>
+#include <BRep_Builder.hxx>
 #include <BRepBuilderAPI_Copy.hxx>
+#include <DBRep.hxx>
+#include <Draw.hxx>
+#include <OSD_Timer.hxx>
+#include <TCollection_AsciiString.hxx>
+#include <TopExp_Explorer.hxx>
+#include <TopoDS_Compound.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopTools_MapOfShape.hxx>
+#include <TopTools_ShapeMapHasher.hxx>
 
+#include <algorithm>
+#include <functional>
+#include <vector>
+//
 static 
-  Standard_Integer bopcheck (Draw_Interpretor&, Standard_Integer, const char** );
-
-static 
-  Standard_Integer bopargcheck (Draw_Interpretor&, Standard_Integer, const char** );
+  void MakeShapeForFullOutput (const TCollection_AsciiString&,
+                               const Standard_Integer,
+                               const BOPCol_ListOfShape&,
+                               Standard_Integer& ,
+                               Draw_Interpretor&,
+                               Standard_Boolean bCurveOnSurf = Standard_False,
+                               Standard_Real aMaxDist = 0.,
+                               Standard_Real aMaxParameter = 0.);
 //
+static Standard_Integer bopcheck   (Draw_Interpretor&, Standard_Integer, const char** );
+static Standard_Integer bopargcheck(Draw_Interpretor&, Standard_Integer, const char** );
+static Standard_Integer xdistef(Draw_Interpretor&, Standard_Integer, const char** );
+static Standard_Integer checkcurveonsurf (Draw_Interpretor&, Standard_Integer, const char**);
 
 //=======================================================================
 //function : CheckCommands
 //purpose  : 
 //=======================================================================
-  void  BOPTest::CheckCommands(Draw_Interpretor& theCommands)
+void  BOPTest::CheckCommands(Draw_Interpretor& theCommands)
 {
   static Standard_Boolean done = Standard_False;
   if (done) 
@@ -61,187 +65,266 @@ static
 
   done = Standard_True;
   // Chapter's name
-  const char* g = "CCR commands";
+  const char* g = "BOPTest commands";
   //
-  theCommands.Add("bopcheck" ,  "Use >bopcheck Shape [level of check: 0(V/V) - 5(all)]",  __FILE__, bopcheck, g);
-  theCommands.Add("bopargcheck" ,  "Use bopargcheck without parameters to get ",  __FILE__, bopargcheck, g);
+  theCommands.Add("bopcheck",  
+                  "use bopcheck Shape [level of check: 0 - 9] [-t]",
+                  __FILE__, bopcheck, g);
+  theCommands.Add("bopargcheck" , 
+                  "use bopargcheck without parameters to get ",  
+                  __FILE__, bopargcheck, g);
+  theCommands.Add ("xdistef" ,
+                   "use xdistef edge face",
+                   __FILE__, xdistef, g);
+  theCommands.Add("checkcurveonsurf",
+                  "use checkcurveonsurf shape",
+                  __FILE__, checkcurveonsurf, g);
 }
-
+//=======================================================================
+//class    : BOPTest_Interf
+//purpose  : Auxiliary class
+//=======================================================================
+class BOPTest_Interf {
+ public:
+  BOPTest_Interf() : myIndex1(-1), myIndex2(-1), myType(-1) {
+  }
+  //
+  ~BOPTest_Interf() {
+  }
+  //
+  void SetIndices(const Standard_Integer theIndex1,
+                  const Standard_Integer theIndex2) {
+    myIndex1=theIndex1; 
+    myIndex2=theIndex2; 
+  }
+  //
+  void Indices(Standard_Integer& theIndex1,
+               Standard_Integer& theIndex2) const {
+    theIndex1=myIndex1; 
+    theIndex2=myIndex2; 
+  }
+  //
+  void SetType(const Standard_Integer theType) {
+    myType=theType;
+  }
+  //
+  Standard_Integer Type() const {
+    return myType;
+  }
+  //
+  bool operator < (const  BOPTest_Interf& aOther) const {
+    bool bFlag;
+    //
+    if (myType==aOther.myType) {
+      if (myIndex1 == aOther.myIndex1) {
+        bFlag=(myIndex2 < aOther.myIndex2);
+      }
+      else {
+        bFlag=(myIndex1 < aOther.myIndex1);
+      }
+    }
+    else {
+      bFlag=(myType < aOther.myType);
+    }
+    //
+    return bFlag;
+  }
+  //
+ protected:
+  Standard_Integer myIndex1;
+  Standard_Integer myIndex2;
+  Standard_Integer myType;
+};
 //=======================================================================
 //function : bopcheck
 //purpose  : 
 //=======================================================================
-Standard_Integer bopcheck (Draw_Interpretor& di, Standard_Integer n,  const char** a )
+Standard_Integer bopcheck (Draw_Interpretor& di, 
+                           Standard_Integer n,  
+                           const char** a )
 {
-  
   if (n<2) {
-    di << " Use >bopcheck Shape [level of check: 0 - 5" << "\n";
-    di << " The level of check defines which interferferences will be checked:\n"; 
-    di << " 0 - only V/V;\n"; 
-    di << " 1 - V/V and V/E;\n";
-    di << " 2 - V/V, V/E and E/E;\n"; 
-    di << " 3 - V/V, V/E, E/E and V/F;\n"; 
-    di << " 4 - V/V, V/E, E/E, V/F and E/F;\n"; 
-    di << " 5 - all interferences, default value.\n"; 
+    di << " use bopcheck Shape [level of check: 0 - 9] [-t]\n";
+    di << " The level of check defines "; 
+    di << " which interferences will be checked:\n";
+    di << " 0 - V/V only\n"; 
+    di << " 1 - V/V, V/E\n";
+    di << " 2 - V/V, V/E, E/E\n"; 
+    di << " 3 - V/V, V/E, E/E , V/F\n"; 
+    di << " 4 - V/V, V/E, E/E, V/F , E/F\n"; 
+    di << " 5 - V/V, V/E, E/E, V/F, E/F, F/F;\n";
+    di << " 6 - V/V, V/E, E/E, V/F, E/F, F/F, V/Z\n";
+    di << " 7 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z\n";
+    di << " 8 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z\n";
+    di << " 9 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z, Z/Z\n";
+    di << " Default level is 9\n";
     return 1;
   }
-
-  TopoDS_Shape aS1 = DBRep::Get(a[1]);
-  if (aS1.IsNull()) {
+  //
+  TopoDS_Shape aS = DBRep::Get(a[1]);
+  if (aS.IsNull()) {
     di << "null shapes are not allowed here!";
     return 1;
   }
-  TopoDS_Shape aS = BRepBuilderAPI_Copy(aS1).Shape();
   //
-  Standard_Integer iErr, aTypeInt, i, ind, j;
-  Standard_Integer nI1, nI2, theLevelOfCheck;
-  Standard_Boolean bSelfInt, bFFInt;
-  char buf[256];
-  char type[6][4] = {"V/V", "V/E", "E/E","V/F", "E/F", "F/F"};
-
-  theLevelOfCheck = (n==3) ? Draw::Atoi(a[2]) : 5;
-  if (theLevelOfCheck >= 0 && theLevelOfCheck < 5) {
-    di << "Info:\nThe level of check is set to " << type[theLevelOfCheck] 
-       << ", i.e. intersection(s)\n";
-    for (i=theLevelOfCheck+1; i<=5; ++i) {
-      di << type[i];
-      if (i<5) {
+  Standard_Boolean bRunParallel, bShowTime;
+  Standard_Integer i, aLevel, aNbInterfTypes;
+  Standard_Real aTol;
+  //
+  aNbInterfTypes=BOPDS_DS::NbInterfTypes();
+  //
+  aLevel=aNbInterfTypes-1;
+  //
+  if (n>2) {
+    if (a[2][0] != '-') {
+      aLevel=Draw::Atoi(a[2]); 
+    }
+  }
+  //
+  if (aLevel < 0 || aLevel > aNbInterfTypes-1) {
+    di << "Invalid level";
+    return 1;
+  }
+  //
+  bShowTime=Standard_False;
+  aTol=BOPTest_Objects::FuzzyValue();
+  bRunParallel=BOPTest_Objects::RunParallel(); 
+  //
+  for (i=2; i<n; ++i) {
+    if (!strcmp(a[i], "-t")) {
+      bShowTime=Standard_True;
+    }
+      }
+  //
+  //aLevel = (n==3) ? Draw::Atoi(a[2]) : aNbInterfTypes-1;
+  //-------------------------------------------------------------------
+  char buf[256], aName1[32], aName2[32];
+  char aInterfTypes[10][4] = {
+    "V/V", "V/E", "E/E","V/F", "E/F", "F/F", "V/Z", "E/Z", "F/Z", "Z/Z"
+  };
+  //
+  Standard_Integer iErr, iCnt, n1, n2, iT;
+  TopAbs_ShapeEnum aType1, aType2;
+  BOPAlgo_CheckerSI aChecker;
+  BOPCol_ListOfShape aLS;
+  BOPDS_MapIteratorMapOfPassKey aItMPK;
+  //
+  if (aLevel < (aNbInterfTypes-1)) {
+    di << "Info:\nThe level of check is set to " 
+      << aInterfTypes[aLevel] << ", i.e. intersection(s)\n";
+    
+    for (i=aLevel+1; i<aNbInterfTypes; ++i) {
+      di << aInterfTypes[i];
+      if (i<aNbInterfTypes-1) {
         di << ", ";
       }
     }
     di << " will not be checked.\n\n";
   }
-  
-  BOPAlgo_CheckerSI aChecker;
-  BOPCol_ListOfShape anArgs;
-  anArgs.Append(aS);
-  aChecker.SetArguments(anArgs);
-  aChecker.SetLevelOfCheck(theLevelOfCheck);
+  //
+  aLS.Append(aS);
+  aChecker.SetArguments(aLS);
+  aChecker.SetLevelOfCheck(aLevel);
+  aChecker.SetRunParallel(bRunParallel);
+  aChecker.SetFuzzyValue(aTol);
+  //
+  OSD_Timer aTimer;
+  aTimer.Start();
   //
   aChecker.Perform();
-  iErr = aChecker.ErrorStatus();
-  //
-  const BOPDS_PDS& theDS = aChecker.PDS();
-  BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV();
-  BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE();
-  BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE();
-  BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF();
-  BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF();
-  BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF();
-  //
-  Standard_Integer aNb[6] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), 
-                             aVFs.Extent(), aEFs.Extent(), aFFs.Extent()};
-  //
-  bSelfInt = Standard_False;
-  ind = 0;
-  for (aTypeInt = 0; aTypeInt < 6; ++aTypeInt) {
-    for (i = 0; i < aNb[aTypeInt]; ++i) {
-      BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) : 
-                          ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) :
-                          ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) : 
-                          ((aTypeInt==3) ? (BOPDS_Interf*)(&aVFs(i)) :
-                          ((aTypeInt==4) ? (BOPDS_Interf*)(&aEFs(i)) : (BOPDS_Interf*)(&aFFs(i))))));
-      //
-      nI1 = aInt->Index1();
-      nI2 = aInt->Index2();
-      if (nI1 == nI2) {
-        continue;
-      }
-      //
-      if (aTypeInt == 4) {
-        BOPDS_InterfEF& aEF=aEFs(i);
-        if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
-          continue;
-        }
-      }
-      //
-      const TopoDS_Shape& aS1 = theDS->Shape(nI1);
-      const TopoDS_Shape& aS2 = theDS->Shape(nI2);
-      //
-      if (aTypeInt == 5) {
-        bFFInt = Standard_False;
-        BOPDS_InterfFF& aFF = aFFs(i);
-        BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
-        Standard_Integer aNbP=aVP.Extent();
-        BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
-        Standard_Integer aNbC=aVC.Extent();
-        if (!aNbP && !aNbC) {
-          continue;
-        }
-        for (j=0; j<aNbC; ++j) {
-          BOPDS_Curve& aNC=aVC(j);
-          BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
-          if (aLPBC.Extent()) {
-            bFFInt = Standard_True;
-            break;
-          }
-        }
-        if (!bFFInt) {
-          continue;
-        }
-      }
-      //
-      di << type[aTypeInt] << ":";
-      //
-      TCollection_AsciiString aBaseName("x");
-      TCollection_AsciiString anumbername(ind);
-      TCollection_AsciiString aXName = aBaseName + anumbername;
-      Standard_CString aname=aXName.ToCString();
-      DBRep::Set (aname, aS1);
-      ++ind;
-      TCollection_AsciiString anumbername1(ind);
-      TCollection_AsciiString aXName1 = aBaseName + anumbername1;
-      Standard_CString aname1=aXName1.ToCString();
-      DBRep::Set (aname1, aS2);
-      ++ind;
-      //
-      Sprintf(buf, "%s, %s \n", aname, aname1);
-      di << buf;
-      bSelfInt = Standard_True;
+  //
+  aTimer.Stop();
+  //
+  iErr=aChecker.ErrorStatus();
+  //
+  const BOPDS_DS& aDS=*(aChecker.PDS());
+  //
+  const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
+  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+  using namespace std;
+  vector <BOPTest_Interf> aVec;
+  vector <BOPTest_Interf>::iterator aIt;
+  BOPTest_Interf aBInterf;
+  //
+  aItMPK.Initialize(aMPK);
+  for (; aItMPK.More(); aItMPK.Next()) {
+    const BOPDS_PassKey& aPK=aItMPK.Value();
+    aPK.Ids(n1, n2);
+    if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
+      continue;
     }
+    //
+    const BOPDS_ShapeInfo& aSI1=aDS.ShapeInfo(n1);
+    const BOPDS_ShapeInfo& aSI2=aDS.ShapeInfo(n2);
+    aType1=aSI1.ShapeType();
+    aType2=aSI2.ShapeType();
+    //
+    iT=BOPDS_Tools::TypeToInteger(aType1, aType2);
+    //
+    aBInterf.SetIndices(n1, n2);
+    aBInterf.SetType(iT);
+    //
+    aVec.push_back(aBInterf);
   }
-  
+  //
+  sort( aVec.begin(), aVec.end(), less<BOPTest_Interf>());
+  //
+  iCnt=0;
+  for (aIt=aVec.begin(); aIt!=aVec.end(); aIt++) {
+    const BOPTest_Interf& aBI=*aIt;
+    //
+    aBI.Indices(n1, n2);
+    if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
+      continue;
+    }
+    //
+    const TopoDS_Shape& aS1=aDS.Shape(n1);
+    const TopoDS_Shape& aS2=aDS.Shape(n2);
+    //
+    iT=aBI.Type(); 
+    di << aInterfTypes[iT] << ": ";
+    //
+    sprintf(aName1, "x%d", n1);
+    //sprintf(aName1, "x%d", iCnt);
+    DBRep::Set (aName1, aS1);
+    //
+    ++iCnt;
+    sprintf(aName2, "x%d", n2);
+    //sprintf(aName2, "x%d", iCnt);
+    DBRep::Set (aName2, aS2);
+    ++iCnt;
+    //
+    sprintf(buf, "%s %s \n", aName1, aName2);
+    di << buf;
+  }
+  //
   if (iErr) {
-    di << "There were errors during the operation, so the list may be incomplete." << "\n";
+    di << "There were errors during the operation, ";
+    di << "so the list may be incomplete." << "\n";
   }
-  
-  if (!bSelfInt) {
+  //
+  if (!iCnt) {
     di << " This shape seems to be OK." << "\n";
   }
-  
-  return 0;
-}
-
-static void MakeShapeForFullOutput(const TCollection_AsciiString & aBaseName,
-                                   const Standard_Integer          aIndex,
-                                   const BOPCol_ListOfShape &    aList,
-                                   Standard_Integer&               aCount,
-                                   Draw_Interpretor&               di)
-{
-  TCollection_AsciiString aNum(aIndex);
-  TCollection_AsciiString aName = aBaseName + aNum;
-  Standard_CString name = aName.ToCString();
-
-  TopoDS_Compound cmp;
-  BRep_Builder BB;
-  BB.MakeCompound(cmp);
-
-  BOPCol_ListIteratorOfListOfShape anIt(aList);
-  for(; anIt.More(); anIt.Next()) {
-    const TopoDS_Shape & aS = anIt.Value();
-    BB.Add(cmp, aS);
-    aCount++;
+  if (bShowTime)
+  {
+    Sprintf(buf, "  Tps: %7.2lf\n", aTimer.ElapsedTime());
+    di << buf;
   }
-  di << "Made faulty shape: " << name << "\n";
-  DBRep::Set(name, cmp);
+  return 0;
 }
-
-
-Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const char** a )
+//=======================================================================
+//function : bopargcheck
+//purpose  : 
+//=======================================================================
+Standard_Integer bopargcheck (Draw_Interpretor& di,
+                              Standard_Integer n,
+                              const char** a )
 {
   if (n<2) {
     di << "\n";
-    di << " Use >bopargcheck Shape1 [[Shape2] [-F/O/C/T/S/U] [/R|F|T|V|E|I|P]] [#BF]" << "\n" << "\n";
+    di << " Use >bopargcheck Shape1 [[Shape2] ";
+    di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P|C|S]] [#BF]\n\n";
     di << " -<Boolean Operation>" << "\n";
     di << " F (fuse)" << "\n";
     di << " O (common)" << "\n";
@@ -249,7 +332,8 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
     di << " T (cut21)" << "\n";
     di << " S (section)" << "\n";
     di << " U (unknown)" << "\n";
-    di << " For example: \"bopargcheck s1 s2 -F\" enables checking for Fuse operation" << "\n";
+    di << " For example: \"bopargcheck s1 s2 -F\" enables" ;
+    di << " checking for Fuse operation" << "\n";
     di << " default - section" << "\n" << "\n";
     di << " /<Test Options>" << "\n";
     di << " R (disable small edges (shrank range) test)" << "\n";
@@ -260,26 +344,31 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
     di << " I (disable self-interference test)" << "\n";
     di << " P (disable shape type test)" << "\n";
     di << " C (disable test for shape continuity)" << "\n";
-    di << " For example: \"bopargcheck s1 s2 /RI\" disables small edge detection and self-intersection detection" << "\n";
+    di << " S (disable curve on surface check)" << "\n";
+    di << " For example: \"bopargcheck s1 s2 /RI\" disables ";
+    di << "small edge detection and self-intersection detection" << "\n";
     di << " default - all options are enabled" << "\n" << "\n";
     di << " #<Additional Test Options>" << "\n";
     di << " B (stop test on first faulty found); default OFF" << "\n";
-    di << " F (full output for faulty shapes); default - output in a short format" << "\n" << "\n";
-    di << " NOTE: <Boolean Operation> and <Test Options> are used only for couple" << "\n";
-    di << "       of argument shapes, except I and P options that are always used for" << "\n";
-    di << "       couple of shapes as well as for single shape test." << "\n";
+    di << " F (full output for faulty shapes); default - output ";
+    di << "in a short format" << "\n" << "\n";
+    di << " NOTE: <Boolean Operation> and <Test Options> are ";
+    di <<  "used only for couple" << "\n";
+    di << "       of argument shapes, except I and P options ";
+    di << "that are always used for" << "\n";
+    di << "       couple of shapes as well as for ";
+    di <<"single shape test." << "\n";
     return 1;
   }
 
-  TopoDS_Shape aS11 = DBRep::Get(a[1]);
+  TopoDS_Shape aS1 = DBRep::Get(a[1]);
 
-  if(aS11.IsNull()) {
+  if(aS1.IsNull()) {
     di << "Error: null shape not allowed!" << "\n";
-    di << "Type bopargcheck without arguments for more information" << "\n";
+    di << "Type bopargcheck without arguments for more ";
+    di <<"information" << "\n";
     return 1;
   }
-  TopoDS_Shape aS1 = BRepBuilderAPI_Copy(aS11).Shape();
-  
 
   Standard_Boolean isBO = Standard_False;
   Standard_Integer indxBO = 0;
@@ -289,23 +378,22 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
   Standard_Integer indxAD = 0;
   Standard_Boolean isS2 = Standard_False;
   Standard_Integer indxS2 = 0;
+  Standard_Real aTolerance = 0;
 
+  aTolerance=BOPTest_Objects::FuzzyValue();
+  
   if(n >= 3) {
     Standard_Integer iIndex = 0;
     for(iIndex = 2; iIndex < n; iIndex++) {
-      if(a[iIndex][0] == '-')
-      {
+      if(a[iIndex][0] == '-')   {
         isBO = Standard_True;
         indxBO = iIndex;
       }
-      //else if(a[iIndex][0] == '+')
-      else if(a[iIndex][0] == '/')
-      {
+      else if(a[iIndex][0] == '/') {
         isOP = Standard_True;
         indxOP = iIndex;
       }
-      else if(a[iIndex][0] == '#')
-      {
+      else if(a[iIndex][0] == '#') {
         isAD = Standard_True;
         indxAD = iIndex;
       }
@@ -315,7 +403,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
       }
     }
   }
-
+  
   // set & test second shape
   TopoDS_Shape aS22, aS2;
   if(isS2) {
@@ -333,17 +421,19 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
       }
     }
   }
-
+  
   // init checker
   BOPAlgo_ArgumentAnalyzer aChecker;
+  aChecker.SetFuzzyValue(aTolerance);
   aChecker.SetShape1(aS1);
 
   // set default options (always tested!) for single and couple shapes
-  aChecker.ArgumentTypeMode() = Standard_True;
-  aChecker.SelfInterMode()    = Standard_True;
-  aChecker.SmallEdgeMode()    = Standard_True;
-  aChecker.RebuildFaceMode()  = Standard_True;
-  aChecker.ContinuityMode()   = Standard_True;
+  aChecker.ArgumentTypeMode()   = Standard_True;
+  aChecker.SelfInterMode()      = Standard_True;
+  aChecker.SmallEdgeMode()      = Standard_True;
+  aChecker.RebuildFaceMode()    = Standard_True;
+  aChecker.ContinuityMode()     = Standard_True;
+  aChecker.CurveOnSurfaceMode() = Standard_True;
 
   // test & set options and operation for two shapes
   if(!aS22.IsNull()) {
@@ -411,6 +501,9 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
       else if(a[indxOP][ind] == 'C' || a[indxOP][ind] == 'c') {
         aChecker.ContinuityMode() = Standard_False;
       }
+      else if(a[indxOP][ind] == 'S' || a[indxOP][ind] == 's') {
+        aChecker.CurveOnSurfaceMode() = Standard_False;
+      }
       else {
         di << "Error: invalid test option(s)!" << "\n";
         di << "Type bopargcheck without arguments for more information" << "\n";
@@ -461,6 +554,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
       Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0;
       Standard_Integer S1_OpAb = 0, S2_OpAb = 0;
       Standard_Integer S1_C0 = 0, S2_C0 = 0, S1_C0All = 0, S2_C0All = 0;
+      Standard_Integer S1_COnS = 0, S2_COnS = 0, S1_COnSAll = 0, S2_COnSAll = 0;
       Standard_Boolean hasUnknown = Standard_False;
 
       TCollection_AsciiString aS1SIBaseName("s1si_");
@@ -469,12 +563,14 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
       TCollection_AsciiString aS1BVBaseName("s1bv_");
       TCollection_AsciiString aS1BEBaseName("s1be_");
       TCollection_AsciiString aS1C0BaseName("s1C0_");
+      TCollection_AsciiString aS1COnSBaseName("s1COnS_");
       TCollection_AsciiString aS2SIBaseName("s2si_");
       TCollection_AsciiString aS2SEBaseName("s2se_");
       TCollection_AsciiString aS2BFBaseName("s2bf_");
       TCollection_AsciiString aS2BVBaseName("s2bv_");
       TCollection_AsciiString aS2BEBaseName("s2be_");
       TCollection_AsciiString aS2C0BaseName("s2C0_");
+      TCollection_AsciiString aS2COnSBaseName("s2COnS_");
 
       for(; anIt.More(); anIt.Next()) {
         const BOPAlgo_CheckResult& aResult = anIt.Value();
@@ -579,6 +675,27 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
           }
         }
           break;
+        case BOPAlgo_InvalidCurveOnSurface: {
+          if(!aSS1.IsNull()) {
+            S1_COnS++;
+            if(isL1) {
+              Standard_Real aMaxDist = aResult.GetMaxDistance1();
+              Standard_Real aMaxParameter = aResult.GetMaxParameter1();
+              MakeShapeForFullOutput(aS1COnSBaseName, S1_COnS, aLS1, S1_COnSAll, di,
+                                     Standard_True, aMaxDist, aMaxParameter);
+            }
+          }
+          if(!aSS2.IsNull()) {
+            S2_COnS++;
+            if(isL2) {
+              Standard_Real aMaxDist = aResult.GetMaxDistance2();
+              Standard_Real aMaxParameter = aResult.GetMaxParameter2();
+              MakeShapeForFullOutput(aS2COnSBaseName, S2_COnS, aLS2, S2_COnSAll, di,
+                                     Standard_True, aMaxDist, aMaxParameter);
+            }
+          }
+        }
+          break;
         case BOPAlgo_OperationAborted: {
           if(!aSS1.IsNull()) S1_OpAb++;
           if(!aSS2.IsNull()) S2_OpAb++;
@@ -592,9 +709,9 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         } // switch
       }// faulties
 
-      Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0;
+      Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0 + S1_COnS;
       FS1 += (S1_BadType != 0) ? 1 : 0;
-      Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0;
+      Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0 + S2_COnS;
       FS2 += (S2_BadType != 0) ? 1 : 0;
       
       // output for first shape
@@ -605,13 +722,13 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_BadType != 0)
           CString1="YES";
         else
-          CString1="NO";
+          CString1=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
         di << "Shapes are not suppotrted by BOP: " << CString1 << "\n";
         Standard_CString CString2;
         if (S1_SelfInt != 0)
           CString2="YES";
         else
-          CString2="NO";
+          CString2=aChecker.SelfInterMode() ? "NO" : "DISABLED";
         di << "Self-Intersections              : " << CString2;
         if(S1_SelfInt != 0)
           di << "  Cases(" << S1_SelfInt << ")  Total shapes(" << S1_SelfIntAll << ")" << "\n";
@@ -621,13 +738,13 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_OpAb != 0)
           CString13="YES";
         else
-          CString13="NO";
+          CString13=aChecker.SelfInterMode() ? "NO" : "DISABLED";
         di << "Check for SI has been aborted   : " << CString13 << "\n";
         Standard_CString CString3;
         if (S1_SmalE != 0)
           CString3="YES";
         else
-          CString3="NO";
+          CString3=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
         di << "Too small edges                 : " << CString3;
         if(S1_SmalE != 0)
           di << "  Cases(" << S1_SmalE << ")  Total shapes(" << S1_SmalEAll << ")" << "\n";
@@ -637,7 +754,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_BadF != 0)
           CString4="YES";
         else
-          CString4="NO";
+          CString4=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
         di << "Bad faces                       : " << CString4;
         if(S1_BadF != 0)
           di << "  Cases(" << S1_BadF << ")  Total shapes(" << S1_BadFAll << ")" << "\n";
@@ -647,7 +764,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_BadV != 0)
           CString5="YES";
         else
-          CString5="NO";
+          CString5=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
         di << "Too close vertices              : " << CString5;
         if(S1_BadV != 0)
           di << "  Cases(" << S1_BadV << ")  Total shapes(" << S1_BadVAll << ")" << "\n";
@@ -657,7 +774,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_BadE != 0)
           CString6="YES";
         else
-          CString6="NO";
+          CString6=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
         di << "Too close edges                 : " << CString6;
         if(S1_BadE != 0)
           di << "  Cases(" << S1_BadE << ")  Total shapes(" << S1_BadEAll << ")" << "\n";
@@ -667,12 +784,23 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S1_C0 != 0)
           CString15="YES";
         else
-          CString15="NO";
+          CString15=aChecker.ContinuityMode() ? "NO" : "DISABLED";
         di << "Shapes with Continuity C0       : " << CString15;
         if(S1_C0 != 0)
           di << "  Cases(" << S1_C0 << ")  Total shapes(" << S1_C0All << ")" << "\n";
         else
           di << "\n";
+
+        Standard_CString CString17;
+        if (S1_COnS != 0)
+          CString17="YES";
+        else
+          CString17=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
+        di << "Invalid Curve on Surface        : " << CString17;
+        if(S1_COnS != 0)
+          di << "  Cases(" << S1_COnS << ")  Total shapes(" << S1_COnSAll << ")" << "\n";
+        else
+          di << "\n";
       }
 
       // output for second shape
@@ -684,13 +812,13 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_BadType != 0)
           CString7="YES";
         else
-          CString7="NO";
+          CString7=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
         di << "Shapes are not suppotrted by BOP: " << CString7 << "\n";
         Standard_CString CString8;
         if (S2_SelfInt != 0)
           CString8="YES";
         else
-          CString8="NO";
+          CString8=aChecker.SelfInterMode() ? "NO" : "DISABLED";
         di << "Self-Intersections              : " << CString8;
         if(S2_SelfInt != 0)
           di << "  Cases(" << S2_SelfInt << ")  Total shapes(" << S2_SelfIntAll << ")" << "\n";
@@ -701,13 +829,13 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_OpAb != 0)
           CString14="YES";
         else
-          CString14="NO";
+          CString14=aChecker.SelfInterMode() ? "NO" : "DISABLED";
         di << "Check for SI has been aborted   : " << CString14 << "\n";
         Standard_CString CString9;
         if (S2_SmalE != 0)
           CString9="YES";
         else
-          CString9="NO";
+          CString9=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
         di << "Too small edges                 : " << CString9;
         if(S2_SmalE != 0)
           di << "  Cases(" << S2_SmalE << ")  Total shapes(" << S2_SmalEAll << ")" << "\n";
@@ -717,7 +845,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_BadF != 0)
           CString10="YES";
         else
-          CString10="NO";
+          CString10=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
         di << "Bad faces                       : " << CString10;
         if(S2_BadF != 0)
           di << "  Cases(" << S2_BadF << ")  Total shapes(" << S2_BadFAll << ")" << "\n";
@@ -727,7 +855,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_BadV != 0)
           CString11="YES";
         else
-          CString11="NO";
+          CString11=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
         di << "Too close vertices              : " << CString11;
         if(S2_BadV != 0)
           di << "  Cases(" << S2_BadV << ")  Total shapes(" << S2_BadVAll << ")" << "\n";
@@ -737,7 +865,7 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_BadE != 0)
           CString12="YES";
         else
-          CString12="NO";
+          CString12=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
         di << "Too close edges                 : " << CString12;
         if(S2_BadE != 0)
           di << "  Cases(" << S2_BadE << ")  Total shapes(" << S2_BadEAll << ")" << "\n";
@@ -747,20 +875,232 @@ Standard_Integer bopargcheck (Draw_Interpretor& di, Standard_Integer n,  const c
         if (S2_C0 != 0)
           CString16="YES";
         else
-          CString16="NO";
+          CString16=aChecker.ContinuityMode() ? "NO" : "DISABLED";
         di << "Shapes with Continuity C0       : " << CString16;
         if(S2_C0 != 0)
           di << "  Cases(" << S2_C0 << ")  Total shapes(" << S2_C0All << ")" << "\n";
         else
           di << "\n";
 
-        // warning
+        Standard_CString CString18;
+        if (S2_COnS != 0)
+          CString18="YES";
+        else
+          CString18=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
+        di << "Invalid Curve on Surface        : " << CString18;
+        if(S2_COnS != 0)
+          di << "  Cases(" << S2_COnS << ")  Total shapes(" << S2_COnSAll << ")" << "\n";
+        else
+          di << "\n";
+      }
+      // warning
+      if(hasUnknown) {
         di << "\n";
-        if(hasUnknown)
-          di << "WARNING: The unexpected test break occurs!" << "\n";
+        di << "WARNING: The unexpected test break occurs!" << "\n";
       }
     } // full output
   } // has faulties
 
   return 0;
 }
+
+//=======================================================================
+//function : xdistef
+//purpose  : 
+//=======================================================================
+Standard_Integer xdistef(Draw_Interpretor& di,
+                         Standard_Integer n,
+                         const char** a)
+{
+  if(n < 3) {
+    di << "use xdistef edge face\n";
+    return 1;
+  }
+  //
+  const TopoDS_Shape aS1 = DBRep::Get(a[1]);
+  const TopoDS_Shape aS2 = DBRep::Get(a[2]);
+  //
+  if (aS1.IsNull() || aS2.IsNull()) {
+    di << "null shapes\n";
+    return 1;
+  }
+  //
+  if (aS1.ShapeType() != TopAbs_EDGE || 
+      aS2.ShapeType() != TopAbs_FACE) {
+    di << "type mismatch\n";
+    return 1;
+  }
+  //
+  Standard_Real aMaxDist = 0.0, aMaxPar = 0.0;
+  //
+  const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&aS1;
+  const TopoDS_Face& aFace  = *(TopoDS_Face*)&aS2;
+  //
+  if(!BOPTools_AlgoTools::ComputeTolerance
+     (aFace, anEdge, aMaxDist, aMaxPar)) {
+    di << "Tolerance cannot be computed\n";
+    return 1;
+  }
+  //
+  di << "Max Distance = " << aMaxDist 
+     << "; Parameter on curve = " << aMaxPar << "\n";
+  //
+  return 0;
+}
+
+//=======================================================================
+//function : checkcurveonsurf
+//purpose  : 
+//=======================================================================
+Standard_Integer checkcurveonsurf(Draw_Interpretor& di,
+                                  Standard_Integer n, 
+                                  const char** a)
+{
+  if (n != 2) {
+    di << "use checkcurveonsurf shape\n";
+    return 1;
+  }
+  //
+  TopoDS_Shape aS =  DBRep::Get(a[1]);
+  if (aS.IsNull()) {
+    di << "null shape\n";
+    return 1;
+  }
+  //
+  Standard_Integer nE, nF, anECounter, aFCounter;
+  Standard_Real aT, aTolE, aDMax;
+  TopExp_Explorer aExpF, aExpE;
+  char buf[200], aFName[10], anEName[10];
+  NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> aDMETol;
+  BOPCol_DataMapOfShapeInteger aMSI;
+  //
+  anECounter = 0;
+  aFCounter  = 0;
+  //
+  aExpF.Init(aS, TopAbs_FACE);
+  for (; aExpF.More(); aExpF.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
+    //
+    aExpE.Init(aF, TopAbs_EDGE);
+    for (; aExpE.More(); aExpE.Next()) {
+      const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
+      //
+      if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) {
+        continue;
+      }
+      //
+      aTolE = BRep_Tool::Tolerance(aE);
+      if (!(aDMax > aTolE)) {
+        continue;
+      }
+      //
+      if (aDMETol.IsBound(aE)) {
+        Standard_Real& aD = aDMETol.ChangeFind(aE);
+        if (aDMax > aD) {
+          aD = aDMax;
+        }
+      }
+      else {
+        aDMETol.Bind(aE, aDMax);
+      }
+      //
+      if (anECounter == 0) {
+        di << "Invalid curves on surface:\n";
+      }
+      //
+      if (aMSI.IsBound(aE)) {
+        nE = aMSI.Find(aE);
+      }
+      else {
+        nE = anECounter;
+        aMSI.Bind(aE, nE);
+        ++anECounter;
+      }
+      //
+      if (aMSI.IsBound(aF)) {
+        nF = aMSI.Find(aF);
+      } else {
+        nF = aFCounter;
+        aMSI.Bind(aF, nF);
+        ++aFCounter;
+      }
+      //
+      sprintf(anEName, "e_%d", nE);
+      sprintf(aFName , "f_%d", nF);
+      sprintf(buf, "edge %s on face %s (max dist: %3.16f, parameter on curve: %3.16f)\n",
+              anEName, aFName, aDMax, aT);
+      di << buf;
+      //
+      DBRep::Set(anEName, aE);
+      DBRep::Set(aFName , aF);
+    }
+  }
+  //
+  if (anECounter > 0) {
+    di << "\n\nSugestions to fix the shape:\n";
+    di << "explode " << a[1] << " e;\n";
+    //
+    TopTools_MapOfShape M;
+    aExpE.Init(aS, TopAbs_EDGE);
+    for (anECounter = 0; aExpE.More(); aExpE.Next()) {
+      const TopoDS_Shape& aE = aExpE.Current();
+      if (!M.Add(aE)) {
+        continue;
+      }
+      ++anECounter;
+      //
+      if (!aDMETol.IsBound(aE)) {
+        continue;
+      }
+      //
+      aTolE = aDMETol.Find(aE);
+      aTolE *= 1.001;
+      sprintf(buf, "settolerance %s_%d %3.16f;\n", a[1], anECounter, aTolE);
+      di << buf;
+    }
+  }
+  else {
+    di << "This shape seems to be OK.\n";
+  }
+  //
+  return 0;
+}
+
+//=======================================================================
+//function : MakeShapeForFullOutput
+//purpose  : 
+//=======================================================================
+void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName,
+                             const Standard_Integer          aIndex,
+                             const BOPCol_ListOfShape &      aList,
+                             Standard_Integer&               aCount,
+                             Draw_Interpretor&               di,
+                             Standard_Boolean                bCurveOnSurf,
+                             Standard_Real                   aMaxDist,
+                             Standard_Real                   aMaxParameter)
+{
+  TCollection_AsciiString aNum(aIndex);
+  TCollection_AsciiString aName = aBaseName + aNum;
+  Standard_CString name = aName.ToCString();
+
+  TopoDS_Compound cmp;
+  BRep_Builder BB;
+  BB.MakeCompound(cmp);
+
+  BOPCol_ListIteratorOfListOfShape anIt(aList);
+  for(; anIt.More(); anIt.Next()) {
+    const TopoDS_Shape & aS = anIt.Value();
+    BB.Add(cmp, aS);
+    aCount++;
+  }
+  di << "Made faulty shape: " << name;
+  //
+  if (bCurveOnSurf) {
+    di << " (MaxDist = " << aMaxDist 
+       << ", MaxPar = " << aMaxParameter << ")";
+  }
+  //
+  di << "\n";
+  //
+  DBRep::Set(name, cmp);
+}