0030386: Modeling Algorithms - Unable to perform Cut operation
[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 under
7 // the terms of the GNU Lesser General Public License 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.hxx>
16 #include <BOPAlgo_BuilderFace.hxx>
17 #include <BOPAlgo_CheckerSI.hxx>
18 #include <BOPAlgo_Operation.hxx>
19 #include <BOPDS_DS.hxx>
20 #include <BOPDS_MapOfPair.hxx>
21 #include <BOPTools_AlgoTools.hxx>
22 #include <BOPTools_AlgoTools3D.hxx>
23 #include <BRep_Builder.hxx>
24 #include <BRep_TEdge.hxx>
25 #include <BRep_TFace.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_TVertex.hxx>
28 #include <BRepExtrema_DistShapeShape.hxx>
29 #include <Geom_Surface.hxx>
30 #include <gp_Pnt.hxx>
31 #include <IntTools_CommonPrt.hxx>
32 #include <IntTools_Context.hxx>
33 #include <IntTools_EdgeEdge.hxx>
34 #include <IntTools_Range.hxx>
35 #include <Standard_ErrorHandler.hxx>
36 #include <Standard_Failure.hxx>
37 #include <TColStd_Array2OfBoolean.hxx>
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Edge.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Shell.hxx>
44 #include <TopoDS_Solid.hxx>
45 #include <TopoDS_Vertex.hxx>
46 #include <TopoDS_Wire.hxx>
47 #include <TopTools_IndexedMapOfShape.hxx>
48 #include <TopTools_ListOfShape.hxx>
49 #include <TopTools_MapOfShape.hxx>
50 #include <TopTools_SequenceOfShape.hxx>
51
52 // ================================================================================
53 // function: Constructor
54 // purpose:
55 // ================================================================================
56 BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() : 
57 BOPAlgo_Algo(),
58 myStopOnFirst(Standard_False),
59 myOperation(BOPAlgo_UNKNOWN),
60 myArgumentTypeMode(Standard_False),
61 mySelfInterMode(Standard_False),
62 mySmallEdgeMode(Standard_False),
63 myRebuildFaceMode(Standard_False),
64 myTangentMode(Standard_False),
65 myMergeVertexMode(Standard_False),
66 myMergeEdgeMode(Standard_False),
67 myContinuityMode(Standard_False),
68 myCurveOnSurfaceMode(Standard_False),
69 myEmpty1(Standard_False),
70 myEmpty2(Standard_False)
71 {
72 }
73 //=======================================================================
74 // function: ~
75 // purpose: 
76 //=======================================================================
77 BOPAlgo_ArgumentAnalyzer::~BOPAlgo_ArgumentAnalyzer()
78 {
79   myResult.Clear();
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     UserBreak();
161     //
162     // 1. Prepare
163     Prepare();
164     //
165     UserBreak();
166     //
167     // 2. Test types
168     if(myArgumentTypeMode) {
169       TestTypes();
170     }
171     //
172     UserBreak();
173     //
174     // 3. Test self-interference
175     if(mySelfInterMode) {
176       TestSelfInterferences();
177     }
178     //
179     UserBreak();
180     //
181     // 4. Test small edges
182     if(mySmallEdgeMode) {
183       if(!(!myResult.IsEmpty() && myStopOnFirst))
184         TestSmallEdge();
185     }
186     //
187     UserBreak();
188     //
189     // 5. Test possibility to rebuild faces
190     if(myRebuildFaceMode) {
191       if(!(!myResult.IsEmpty() && myStopOnFirst))
192         TestRebuildFace();
193     }
194     //
195     UserBreak();
196     //
197     // 6. Test tangent
198     if(myTangentMode) {
199       if(!(!myResult.IsEmpty() && myStopOnFirst))
200         TestTangent();
201     }
202     //
203     UserBreak();
204     //
205     // 7. Test merge vertices
206     if(myMergeVertexMode) {
207       if(!(!myResult.IsEmpty() && myStopOnFirst))
208         TestMergeVertex();
209     }
210     //
211     UserBreak();
212     //
213     // 8. Test merge edges
214     if(myMergeEdgeMode) {
215       if(!(!myResult.IsEmpty() && myStopOnFirst))
216         TestMergeEdge();
217     }
218     //
219     UserBreak();
220     //
221     // 9. Test shapes continuity
222     if(myContinuityMode) {
223       if(!(!myResult.IsEmpty() && myStopOnFirst))
224         TestContinuity();
225     }
226     //
227     UserBreak();
228     //
229     // 10. Test validity of the curves on the surfaces
230     if(myCurveOnSurfaceMode) {
231       if(!(!myResult.IsEmpty() && myStopOnFirst))
232         TestCurveOnSurface();
233     }
234   }
235   catch(Standard_Failure const&) {
236     BOPAlgo_CheckResult aResult;
237     aResult.SetCheckStatus(BOPAlgo_CheckUnknown);
238     myResult.Append(aResult);
239   }
240 }
241
242 // ================================================================================
243 // function: HasFaulty
244 // purpose:
245 // ================================================================================
246 Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const
247 {
248   return ( !myResult.IsEmpty());
249 }
250
251 // ================================================================================
252 // function: GetCheckResult
253 // purpose:
254 // ================================================================================
255 const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const
256 {
257   return myResult;
258 }
259
260 // ================================================================================
261 // function: TestTypes
262 // purpose:
263 // ================================================================================
264 void BOPAlgo_ArgumentAnalyzer::TestTypes()
265 {
266   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
267
268   if(isS1 && isS2) {
269     BOPAlgo_CheckResult aResult;
270     aResult.SetCheckStatus(BOPAlgo_BadType);
271     myResult.Append(aResult);
272     return;
273   }
274
275   //single shape check
276   if((isS1 && !isS2) || (!isS1 && isS2)) {
277     Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1;
278
279     if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) {
280       const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1;
281       BOPAlgo_CheckResult aResult;
282       aResult.SetShape1(aS);
283       aResult.SetCheckStatus(BOPAlgo_BadType);
284       myResult.Append(aResult);
285       return;
286     }
287   }
288   // two shapes check (begin)
289   else {
290     if(myEmpty1 || myEmpty2) {
291       BOPAlgo_CheckResult aResult;
292       if(myEmpty1 && myEmpty2) {
293         aResult.SetShape1(myShape1);
294         aResult.SetShape2(myShape2);
295       }
296       else {
297         const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2;
298         if(myEmpty1)
299           aResult.SetShape1(aS);
300         else
301           aResult.SetShape2(aS);
302       }
303       aResult.SetCheckStatus(BOPAlgo_BadType);
304       myResult.Append(aResult);
305       return;
306     }
307     //
308     if (myOperation != BOPAlgo_UNKNOWN &&
309         myOperation != BOPAlgo_COMMON)
310     {
311       Standard_Integer iDimMin[2], iDimMax[2];
312       BOPTools_AlgoTools::Dimensions(myShape1, iDimMin[0], iDimMax[0]);
313       BOPTools_AlgoTools::Dimensions(myShape2, iDimMin[1], iDimMax[1]);
314
315       Standard_Boolean bBadTypes =
316         ((myOperation == BOPAlgo_FUSE) &&
317            (iDimMin[0] != iDimMax[0] || iDimMin[1] != iDimMax[1] || iDimMin[0] != iDimMin[1])) ||
318         ((myOperation == BOPAlgo_CUT)   && (iDimMax[0] > iDimMin[1])) ||
319         ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1]));
320
321       if (bBadTypes) {
322         BOPAlgo_CheckResult aResult;
323         aResult.SetShape1(myShape1);
324         aResult.SetShape2(myShape2);
325         aResult.SetCheckStatus(BOPAlgo_BadType);
326         myResult.Append(aResult);
327       }
328     }
329   }
330 }
331 //=======================================================================
332 //function : TestSelfInterferences
333 //purpose  : 
334 //=======================================================================
335 void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
336 {
337   Standard_Integer ii;
338   //
339   for(ii = 0; ii < 2; ii++) {
340     const TopoDS_Shape& aS = (ii == 0) ? myShape1 : myShape2;
341     if(aS.IsNull()) {
342       continue;
343     }
344     //
345     Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2;
346     if (bIsEmpty) {
347       continue;
348     }
349     //
350     Standard_Integer n1, n2;
351     BOPDS_MapIteratorOfMapOfPair aItMPK;
352     TopTools_ListOfShape anArgs;
353     BOPAlgo_CheckerSI aChecker;
354     //
355     anArgs.Append(aS);
356     aChecker.SetArguments(anArgs);
357     aChecker.SetNonDestructive(Standard_True);
358     aChecker.SetRunParallel(myRunParallel);
359     aChecker.SetFuzzyValue(myFuzzyValue);
360     aChecker.SetProgressIndicator(myProgressIndicator);
361     //
362     aChecker.Perform();
363     Standard_Boolean hasError = aChecker.HasErrors();
364     //
365     const BOPDS_DS& aDS=*(aChecker.PDS());
366     const BOPDS_MapOfPair& aMPK=aDS.Interferences();
367     //
368     aItMPK.Initialize(aMPK);
369     for (; aItMPK.More(); aItMPK.Next()) {
370       const BOPDS_Pair& aPK=aItMPK.Value();
371       aPK.Indices(n1, n2);
372       if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
373         continue;
374       }
375       //
376       const TopoDS_Shape& aS1=aDS.Shape(n1);
377       const TopoDS_Shape& aS2=aDS.Shape(n2);
378       //
379       BOPAlgo_CheckResult aResult;
380       if(ii == 0) {
381         aResult.SetShape1(myShape1);
382         aResult.AddFaultyShape1(aS1);
383         if (!aS1.IsSame(aS2))
384           aResult.AddFaultyShape1(aS2);
385       }
386       else {
387         aResult.SetShape2(myShape2);
388         aResult.AddFaultyShape2(aS1);
389         if (!aS1.IsSame(aS2))
390           aResult.AddFaultyShape2(aS2);
391       }
392       aResult.SetCheckStatus(BOPAlgo_SelfIntersect);
393       myResult.Append(aResult);
394     }
395     //
396     if (hasError) {
397       BOPAlgo_CheckResult aResult;
398       if(ii == 0) {
399         aResult.SetShape1(myShape1);
400         aResult.AddFaultyShape1(myShape1);
401       }
402       else {
403         aResult.SetShape2(myShape2);
404         aResult.AddFaultyShape2(myShape2);
405       }
406       aResult.SetCheckStatus(BOPAlgo_OperationAborted);
407       myResult.Append(aResult);
408     }
409   }// for(ii = 0; ii < 2; ii++) {
410 }
411 // ================================================================================
412 // function: TestSmallEdge
413 // purpose:
414 // ================================================================================
415 void BOPAlgo_ArgumentAnalyzer::TestSmallEdge() 
416 {
417   Standard_Integer i = 0;
418   BRepExtrema_DistShapeShape aDist;
419   Handle(IntTools_Context) aCtx;
420   //
421   aCtx = new IntTools_Context;
422   
423   for(i = 0; i < 2; i++) {
424     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
425
426     if(aS.IsNull())
427       continue;
428
429     TopExp_Explorer anExp(aS, TopAbs_EDGE);
430
431     for(; anExp.More(); anExp.Next()) {
432       const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&anExp.Current();
433       if (BRep_Tool::Degenerated(anEdge)) {
434         continue;
435       }
436
437       if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
438         Standard_Boolean bKeepResult = Standard_True;
439         
440         if(myOperation == BOPAlgo_SECTION) {
441           const TopoDS_Shape& anOtherS = (i == 0) ? myShape2 : myShape1;
442           
443           if(!anOtherS.IsNull()) {
444             aDist.LoadS2(anOtherS);
445             
446             Standard_Boolean bVertexIsOnShape = Standard_False;
447             Standard_Integer ii = 0;
448             TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
449             
450             for(; anExpV.More(); anExpV.Next()) {
451               const TopoDS_Shape& aV = anExpV.Current();
452               
453               aDist.LoadS1(aV);
454               aDist.Perform();
455               
456               if(aDist.IsDone()) {
457                 
458                 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
459                   Standard_Real aTolerance = BRep_Tool::Tolerance(*(TopoDS_Vertex*)&aV);
460                   const TopoDS_Shape& aSupportShape = aDist.SupportOnShape2(ii);
461                   
462                   switch(aSupportShape.ShapeType()) {
463                   case TopAbs_VERTEX: {
464                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Vertex*)&(aSupportShape));
465                     break;
466                   }
467                   case TopAbs_EDGE: {
468                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Edge*)&(aSupportShape));
469                     break;
470                   }
471                   case TopAbs_FACE: {
472                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Face*)&(aSupportShape));
473                     break;
474                   }
475                   default:
476                     break;
477                   }
478                   
479                   if(aDist.Value() < aTolerance) {
480                     bVertexIsOnShape = Standard_True;
481                     break;
482                   }
483                 }
484               }
485             }
486             
487             if(!bVertexIsOnShape) {
488               bKeepResult = Standard_False;
489             }
490           }
491         }
492         
493         if(bKeepResult) {
494           BOPAlgo_CheckResult aResult;
495           
496           if(i == 0) {
497             aResult.SetShape1(myShape1);
498             aResult.AddFaultyShape1(anEdge);
499           }
500           else {
501             aResult.SetShape2(myShape2);
502             aResult.AddFaultyShape2(anEdge);
503           }
504           
505           aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
506           myResult.Append(aResult);
507           
508           if(myStopOnFirst) {
509             return;
510           }
511         }
512       }
513     }
514   }
515 }
516 // ================================================================================
517 // function: TestRebuildFace
518 // purpose:
519 // ================================================================================
520 void BOPAlgo_ArgumentAnalyzer::TestRebuildFace() 
521 {
522   if((myOperation == BOPAlgo_SECTION) ||
523      (myOperation == BOPAlgo_UNKNOWN))
524     return;
525   Standard_Integer i = 0;
526
527   for(i = 0; i < 2; i++) {
528     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
529
530     if(aS.IsNull())
531       continue;
532
533     TopExp_Explorer anExp(aS, TopAbs_FACE);
534     TopTools_ListOfShape aLS;
535
536     for(; anExp.More(); anExp.Next()) {
537       const TopoDS_Face& aFace = *(TopoDS_Face*)&(anExp.Current());
538
539       TopoDS_Face aFF = aFace;
540       aFF.Orientation(TopAbs_FORWARD);
541       TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
542       Standard_Integer nbstartedges = 0;
543       aLS.Clear();
544       //
545       for(; anExpE.More(); anExpE.Next()) {
546         const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
547         TopAbs_Orientation anOriE=aE.Orientation();
548         //
549         if (anOriE==TopAbs_INTERNAL) {
550           TopoDS_Edge aEE=aE;
551           aEE.Orientation(TopAbs_FORWARD);
552           aLS.Append(aEE);
553           aEE.Orientation(TopAbs_REVERSED);
554           aLS.Append(aEE);
555         }
556         else {
557           aLS.Append(aE);
558         }
559         nbstartedges++;
560       }
561       BOPAlgo_BuilderFace aBF;
562       aBF.SetFace(aFace);
563       aBF.SetShapes(aLS);
564       aBF.Perform();
565       const TopTools_ListOfShape& aLF = aBF.Areas();
566       Standard_Boolean bBadFace = Standard_False;
567
568       if(aLF.Extent() != 1) {
569         bBadFace = Standard_True;
570       }
571       else {
572         Standard_Integer nbedgeused = 0;
573         anExpE.Init(aLF.First(), TopAbs_EDGE);
574         
575         for(; anExpE.More(); anExpE.Next(), nbedgeused++);
576         
577         if(nbstartedges != nbedgeused) {
578           bBadFace = Standard_True;
579         }
580       }
581
582       if(bBadFace) {
583         BOPAlgo_CheckResult aResult;
584         
585         if(i == 0) {
586           aResult.SetShape1(myShape1);
587           aResult.AddFaultyShape1(aFace);
588         }
589         else {
590           aResult.SetShape2(myShape2);
591           aResult.AddFaultyShape2(aFace);
592         }
593         
594         aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
595         myResult.Append(aResult);
596         
597         if(myStopOnFirst) {
598           return;
599         }
600       }
601     }
602   }
603 }
604
605 // ================================================================================
606 // function: TestTangent
607 // purpose:
608 // ================================================================================
609 void BOPAlgo_ArgumentAnalyzer::TestTangent() 
610 {
611  // not implemented
612 }
613
614 // ================================================================================
615 // function: TestMergeSubShapes
616 // purpose:
617 // ================================================================================
618  void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) 
619 {
620   if(myShape1.IsNull() || myShape2.IsNull())
621     return;
622
623   if (myEmpty1 || myEmpty2) 
624     return;
625
626   BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
627
628   switch(theType) {
629   case TopAbs_VERTEX: {
630     aStatus = BOPAlgo_IncompatibilityOfVertex;
631     break;
632   }
633   case TopAbs_EDGE: {
634     aStatus = BOPAlgo_IncompatibilityOfEdge;
635     break;
636   }
637   case TopAbs_FACE: {
638     aStatus = BOPAlgo_IncompatibilityOfFace;
639     break;
640   }
641   default: 
642     return;
643   }
644   TopExp_Explorer anExp1(myShape1, theType);
645   TopExp_Explorer anExp2(myShape2, theType);
646   TopTools_SequenceOfShape aSeq1, aSeq2;
647   TopTools_MapOfShape aMap1, aMap2;
648
649   for(; anExp1.More(); anExp1.Next()) {
650     const TopoDS_Shape& aS1 = anExp1.Current();
651
652     if(aMap1.Contains(aS1))
653       continue;
654     aSeq1.Append(aS1);
655     aMap1.Add(aS1);
656   }
657
658   for(; anExp2.More(); anExp2.Next()) {
659     const TopoDS_Shape& aS2 = anExp2.Current();
660     if(aMap2.Contains(aS2))
661       continue;
662     aSeq2.Append(aS2);
663     aMap2.Add(aS2);
664   }
665
666   TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
667   Standard_Integer i = 0, j = 0;
668   for(i = 1; i <= aSeq1.Length(); i++)
669     for(j = 1; j <= aSeq2.Length(); j++)
670       anArrayOfFlag.SetValue(i, j, Standard_False);
671
672   for(i = 1; i <= aSeq1.Length(); i++) {
673     const TopoDS_Shape& aS1 = aSeq1.Value(i);
674     TopTools_ListOfShape aListOfS2;
675     Standard_Integer nbs = 0;
676
677     for(j = 1; j <= aSeq2.Length(); j++) {
678       const TopoDS_Shape& aS2 = aSeq2.Value(j);
679       Standard_Boolean bIsEqual = Standard_False;
680
681       if(theType == TopAbs_VERTEX) {
682
683         const TopoDS_Vertex& aV1 = *(TopoDS_Vertex*)&(aS1);
684         const TopoDS_Vertex& aV2 = *(TopoDS_Vertex*)&(aS2);
685         gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
686         gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
687         Standard_Real aDist = aP1.Distance(aP2);
688
689         if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
690           bIsEqual = Standard_True;
691         }
692       }
693       else if(theType == TopAbs_EDGE) {
694         const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&(aS1);
695         const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&(aS2);
696         //
697         IntTools_EdgeEdge aEE(aE1, aE2);
698         //
699         aEE.Perform();
700         if (aEE.IsDone()) {
701           const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
702           Standard_Integer ii = 0;
703           
704           for (ii = 1; ii <= aCPrts.Length(); ii++) {
705             const IntTools_CommonPrt& aCPart = aCPrts(ii);
706             
707             if (aCPart.Type() == TopAbs_EDGE) {
708               bIsEqual = Standard_True;
709             }
710           }
711         }
712       }
713       else if(theType == TopAbs_FACE) {
714         // not yet implemented!
715       }
716
717       if(bIsEqual) {
718         anArrayOfFlag.SetValue(i, j, Standard_True );
719         aListOfS2.Append(aS2);
720         nbs++;
721       }
722     }
723
724     if(nbs > 1) {
725       BOPAlgo_CheckResult aResult;
726
727       aResult.SetShape1(myShape1);
728       aResult.SetShape2(myShape2);
729       aResult.AddFaultyShape1(aS1);
730       TopTools_ListIteratorOfListOfShape anIt(aListOfS2);
731
732       for(; anIt.More(); anIt.Next()) {
733         aResult.AddFaultyShape2(anIt.Value());
734       }
735
736       aResult.SetCheckStatus(aStatus);
737       myResult.Append(aResult);
738
739       if(myStopOnFirst) {
740         return;
741       }
742     }
743   }
744
745   for(i = 1; i <= aSeq2.Length(); i++) {
746     const TopoDS_Shape& aS2 = aSeq2.Value(i);
747     TopTools_ListOfShape aListOfS1;
748     Standard_Integer nbs = 0;
749
750     for(j = 1; j <= aSeq1.Length(); j++) {
751       const TopoDS_Shape& aS1 = aSeq1.Value(j);
752
753       if(anArrayOfFlag.Value(j, i)) {
754         aListOfS1.Append(aS1);
755         nbs++;
756       }
757     }
758     
759     if(nbs > 1) {
760       BOPAlgo_CheckResult aResult;
761
762       aResult.SetShape1(myShape1);
763       aResult.SetShape2(myShape2);
764       TopTools_ListIteratorOfListOfShape anIt(aListOfS1);
765
766       for(; anIt.More(); anIt.Next()) {
767         aResult.AddFaultyShape1(anIt.Value());
768       }
769       aResult.AddFaultyShape2(aS2);
770
771       aResult.SetCheckStatus(aStatus);
772       myResult.Append(aResult);
773
774       if(myStopOnFirst) {
775         return;
776       }
777     }
778   }
779 }
780
781 // ================================================================================
782 // function: TestMergeVertex
783 // purpose:
784 // ================================================================================
785 void BOPAlgo_ArgumentAnalyzer::TestMergeVertex() 
786 {
787   TestMergeSubShapes(TopAbs_VERTEX); 
788 }
789
790 // ================================================================================
791 // function: TestMergeEdge
792 // purpose:
793 // ================================================================================
794 void BOPAlgo_ArgumentAnalyzer::TestMergeEdge() 
795 {
796   TestMergeSubShapes(TopAbs_EDGE); 
797 }
798
799 // ================================================================================
800 // function: TestContinuity
801 // purpose:
802 // ================================================================================
803 void BOPAlgo_ArgumentAnalyzer::TestContinuity() 
804 {
805   Standard_Integer i, j, aNbS;
806   Standard_Real f, l;
807   TopExp_Explorer aExp;
808   //
809   for (i = 0; i < 2; ++i) {
810     const TopoDS_Shape& aS = !i ? myShape1 : myShape2;
811     if(aS.IsNull()) {
812       continue;
813     }
814     //
815     TopTools_IndexedMapOfShape aMS;
816     //Edges
817     aExp.Init(aS, TopAbs_EDGE);
818     for (; aExp.More(); aExp.Next()) {
819       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
820       if (BRep_Tool::Degenerated(aE)) {
821         continue;
822       }
823       const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, f, l);
824       if (aC->Continuity() == GeomAbs_C0) {
825         aMS.Add(aE);
826       }
827     }
828     //Faces
829     aExp.Init(aS, TopAbs_FACE);
830     for (; aExp.More(); aExp.Next()) {
831       const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
832       Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aF);
833       if (aSurf->Continuity() == GeomAbs_C0) {
834         aMS.Add(aF);
835       }
836     }
837     //
838     //add shapes with continuity C0 to result
839     aNbS = aMS.Extent();
840     for (j = 1; j <= aNbS; ++j) {
841       const TopoDS_Shape& aFS = aMS(j);
842       BOPAlgo_CheckResult aResult;
843       if(i == 0) {
844         aResult.SetShape1(myShape1);
845         aResult.AddFaultyShape1(aFS);
846       } else {
847         aResult.SetShape2(myShape2);
848         aResult.AddFaultyShape2(aFS);
849       }
850       aResult.SetCheckStatus(BOPAlgo_GeomAbs_C0);
851       myResult.Append(aResult);
852     }
853   }
854 }
855
856 // ================================================================================
857 // function: TestCurveOnSurface
858 // purpose:
859 // ================================================================================
860 void BOPAlgo_ArgumentAnalyzer::TestCurveOnSurface()
861 {
862   Standard_Integer i;
863   Standard_Real aT, aD, aTolE;
864   TopExp_Explorer aExpF, aExpE;
865   //
866   for(i = 0; i < 2; i++) {
867     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
868     if(aS.IsNull()) {
869       continue;
870     }
871     //
872     aExpF.Init(aS, TopAbs_FACE);
873     for (; aExpF.More(); aExpF.Next()) {
874       const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
875       //
876       aExpE.Init(aF, TopAbs_EDGE);
877       for (; aExpE.More(); aExpE.Next()) {
878         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
879         //
880         if (BOPTools_AlgoTools::ComputeTolerance(aF, aE, aD, aT)) {
881           aTolE = BRep_Tool::Tolerance(aE);
882           if (aD > aTolE) {
883             BOPAlgo_CheckResult aResult;
884             aResult.SetCheckStatus(BOPAlgo_InvalidCurveOnSurface);
885             if(i == 0) {
886               aResult.SetShape1(myShape1);
887               aResult.AddFaultyShape1(aE);
888               aResult.AddFaultyShape1(aF);
889               aResult.SetMaxDistance1(aD);
890               aResult.SetMaxParameter1(aT);
891             }
892             else {
893               aResult.SetShape2(myShape2);
894               aResult.AddFaultyShape2(aE);
895               aResult.AddFaultyShape2(aF);
896               aResult.SetMaxDistance2(aD);
897               aResult.SetMaxParameter2(aT);
898             }
899             myResult.Append(aResult);
900           }
901         }
902       }
903     }
904   }
905 }