44349abccc8c2bcb60b03aee7fd4c2972622ea25
[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     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     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       TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
443
444       if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
445         Standard_Boolean bKeepResult = Standard_True;
446         
447         if(myOperation == BOPAlgo_SECTION) {
448           TopoDS_Shape anOtherS = (i == 0) ? myShape2 : myShape1;
449           
450           if(!anOtherS.IsNull()) {
451             aDist.LoadS2(anOtherS);
452             
453             Standard_Boolean bVertexIsOnShape = Standard_False;
454             Standard_Integer ii = 0;
455             TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
456             
457             for(; anExpV.More(); anExpV.Next()) {
458               TopoDS_Shape aV = anExpV.Current();
459               
460               aDist.LoadS1(aV);
461               aDist.Perform();
462               
463               if(aDist.IsDone()) {
464                 
465                 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
466                   Standard_Real aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aV));
467                   TopoDS_Shape aSupportShape = aDist.SupportOnShape2(ii);
468                   
469                   switch(aSupportShape.ShapeType()) {
470                   case TopAbs_VERTEX: {
471                     aTolerance += BRep_Tool::Tolerance(TopoDS::Vertex(aSupportShape));
472                     break;
473                   }
474                   case TopAbs_EDGE: {
475                     aTolerance += BRep_Tool::Tolerance(TopoDS::Edge(aSupportShape));
476                     break;
477                   }
478                   case TopAbs_FACE: {
479                     aTolerance += BRep_Tool::Tolerance(TopoDS::Face(aSupportShape));
480                     break;
481                   }
482                   default:
483                     break;
484                   }
485                   
486                   if(aDist.Value() < aTolerance) {
487                     bVertexIsOnShape = Standard_True;
488                     break;
489                   }
490                 }
491               }
492             }
493             
494             if(!bVertexIsOnShape) {
495               bKeepResult = Standard_False;
496             }
497           }
498         }
499         
500         if(bKeepResult) {
501           BOPAlgo_CheckResult aResult;
502           
503           if(i == 0) {
504             aResult.SetShape1(myShape1);
505             aResult.AddFaultyShape1(anEdge);
506           }
507           else {
508             aResult.SetShape2(myShape2);
509             aResult.AddFaultyShape2(anEdge);
510           }
511           
512           aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
513           myResult.Append(aResult);
514           
515           if(myStopOnFirst) {
516             return;
517           }
518         }
519       }
520     }
521   }
522 }
523
524 // ================================================================================
525 // function: TestRebuildFace
526 // purpose:
527 // ================================================================================
528 void BOPAlgo_ArgumentAnalyzer::TestRebuildFace() 
529 {
530   if((myOperation == BOPAlgo_SECTION) ||
531      (myOperation == BOPAlgo_UNKNOWN))
532     return;
533   Standard_Integer i = 0;
534
535   for(i = 0; i < 2; i++) {
536     TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
537
538     if(aS.IsNull())
539       continue;
540
541     TopExp_Explorer anExp(aS, TopAbs_FACE);
542     BOPCol_ListOfShape aLS;
543
544     for(; anExp.More(); anExp.Next()) {
545       TopoDS_Face aFace = TopoDS::Face(anExp.Current());
546
547       TopoDS_Face aFF = aFace;
548       aFF.Orientation(TopAbs_FORWARD);
549       TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
550       Standard_Integer nbstartedges = 0;
551       aLS.Clear();
552       //
553       for(; anExpE.More(); anExpE.Next()) {
554         const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
555         TopAbs_Orientation anOriE=aE.Orientation();
556         //
557         if (anOriE==TopAbs_INTERNAL) {
558           TopoDS_Edge aEE=aE;
559           aEE.Orientation(TopAbs_FORWARD);
560           aLS.Append(aEE);
561           aEE.Orientation(TopAbs_REVERSED);
562           aLS.Append(aEE);
563         }
564         else {
565           aLS.Append(aE);
566         }
567         nbstartedges++;
568       }
569       BOPAlgo_BuilderFace aBF;
570       aBF.SetFace(aFace);
571       aBF.SetShapes(aLS);
572       aBF.Perform();
573       const BOPCol_ListOfShape& aLF = aBF.Areas();
574       Standard_Boolean bBadFace = Standard_False;
575
576       if(aLF.Extent() != 1) {
577         bBadFace = Standard_True;
578       }
579       else {
580         Standard_Integer nbedgeused = 0;
581         anExpE.Init(aLF.First(), TopAbs_EDGE);
582         
583         for(; anExpE.More(); anExpE.Next(), nbedgeused++);
584         
585         if(nbstartedges != nbedgeused) {
586           bBadFace = Standard_True;
587         }
588       }
589
590       if(bBadFace) {
591         BOPAlgo_CheckResult aResult;
592         
593         if(i == 0) {
594           aResult.SetShape1(myShape1);
595           aResult.AddFaultyShape1(aFace);
596         }
597         else {
598           aResult.SetShape2(myShape2);
599           aResult.AddFaultyShape2(aFace);
600         }
601         
602         aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
603         myResult.Append(aResult);
604         
605         if(myStopOnFirst) {
606           return;
607         }
608       }
609     }
610   }
611 }
612
613 // ================================================================================
614 // function: TestTangent
615 // purpose:
616 // ================================================================================
617 void BOPAlgo_ArgumentAnalyzer::TestTangent() 
618 {
619  // not implemented
620 }
621
622 // ================================================================================
623 // function: TestMergeSubShapes
624 // purpose:
625 // ================================================================================
626  void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) 
627 {
628   if(myShape1.IsNull() || myShape2.IsNull())
629     return;
630
631   if (myEmpty1 || myEmpty2) 
632     return;
633
634   BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
635
636   switch(theType) {
637   case TopAbs_VERTEX: {
638     aStatus = BOPAlgo_IncompatibilityOfVertex;
639     break;
640   }
641   case TopAbs_EDGE: {
642     aStatus = BOPAlgo_IncompatibilityOfEdge;
643     break;
644   }
645   case TopAbs_FACE: {
646     aStatus = BOPAlgo_IncompatibilityOfFace;
647     break;
648   }
649   default: 
650     return;
651   }
652   TopExp_Explorer anExp1(myShape1, theType);
653   TopExp_Explorer anExp2(myShape2, theType);
654   BOPCol_SequenceOfShape aSeq1, aSeq2;
655   BOPCol_MapOfShape aMap1, aMap2;
656
657   for(; anExp1.More(); anExp1.Next()) {
658     TopoDS_Shape aS1 = anExp1.Current();
659
660     if(aMap1.Contains(aS1))
661       continue;
662     aSeq1.Append(aS1);
663     aMap1.Add(aS1);
664   }
665
666   for(; anExp2.More(); anExp2.Next()) {
667     TopoDS_Shape aS2 = anExp2.Current();
668     if(aMap2.Contains(aS2))
669       continue;
670     aSeq2.Append(aS2);
671     aMap2.Add(aS2);
672   }
673
674   TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
675   Standard_Integer i = 0, j = 0;
676   for(i = 1; i <= aSeq1.Length(); i++)
677     for(j = 1; j <= aSeq2.Length(); j++)
678       anArrayOfFlag.SetValue(i, j, Standard_False);
679
680   for(i = 1; i <= aSeq1.Length(); i++) {
681     TopoDS_Shape aS1 = aSeq1.Value(i);
682     BOPCol_ListOfShape aListOfS2;
683     Standard_Integer nbs = 0;
684
685     for(j = 1; j <= aSeq2.Length(); j++) {
686       TopoDS_Shape aS2 = aSeq2.Value(j);
687       Standard_Boolean bIsEqual = Standard_False;
688
689       if(theType == TopAbs_VERTEX) {
690
691         TopoDS_Vertex aV1 = TopoDS::Vertex(aS1);
692         TopoDS_Vertex aV2 = TopoDS::Vertex(aS2);
693         gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
694         gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
695         Standard_Real aDist = aP1.Distance(aP2);
696
697         if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
698           bIsEqual = Standard_True;
699         }
700       }
701       else if(theType == TopAbs_EDGE) {
702         Standard_Integer aDiscretize = 30;
703         Standard_Real    aDeflection = 0.01;
704         TopoDS_Edge aE1 = TopoDS::Edge(aS1);
705         TopoDS_Edge aE2 = TopoDS::Edge(aS2);
706         
707         IntTools_EdgeEdge aEE;
708         aEE.SetEdge1 (aE1);
709         aEE.SetEdge2 (aE2);
710         aEE.SetTolerance1 (BRep_Tool::Tolerance(aE1));
711         aEE.SetTolerance2 (BRep_Tool::Tolerance(aE2));
712         aEE.SetDiscretize (aDiscretize);
713         aEE.SetDeflection (aDeflection);
714         
715         Standard_Real f = 0., l = 0.;
716         BRep_Tool::Range(aE1, f, l);
717         aEE.SetRange1(f, l);
718         
719         BRep_Tool::Range(aE2, f, l);
720         aEE.SetRange2(f, l);
721         
722         aEE.Perform();
723         
724         if (aEE.IsDone()) {
725           const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
726           Standard_Integer ii = 0;
727           
728           for (ii = 1; ii <= aCPrts.Length(); ii++) {
729             const IntTools_CommonPrt& aCPart = aCPrts(ii);
730             
731             if (aCPart.Type() == TopAbs_EDGE) {
732               bIsEqual = Standard_True;
733             }
734           }
735         }
736       }
737       else if(theType == TopAbs_FACE) {
738         // not yet implemented!
739       }
740
741       if(bIsEqual) {
742         anArrayOfFlag.SetValue(i, j, Standard_True );
743         aListOfS2.Append(aS2);
744         nbs++;
745       }
746     }
747
748     if(nbs > 1) {
749       BOPAlgo_CheckResult aResult;
750
751       aResult.SetShape1(myShape1);
752       aResult.SetShape2(myShape2);
753       aResult.AddFaultyShape1(aS1);
754       BOPCol_ListIteratorOfListOfShape anIt(aListOfS2);
755
756       for(; anIt.More(); anIt.Next()) {
757         aResult.AddFaultyShape2(anIt.Value());
758       }
759
760       aResult.SetCheckStatus(aStatus);
761       myResult.Append(aResult);
762
763       if(myStopOnFirst) {
764         return;
765       }
766     }
767   }
768
769   for(i = 1; i <= aSeq2.Length(); i++) {
770     TopoDS_Shape aS2 = aSeq2.Value(i);
771     BOPCol_ListOfShape aListOfS1;
772     Standard_Integer nbs = 0;
773
774     for(j = 1; j <= aSeq1.Length(); j++) {
775       TopoDS_Shape aS1 = aSeq1.Value(j);
776
777       if(anArrayOfFlag.Value(j, i)) {
778         aListOfS1.Append(aS1);
779         nbs++;
780       }
781     }
782     
783     if(nbs > 1) {
784       BOPAlgo_CheckResult aResult;
785
786       aResult.SetShape1(myShape1);
787       aResult.SetShape2(myShape2);
788       BOPCol_ListIteratorOfListOfShape anIt(aListOfS1);
789
790       for(; anIt.More(); anIt.Next()) {
791         aResult.AddFaultyShape1(anIt.Value());
792       }
793       aResult.AddFaultyShape2(aS2);
794
795       aResult.SetCheckStatus(aStatus);
796       myResult.Append(aResult);
797
798       if(myStopOnFirst) {
799         return;
800       }
801     }
802   }
803 }
804
805 // ================================================================================
806 // function: TestMergeVertex
807 // purpose:
808 // ================================================================================
809 void BOPAlgo_ArgumentAnalyzer::TestMergeVertex() 
810 {
811   TestMergeSubShapes(TopAbs_VERTEX); 
812 }
813
814 // ================================================================================
815 // function: TestMergeEdge
816 // purpose:
817 // ================================================================================
818 void BOPAlgo_ArgumentAnalyzer::TestMergeEdge() 
819 {
820   TestMergeSubShapes(TopAbs_EDGE); 
821 }
822
823 // ================================================================================
824 // function: TestMergeFace
825 // purpose:
826 // ================================================================================
827 // void BOPAlgo_ArgumentAnalyzer::TestMergeFace() 
828 // {
829   // not implemented
830 // }