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