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