1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
16 #include <BOPAlgo_ArgumentAnalyzer.hxx>
17 #include <BOPAlgo_CheckerSI.hxx>
18 #include <BOPAlgo_CheckResult.hxx>
19 #include <BOPDS_DS.hxx>
20 #include <BOPDS_MapOfPair.hxx>
21 #include <BOPTest.hxx>
22 #include <BOPTest_Objects.hxx>
23 #include <BOPTools_AlgoTools.hxx>
24 #include <BRep_Builder.hxx>
25 #include <BRepAlgoAPI_Check.hxx>
26 #include <BRepBuilderAPI_Copy.hxx>
29 #include <OSD_Timer.hxx>
30 #include <TCollection_AsciiString.hxx>
31 #include <TopExp_Explorer.hxx>
32 #include <TopoDS_Compound.hxx>
33 #include <TopoDS_Shape.hxx>
34 #include <TopTools_ListOfShape.hxx>
35 #include <TopTools_MapOfShape.hxx>
36 #include <TopTools_ShapeMapHasher.hxx>
43 void MakeShapeForFullOutput (const TCollection_AsciiString&,
44 const Standard_Integer,
45 const TopTools_ListOfShape&,
48 Standard_Boolean bCurveOnSurf = Standard_False,
49 Standard_Real aMaxDist = 0.,
50 Standard_Real aMaxParameter = 0.);
52 static Standard_Integer bopcheck (Draw_Interpretor&, Standard_Integer, const char** );
53 static Standard_Integer bopargcheck(Draw_Interpretor&, Standard_Integer, const char** );
54 static Standard_Integer bopapicheck(Draw_Interpretor&, Standard_Integer, const char** );
55 static Standard_Integer xdistef(Draw_Interpretor&, Standard_Integer, const char** );
56 static Standard_Integer checkcurveonsurf (Draw_Interpretor&, Standard_Integer, const char**);
58 //=======================================================================
59 //function : CheckCommands
61 //=======================================================================
62 void BOPTest::CheckCommands(Draw_Interpretor& theCommands)
64 static Standard_Boolean done = Standard_False;
70 const char* g = "BOPTest commands";
72 theCommands.Add("bopcheck",
73 "use bopcheck Shape [level of check: 0 - 9] [-t]",
74 __FILE__, bopcheck, g);
75 theCommands.Add("bopargcheck" ,
76 "use bopargcheck without parameters to get ",
77 __FILE__, bopargcheck, g);
78 theCommands.Add ("xdistef" ,
79 "use xdistef edge face",
80 __FILE__, xdistef, g);
81 theCommands.Add("checkcurveonsurf",
82 "use checkcurveonsurf shape",
83 __FILE__, checkcurveonsurf, g);
84 theCommands.Add("bopapicheck",
85 "Checks the validity of shape/pair of shapes.\n"
86 "\t\tUsage: bopapicheck s1 [s2] [-op common/fuse/cut/tuc] [-se] [-si]\n"
88 "\t\ts1, s2 - shapes for checking;\n"
89 "\t\t-op - specifies the type of Boolean operation, for which the validity of shapes should be checked;"
90 " Should be followed by the operation;\n"
91 "\t\t-se - disables the check of the shapes on small edges;\n"
92 "\t\t-si - disables the check of the shapes on self-interference.\n",
93 __FILE__, bopapicheck, g);
95 //=======================================================================
96 //class : BOPTest_Interf
97 //purpose : Auxiliary class
98 //=======================================================================
99 class BOPTest_Interf {
101 BOPTest_Interf() : myIndex1(-1), myIndex2(-1), myType(-1) {
107 void SetIndices(const Standard_Integer theIndex1,
108 const Standard_Integer theIndex2) {
113 void Indices(Standard_Integer& theIndex1,
114 Standard_Integer& theIndex2) const {
119 void SetType(const Standard_Integer theType) {
123 Standard_Integer Type() const {
127 bool operator < (const BOPTest_Interf& aOther) const {
130 if (myType==aOther.myType) {
131 if (myIndex1 == aOther.myIndex1) {
132 bFlag=(myIndex2 < aOther.myIndex2);
135 bFlag=(myIndex1 < aOther.myIndex1);
139 bFlag=(myType < aOther.myType);
146 Standard_Integer myIndex1;
147 Standard_Integer myIndex2;
148 Standard_Integer myType;
150 //=======================================================================
151 //function : bopcheck
153 //=======================================================================
154 Standard_Integer bopcheck (Draw_Interpretor& di,
159 di << " use bopcheck Shape [level of check: 0 - 9] [-t]\n";
160 di << " The level of check defines ";
161 di << " which interferences will be checked:\n";
162 di << " 0 - V/V only\n";
163 di << " 1 - V/V, V/E\n";
164 di << " 2 - V/V, V/E, E/E\n";
165 di << " 3 - V/V, V/E, E/E , V/F\n";
166 di << " 4 - V/V, V/E, E/E, V/F , E/F\n";
167 di << " 5 - V/V, V/E, E/E, V/F, E/F, F/F;\n";
168 di << " 6 - V/V, V/E, E/E, V/F, E/F, F/F, V/Z\n";
169 di << " 7 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z\n";
170 di << " 8 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z\n";
171 di << " 9 - V/V, V/E, E/E, V/F, E/F, F/F, E/Z, F/Z, Z/Z\n";
172 di << " Default level is 9\n";
176 TopoDS_Shape aS = DBRep::Get(a[1]);
178 di << "null shapes are not allowed here!";
182 Standard_Boolean bRunParallel, bShowTime;
183 Standard_Integer i, aLevel, aNbInterfTypes;
186 aNbInterfTypes=BOPDS_DS::NbInterfTypes();
188 aLevel=aNbInterfTypes-1;
191 if (a[2][0] != '-') {
192 aLevel=Draw::Atoi(a[2]);
196 if (aLevel < 0 || aLevel > aNbInterfTypes-1) {
197 di << "Invalid level";
201 bShowTime=Standard_False;
202 aTol=BOPTest_Objects::FuzzyValue();
203 bRunParallel=BOPTest_Objects::RunParallel();
205 for (i=2; i<n; ++i) {
206 if (!strcmp(a[i], "-t")) {
207 bShowTime=Standard_True;
211 //aLevel = (n==3) ? Draw::Atoi(a[2]) : aNbInterfTypes-1;
212 //-------------------------------------------------------------------
213 char buf[256], aName1[32], aName2[32];
214 char aInterfTypes[10][4] = {
215 "V/V", "V/E", "E/E","V/F", "E/F", "F/F", "V/Z", "E/Z", "F/Z", "Z/Z"
218 Standard_Integer iErr, iCnt, n1, n2, iT;
219 TopAbs_ShapeEnum aType1, aType2;
220 BOPAlgo_CheckerSI aChecker;
221 TopTools_ListOfShape aLS;
222 BOPDS_MapIteratorOfMapOfPair aItMPK;
224 if (aLevel < (aNbInterfTypes-1)) {
225 di << "Info:\nThe level of check is set to "
226 << aInterfTypes[aLevel] << ", i.e. intersection(s)\n";
228 for (i=aLevel+1; i<aNbInterfTypes; ++i) {
229 di << aInterfTypes[i];
230 if (i<aNbInterfTypes-1) {
234 di << " will not be checked.\n\n";
238 aChecker.SetArguments(aLS);
239 aChecker.SetLevelOfCheck(aLevel);
240 aChecker.SetRunParallel(bRunParallel);
241 aChecker.SetFuzzyValue(aTol);
250 BOPTest::ReportAlerts(aChecker.GetReport());
252 iErr=aChecker.HasErrors();
254 const BOPDS_DS& aDS=*(aChecker.PDS());
256 const BOPDS_MapOfPair& aMPK=aDS.Interferences();
257 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
258 std::vector <BOPTest_Interf> aVec;
259 std::vector <BOPTest_Interf>::iterator aIt;
260 BOPTest_Interf aBInterf;
262 aItMPK.Initialize(aMPK);
263 for (; aItMPK.More(); aItMPK.Next()) {
264 const BOPDS_Pair& aPK=aItMPK.Value();
266 if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
270 const BOPDS_ShapeInfo& aSI1=aDS.ShapeInfo(n1);
271 const BOPDS_ShapeInfo& aSI2=aDS.ShapeInfo(n2);
272 aType1=aSI1.ShapeType();
273 aType2=aSI2.ShapeType();
275 iT=BOPDS_Tools::TypeToInteger(aType1, aType2);
277 aBInterf.SetIndices(n1, n2);
278 aBInterf.SetType(iT);
280 aVec.push_back(aBInterf);
283 sort( aVec.begin(), aVec.end(), std::less<BOPTest_Interf>());
286 for (aIt=aVec.begin(); aIt!=aVec.end(); aIt++) {
287 const BOPTest_Interf& aBI=*aIt;
290 if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
294 const TopoDS_Shape& aS1=aDS.Shape(n1);
295 const TopoDS_Shape& aS2=aDS.Shape(n2);
298 di << aInterfTypes[iT] << ": ";
300 sprintf(aName1, "x%d", n1);
301 //sprintf(aName1, "x%d", iCnt);
302 DBRep::Set (aName1, aS1);
305 sprintf(aName2, "x%d", n2);
306 //sprintf(aName2, "x%d", iCnt);
307 DBRep::Set (aName2, aS2);
310 sprintf(buf, "%s %s \n", aName1, aName2);
315 di << "There were errors during the operation, ";
316 di << "so the list may be incomplete.\n";
320 di << " This shape seems to be OK.\n";
324 Sprintf(buf, " Tps: %7.2lf\n", aTimer.ElapsedTime());
329 //=======================================================================
330 //function : bopargcheck
332 //=======================================================================
333 Standard_Integer bopargcheck (Draw_Interpretor& di,
339 di << " Use >bopargcheck Shape1 [[Shape2] ";
340 di << "[-F/O/C/T/S/U] [/R|F|T|V|E|I|P|C|S]] [#BF]\n\n";
341 di << " -<Boolean Operation>\n";
343 di << " O (common)\n";
345 di << " T (cut21)\n";
346 di << " S (section)\n";
347 di << " U (unknown)\n";
348 di << " For example: \"bopargcheck s1 s2 -F\" enables" ;
349 di << " checking for Fuse operation\n";
350 di << " default - section\n\n";
351 di << " /<Test Options>\n";
352 di << " R (disable small edges (shrank range) test)\n";
353 di << " F (disable faces verification test)\n";
354 di << " T (disable tangent faces searching test)\n";
355 di << " V (disable test possibility to merge vertices)\n";
356 di << " E (disable test possibility to merge edges)\n";
357 di << " I (disable self-interference test)\n";
358 di << " P (disable shape type test)\n";
359 di << " C (disable test for shape continuity)\n";
360 di << " S (disable curve on surface check)\n";
361 di << " For example: \"bopargcheck s1 s2 /RI\" disables ";
362 di << "small edge detection and self-intersection detection\n";
363 di << " default - all options are enabled\n\n";
364 di << " #<Additional Test Options>\n";
365 di << " B (stop test on first faulty found); default OFF\n";
366 di << " F (full output for faulty shapes); default - output ";
367 di << "in a short format\n\n";
368 di << " NOTE: <Boolean Operation> and <Test Options> are ";
369 di << "used only for couple\n";
370 di << " of argument shapes, except I and P options ";
371 di << "that are always used for\n";
372 di << " couple of shapes as well as for ";
373 di <<"single shape test.\n";
377 TopoDS_Shape aS1 = DBRep::Get(a[1]);
380 di << "Error: null shape not allowed!\n";
381 di << "Type bopargcheck without arguments for more ";
382 di <<"information\n";
386 Standard_Boolean isBO = Standard_False;
387 Standard_Integer indxBO = 0;
388 Standard_Boolean isOP = Standard_False;
389 Standard_Integer indxOP = 0;
390 Standard_Boolean isAD = Standard_False;
391 Standard_Integer indxAD = 0;
392 Standard_Boolean isS2 = Standard_False;
393 Standard_Integer indxS2 = 0;
394 Standard_Real aTolerance = 0;
395 Standard_Boolean bRunParallel;
397 bRunParallel=BOPTest_Objects::RunParallel();
398 aTolerance=BOPTest_Objects::FuzzyValue();
401 Standard_Integer iIndex = 0;
402 for(iIndex = 2; iIndex < n; iIndex++) {
403 if(a[iIndex][0] == '-') {
404 isBO = Standard_True;
407 else if(a[iIndex][0] == '/') {
408 isOP = Standard_True;
411 else if(a[iIndex][0] == '#') {
412 isAD = Standard_True;
416 isS2 = Standard_True;
422 // set & test second shape
423 TopoDS_Shape aS22, aS2;
426 di << "Error: second shape should follow the first one!\n";
427 di << "Type bopargcheck without arguments for more information\n";
431 aS22 = DBRep::Get(a[2]);
433 di << "Error: second shape is null!\n";
434 di << "Type bopargcheck without arguments for more information\n";
441 BOPAlgo_ArgumentAnalyzer aChecker;
442 aChecker.SetRunParallel(bRunParallel);
443 aChecker.SetFuzzyValue(aTolerance);
444 aChecker.SetShape1(aS1);
446 // set default options (always tested!) for single and couple shapes
447 aChecker.ArgumentTypeMode() = Standard_True;
448 aChecker.SelfInterMode() = Standard_True;
449 aChecker.SmallEdgeMode() = Standard_True;
450 aChecker.RebuildFaceMode() = Standard_True;
451 aChecker.ContinuityMode() = Standard_True;
452 aChecker.CurveOnSurfaceMode() = Standard_True;
454 // test & set options and operation for two shapes
456 aS2 = BRepBuilderAPI_Copy(aS22).Shape();
457 aChecker.SetShape2(aS2);
458 // set operation (default - Section)
460 if(a[indxBO][1] == 'F' || a[indxBO][1] == 'f') {
461 aChecker.OperationType() = BOPAlgo_FUSE;
463 else if(a[indxBO][1] == 'O' || a[indxBO][1] == 'o') {
464 aChecker.OperationType() = BOPAlgo_COMMON;
466 else if(a[indxBO][1] == 'C' || a[indxBO][1] == 'c') {
467 aChecker.OperationType() = BOPAlgo_CUT;
469 else if(a[indxBO][1] == 'T' || a[indxBO][1] == 't') {
470 aChecker.OperationType() = BOPAlgo_CUT21;
472 else if(a[indxBO][1] == 'S' || a[indxBO][1] == 's') {
473 aChecker.OperationType() = BOPAlgo_SECTION;
475 else if(a[indxBO][1] == 'U' || a[indxBO][1] == 'u') {
476 aChecker.OperationType() = BOPAlgo_UNKNOWN;
479 di << "Error: invalid boolean operation type!\n";
480 di << "Type bopargcheck without arguments for more information\n";
485 aChecker.OperationType() = BOPAlgo_SECTION;
487 aChecker.TangentMode() = Standard_True;
488 aChecker.MergeVertexMode() = Standard_True;
489 aChecker.MergeEdgeMode() = Standard_True;
492 // set options (default - all ON)
494 Standard_Integer ind = 1;
495 while(a[indxOP][ind] != 0) {
496 if(a[indxOP][ind] == 'R' || a[indxOP][ind] == 'r') {
497 aChecker.SmallEdgeMode() = Standard_False;
499 else if(a[indxOP][ind] == 'F' || a[indxOP][ind] == 'f') {
500 aChecker.RebuildFaceMode() = Standard_False;
502 else if(a[indxOP][ind] == 'T' || a[indxOP][ind] == 't') {
503 aChecker.TangentMode() = Standard_False;
505 else if(a[indxOP][ind] == 'V' || a[indxOP][ind] == 'v') {
506 aChecker.MergeVertexMode() = Standard_False;
508 else if(a[indxOP][ind] == 'E' || a[indxOP][ind] == 'e') {
509 aChecker.MergeEdgeMode() = Standard_False;
511 else if(a[indxOP][ind] == 'I' || a[indxOP][ind] == 'i') {
512 aChecker.SelfInterMode() = Standard_False;
514 else if(a[indxOP][ind] == 'P' || a[indxOP][ind] == 'p') {
515 aChecker.ArgumentTypeMode() = Standard_False;
517 else if(a[indxOP][ind] == 'C' || a[indxOP][ind] == 'c') {
518 aChecker.ContinuityMode() = Standard_False;
520 else if(a[indxOP][ind] == 'S' || a[indxOP][ind] == 's') {
521 aChecker.CurveOnSurfaceMode() = Standard_False;
524 di << "Error: invalid test option(s)!\n";
525 di << "Type bopargcheck without arguments for more information\n";
532 // set additional options
533 Standard_Boolean fullOutput = Standard_False;
535 Standard_Integer ind = 1;
536 while(a[indxAD][ind] != 0) {
537 if(a[indxAD][ind] == 'B' || a[indxAD][ind] == 'b') {
538 aChecker.StopOnFirstFaulty() = Standard_True;
540 else if(a[indxAD][ind] == 'F' || a[indxAD][ind] == 'f') {
541 fullOutput = Standard_True;
544 di << "Error: invalid additional test option(s)!\n";
545 di << "Type bopargcheck without arguments for more information\n";
555 // process result of checking
556 if(!aChecker.HasFaulty()) {
557 di << "Shape(s) seem(s) to be valid for BOP." << "\n";
561 di << "Faulties, that can not be treated by BOP, are detected.\n";
564 const BOPAlgo_ListOfCheckResult& aResultList = aChecker.GetCheckResult();
565 BOPAlgo_ListIteratorOfListOfCheckResult anIt(aResultList);
567 Standard_Integer S1_BadType = 0, S1_SelfInt = 0, S1_SmalE = 0, S1_BadF = 0, S1_BadV = 0, S1_BadE = 0;
568 Standard_Integer S1_SelfIntAll = 0, S1_SmalEAll = 0, S1_BadFAll = 0, S1_BadVAll = 0, S1_BadEAll = 0;
569 Standard_Integer S2_BadType = 0, S2_SelfInt = 0, S2_SmalE = 0, S2_BadF = 0, S2_BadV = 0, S2_BadE = 0;
570 Standard_Integer S2_SelfIntAll = 0, S2_SmalEAll = 0, S2_BadFAll = 0, S2_BadVAll = 0, S2_BadEAll = 0;
571 Standard_Integer S1_OpAb = 0, S2_OpAb = 0;
572 Standard_Integer S1_C0 = 0, S2_C0 = 0, S1_C0All = 0, S2_C0All = 0;
573 Standard_Integer S1_COnS = 0, S2_COnS = 0, S1_COnSAll = 0, S2_COnSAll = 0;
574 Standard_Boolean hasUnknown = Standard_False;
576 TCollection_AsciiString aS1SIBaseName("s1si_");
577 TCollection_AsciiString aS1SEBaseName("s1se_");
578 TCollection_AsciiString aS1BFBaseName("s1bf_");
579 TCollection_AsciiString aS1BVBaseName("s1bv_");
580 TCollection_AsciiString aS1BEBaseName("s1be_");
581 TCollection_AsciiString aS1C0BaseName("s1C0_");
582 TCollection_AsciiString aS1COnSBaseName("s1COnS_");
583 TCollection_AsciiString aS2SIBaseName("s2si_");
584 TCollection_AsciiString aS2SEBaseName("s2se_");
585 TCollection_AsciiString aS2BFBaseName("s2bf_");
586 TCollection_AsciiString aS2BVBaseName("s2bv_");
587 TCollection_AsciiString aS2BEBaseName("s2be_");
588 TCollection_AsciiString aS2C0BaseName("s2C0_");
589 TCollection_AsciiString aS2COnSBaseName("s2COnS_");
591 for(; anIt.More(); anIt.Next()) {
592 const BOPAlgo_CheckResult& aResult = anIt.Value();
593 const TopoDS_Shape & aSS1 = aResult.GetShape1();
594 const TopoDS_Shape & aSS2 = aResult.GetShape2();
595 const TopTools_ListOfShape & aLS1 = aResult.GetFaultyShapes1();
596 const TopTools_ListOfShape & aLS2 = aResult.GetFaultyShapes2();
597 Standard_Boolean isL1 = !aLS1.IsEmpty();
598 Standard_Boolean isL2 = !aLS2.IsEmpty();
600 switch(aResult.GetCheckStatus()) {
601 case BOPAlgo_BadType: {
602 if(!aSS1.IsNull()) S1_BadType++;
603 if(!aSS2.IsNull()) S2_BadType++;
606 case BOPAlgo_SelfIntersect: {
610 MakeShapeForFullOutput(aS1SIBaseName, S1_SelfInt, aLS1, S1_SelfIntAll, di);
615 MakeShapeForFullOutput(aS2SIBaseName, S2_SelfInt, aLS2, S2_SelfIntAll, di);
619 case BOPAlgo_TooSmallEdge: {
623 MakeShapeForFullOutput(aS1SEBaseName, S1_SmalE, aLS1, S1_SmalEAll, di);
628 MakeShapeForFullOutput(aS2SEBaseName, S2_SmalE, aLS2, S2_SmalEAll, di);
632 case BOPAlgo_NonRecoverableFace: {
636 MakeShapeForFullOutput(aS1BFBaseName, S1_BadF, aLS1, S1_BadFAll, di);
641 MakeShapeForFullOutput(aS2BFBaseName, S2_BadF, aLS2, S2_BadFAll, di);
645 case BOPAlgo_IncompatibilityOfVertex: {
649 MakeShapeForFullOutput(aS1BVBaseName, S1_BadV, aLS1, S1_BadVAll, di);
655 MakeShapeForFullOutput(aS2BVBaseName, S2_BadV, aLS2, S2_BadVAll, di);
660 case BOPAlgo_IncompatibilityOfEdge: {
664 MakeShapeForFullOutput(aS1BEBaseName, S1_BadE, aLS1, S1_BadEAll, di);
670 MakeShapeForFullOutput(aS2BEBaseName, S2_BadE, aLS2, S2_BadEAll, di);
675 case BOPAlgo_IncompatibilityOfFace: {
676 // not yet implemented
679 case BOPAlgo_GeomAbs_C0: {
683 MakeShapeForFullOutput(aS1C0BaseName, S1_C0, aLS1, S1_C0All, di);
689 MakeShapeForFullOutput(aS2C0BaseName, S2_C0, aLS2, S2_C0All, di);
694 case BOPAlgo_InvalidCurveOnSurface: {
698 Standard_Real aMaxDist = aResult.GetMaxDistance1();
699 Standard_Real aMaxParameter = aResult.GetMaxParameter1();
700 MakeShapeForFullOutput(aS1COnSBaseName, S1_COnS, aLS1, S1_COnSAll, di,
701 Standard_True, aMaxDist, aMaxParameter);
707 Standard_Real aMaxDist = aResult.GetMaxDistance2();
708 Standard_Real aMaxParameter = aResult.GetMaxParameter2();
709 MakeShapeForFullOutput(aS2COnSBaseName, S2_COnS, aLS2, S2_COnSAll, di,
710 Standard_True, aMaxDist, aMaxParameter);
715 case BOPAlgo_OperationAborted: {
716 if(!aSS1.IsNull()) S1_OpAb++;
717 if(!aSS2.IsNull()) S2_OpAb++;
720 case BOPAlgo_CheckUnknown:
722 hasUnknown = Standard_True;
728 Standard_Integer FS1 = S1_SelfInt + S1_SmalE + S1_BadF + S1_BadV + S1_BadE + S1_OpAb + S1_C0 + S1_COnS;
729 FS1 += (S1_BadType != 0) ? 1 : 0;
730 Standard_Integer FS2 = S2_SelfInt + S2_SmalE + S2_BadF + S2_BadV + S2_BadE + S2_OpAb + S2_C0 + S2_COnS;
731 FS2 += (S2_BadType != 0) ? 1 : 0;
733 // output for first shape
734 di << "Faulties for FIRST shape found : " << FS1 << "\n";
736 di << "---------------------------------\n";
737 Standard_CString CString1;
741 CString1=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
742 di << "Shapes are not suppotrted by BOP: " << CString1 << "\n";
743 Standard_CString CString2;
747 CString2=aChecker.SelfInterMode() ? "NO" : "DISABLED";
748 di << "Self-Intersections : " << CString2;
750 di << " Cases(" << S1_SelfInt << ") Total shapes(" << S1_SelfIntAll << ")\n";
753 Standard_CString CString13;
757 CString13=aChecker.SelfInterMode() ? "NO" : "DISABLED";
758 di << "Check for SI has been aborted : " << CString13 << "\n";
759 Standard_CString CString3;
763 CString3=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
764 di << "Too small edges : " << CString3;
766 di << " Cases(" << S1_SmalE << ") Total shapes(" << S1_SmalEAll << ")\n";
769 Standard_CString CString4;
773 CString4=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
774 di << "Bad faces : " << CString4;
776 di << " Cases(" << S1_BadF << ") Total shapes(" << S1_BadFAll << ")\n";
779 Standard_CString CString5;
783 CString5=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
784 di << "Too close vertices : " << CString5;
786 di << " Cases(" << S1_BadV << ") Total shapes(" << S1_BadVAll << ")\n";
789 Standard_CString CString6;
793 CString6=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
794 di << "Too close edges : " << CString6;
796 di << " Cases(" << S1_BadE << ") Total shapes(" << S1_BadEAll << ")\n";
799 Standard_CString CString15;
803 CString15=aChecker.ContinuityMode() ? "NO" : "DISABLED";
804 di << "Shapes with Continuity C0 : " << CString15;
806 di << " Cases(" << S1_C0 << ") Total shapes(" << S1_C0All << ")\n";
810 Standard_CString CString17;
814 CString17=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
815 di << "Invalid Curve on Surface : " << CString17;
817 di << " Cases(" << S1_COnS << ") Total shapes(" << S1_COnSAll << ")\n";
822 // output for second shape
824 di << "Faulties for SECOND shape found : " << FS2 << "\n";
826 di << "---------------------------------\n";
827 Standard_CString CString7;
831 CString7=aChecker.ArgumentTypeMode() ? "NO" : "DISABLED";
832 di << "Shapes are not suppotrted by BOP: " << CString7 << "\n";
833 Standard_CString CString8;
837 CString8=aChecker.SelfInterMode() ? "NO" : "DISABLED";
838 di << "Self-Intersections : " << CString8;
840 di << " Cases(" << S2_SelfInt << ") Total shapes(" << S2_SelfIntAll << ")\n";
844 Standard_CString CString14;
848 CString14=aChecker.SelfInterMode() ? "NO" : "DISABLED";
849 di << "Check for SI has been aborted : " << CString14 << "\n";
850 Standard_CString CString9;
854 CString9=aChecker.SmallEdgeMode() ? "NO" : "DISABLED";
855 di << "Too small edges : " << CString9;
857 di << " Cases(" << S2_SmalE << ") Total shapes(" << S2_SmalEAll << ")\n";
860 Standard_CString CString10;
864 CString10=aChecker.RebuildFaceMode() ? "NO" : "DISABLED";
865 di << "Bad faces : " << CString10;
867 di << " Cases(" << S2_BadF << ") Total shapes(" << S2_BadFAll << ")\n";
870 Standard_CString CString11;
874 CString11=aChecker.MergeVertexMode() ? "NO" : "DISABLED";
875 di << "Too close vertices : " << CString11;
877 di << " Cases(" << S2_BadV << ") Total shapes(" << S2_BadVAll << ")\n";
880 Standard_CString CString12;
884 CString12=aChecker.MergeEdgeMode() ? "NO" : "DISABLED";
885 di << "Too close edges : " << CString12;
887 di << " Cases(" << S2_BadE << ") Total shapes(" << S2_BadEAll << ")\n";
890 Standard_CString CString16;
894 CString16=aChecker.ContinuityMode() ? "NO" : "DISABLED";
895 di << "Shapes with Continuity C0 : " << CString16;
897 di << " Cases(" << S2_C0 << ") Total shapes(" << S2_C0All << ")\n";
901 Standard_CString CString18;
905 CString18=aChecker.CurveOnSurfaceMode() ? "NO" : "DISABLED";
906 di << "Invalid Curve on Surface : " << CString18;
908 di << " Cases(" << S2_COnS << ") Total shapes(" << S2_COnSAll << ")\n";
915 di << "WARNING: The unexpected test break occurs!\n";
923 //=======================================================================
924 //function : bopapicheck
926 //=======================================================================
927 Standard_Integer bopapicheck(Draw_Interpretor& di,
937 TopoDS_Shape aS1 = DBRep::Get(a[1]);
941 // Try to get the second shape
942 aS2 = DBRep::Get(a[2]);
945 BOPAlgo_Operation anOp = BOPAlgo_UNKNOWN;
946 Standard_Boolean bTestSE = Standard_True;
947 Standard_Boolean bTestSI = Standard_True;
949 for (Standard_Integer i = aS2.IsNull() ? 2 : 3; i < n; ++i)
951 if (!strcmp(a[i], "-op"))
953 // Get the operation type
955 if (!strcmp(a[i], "common"))
956 anOp = BOPAlgo_COMMON;
957 else if (!strcmp(a[i], "fuse"))
959 else if (!strcmp(a[i], "cut"))
961 else if (!strcmp(a[i], "tuc"))
962 anOp = BOPAlgo_CUT21;
963 else if (!strcmp(a[i], "section"))
964 anOp = BOPAlgo_SECTION;
966 else if (!strcmp(a[i], "-se"))
968 bTestSE = Standard_False;
970 else if (!strcmp(a[i], "-si"))
972 bTestSI = Standard_False;
976 di << "Invalid key: " << a[i] << ". Skipped.\n";
980 BRepAlgoAPI_Check aChecker(aS1, aS2, anOp, bTestSE, bTestSI);
981 if (aChecker.IsValid())
984 di << "The shape seems to be valid\n";
986 di << "The shapes seem to be valid\n";
990 // Shapes seem to be invalid.
991 // Analyze the invalidity.
993 Standard_Boolean isInv1 = Standard_False, isInv2 = Standard_False;
994 Standard_Boolean isBadOp = Standard_False;
995 BOPAlgo_ListIteratorOfListOfCheckResult itF(aChecker.Result());
996 for (; itF.More(); itF.Next())
998 const BOPAlgo_CheckResult& aFaulty = itF.Value();
999 if (aFaulty.GetCheckStatus() == BOPAlgo_BadType)
1001 isBadOp = Standard_True;
1007 isInv1 = !aFaulty.GetShape1().IsNull();
1011 isInv2 = !aFaulty.GetShape2().IsNull();
1015 if (isInv1 && isInv2 && isBadOp)
1022 di << "The shape is invalid\n";
1024 di << "The first shape is invalid\n";
1028 di << "The second shape is invalid\n";
1033 di << "The shape is empty\n";
1035 di << "The shapes are not valid for Boolean operation\n";
1040 //=======================================================================
1041 //function : xdistef
1043 //=======================================================================
1044 Standard_Integer xdistef(Draw_Interpretor& di,
1049 di << "use xdistef edge face\n";
1053 const TopoDS_Shape aS1 = DBRep::Get(a[1]);
1054 const TopoDS_Shape aS2 = DBRep::Get(a[2]);
1056 if (aS1.IsNull() || aS2.IsNull()) {
1057 di << "null shapes\n";
1061 if (aS1.ShapeType() != TopAbs_EDGE ||
1062 aS2.ShapeType() != TopAbs_FACE) {
1063 di << "type mismatch\n";
1067 Standard_Real aMaxDist = 0.0, aMaxPar = 0.0;
1069 const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&aS1;
1070 const TopoDS_Face& aFace = *(TopoDS_Face*)&aS2;
1072 if(!BOPTools_AlgoTools::ComputeTolerance
1073 (aFace, anEdge, aMaxDist, aMaxPar)) {
1074 di << "Tolerance cannot be computed\n";
1078 di << "Max Distance = " << aMaxDist
1079 << "; Parameter on curve = " << aMaxPar << "\n";
1084 //=======================================================================
1085 //function : checkcurveonsurf
1087 //=======================================================================
1088 Standard_Integer checkcurveonsurf(Draw_Interpretor& di,
1093 di << "use checkcurveonsurf shape\n";
1097 TopoDS_Shape aS = DBRep::Get(a[1]);
1099 di << "null shape\n";
1103 Standard_Integer nE, nF, anECounter, aFCounter;
1104 Standard_Real aT, aTolE, aDMax;
1105 TopExp_Explorer aExpF, aExpE;
1106 char buf[200], aFName[10], anEName[10];
1107 NCollection_DataMap<TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> aDMETol;
1108 TopTools_DataMapOfShapeInteger aMSI;
1113 aExpF.Init(aS, TopAbs_FACE);
1114 for (; aExpF.More(); aExpF.Next()) {
1115 const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
1117 aExpE.Init(aF, TopAbs_EDGE);
1118 for (; aExpE.More(); aExpE.Next()) {
1119 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
1121 if (!BOPTools_AlgoTools::ComputeTolerance(aF, aE, aDMax, aT)) {
1125 aTolE = BRep_Tool::Tolerance(aE);
1126 if (!(aDMax > aTolE)) {
1130 if (aDMETol.IsBound(aE)) {
1131 Standard_Real& aD = aDMETol.ChangeFind(aE);
1137 aDMETol.Bind(aE, aDMax);
1140 if (anECounter == 0) {
1141 di << "Invalid curves on surface:\n";
1144 if (aMSI.IsBound(aE)) {
1153 if (aMSI.IsBound(aF)) {
1161 sprintf(anEName, "e_%d", nE);
1162 sprintf(aFName , "f_%d", nF);
1163 sprintf(buf, "edge %s on face %s (max dist: %3.16f, parameter on curve: %3.16f)\n",
1164 anEName, aFName, aDMax, aT);
1167 DBRep::Set(anEName, aE);
1168 DBRep::Set(aFName , aF);
1172 if (anECounter > 0) {
1173 di << "\n\nSugestions to fix the shape:\n";
1174 di << "explode " << a[1] << " e;\n";
1176 TopTools_MapOfShape M;
1177 aExpE.Init(aS, TopAbs_EDGE);
1178 for (anECounter = 0; aExpE.More(); aExpE.Next()) {
1179 const TopoDS_Shape& aE = aExpE.Current();
1185 if (!aDMETol.IsBound(aE)) {
1189 aTolE = aDMETol.Find(aE);
1191 sprintf(buf, "settolerance %s_%d %3.16f;\n", a[1], anECounter, aTolE);
1196 di << "This shape seems to be OK.\n";
1202 //=======================================================================
1203 //function : MakeShapeForFullOutput
1205 //=======================================================================
1206 void MakeShapeForFullOutput (const TCollection_AsciiString & aBaseName,
1207 const Standard_Integer aIndex,
1208 const TopTools_ListOfShape & aList,
1209 Standard_Integer& aCount,
1210 Draw_Interpretor& di,
1211 Standard_Boolean bCurveOnSurf,
1212 Standard_Real aMaxDist,
1213 Standard_Real aMaxParameter)
1215 TCollection_AsciiString aNum(aIndex);
1216 TCollection_AsciiString aName = aBaseName + aNum;
1217 Standard_CString name = aName.ToCString();
1219 TopoDS_Compound cmp;
1221 BB.MakeCompound(cmp);
1223 TopTools_ListIteratorOfListOfShape anIt(aList);
1224 for(; anIt.More(); anIt.Next()) {
1225 const TopoDS_Shape & aS = anIt.Value();
1229 di << "Made faulty shape: " << name;
1232 di << " (MaxDist = " << aMaxDist
1233 << ", MaxPar = " << aMaxParameter << ")";
1238 DBRep::Set(name, cmp);