c715e0598460f3888d657bf2389a8a24c7d67888
[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 // ================================================================================
301 // function: TestSelfInterferences
302 // purpose:
303 // ================================================================================
304 void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
305 {
306   Standard_Integer ii = 0, j;
307   Standard_Boolean bSelfInt;
308
309   for(ii = 0; ii < 2; ii++) {
310     const TopoDS_Shape& aS = (ii == 0) ? myShape1 : myShape2;
311
312     if(aS.IsNull())
313       continue;
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     anArgs.Append(aS);
323     aChecker.SetArguments(anArgs);
324     //
325     aChecker.Perform();
326     Standard_Integer iErr = aChecker.ErrorStatus();
327     //
328     const BOPDS_PDS& theDS = aChecker.PDS();
329     BOPDS_VectorOfInterfVV& aVVs=theDS->InterfVV();
330     BOPDS_VectorOfInterfVE& aVEs=theDS->InterfVE();
331     BOPDS_VectorOfInterfEE& aEEs=theDS->InterfEE();
332     BOPDS_VectorOfInterfVF& aVFs=theDS->InterfVF();
333     BOPDS_VectorOfInterfEF& aEFs=theDS->InterfEF();
334     BOPDS_VectorOfInterfFF& aFFs=theDS->InterfFF();
335     //
336     Standard_Integer aNb[6] = {aVVs.Extent(), aVEs.Extent(), aEEs.Extent(), 
337                                aVFs.Extent(), aEFs.Extent(), aFFs.Extent()};
338     //
339     for (Standard_Integer aTypeInt = 0; aTypeInt < 6; ++aTypeInt) {
340       for (Standard_Integer i = 0; i < aNb[aTypeInt]; ++i) {
341         BOPDS_Interf* aInt = (aTypeInt==0) ? (BOPDS_Interf*)(&aVVs(i)) : 
342           ((aTypeInt==1) ? (BOPDS_Interf*)(&aVEs(i)) :
343            ((aTypeInt==2) ? (BOPDS_Interf*)(&aEEs(i)) : 
344             ((aTypeInt==3) ? (BOPDS_Interf*)(&aVFs(i)) :
345              ((aTypeInt==4) ? (BOPDS_Interf*)(&aEFs(i)) : (BOPDS_Interf*)(&aFFs(i))))));
346         //
347         Standard_Integer nI1 = aInt->Index1();
348         Standard_Integer nI2 = aInt->Index2();
349         if (nI1 == nI2) {
350           continue;
351         }
352         //
353         if (aTypeInt == 4) {
354           BOPDS_InterfEF& aEF=aEFs(i);
355           if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
356             continue;
357           }
358         }
359         //
360         const TopoDS_Shape& aS1 = theDS->Shape(nI1);
361         const TopoDS_Shape& aS2 = theDS->Shape(nI2);
362         //
363         if (aTypeInt == 5) {
364           bSelfInt = Standard_False;
365           BOPDS_InterfFF& aFF = aFFs(i);
366           BOPDS_VectorOfPoint& aVP=aFF.ChangePoints();
367           Standard_Integer aNbP=aVP.Extent();
368           BOPDS_VectorOfCurve& aVC=aFF.ChangeCurves();
369           Standard_Integer aNbC=aVC.Extent();
370           if (!aNbP && !aNbC) {
371             continue;
372           }
373           for (j=0; j<aNbC; ++j) {
374             BOPDS_Curve& aNC=aVC(j);
375             BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
376             if (aLPBC.Extent()) {
377               bSelfInt = Standard_True;
378               break;
379             }
380           }
381           if (!bSelfInt) {
382             continue;
383           }
384         }
385         //
386         BOPAlgo_CheckResult aResult;
387         if(ii == 0) {
388           aResult.SetShape1(myShape1);
389           aResult.AddFaultyShape1(aS1);
390           aResult.AddFaultyShape1(aS2);
391         }
392         else {
393           aResult.SetShape2(myShape2);
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         aResult.AddFaultyShape1(myShape1);
406       }
407       else {
408         aResult.SetShape2(myShape2);
409         aResult.AddFaultyShape2(myShape2);
410       }
411       aResult.SetCheckStatus(BOPAlgo_OperationAborted);
412       myResult.Append(aResult);
413     }
414   }
415   
416 }
417
418 // ================================================================================
419 // function: TestSmallEdge
420 // purpose:
421 // ================================================================================
422 void BOPAlgo_ArgumentAnalyzer::TestSmallEdge() 
423 {
424   Standard_Integer i = 0;
425   BRepExtrema_DistShapeShape aDist;
426   Handle(BOPInt_Context) aCtx;
427   //
428   aCtx = new BOPInt_Context;
429   
430   for(i = 0; i < 2; i++) {
431     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
432
433     if(aS.IsNull())
434       continue;
435
436     TopExp_Explorer anExp(aS, TopAbs_EDGE);
437
438     for(; anExp.More(); anExp.Next()) {
439       const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&anExp.Current();
440       if (BRep_Tool::Degenerated(anEdge)) {
441         continue;
442       }
443
444       if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
445         Standard_Boolean bKeepResult = Standard_True;
446         
447         if(myOperation == BOPAlgo_SECTION) {
448           const 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               const 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                   const 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     const 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       const 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     const 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     const 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     const 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       const TopoDS_Shape& aS2 = aSeq2.Value(j);
687       Standard_Boolean bIsEqual = Standard_False;
688
689       if(theType == TopAbs_VERTEX) {
690
691         const TopoDS_Vertex& aV1 = *(TopoDS_Vertex*)&(aS1);
692         const 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         const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&(aS1);
705         const 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     const 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       const 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: TestContinuity
825 // purpose:
826 // ================================================================================
827 void BOPAlgo_ArgumentAnalyzer::TestContinuity() 
828 {
829   Standard_Integer i;
830   Standard_Real f, l;
831   TopExp_Explorer aExp;
832   BOPCol_MapIteratorOfMapOfShape aIt;
833   //
834   for (i = 0; i < 2; ++i) {
835     const TopoDS_Shape& aS = !i ? myShape1 : myShape2;
836     if(aS.IsNull()) {
837       continue;
838     }
839     //
840     BOPCol_MapOfShape aMS;
841     //Edges
842     aExp.Init(aS, TopAbs_EDGE);
843     for (; aExp.More(); aExp.Next()) {
844       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
845       if (BRep_Tool::Degenerated(aE)) {
846         continue;
847       }
848       const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, f, l);
849       if (aC->Continuity() == GeomAbs_C0) {
850         aMS.Add(aE);
851       }
852     }
853     //Faces
854     aExp.Init(aS, TopAbs_FACE);
855     for (; aExp.More(); aExp.Next()) {
856       const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
857       const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF);
858       if (aS->Continuity() == GeomAbs_C0) {
859         aMS.Add(aF);
860       }
861     }
862     //
863     //add shapes with continuity C0 to result
864     aIt.Initialize(aMS);
865     for (; aIt.More(); aIt.Next()) {
866       const TopoDS_Shape& aFS = aIt.Value();
867       BOPAlgo_CheckResult aResult;
868       if(i == 0) {
869         aResult.SetShape1(myShape1);
870         aResult.AddFaultyShape1(aFS);
871       } else {
872         aResult.SetShape2(myShape2);
873         aResult.AddFaultyShape2(aFS);
874       }
875       aResult.SetCheckStatus(BOPAlgo_GeomAbs_C0);
876       myResult.Append(aResult);
877     }
878   }
879 }
880
881 // ================================================================================
882 // function: TestMergeFace
883 // purpose:
884 // ================================================================================
885 // void BOPAlgo_ArgumentAnalyzer::TestMergeFace() 
886 // {
887   // not implemented
888 // }