0024492: The command bopargcheck produces wrong results for cases.
[occt.git] / src / BOPAlgo / BOPAlgo_ArgumentAnalyzer.cxx
1 // Created on: 2004-09-02
2 // Copyright (c) 2004-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and / or modify it
7 // under the terms of the GNU Lesser General Public version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPAlgo_ArgumentAnalyzer.ixx>
16
17 #include <Standard_ErrorHandler.hxx>
18 #include <Standard_Failure.hxx>
19 #include <TopExp.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepExtrema_DistShapeShape.hxx>
24 #include <gp_Pnt.hxx>
25 #include <TopoDS_Iterator.hxx>
26 #include <TopoDS.hxx>
27 #include <TopoDS_Vertex.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Wire.hxx>
30 #include <TopoDS_Shell.hxx>
31 #include <TopoDS_Solid.hxx>
32 #include <BOPCol_ListOfShape.hxx>
33 #include <BOPCol_SequenceOfShape.hxx>
34 #include <BOPCol_MapOfShape.hxx>
35
36 #include <TColStd_Array2OfBoolean.hxx>
37
38 #include <IntTools_Range.hxx>
39 #include <IntTools_EdgeEdge.hxx>
40 #include <IntTools_CommonPrt.hxx>
41
42 #include <BOPAlgo_Operation.hxx>
43 #include <BOPAlgo_CheckerSI.hxx>
44 #include <BOPAlgo_BuilderFace.hxx>
45
46 #include <BOPDS_DS.hxx>
47 #include <BOPDS_VectorOfInterfVV.hxx>
48 #include <BOPDS_VectorOfInterfVE.hxx>
49 #include <BOPDS_VectorOfInterfEE.hxx>
50 #include <BOPDS_VectorOfInterfVF.hxx>
51 #include <BOPDS_VectorOfInterfEF.hxx>
52 #include <BOPDS_VectorOfInterfFF.hxx>
53
54 #include <BOPInt_Context.hxx>
55
56 #include <BOPTools_AlgoTools3D.hxx>
57 #include <BOPTools_AlgoTools.hxx>
58 #include <BOPCol_ListOfShape.hxx>
59 #include <Geom_Surface.hxx>
60
61 // ================================================================================
62 // function: Constructor
63 // purpose:
64 // ================================================================================
65 BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() : 
66 myStopOnFirst(Standard_False),
67 myOperation(BOPAlgo_UNKNOWN),
68 myArgumentTypeMode(Standard_False),
69 mySelfInterMode(Standard_False),
70 mySmallEdgeMode(Standard_False),
71 myRebuildFaceMode(Standard_False),
72 myTangentMode(Standard_False),
73 myMergeVertexMode(Standard_False),
74 myMergeEdgeMode(Standard_False),
75 myContinuityMode(Standard_False),
76 myEmpty1(Standard_False),
77 myEmpty2(Standard_False)
78 // myMergeFaceMode(Standard_False)
79 {
80 }
81
82 // ================================================================================
83 // function: SetShape1
84 // purpose:
85 // ================================================================================
86 void BOPAlgo_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape)
87 {
88   myShape1 = TheShape;
89 }
90
91 // ================================================================================
92 // function: SetShape2
93 // purpose:
94 // ================================================================================
95 void BOPAlgo_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape)
96 {
97   myShape2 = TheShape;
98 }
99
100 // ================================================================================
101 // function: GetShape1
102 // purpose:
103 // ================================================================================
104 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape1() const
105 {
106   return myShape1;
107 }
108
109 // ================================================================================
110 // function: GetShape2
111 // purpose:
112 // ================================================================================
113 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape2() const
114 {
115   return myShape2;
116 }
117
118 // ================================================================================
119 // function: OperationType
120 // purpose:
121 // ================================================================================
122 BOPAlgo_Operation& BOPAlgo_ArgumentAnalyzer::OperationType() 
123 {
124   return myOperation;
125 }
126
127 // ================================================================================
128 // function: StopOnFirstFaulty
129 // purpose:
130 // ================================================================================
131 Standard_Boolean & BOPAlgo_ArgumentAnalyzer::StopOnFirstFaulty()
132 {
133   return myStopOnFirst;
134 }
135
136 // ================================================================================
137 // function: Prepare
138 // purpose:
139 // ================================================================================
140 void BOPAlgo_ArgumentAnalyzer::Prepare()
141 {
142   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
143   if (!isS1) {
144     myEmpty1 = BOPTools_AlgoTools3D::IsEmptyShape(myShape1);
145   }
146   if (!isS2) {
147     myEmpty2 = BOPTools_AlgoTools3D::IsEmptyShape(myShape2);
148   }
149 }
150 // ================================================================================
151 // function: Perform
152 // purpose:
153 // ================================================================================
154 void BOPAlgo_ArgumentAnalyzer::Perform()
155 {
156   try {
157     OCC_CATCH_SIGNALS
158     myResult.Clear();
159
160     Prepare();
161
162     if(myArgumentTypeMode) {
163       TestTypes();
164     }
165
166     if(mySelfInterMode) {
167       TestSelfInterferences();
168     }
169
170     if(mySmallEdgeMode) {
171       if(!(!myResult.IsEmpty() && myStopOnFirst))
172         TestSmallEdge();
173     }
174
175     if(myRebuildFaceMode) {
176       if(!(!myResult.IsEmpty() && myStopOnFirst))
177         TestRebuildFace();
178     }
179
180     if(myTangentMode) {
181       if(!(!myResult.IsEmpty() && myStopOnFirst))
182         TestTangent();
183     }
184
185     if(myMergeVertexMode) {
186       if(!(!myResult.IsEmpty() && myStopOnFirst))
187         TestMergeVertex();
188     }
189     
190     if(myMergeEdgeMode) {
191       if(!(!myResult.IsEmpty() && myStopOnFirst))
192         TestMergeEdge();
193     }
194
195     if(myContinuityMode) {
196       if(!(!myResult.IsEmpty() && myStopOnFirst))
197         TestContinuity();
198     }
199   }
200   catch(Standard_Failure) {
201     BOPAlgo_CheckResult aResult;
202     aResult.SetCheckStatus(BOPAlgo_CheckUnknown);
203     myResult.Append(aResult);
204   }
205 }
206
207 // ================================================================================
208 // function: HasFaulty
209 // purpose:
210 // ================================================================================
211 Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const
212 {
213   return ( !myResult.IsEmpty());
214 }
215
216 // ================================================================================
217 // function: GetCheckResult
218 // purpose:
219 // ================================================================================
220 const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const
221 {
222   return myResult;
223 }
224
225 // ================================================================================
226 // function: TestTypes
227 // purpose:
228 // ================================================================================
229 void BOPAlgo_ArgumentAnalyzer::TestTypes()
230 {
231   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
232
233   if(isS1 && isS2) {
234     BOPAlgo_CheckResult aResult;
235     aResult.SetCheckStatus(BOPAlgo_BadType);
236     myResult.Append(aResult);
237     return;
238   }
239
240   //single shape check
241   if((isS1 && !isS2) || (!isS1 && isS2)) {
242     Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1;
243
244     if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) {
245       const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1;
246       BOPAlgo_CheckResult aResult;
247       aResult.SetShape1(aS);
248       aResult.SetCheckStatus(BOPAlgo_BadType);
249       myResult.Append(aResult);
250       return;
251     }
252   }
253   // two shapes check (begin)
254   else {
255     if(myEmpty1 || myEmpty2) {
256       BOPAlgo_CheckResult aResult;
257       if(myEmpty1 && myEmpty2) {
258         aResult.SetShape1(myShape1);
259         aResult.SetShape2(myShape2);
260       }
261       else {
262         const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2;
263         if(myEmpty1)
264           aResult.SetShape1(aS);
265         else
266           aResult.SetShape2(aS);
267       }
268       aResult.SetCheckStatus(BOPAlgo_BadType);
269       myResult.Append(aResult);
270       return;
271     }
272     //
273     Standard_Integer aDim1, aDim2;
274     Standard_Boolean bBadTypes = Standard_False;
275     //
276     aDim1 = BOPTools_AlgoTools::Dimension(myShape1);
277     aDim2 = BOPTools_AlgoTools::Dimension(myShape2);
278     if (aDim1 < aDim2) {
279       if (myOperation == BOPAlgo_FUSE ||
280           myOperation == BOPAlgo_CUT21) {
281         bBadTypes = Standard_True;
282       }
283     }
284     else if (aDim1 > aDim2) {
285       if (myOperation == BOPAlgo_FUSE ||
286           myOperation == BOPAlgo_CUT) {
287         bBadTypes = Standard_True;
288       }
289     }
290     if (bBadTypes) {
291       BOPAlgo_CheckResult aResult;
292       aResult.SetShape1(myShape1);
293       aResult.SetShape2(myShape2);
294       aResult.SetCheckStatus(BOPAlgo_BadType);
295       myResult.Append(aResult);
296     }
297   }
298 }
299 //=======================================================================
300 //function : TestSelfInterferences
301 //purpose  : 
302 //=======================================================================
303 void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
304 {
305   Standard_Integer ii=0, j;
306   Standard_Boolean bSelfInt;
307
308   for(ii = 0; ii < 2; ii++) {
309     const TopoDS_Shape& aS = (ii == 0) ? myShape1 : myShape2;
310
311     if(aS.IsNull()) {
312       continue;
313     }
314
315     Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2;
316     if (bIsEmpty) {
317       continue;
318     }
319
320     BOPAlgo_CheckerSI aChecker;
321     BOPCol_ListOfShape anArgs;
322     //
323     anArgs.Append(aS);
324     aChecker.SetArguments(anArgs);
325     //
326     aChecker.Perform();
327     Standard_Integer iErr = aChecker.ErrorStatus();
328     //
329     const BOPDS_PDS& theDS = aChecker.PDS();
330     BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV();
331     BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE();
332     BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE();
333     BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF();
334     BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF();
335     BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF();
336     BOPDS_VectorOfInterfVZ& aVZs=theDS->InterfVZ();
337     BOPDS_VectorOfInterfEZ& aEZs=theDS->InterfEZ();
338     BOPDS_VectorOfInterfFZ& aFZs=theDS->InterfFZ();
339     BOPDS_VectorOfInterfZZ& aZZs=theDS->InterfZZ();
340     //
341     const Standard_Integer aNbTypeInt=10;
342     Standard_Integer aTypeInt, i, nI1, nI2;
343     Standard_Integer aNb[aNbTypeInt] = {
344       aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), 
345       aVFs.Extent(), aEFs.Extent(), aFFs.Extent(),
346       aVZs.Extent(), aEZs.Extent(), aFZs.Extent(), aZZs.Extent()};
347     BOPDS_Interf* aInt=NULL;
348     //
349     for (aTypeInt = 0; aTypeInt < aNbTypeInt; ++aTypeInt) {
350       for (i = 0; i < aNb[aTypeInt]; ++i) {
351         switch(aTypeInt) {
352           case 0:
353             aInt=(BOPDS_Interf*)(&aVVs(i));
354             break;
355           case 1:
356             aInt=(BOPDS_Interf*)(&aVEs(i));
357             break;
358           case 2:
359             aInt=(BOPDS_Interf*)(&aEEs(i));
360             break;
361           case 3:
362             aInt=(BOPDS_Interf*)(&aVFs(i));
363             break;
364           case 4:
365             aInt=(BOPDS_Interf*)(&aEFs(i));
366             break;
367           case 5:
368             aInt=(BOPDS_Interf*)(&aFFs(i));
369             break;
370           case 6:
371             aInt=(BOPDS_Interf*)(&aVZs(i));
372             break;
373           case 7:
374             aInt=(BOPDS_Interf*)(&aEZs(i));
375             break;
376           case 8:
377             aInt=(BOPDS_Interf*)(&aFZs(i));
378             break;
379           case 9:
380             aInt=(BOPDS_Interf*)(&aZZs(i));
381             break;
382           default:
383             aInt=NULL;
384         }
385         //
386         aInt->Indices(nI1, nI2);
387         if (nI1 == nI2) {
388           continue;
389         }
390         //
391         if (aTypeInt == 4) {
392           BOPDS_InterfEF& aEF=aEFs(i);
393           if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
394             continue;
395           }
396         }
397         //
398         const TopoDS_Shape& aS1 = theDS->Shape(nI1);
399         const TopoDS_Shape& aS2 = theDS->Shape(nI2);
400         //
401         if (aTypeInt == 5) {
402           bSelfInt = Standard_False;
403           BOPDS_InterfFF& aFF = aFFs(i);
404           BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
405           Standard_Integer aNbP=aVP.Extent();
406           BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
407           Standard_Integer aNbC=aVC.Extent();
408           if (!aNbP && !aNbC) {
409             continue;
410           }
411           for (j=0; j<aNbC; ++j) {
412             BOPDS_Curve& aNC=aVC(j);
413             BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
414             if (aLPBC.Extent()) {
415               bSelfInt = Standard_True;
416               break;
417             }
418           }
419           if (!bSelfInt) {
420             continue;
421           }
422         }
423         //
424         BOPAlgo_CheckResult aResult;
425         if(ii == 0) {
426           aResult.SetShape1(myShape1);
427           aResult.AddFaultyShape1(aS1);
428           aResult.AddFaultyShape1(aS2);
429         }
430         else {
431           aResult.SetShape2(myShape2);
432           aResult.AddFaultyShape2(aS1);
433           aResult.AddFaultyShape2(aS2);
434         }
435         aResult.SetCheckStatus(BOPAlgo_SelfIntersect);
436         myResult.Append(aResult);
437       }
438     }
439     //
440     if (iErr) {
441       BOPAlgo_CheckResult aResult;
442       if(ii == 0) {
443         aResult.SetShape1(myShape1);
444         aResult.AddFaultyShape1(myShape1);
445       }
446       else {
447         aResult.SetShape2(myShape2);
448         aResult.AddFaultyShape2(myShape2);
449       }
450       aResult.SetCheckStatus(BOPAlgo_OperationAborted);
451       myResult.Append(aResult);
452     }
453   }
454 }
455 // ================================================================================
456 // function: TestSmallEdge
457 // purpose:
458 // ================================================================================
459 void BOPAlgo_ArgumentAnalyzer::TestSmallEdge() 
460 {
461   Standard_Integer i = 0;
462   BRepExtrema_DistShapeShape aDist;
463   Handle(BOPInt_Context) aCtx;
464   //
465   aCtx = new BOPInt_Context;
466   
467   for(i = 0; i < 2; i++) {
468     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
469
470     if(aS.IsNull())
471       continue;
472
473     TopExp_Explorer anExp(aS, TopAbs_EDGE);
474
475     for(; anExp.More(); anExp.Next()) {
476       const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&anExp.Current();
477       if (BRep_Tool::Degenerated(anEdge)) {
478         continue;
479       }
480
481       if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
482         Standard_Boolean bKeepResult = Standard_True;
483         
484         if(myOperation == BOPAlgo_SECTION) {
485           const TopoDS_Shape& anOtherS = (i == 0) ? myShape2 : myShape1;
486           
487           if(!anOtherS.IsNull()) {
488             aDist.LoadS2(anOtherS);
489             
490             Standard_Boolean bVertexIsOnShape = Standard_False;
491             Standard_Integer ii = 0;
492             TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
493             
494             for(; anExpV.More(); anExpV.Next()) {
495               const TopoDS_Shape& aV = anExpV.Current();
496               
497               aDist.LoadS1(aV);
498               aDist.Perform();
499               
500               if(aDist.IsDone()) {
501                 
502                 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
503                   Standard_Real aTolerance = BRep_Tool::Tolerance(*(TopoDS_Vertex*)&aV);
504                   const TopoDS_Shape& aSupportShape = aDist.SupportOnShape2(ii);
505                   
506                   switch(aSupportShape.ShapeType()) {
507                   case TopAbs_VERTEX: {
508                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Vertex*)&(aSupportShape));
509                     break;
510                   }
511                   case TopAbs_EDGE: {
512                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Edge*)&(aSupportShape));
513                     break;
514                   }
515                   case TopAbs_FACE: {
516                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Face*)&(aSupportShape));
517                     break;
518                   }
519                   default:
520                     break;
521                   }
522                   
523                   if(aDist.Value() < aTolerance) {
524                     bVertexIsOnShape = Standard_True;
525                     break;
526                   }
527                 }
528               }
529             }
530             
531             if(!bVertexIsOnShape) {
532               bKeepResult = Standard_False;
533             }
534           }
535         }
536         
537         if(bKeepResult) {
538           BOPAlgo_CheckResult aResult;
539           
540           if(i == 0) {
541             aResult.SetShape1(myShape1);
542             aResult.AddFaultyShape1(anEdge);
543           }
544           else {
545             aResult.SetShape2(myShape2);
546             aResult.AddFaultyShape2(anEdge);
547           }
548           
549           aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
550           myResult.Append(aResult);
551           
552           if(myStopOnFirst) {
553             return;
554           }
555         }
556       }
557     }
558   }
559 }
560 // ================================================================================
561 // function: TestRebuildFace
562 // purpose:
563 // ================================================================================
564 void BOPAlgo_ArgumentAnalyzer::TestRebuildFace() 
565 {
566   if((myOperation == BOPAlgo_SECTION) ||
567      (myOperation == BOPAlgo_UNKNOWN))
568     return;
569   Standard_Integer i = 0;
570
571   for(i = 0; i < 2; i++) {
572     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
573
574     if(aS.IsNull())
575       continue;
576
577     TopExp_Explorer anExp(aS, TopAbs_FACE);
578     BOPCol_ListOfShape aLS;
579
580     for(; anExp.More(); anExp.Next()) {
581       const TopoDS_Face& aFace = *(TopoDS_Face*)&(anExp.Current());
582
583       TopoDS_Face aFF = aFace;
584       aFF.Orientation(TopAbs_FORWARD);
585       TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
586       Standard_Integer nbstartedges = 0;
587       aLS.Clear();
588       //
589       for(; anExpE.More(); anExpE.Next()) {
590         const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
591         TopAbs_Orientation anOriE=aE.Orientation();
592         //
593         if (anOriE==TopAbs_INTERNAL) {
594           TopoDS_Edge aEE=aE;
595           aEE.Orientation(TopAbs_FORWARD);
596           aLS.Append(aEE);
597           aEE.Orientation(TopAbs_REVERSED);
598           aLS.Append(aEE);
599         }
600         else {
601           aLS.Append(aE);
602         }
603         nbstartedges++;
604       }
605       BOPAlgo_BuilderFace aBF;
606       aBF.SetFace(aFace);
607       aBF.SetShapes(aLS);
608       aBF.Perform();
609       const BOPCol_ListOfShape& aLF = aBF.Areas();
610       Standard_Boolean bBadFace = Standard_False;
611
612       if(aLF.Extent() != 1) {
613         bBadFace = Standard_True;
614       }
615       else {
616         Standard_Integer nbedgeused = 0;
617         anExpE.Init(aLF.First(), TopAbs_EDGE);
618         
619         for(; anExpE.More(); anExpE.Next(), nbedgeused++);
620         
621         if(nbstartedges != nbedgeused) {
622           bBadFace = Standard_True;
623         }
624       }
625
626       if(bBadFace) {
627         BOPAlgo_CheckResult aResult;
628         
629         if(i == 0) {
630           aResult.SetShape1(myShape1);
631           aResult.AddFaultyShape1(aFace);
632         }
633         else {
634           aResult.SetShape2(myShape2);
635           aResult.AddFaultyShape2(aFace);
636         }
637         
638         aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
639         myResult.Append(aResult);
640         
641         if(myStopOnFirst) {
642           return;
643         }
644       }
645     }
646   }
647 }
648
649 // ================================================================================
650 // function: TestTangent
651 // purpose:
652 // ================================================================================
653 void BOPAlgo_ArgumentAnalyzer::TestTangent() 
654 {
655  // not implemented
656 }
657
658 // ================================================================================
659 // function: TestMergeSubShapes
660 // purpose:
661 // ================================================================================
662  void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) 
663 {
664   if(myShape1.IsNull() || myShape2.IsNull())
665     return;
666
667   if (myEmpty1 || myEmpty2) 
668     return;
669
670   BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
671
672   switch(theType) {
673   case TopAbs_VERTEX: {
674     aStatus = BOPAlgo_IncompatibilityOfVertex;
675     break;
676   }
677   case TopAbs_EDGE: {
678     aStatus = BOPAlgo_IncompatibilityOfEdge;
679     break;
680   }
681   case TopAbs_FACE: {
682     aStatus = BOPAlgo_IncompatibilityOfFace;
683     break;
684   }
685   default: 
686     return;
687   }
688   TopExp_Explorer anExp1(myShape1, theType);
689   TopExp_Explorer anExp2(myShape2, theType);
690   BOPCol_SequenceOfShape aSeq1, aSeq2;
691   BOPCol_MapOfShape aMap1, aMap2;
692
693   for(; anExp1.More(); anExp1.Next()) {
694     const TopoDS_Shape& aS1 = anExp1.Current();
695
696     if(aMap1.Contains(aS1))
697       continue;
698     aSeq1.Append(aS1);
699     aMap1.Add(aS1);
700   }
701
702   for(; anExp2.More(); anExp2.Next()) {
703     const TopoDS_Shape& aS2 = anExp2.Current();
704     if(aMap2.Contains(aS2))
705       continue;
706     aSeq2.Append(aS2);
707     aMap2.Add(aS2);
708   }
709
710   TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
711   Standard_Integer i = 0, j = 0;
712   for(i = 1; i <= aSeq1.Length(); i++)
713     for(j = 1; j <= aSeq2.Length(); j++)
714       anArrayOfFlag.SetValue(i, j, Standard_False);
715
716   for(i = 1; i <= aSeq1.Length(); i++) {
717     const TopoDS_Shape& aS1 = aSeq1.Value(i);
718     BOPCol_ListOfShape aListOfS2;
719     Standard_Integer nbs = 0;
720
721     for(j = 1; j <= aSeq2.Length(); j++) {
722       const TopoDS_Shape& aS2 = aSeq2.Value(j);
723       Standard_Boolean bIsEqual = Standard_False;
724
725       if(theType == TopAbs_VERTEX) {
726
727         const TopoDS_Vertex& aV1 = *(TopoDS_Vertex*)&(aS1);
728         const TopoDS_Vertex& aV2 = *(TopoDS_Vertex*)&(aS2);
729         gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
730         gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
731         Standard_Real aDist = aP1.Distance(aP2);
732
733         if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
734           bIsEqual = Standard_True;
735         }
736       }
737       else if(theType == TopAbs_EDGE) {
738         Standard_Integer aDiscretize = 30;
739         Standard_Real    aDeflection = 0.01;
740         const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&(aS1);
741         const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&(aS2);
742         
743         IntTools_EdgeEdge aEE;
744         aEE.SetEdge1 (aE1);
745         aEE.SetEdge2 (aE2);
746         aEE.SetTolerance1 (BRep_Tool::Tolerance(aE1));
747         aEE.SetTolerance2 (BRep_Tool::Tolerance(aE2));
748         aEE.SetDiscretize (aDiscretize);
749         aEE.SetDeflection (aDeflection);
750         
751         Standard_Real f = 0., l = 0.;
752         BRep_Tool::Range(aE1, f, l);
753         aEE.SetRange1(f, l);
754         
755         BRep_Tool::Range(aE2, f, l);
756         aEE.SetRange2(f, l);
757         
758         aEE.Perform();
759         
760         if (aEE.IsDone()) {
761           const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
762           Standard_Integer ii = 0;
763           
764           for (ii = 1; ii <= aCPrts.Length(); ii++) {
765             const IntTools_CommonPrt& aCPart = aCPrts(ii);
766             
767             if (aCPart.Type() == TopAbs_EDGE) {
768               bIsEqual = Standard_True;
769             }
770           }
771         }
772       }
773       else if(theType == TopAbs_FACE) {
774         // not yet implemented!
775       }
776
777       if(bIsEqual) {
778         anArrayOfFlag.SetValue(i, j, Standard_True );
779         aListOfS2.Append(aS2);
780         nbs++;
781       }
782     }
783
784     if(nbs > 1) {
785       BOPAlgo_CheckResult aResult;
786
787       aResult.SetShape1(myShape1);
788       aResult.SetShape2(myShape2);
789       aResult.AddFaultyShape1(aS1);
790       BOPCol_ListIteratorOfListOfShape anIt(aListOfS2);
791
792       for(; anIt.More(); anIt.Next()) {
793         aResult.AddFaultyShape2(anIt.Value());
794       }
795
796       aResult.SetCheckStatus(aStatus);
797       myResult.Append(aResult);
798
799       if(myStopOnFirst) {
800         return;
801       }
802     }
803   }
804
805   for(i = 1; i <= aSeq2.Length(); i++) {
806     const TopoDS_Shape& aS2 = aSeq2.Value(i);
807     BOPCol_ListOfShape aListOfS1;
808     Standard_Integer nbs = 0;
809
810     for(j = 1; j <= aSeq1.Length(); j++) {
811       const TopoDS_Shape& aS1 = aSeq1.Value(j);
812
813       if(anArrayOfFlag.Value(j, i)) {
814         aListOfS1.Append(aS1);
815         nbs++;
816       }
817     }
818     
819     if(nbs > 1) {
820       BOPAlgo_CheckResult aResult;
821
822       aResult.SetShape1(myShape1);
823       aResult.SetShape2(myShape2);
824       BOPCol_ListIteratorOfListOfShape anIt(aListOfS1);
825
826       for(; anIt.More(); anIt.Next()) {
827         aResult.AddFaultyShape1(anIt.Value());
828       }
829       aResult.AddFaultyShape2(aS2);
830
831       aResult.SetCheckStatus(aStatus);
832       myResult.Append(aResult);
833
834       if(myStopOnFirst) {
835         return;
836       }
837     }
838   }
839 }
840
841 // ================================================================================
842 // function: TestMergeVertex
843 // purpose:
844 // ================================================================================
845 void BOPAlgo_ArgumentAnalyzer::TestMergeVertex() 
846 {
847   TestMergeSubShapes(TopAbs_VERTEX); 
848 }
849
850 // ================================================================================
851 // function: TestMergeEdge
852 // purpose:
853 // ================================================================================
854 void BOPAlgo_ArgumentAnalyzer::TestMergeEdge() 
855 {
856   TestMergeSubShapes(TopAbs_EDGE); 
857 }
858
859 // ================================================================================
860 // function: TestContinuity
861 // purpose:
862 // ================================================================================
863 void BOPAlgo_ArgumentAnalyzer::TestContinuity() 
864 {
865   Standard_Integer i;
866   Standard_Real f, l;
867   TopExp_Explorer aExp;
868   BOPCol_MapIteratorOfMapOfShape aIt;
869   //
870   for (i = 0; i < 2; ++i) {
871     const TopoDS_Shape& aS = !i ? myShape1 : myShape2;
872     if(aS.IsNull()) {
873       continue;
874     }
875     //
876     BOPCol_MapOfShape aMS;
877     //Edges
878     aExp.Init(aS, TopAbs_EDGE);
879     for (; aExp.More(); aExp.Next()) {
880       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
881       if (BRep_Tool::Degenerated(aE)) {
882         continue;
883       }
884       const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, f, l);
885       if (aC->Continuity() == GeomAbs_C0) {
886         aMS.Add(aE);
887       }
888     }
889     //Faces
890     aExp.Init(aS, TopAbs_FACE);
891     for (; aExp.More(); aExp.Next()) {
892       const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
893       const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF);
894       if (aS->Continuity() == GeomAbs_C0) {
895         aMS.Add(aF);
896       }
897     }
898     //
899     //add shapes with continuity C0 to result
900     aIt.Initialize(aMS);
901     for (; aIt.More(); aIt.Next()) {
902       const TopoDS_Shape& aFS = aIt.Value();
903       BOPAlgo_CheckResult aResult;
904       if(i == 0) {
905         aResult.SetShape1(myShape1);
906         aResult.AddFaultyShape1(aFS);
907       } else {
908         aResult.SetShape2(myShape2);
909         aResult.AddFaultyShape2(aFS);
910       }
911       aResult.SetCheckStatus(BOPAlgo_GeomAbs_C0);
912       myResult.Append(aResult);
913     }
914   }
915 }
916
917 // ================================================================================
918 // function: TestMergeFace
919 // purpose:
920 // ================================================================================
921 // void BOPAlgo_ArgumentAnalyzer::TestMergeFace() 
922 // {
923   // not implemented
924 // }