0024002: Overall code and build procedure refactoring -- automatic
[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
16 #include <BOPAlgo_ArgumentAnalyzer.hxx>
17 #include <BOPAlgo_BuilderFace.hxx>
18 #include <BOPAlgo_CheckerSI.hxx>
19 #include <BOPAlgo_Operation.hxx>
20 #include <BOPCol_ListOfShape.hxx>
21 #include <BOPCol_MapOfShape.hxx>
22 #include <BOPCol_SequenceOfShape.hxx>
23 #include <BOPDS_DS.hxx>
24 #include <BOPDS_MapOfPassKey.hxx>
25 #include <BOPTools.hxx>
26 #include <BOPTools_AlgoTools.hxx>
27 #include <BOPTools_AlgoTools3D.hxx>
28 #include <BRep_Builder.hxx>
29 #include <BRep_TEdge.hxx>
30 #include <BRep_TFace.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRep_TVertex.hxx>
33 #include <BRepExtrema_DistShapeShape.hxx>
34 #include <Geom_Surface.hxx>
35 #include <gp_Pnt.hxx>
36 #include <IntTools_CommonPrt.hxx>
37 #include <IntTools_Context.hxx>
38 #include <IntTools_EdgeEdge.hxx>
39 #include <IntTools_Range.hxx>
40 #include <Standard_ErrorHandler.hxx>
41 #include <Standard_Failure.hxx>
42 #include <TColStd_Array2OfBoolean.hxx>
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45 #include <TopoDS.hxx>
46 #include <TopoDS_Edge.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopoDS_Shell.hxx>
50 #include <TopoDS_Solid.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <TopoDS_Wire.hxx>
53
54 //
55 // ================================================================================
56 // function: Constructor
57 // purpose:
58 // ================================================================================
59 BOPAlgo_ArgumentAnalyzer::BOPAlgo_ArgumentAnalyzer() : 
60 BOPAlgo_Algo(),
61 myStopOnFirst(Standard_False),
62 myOperation(BOPAlgo_UNKNOWN),
63 myArgumentTypeMode(Standard_False),
64 mySelfInterMode(Standard_False),
65 mySmallEdgeMode(Standard_False),
66 myRebuildFaceMode(Standard_False),
67 myTangentMode(Standard_False),
68 myMergeVertexMode(Standard_False),
69 myMergeEdgeMode(Standard_False),
70 myContinuityMode(Standard_False),
71 myCurveOnSurfaceMode(Standard_False),
72 myEmpty1(Standard_False),
73 myEmpty2(Standard_False),
74 myFuzzyValue(0.)
75 {
76 }
77 //=======================================================================
78 // function: ~
79 // purpose: 
80 //=======================================================================
81 BOPAlgo_ArgumentAnalyzer::~BOPAlgo_ArgumentAnalyzer()
82 {
83   myResult.Clear();
84   myToleranceMap.Clear();
85 }
86
87 // ================================================================================
88 // function: SetShape1
89 // purpose:
90 // ================================================================================
91 void BOPAlgo_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape)
92 {
93   myShape1 = TheShape;
94 }
95
96 // ================================================================================
97 // function: SetShape2
98 // purpose:
99 // ================================================================================
100 void BOPAlgo_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape)
101 {
102   myShape2 = TheShape;
103 }
104
105 // ================================================================================
106 // function: GetShape1
107 // purpose:
108 // ================================================================================
109 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape1() const
110 {
111   return myShape1;
112 }
113
114 // ================================================================================
115 // function: GetShape2
116 // purpose:
117 // ================================================================================
118 const TopoDS_Shape & BOPAlgo_ArgumentAnalyzer::GetShape2() const
119 {
120   return myShape2;
121 }
122
123 // ================================================================================
124 // function: OperationType
125 // purpose:
126 // ================================================================================
127 BOPAlgo_Operation& BOPAlgo_ArgumentAnalyzer::OperationType() 
128 {
129   return myOperation;
130 }
131
132 // ================================================================================
133 // function: StopOnFirstFaulty
134 // purpose:
135 // ================================================================================
136 Standard_Boolean & BOPAlgo_ArgumentAnalyzer::StopOnFirstFaulty()
137 {
138   return myStopOnFirst;
139 }
140
141 // ================================================================================
142 // function: Prepare
143 // purpose:
144 // ================================================================================
145 void BOPAlgo_ArgumentAnalyzer::Prepare()
146 {
147   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
148   if (!isS1) {
149     myEmpty1 = BOPTools_AlgoTools3D::IsEmptyShape(myShape1);
150   }
151   if (!isS2) {
152     myEmpty2 = BOPTools_AlgoTools3D::IsEmptyShape(myShape2);
153   }
154 }
155 // ================================================================================
156 // function: Perform
157 // purpose:
158 // ================================================================================
159 void BOPAlgo_ArgumentAnalyzer::Perform()
160 {
161   try {
162     OCC_CATCH_SIGNALS
163     myResult.Clear();
164     //
165     UserBreak();
166     //
167     // 1. Prepare
168     Prepare();
169     //
170     UserBreak();
171     //
172     // 2. Update Tolerances according to myFuzzyValue
173     UpdateTolerances();
174     //
175     UserBreak();
176     //
177     // 3. Test types
178     if(myArgumentTypeMode) {
179       TestTypes();
180     }
181     //
182     UserBreak();
183     //
184     // 4. Test self-interference
185     if(mySelfInterMode) {
186       TestSelfInterferences();
187     }
188     //
189     UserBreak();
190     //
191     // 5. Test small edges
192     if(mySmallEdgeMode) {
193       if(!(!myResult.IsEmpty() && myStopOnFirst))
194         TestSmallEdge();
195     }
196     //
197     UserBreak();
198     //
199     // 6. Test possibility to rebuild faces
200     if(myRebuildFaceMode) {
201       if(!(!myResult.IsEmpty() && myStopOnFirst))
202         TestRebuildFace();
203     }
204     //
205     UserBreak();
206     //
207     // 7. Test tangent
208     if(myTangentMode) {
209       if(!(!myResult.IsEmpty() && myStopOnFirst))
210         TestTangent();
211     }
212     //
213     UserBreak();
214     //
215     // 8. Test merge vertices
216     if(myMergeVertexMode) {
217       if(!(!myResult.IsEmpty() && myStopOnFirst))
218         TestMergeVertex();
219     }
220     //
221     UserBreak();
222     //
223     // 9. Test merge edges
224     if(myMergeEdgeMode) {
225       if(!(!myResult.IsEmpty() && myStopOnFirst))
226         TestMergeEdge();
227     }
228     //
229     UserBreak();
230     //
231     // 10. Test shapes continuity
232     if(myContinuityMode) {
233       if(!(!myResult.IsEmpty() && myStopOnFirst))
234         TestContinuity();
235     }
236     //
237     UserBreak();
238     //
239     // 11. Test validity of the curves on the surfaces
240     if(myCurveOnSurfaceMode) {
241       if(!(!myResult.IsEmpty() && myStopOnFirst))
242         TestCurveOnSurface();
243     }
244   }
245   catch(Standard_Failure) {
246     BOPAlgo_CheckResult aResult;
247     aResult.SetCheckStatus(BOPAlgo_CheckUnknown);
248     myResult.Append(aResult);
249   }
250   //
251   SetDefaultTolerances();
252 }
253
254 // ================================================================================
255 // function: HasFaulty
256 // purpose:
257 // ================================================================================
258 Standard_Boolean BOPAlgo_ArgumentAnalyzer::HasFaulty() const
259 {
260   return ( !myResult.IsEmpty());
261 }
262
263 // ================================================================================
264 // function: GetCheckResult
265 // purpose:
266 // ================================================================================
267 const BOPAlgo_ListOfCheckResult& BOPAlgo_ArgumentAnalyzer::GetCheckResult() const
268 {
269   return myResult;
270 }
271
272 // ================================================================================
273 // function: TestTypes
274 // purpose:
275 // ================================================================================
276 void BOPAlgo_ArgumentAnalyzer::TestTypes()
277 {
278   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
279
280   if(isS1 && isS2) {
281     BOPAlgo_CheckResult aResult;
282     aResult.SetCheckStatus(BOPAlgo_BadType);
283     myResult.Append(aResult);
284     return;
285   }
286
287   //single shape check
288   if((isS1 && !isS2) || (!isS1 && isS2)) {
289     Standard_Boolean bIsEmpty = (isS1) ? myEmpty2 : myEmpty1;
290
291     if(bIsEmpty || myOperation!=BOPAlgo_UNKNOWN) {
292       const TopoDS_Shape & aS = (isS1) ? myShape2 : myShape1;
293       BOPAlgo_CheckResult aResult;
294       aResult.SetShape1(aS);
295       aResult.SetCheckStatus(BOPAlgo_BadType);
296       myResult.Append(aResult);
297       return;
298     }
299   }
300   // two shapes check (begin)
301   else {
302     if(myEmpty1 || myEmpty2) {
303       BOPAlgo_CheckResult aResult;
304       if(myEmpty1 && myEmpty2) {
305         aResult.SetShape1(myShape1);
306         aResult.SetShape2(myShape2);
307       }
308       else {
309         const TopoDS_Shape & aS = myEmpty1 ? myShape1 : myShape2;
310         if(myEmpty1)
311           aResult.SetShape1(aS);
312         else
313           aResult.SetShape2(aS);
314       }
315       aResult.SetCheckStatus(BOPAlgo_BadType);
316       myResult.Append(aResult);
317       return;
318     }
319     //
320     Standard_Integer aDim1, aDim2;
321     Standard_Boolean bBadTypes = Standard_False;
322     //
323     aDim1 = BOPTools_AlgoTools::Dimension(myShape1);
324     aDim2 = BOPTools_AlgoTools::Dimension(myShape2);
325     if (aDim1 < aDim2) {
326       if (myOperation == BOPAlgo_FUSE ||
327           myOperation == BOPAlgo_CUT21) {
328         bBadTypes = Standard_True;
329       }
330     }
331     else if (aDim1 > aDim2) {
332       if (myOperation == BOPAlgo_FUSE ||
333           myOperation == BOPAlgo_CUT) {
334         bBadTypes = Standard_True;
335       }
336     }
337     if (bBadTypes) {
338       BOPAlgo_CheckResult aResult;
339       aResult.SetShape1(myShape1);
340       aResult.SetShape2(myShape2);
341       aResult.SetCheckStatus(BOPAlgo_BadType);
342       myResult.Append(aResult);
343     }
344   }
345 }
346 //=======================================================================
347 //function : TestSelfInterferences
348 //purpose  : 
349 //=======================================================================
350 void BOPAlgo_ArgumentAnalyzer::TestSelfInterferences()
351 {
352   Standard_Integer ii;
353   //
354   for(ii = 0; ii < 2; ii++) {
355     const TopoDS_Shape& aS = (ii == 0) ? myShape1 : myShape2;
356     if(aS.IsNull()) {
357       continue;
358     }
359     //
360     Standard_Boolean bIsEmpty = (ii == 0) ? myEmpty1 : myEmpty2;
361     if (bIsEmpty) {
362       continue;
363     }
364     //
365     Standard_Integer iErr, n1, n2;
366     BOPDS_MapIteratorMapOfPassKey aItMPK;
367     BOPCol_ListOfShape anArgs;
368     BOPAlgo_CheckerSI aChecker;
369     //
370     anArgs.Append(aS);
371     aChecker.SetArguments(anArgs);
372     aChecker.SetNonDestructive(Standard_True);
373     aChecker.SetRunParallel(myRunParallel);
374     aChecker.SetProgressIndicator(myProgressIndicator);
375     //
376     aChecker.Perform();
377     iErr=aChecker.ErrorStatus();
378     //
379     const BOPDS_DS& aDS=*(aChecker.PDS());
380     const BOPDS_MapOfPassKey& aMPK=aDS.Interferences();
381     //
382     aItMPK.Initialize(aMPK);
383     for (; aItMPK.More(); aItMPK.Next()) {
384       const BOPDS_PassKey& aPK=aItMPK.Value();
385       aPK.Ids(n1, n2);
386       if(aDS.IsNewShape(n1) || aDS.IsNewShape(n2)) {
387         continue;
388       }
389       //
390       const TopoDS_Shape& aS1=aDS.Shape(n1);
391       const TopoDS_Shape& aS2=aDS.Shape(n2);
392       //
393       BOPAlgo_CheckResult aResult;
394       if(ii == 0) {
395         aResult.SetShape1(myShape1);
396         aResult.AddFaultyShape1(aS1);
397         aResult.AddFaultyShape1(aS2);
398       }
399       else {
400         aResult.SetShape2(myShape2);
401         aResult.AddFaultyShape2(aS1);
402         aResult.AddFaultyShape2(aS2);
403       }
404       aResult.SetCheckStatus(BOPAlgo_SelfIntersect);
405       myResult.Append(aResult);
406     }
407     //
408     if (iErr) {
409       BOPAlgo_CheckResult aResult;
410       if(ii == 0) {
411         aResult.SetShape1(myShape1);
412         aResult.AddFaultyShape1(myShape1);
413       }
414       else {
415         aResult.SetShape2(myShape2);
416         aResult.AddFaultyShape2(myShape2);
417       }
418       aResult.SetCheckStatus(BOPAlgo_OperationAborted);
419       myResult.Append(aResult);
420     }
421   }// for(ii = 0; ii < 2; ii++) {
422 }
423 // ================================================================================
424 // function: TestSmallEdge
425 // purpose:
426 // ================================================================================
427 void BOPAlgo_ArgumentAnalyzer::TestSmallEdge() 
428 {
429   Standard_Integer i = 0;
430   BRepExtrema_DistShapeShape aDist;
431   Handle(IntTools_Context) aCtx;
432   //
433   aCtx = new IntTools_Context;
434   
435   for(i = 0; i < 2; i++) {
436     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
437
438     if(aS.IsNull())
439       continue;
440
441     TopExp_Explorer anExp(aS, TopAbs_EDGE);
442
443     for(; anExp.More(); anExp.Next()) {
444       const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&anExp.Current();
445       if (BRep_Tool::Degenerated(anEdge)) {
446         continue;
447       }
448
449       if(BOPTools_AlgoTools::IsMicroEdge(anEdge, aCtx)) {
450         Standard_Boolean bKeepResult = Standard_True;
451         
452         if(myOperation == BOPAlgo_SECTION) {
453           const TopoDS_Shape& anOtherS = (i == 0) ? myShape2 : myShape1;
454           
455           if(!anOtherS.IsNull()) {
456             aDist.LoadS2(anOtherS);
457             
458             Standard_Boolean bVertexIsOnShape = Standard_False;
459             Standard_Integer ii = 0;
460             TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
461             
462             for(; anExpV.More(); anExpV.Next()) {
463               const TopoDS_Shape& aV = anExpV.Current();
464               
465               aDist.LoadS1(aV);
466               aDist.Perform();
467               
468               if(aDist.IsDone()) {
469                 
470                 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
471                   Standard_Real aTolerance = BRep_Tool::Tolerance(*(TopoDS_Vertex*)&aV);
472                   const TopoDS_Shape& aSupportShape = aDist.SupportOnShape2(ii);
473                   
474                   switch(aSupportShape.ShapeType()) {
475                   case TopAbs_VERTEX: {
476                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Vertex*)&(aSupportShape));
477                     break;
478                   }
479                   case TopAbs_EDGE: {
480                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Edge*)&(aSupportShape));
481                     break;
482                   }
483                   case TopAbs_FACE: {
484                     aTolerance += BRep_Tool::Tolerance(*(TopoDS_Face*)&(aSupportShape));
485                     break;
486                   }
487                   default:
488                     break;
489                   }
490                   
491                   if(aDist.Value() < aTolerance) {
492                     bVertexIsOnShape = Standard_True;
493                     break;
494                   }
495                 }
496               }
497             }
498             
499             if(!bVertexIsOnShape) {
500               bKeepResult = Standard_False;
501             }
502           }
503         }
504         
505         if(bKeepResult) {
506           BOPAlgo_CheckResult aResult;
507           
508           if(i == 0) {
509             aResult.SetShape1(myShape1);
510             aResult.AddFaultyShape1(anEdge);
511           }
512           else {
513             aResult.SetShape2(myShape2);
514             aResult.AddFaultyShape2(anEdge);
515           }
516           
517           aResult.SetCheckStatus(BOPAlgo_TooSmallEdge);
518           myResult.Append(aResult);
519           
520           if(myStopOnFirst) {
521             return;
522           }
523         }
524       }
525     }
526   }
527 }
528 // ================================================================================
529 // function: TestRebuildFace
530 // purpose:
531 // ================================================================================
532 void BOPAlgo_ArgumentAnalyzer::TestRebuildFace() 
533 {
534   if((myOperation == BOPAlgo_SECTION) ||
535      (myOperation == BOPAlgo_UNKNOWN))
536     return;
537   Standard_Integer i = 0;
538
539   for(i = 0; i < 2; i++) {
540     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
541
542     if(aS.IsNull())
543       continue;
544
545     TopExp_Explorer anExp(aS, TopAbs_FACE);
546     BOPCol_ListOfShape aLS;
547
548     for(; anExp.More(); anExp.Next()) {
549       const TopoDS_Face& aFace = *(TopoDS_Face*)&(anExp.Current());
550
551       TopoDS_Face aFF = aFace;
552       aFF.Orientation(TopAbs_FORWARD);
553       TopExp_Explorer anExpE(aFF, TopAbs_EDGE);
554       Standard_Integer nbstartedges = 0;
555       aLS.Clear();
556       //
557       for(; anExpE.More(); anExpE.Next()) {
558         const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&anExpE.Current()));
559         TopAbs_Orientation anOriE=aE.Orientation();
560         //
561         if (anOriE==TopAbs_INTERNAL) {
562           TopoDS_Edge aEE=aE;
563           aEE.Orientation(TopAbs_FORWARD);
564           aLS.Append(aEE);
565           aEE.Orientation(TopAbs_REVERSED);
566           aLS.Append(aEE);
567         }
568         else {
569           aLS.Append(aE);
570         }
571         nbstartedges++;
572       }
573       BOPAlgo_BuilderFace aBF;
574       aBF.SetFace(aFace);
575       aBF.SetShapes(aLS);
576       aBF.Perform();
577       const BOPCol_ListOfShape& aLF = aBF.Areas();
578       Standard_Boolean bBadFace = Standard_False;
579
580       if(aLF.Extent() != 1) {
581         bBadFace = Standard_True;
582       }
583       else {
584         Standard_Integer nbedgeused = 0;
585         anExpE.Init(aLF.First(), TopAbs_EDGE);
586         
587         for(; anExpE.More(); anExpE.Next(), nbedgeused++);
588         
589         if(nbstartedges != nbedgeused) {
590           bBadFace = Standard_True;
591         }
592       }
593
594       if(bBadFace) {
595         BOPAlgo_CheckResult aResult;
596         
597         if(i == 0) {
598           aResult.SetShape1(myShape1);
599           aResult.AddFaultyShape1(aFace);
600         }
601         else {
602           aResult.SetShape2(myShape2);
603           aResult.AddFaultyShape2(aFace);
604         }
605         
606         aResult.SetCheckStatus(BOPAlgo_NonRecoverableFace);
607         myResult.Append(aResult);
608         
609         if(myStopOnFirst) {
610           return;
611         }
612       }
613     }
614   }
615 }
616
617 // ================================================================================
618 // function: TestTangent
619 // purpose:
620 // ================================================================================
621 void BOPAlgo_ArgumentAnalyzer::TestTangent() 
622 {
623  // not implemented
624 }
625
626 // ================================================================================
627 // function: TestMergeSubShapes
628 // purpose:
629 // ================================================================================
630  void BOPAlgo_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) 
631 {
632   if(myShape1.IsNull() || myShape2.IsNull())
633     return;
634
635   if (myEmpty1 || myEmpty2) 
636     return;
637
638   BOPAlgo_CheckStatus aStatus = BOPAlgo_CheckUnknown;
639
640   switch(theType) {
641   case TopAbs_VERTEX: {
642     aStatus = BOPAlgo_IncompatibilityOfVertex;
643     break;
644   }
645   case TopAbs_EDGE: {
646     aStatus = BOPAlgo_IncompatibilityOfEdge;
647     break;
648   }
649   case TopAbs_FACE: {
650     aStatus = BOPAlgo_IncompatibilityOfFace;
651     break;
652   }
653   default: 
654     return;
655   }
656   TopExp_Explorer anExp1(myShape1, theType);
657   TopExp_Explorer anExp2(myShape2, theType);
658   BOPCol_SequenceOfShape aSeq1, aSeq2;
659   BOPCol_MapOfShape aMap1, aMap2;
660
661   for(; anExp1.More(); anExp1.Next()) {
662     const TopoDS_Shape& aS1 = anExp1.Current();
663
664     if(aMap1.Contains(aS1))
665       continue;
666     aSeq1.Append(aS1);
667     aMap1.Add(aS1);
668   }
669
670   for(; anExp2.More(); anExp2.Next()) {
671     const TopoDS_Shape& aS2 = anExp2.Current();
672     if(aMap2.Contains(aS2))
673       continue;
674     aSeq2.Append(aS2);
675     aMap2.Add(aS2);
676   }
677
678   TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
679   Standard_Integer i = 0, j = 0;
680   for(i = 1; i <= aSeq1.Length(); i++)
681     for(j = 1; j <= aSeq2.Length(); j++)
682       anArrayOfFlag.SetValue(i, j, Standard_False);
683
684   for(i = 1; i <= aSeq1.Length(); i++) {
685     const TopoDS_Shape& aS1 = aSeq1.Value(i);
686     BOPCol_ListOfShape aListOfS2;
687     Standard_Integer nbs = 0;
688
689     for(j = 1; j <= aSeq2.Length(); j++) {
690       const TopoDS_Shape& aS2 = aSeq2.Value(j);
691       Standard_Boolean bIsEqual = Standard_False;
692
693       if(theType == TopAbs_VERTEX) {
694
695         const TopoDS_Vertex& aV1 = *(TopoDS_Vertex*)&(aS1);
696         const TopoDS_Vertex& aV2 = *(TopoDS_Vertex*)&(aS2);
697         gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
698         gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
699         Standard_Real aDist = aP1.Distance(aP2);
700
701         if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
702           bIsEqual = Standard_True;
703         }
704       }
705       else if(theType == TopAbs_EDGE) {
706         const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&(aS1);
707         const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&(aS2);
708         //
709         IntTools_EdgeEdge aEE(aE1, aE2);
710         //
711         aEE.Perform();
712         if (aEE.IsDone()) {
713           const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
714           Standard_Integer ii = 0;
715           
716           for (ii = 1; ii <= aCPrts.Length(); ii++) {
717             const IntTools_CommonPrt& aCPart = aCPrts(ii);
718             
719             if (aCPart.Type() == TopAbs_EDGE) {
720               bIsEqual = Standard_True;
721             }
722           }
723         }
724       }
725       else if(theType == TopAbs_FACE) {
726         // not yet implemented!
727       }
728
729       if(bIsEqual) {
730         anArrayOfFlag.SetValue(i, j, Standard_True );
731         aListOfS2.Append(aS2);
732         nbs++;
733       }
734     }
735
736     if(nbs > 1) {
737       BOPAlgo_CheckResult aResult;
738
739       aResult.SetShape1(myShape1);
740       aResult.SetShape2(myShape2);
741       aResult.AddFaultyShape1(aS1);
742       BOPCol_ListIteratorOfListOfShape anIt(aListOfS2);
743
744       for(; anIt.More(); anIt.Next()) {
745         aResult.AddFaultyShape2(anIt.Value());
746       }
747
748       aResult.SetCheckStatus(aStatus);
749       myResult.Append(aResult);
750
751       if(myStopOnFirst) {
752         return;
753       }
754     }
755   }
756
757   for(i = 1; i <= aSeq2.Length(); i++) {
758     const TopoDS_Shape& aS2 = aSeq2.Value(i);
759     BOPCol_ListOfShape aListOfS1;
760     Standard_Integer nbs = 0;
761
762     for(j = 1; j <= aSeq1.Length(); j++) {
763       const TopoDS_Shape& aS1 = aSeq1.Value(j);
764
765       if(anArrayOfFlag.Value(j, i)) {
766         aListOfS1.Append(aS1);
767         nbs++;
768       }
769     }
770     
771     if(nbs > 1) {
772       BOPAlgo_CheckResult aResult;
773
774       aResult.SetShape1(myShape1);
775       aResult.SetShape2(myShape2);
776       BOPCol_ListIteratorOfListOfShape anIt(aListOfS1);
777
778       for(; anIt.More(); anIt.Next()) {
779         aResult.AddFaultyShape1(anIt.Value());
780       }
781       aResult.AddFaultyShape2(aS2);
782
783       aResult.SetCheckStatus(aStatus);
784       myResult.Append(aResult);
785
786       if(myStopOnFirst) {
787         return;
788       }
789     }
790   }
791 }
792
793 // ================================================================================
794 // function: TestMergeVertex
795 // purpose:
796 // ================================================================================
797 void BOPAlgo_ArgumentAnalyzer::TestMergeVertex() 
798 {
799   TestMergeSubShapes(TopAbs_VERTEX); 
800 }
801
802 // ================================================================================
803 // function: TestMergeEdge
804 // purpose:
805 // ================================================================================
806 void BOPAlgo_ArgumentAnalyzer::TestMergeEdge() 
807 {
808   TestMergeSubShapes(TopAbs_EDGE); 
809 }
810
811 // ================================================================================
812 // function: TestContinuity
813 // purpose:
814 // ================================================================================
815 void BOPAlgo_ArgumentAnalyzer::TestContinuity() 
816 {
817   Standard_Integer i;
818   Standard_Real f, l;
819   TopExp_Explorer aExp;
820   BOPCol_MapIteratorOfMapOfShape aIt;
821   //
822   for (i = 0; i < 2; ++i) {
823     const TopoDS_Shape& aS = !i ? myShape1 : myShape2;
824     if(aS.IsNull()) {
825       continue;
826     }
827     //
828     BOPCol_MapOfShape aMS;
829     //Edges
830     aExp.Init(aS, TopAbs_EDGE);
831     for (; aExp.More(); aExp.Next()) {
832       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
833       if (BRep_Tool::Degenerated(aE)) {
834         continue;
835       }
836       const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, f, l);
837       if (aC->Continuity() == GeomAbs_C0) {
838         aMS.Add(aE);
839       }
840     }
841     //Faces
842     aExp.Init(aS, TopAbs_FACE);
843     for (; aExp.More(); aExp.Next()) {
844       const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
845       const Handle(Geom_Surface)& aS = BRep_Tool::Surface(aF);
846       if (aS->Continuity() == GeomAbs_C0) {
847         aMS.Add(aF);
848       }
849     }
850     //
851     //add shapes with continuity C0 to result
852     aIt.Initialize(aMS);
853     for (; aIt.More(); aIt.Next()) {
854       const TopoDS_Shape& aFS = aIt.Value();
855       BOPAlgo_CheckResult aResult;
856       if(i == 0) {
857         aResult.SetShape1(myShape1);
858         aResult.AddFaultyShape1(aFS);
859       } else {
860         aResult.SetShape2(myShape2);
861         aResult.AddFaultyShape2(aFS);
862       }
863       aResult.SetCheckStatus(BOPAlgo_GeomAbs_C0);
864       myResult.Append(aResult);
865     }
866   }
867 }
868
869 // ================================================================================
870 // function: TestCurveOnSurface
871 // purpose:
872 // ================================================================================
873 void BOPAlgo_ArgumentAnalyzer::TestCurveOnSurface()
874 {
875   Standard_Integer i;
876   Standard_Real aT, aD, aTolE;
877   TopExp_Explorer aExpF, aExpE;
878   //
879   for(i = 0; i < 2; i++) {
880     const TopoDS_Shape& aS = (i == 0) ? myShape1 : myShape2;
881     if(aS.IsNull()) {
882       continue;
883     }
884     //
885     aExpF.Init(aS, TopAbs_FACE);
886     for (; aExpF.More(); aExpF.Next()) {
887       const TopoDS_Face& aF = *(TopoDS_Face*)&aExpF.Current();
888       //
889       aExpE.Init(aF, TopAbs_EDGE);
890       for (; aExpE.More(); aExpE.Next()) {
891         const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExpE.Current();
892         //
893         if (BOPTools_AlgoTools::ComputeTolerance(aF, aE, aD, aT)) {
894           aTolE = BRep_Tool::Tolerance(aE);
895           if (aD > aTolE) {
896             BOPAlgo_CheckResult aResult;
897             aResult.SetCheckStatus(BOPAlgo_InvalidCurveOnSurface);
898             if(i == 0) {
899               aResult.SetShape1(myShape1);
900               aResult.AddFaultyShape1(aE);
901               aResult.AddFaultyShape1(aF);
902               aResult.SetMaxDistance1(aD);
903               aResult.SetMaxParameter1(aT);
904             }
905             else {
906               aResult.SetShape2(myShape2);
907               aResult.AddFaultyShape2(aE);
908               aResult.AddFaultyShape2(aF);
909               aResult.SetMaxDistance2(aD);
910               aResult.SetMaxParameter2(aT);
911             }
912             myResult.Append(aResult);
913           }
914         }
915       }
916     }
917   }
918 }
919
920 // ================================================================================
921 // function: UpdateTolerances
922 // purpose:
923 // ================================================================================
924 void BOPAlgo_ArgumentAnalyzer::UpdateTolerances()
925 {
926   if (myFuzzyValue == 0.) {
927     return;
928   }
929   //
930   BOPCol_MapOfShape aMapShapes;
931   //
932   if (!myShape1.IsNull()) {
933     BOPTools::MapShapes(myShape1, aMapShapes);
934   }
935   if (!myShape2.IsNull()) {
936     BOPTools::MapShapes(myShape2, aMapShapes);
937   }
938   //
939   if (aMapShapes.IsEmpty()) {
940     return;
941   }
942   //
943   Standard_Real aTol, aFuzz;
944   TopAbs_ShapeEnum aType;
945   BOPCol_MapIteratorOfMapOfShape aIt;
946   //
947   aFuzz = myFuzzyValue / 2.;
948   aIt.Initialize(aMapShapes);
949   for (; aIt.More(); aIt.Next()) {
950     const TopoDS_Shape& aS = aIt.Value();
951     aType = aS.ShapeType();
952     //
953     switch (aType) {
954     case TopAbs_VERTEX: {
955       const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aS;
956       const Handle(BRep_TVertex)& TV = 
957         *((Handle(BRep_TVertex)*)&aV.TShape());
958       aTol = TV->Tolerance();
959       myToleranceMap.Bind(aS, aTol);
960       TV->Tolerance(aTol + aFuzz);
961       break;
962     }
963     case TopAbs_EDGE: {
964       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
965       const Handle(BRep_TEdge)& TE = 
966         *((Handle(BRep_TEdge)*)&aE.TShape());
967       aTol = TE->Tolerance();
968       myToleranceMap.Bind(aS, aTol);
969       TE->Tolerance(aTol + aFuzz);
970       break;
971     }
972     case TopAbs_FACE: {
973       const TopoDS_Face& aF = *(TopoDS_Face*)&aS;
974       const Handle(BRep_TFace)& TF = 
975         *((Handle(BRep_TFace)*)&aF.TShape());
976       aTol = TF->Tolerance();
977       myToleranceMap.Bind(aS, aTol);
978       TF->Tolerance(aTol + aFuzz);
979       break;
980     }
981     default:
982       break;
983     } // switch (aType) {
984   } // for (; aIt.More(); aIt.Next()) {
985 }
986
987 // ================================================================================
988 // function: SetDefaultTolerances
989 // purpose:
990 // ================================================================================
991 void BOPAlgo_ArgumentAnalyzer::SetDefaultTolerances()
992 {
993   if (myFuzzyValue == 0.) {
994     return;
995   }
996   //
997   if (myToleranceMap.IsEmpty()) {
998     return;
999   }
1000   //
1001   Standard_Real aTol;
1002   TopAbs_ShapeEnum aType;
1003   BOPCol_DataMapIteratorOfDataMapOfShapeReal aIt;
1004   //
1005   aIt.Initialize(myToleranceMap);
1006   for (; aIt.More(); aIt.Next()) {
1007     const TopoDS_Shape& aS = aIt.Key();
1008     aTol = aIt.Value();
1009     aType = aS.ShapeType();
1010     //
1011     switch (aType) {
1012     case TopAbs_VERTEX: {
1013       const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aS;
1014       const Handle(BRep_TVertex)& TV = 
1015         *((Handle(BRep_TVertex)*)&aV.TShape());
1016       TV->Tolerance(aTol);
1017       break;
1018     }
1019     case TopAbs_EDGE: {
1020       const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
1021       const Handle(BRep_TEdge)& TE = 
1022         *((Handle(BRep_TEdge)*)&aE.TShape());
1023       TE->Tolerance(aTol);
1024       break;
1025     }
1026     case TopAbs_FACE: {
1027       const TopoDS_Face& aF = *(TopoDS_Face*)&aS;
1028       const Handle(BRep_TFace)& TF = 
1029         *((Handle(BRep_TFace)*)&aF.TShape());
1030       TF->Tolerance(aTol);
1031       break;
1032     }
1033     default:
1034       break;
1035     } // switch (aType) {
1036   } // for (; aIt.More(); aIt.Next()) {
1037 }