5c7380901ccfb1e855ed6489fd2e27b70f642383
[occt.git] / src / BOP / BOP_ArgumentAnalyzer.cxx
1 // Created on: 2004-09-02
2 // Copyright (c) 2004-2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19
20 #include <BOP_ArgumentAnalyzer.ixx>
21 #include <BOP_CheckResult.hxx>
22 #include <BOP_ShellSolid.hxx>
23 #include <BOP_WireSolid.hxx>
24 #include <BOP_WireShell.hxx>
25 #include <BOP_WireEdgeSet.hxx>
26 #include <BOP_FaceBuilder.hxx>
27
28 #include <TopExp.hxx>
29 #include <TopExp_Explorer.hxx>
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRepExtrema_DistShapeShape.hxx>
33 #include <gp_Pnt.hxx>
34 #include <TopoDS_Iterator.hxx>
35 #include <TopoDS.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Wire.hxx>
39 #include <TopoDS_Shell.hxx>
40 #include <TopoDS_Solid.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_ListIteratorOfListOfShape.hxx>
43 #include <TopTools_SequenceOfShape.hxx>
44 #include <TopTools_MapOfShape.hxx>
45
46 #include <TColStd_Array2OfBoolean.hxx>
47
48 #include <IntTools_Context.hxx>
49 #include <IntTools_Range.hxx>
50 #include <IntTools_ShrunkRange.hxx>
51 #include <IntTools_EdgeEdge.hxx>
52 #include <IntTools_CommonPrt.hxx>
53
54 #include <BOPTools_DSFiller.hxx>
55 #include <BOPTools_Tools3D.hxx>
56 #include <BOPTools_Checker.hxx>
57 #include <BOPTools_CheckResult.hxx>
58 #include <BOPTools_ListOfCheckResults.hxx>
59 #include <BOPTools_ListIteratorOfListOfCheckResults.hxx>
60
61 #include <Standard_ErrorHandler.hxx>
62 #include <Standard_Failure.hxx>
63
64 static Standard_Boolean TestShapeType(const TopoDS_Shape & TheShape);
65
66 static Standard_Boolean CheckEdge(const TopoDS_Edge& theEdge);
67
68 static Standard_Boolean TestSubShapeType(const TopAbs_ShapeEnum theT1,
69                                          const TopAbs_ShapeEnum theT2,
70                                          const BOP_Operation    theOP);
71
72 // ================================================================================
73 // function: Constructor
74 // purpose:
75 // ================================================================================
76 BOP_ArgumentAnalyzer::BOP_ArgumentAnalyzer() : 
77 myStopOnFirst(Standard_False),
78 myOperation(BOP_UNKNOWN),
79 myArgumentTypeMode(Standard_False),
80 mySelfInterMode(Standard_False),
81 mySmallEdgeMode(Standard_False),
82 myRebuildFaceMode(Standard_False),
83 myTangentMode(Standard_False),
84 myMergeVertexMode(Standard_False),
85 myMergeEdgeMode(Standard_False)
86 // myMergeFaceMode(Standard_False)
87 {
88 }
89
90 // ================================================================================
91 // function: SetShape1
92 // purpose:
93 // ================================================================================
94 void BOP_ArgumentAnalyzer::SetShape1(const TopoDS_Shape & TheShape)
95 {
96   myShape1 = TheShape;
97 }
98
99 // ================================================================================
100 // function: SetShape2
101 // purpose:
102 // ================================================================================
103 void BOP_ArgumentAnalyzer::SetShape2(const TopoDS_Shape & TheShape)
104 {
105   myShape2 = TheShape;
106 }
107
108 // ================================================================================
109 // function: GetShape1
110 // purpose:
111 // ================================================================================
112 const TopoDS_Shape & BOP_ArgumentAnalyzer::GetShape1() const
113 {
114   return myShape1;
115 }
116
117 // ================================================================================
118 // function: GetShape2
119 // purpose:
120 // ================================================================================
121 const TopoDS_Shape & BOP_ArgumentAnalyzer::GetShape2() const
122 {
123   return myShape2;
124 }
125
126 // ================================================================================
127 // function: OperationType
128 // purpose:
129 // ================================================================================
130 BOP_Operation& BOP_ArgumentAnalyzer::OperationType() 
131 {
132   return myOperation;
133 }
134
135 // ================================================================================
136 // function: StopOnFirstFaulty
137 // purpose:
138 // ================================================================================
139 Standard_Boolean & BOP_ArgumentAnalyzer::StopOnFirstFaulty()
140 {
141   return myStopOnFirst;
142 }
143
144 // ================================================================================
145 // function: Perform
146 // purpose:
147 // ================================================================================
148 void BOP_ArgumentAnalyzer::Perform()
149 {
150   try {
151     OCC_CATCH_SIGNALS
152     myResult.Clear();
153
154     if(myArgumentTypeMode) {
155       TestTypes();
156     }
157
158     if(mySelfInterMode) {
159       TestSelfInterferences();
160     }
161
162     if(mySmallEdgeMode) {
163       if(!(!myResult.IsEmpty() && myStopOnFirst))
164         TestSmallEdge();
165     }
166
167     if(myRebuildFaceMode) {
168       if(!(!myResult.IsEmpty() && myStopOnFirst))
169         TestRebuildFace();
170     }
171
172     if(myTangentMode) {
173       if(!(!myResult.IsEmpty() && myStopOnFirst))
174         TestTangent();
175     }
176
177     if(myMergeVertexMode) {
178       if(!(!myResult.IsEmpty() && myStopOnFirst))
179         TestMergeVertex();
180     }
181     
182     if(myMergeEdgeMode) {
183       if(!(!myResult.IsEmpty() && myStopOnFirst))
184         TestMergeEdge();
185     }
186     
187 //     if(myMergeFaceMode) {
188 //       TestMergeFace();
189 //     }
190   }
191   catch(Standard_Failure) {
192     BOP_CheckResult aResult;
193     aResult.SetCheckStatus(BOP_CheckUnknown);
194     myResult.Append(aResult);
195   }
196 }
197
198 // ================================================================================
199 // function: HasFaulty
200 // purpose:
201 // ================================================================================
202 Standard_Boolean BOP_ArgumentAnalyzer::HasFaulty() const
203 {
204   return ( !myResult.IsEmpty());
205 }
206
207 // ================================================================================
208 // function: GetCheckResult
209 // purpose:
210 // ================================================================================
211 const BOP_ListOfCheckResult& BOP_ArgumentAnalyzer::GetCheckResult() const
212 {
213   return myResult;
214 }
215
216 // ================================================================================
217 // function: TestTypes
218 // purpose:
219 // ================================================================================
220 void BOP_ArgumentAnalyzer::TestTypes()
221 {
222   Standard_Boolean isS1 = myShape1.IsNull(), isS2 = myShape2.IsNull();
223
224   if(isS1 && isS2) {
225     BOP_CheckResult aResult;
226     aResult.SetCheckStatus(BOP_BadType);
227     myResult.Append(aResult);
228     return;
229   }
230
231   Standard_Boolean testS1 = TestShapeType(myShape1);
232   Standard_Boolean testS2 = TestShapeType(myShape2);
233
234   // single shape check (begin)
235   if((isS1 && !isS2) || (!isS1 && isS2)) {
236 //     Standard_Boolean testS = (isS1) ? testS1 : testS2;
237     Standard_Boolean testS = (isS1) ? testS2 : testS1;
238
239     if(!testS) {
240       const TopoDS_Shape & aS = (isS1) ? myShape1 : myShape2;
241       BOP_CheckResult aResult;
242       aResult.SetShape1(aS);
243       aResult.SetCheckStatus(BOP_BadType);
244       myResult.Append(aResult);
245       return;
246     }
247     
248   } // single shape is set (end)
249   // two shapes check (begin)
250   else {
251     // test compounds and compsolids
252     if(!testS1 || !testS2) {
253       BOP_CheckResult aResult;
254       if(!testS1 && !testS2) {
255         aResult.SetShape1(myShape1);
256         aResult.SetShape2(myShape2);
257       }
258       else {
259         const TopoDS_Shape & aS = (!testS1) ? myShape1 : myShape2;
260         if(!testS1)
261           aResult.SetShape1(aS);
262         else
263           aResult.SetShape2(aS);
264       }
265       aResult.SetCheckStatus(BOP_BadType);
266       myResult.Append(aResult);
267       return;
268     }
269     // test faces, wires, edges
270     TopAbs_ShapeEnum aT1 = myShape1.ShapeType(), aT2 = myShape2.ShapeType();
271
272     if(aT1 != TopAbs_COMPOUND && aT2 != TopAbs_COMPOUND) {
273       Standard_Boolean aTestRes = TestSubShapeType(aT1,aT2,myOperation);
274       if(!aTestRes) {
275         BOP_CheckResult aResult;
276         aResult.SetShape1(myShape1);
277         aResult.SetShape2(myShape2);
278         aResult.SetCheckStatus(BOP_BadType);
279         myResult.Append(aResult);
280         return;
281       }
282     }
283     else {
284       Standard_Boolean aTestRes = Standard_True;
285       if(aT1 == TopAbs_COMPOUND && aT2 != TopAbs_COMPOUND) {
286         TopoDS_Iterator itS1(myShape1);
287         while(itS1.More()) {
288           aT1 = itS1.Value().ShapeType();
289           aTestRes = TestSubShapeType(aT1,aT2,myOperation);
290           if(!aTestRes)
291             break;
292           itS1.Next();
293         }
294       }
295       else if(aT1 != TopAbs_COMPOUND && aT2 == TopAbs_COMPOUND) {
296         TopoDS_Iterator itS2(myShape2);
297         while(itS2.More()) {
298           aT2 = itS2.Value().ShapeType();
299           aTestRes = TestSubShapeType(aT1,aT2,myOperation);
300           if(!aTestRes)
301             break;
302           itS2.Next();
303         }
304       }
305       else {
306         TopoDS_Iterator itS1(myShape1);
307         while(itS1.More()) {
308           aT1 = itS1.Value().ShapeType();
309           TopoDS_Iterator itS2(myShape2);
310           while(itS2.More()) {
311             aT2 = itS2.Value().ShapeType();
312             aTestRes = TestSubShapeType(aT1,aT2,myOperation);
313             if(!aTestRes)
314               break;
315             itS2.Next();
316           }
317           if(!aTestRes)
318             break;
319           itS1.Next();
320         }
321       }
322
323       if(!aTestRes) {
324         BOP_CheckResult aResult;
325         aResult.SetShape1(myShape1);
326         aResult.SetShape2(myShape2);
327         aResult.SetCheckStatus(BOP_BadType);
328         myResult.Append(aResult);
329         return;
330       }
331     }
332   } // both shapes are set (end)
333 }
334
335 // ================================================================================
336 // function: TestSelfInterferences
337 // purpose:
338 // ================================================================================
339 void BOP_ArgumentAnalyzer::TestSelfInterferences()
340 {
341   Standard_Integer i = 0;
342
343   for(i = 0; i < 2; i++) {
344     TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
345
346     if(aS.IsNull())
347       continue;
348     BOPTools_Checker aChecker(aS);
349     aChecker.Perform();
350
351     if (aChecker.HasFaulty()) {
352       const BOPTools_ListOfCheckResults& aResultList = aChecker.GetCheckResult();
353       BOPTools_ListIteratorOfListOfCheckResults anIt(aResultList);
354
355       for(; anIt.More(); anIt.Next()) {
356         const BOPTools_CheckResult& aCheckResult = anIt.Value();
357
358         if((aCheckResult.GetCheckStatus() == BOPTools_CHKUNKNOWN) ||
359            (aCheckResult.GetCheckStatus() == BOPTools_BADSHRANKRANGE) ||
360            (aCheckResult.GetCheckStatus() == BOPTools_NULLSRANKRANGE)) {
361           continue;
362         }
363         BOP_CheckResult aResult;
364         if(i == 0)
365           aResult.SetShape1(myShape1);
366         else
367           aResult.SetShape2(myShape2);
368         TopTools_ListIteratorOfListOfShape anIt2(aCheckResult.GetShapes());
369
370         for(; anIt2.More(); anIt2.Next()) {
371           if(i == 0)
372             aResult.AddFaultyShape1(anIt2.Value());
373           else
374             aResult.AddFaultyShape2(anIt2.Value());
375         }
376         aResult.SetCheckStatus(BOP_SelfIntersect);
377         myResult.Append(aResult);
378
379         if(myStopOnFirst) {
380           return;
381         }
382       }
383     }
384   }
385 }
386
387 // ================================================================================
388 // function: TestSmallEdge
389 // purpose:
390 // ================================================================================
391 void BOP_ArgumentAnalyzer::TestSmallEdge() 
392 {
393   Standard_Integer i = 0;
394   BRepExtrema_DistShapeShape aDist;
395
396   for(i = 0; i < 2; i++) {
397     TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
398
399     if(aS.IsNull())
400       continue;
401
402     TopExp_Explorer anExp(aS, TopAbs_EDGE);
403
404     for(; anExp.More(); anExp.Next()) {
405       TopoDS_Edge anEdge = TopoDS::Edge(anExp.Current());
406
407       if(!CheckEdge(anEdge)) {
408         Standard_Boolean bKeepResult = Standard_True;
409
410         if(myOperation == BOP_SECTION) {
411           TopoDS_Shape anOtherS = (i == 0) ? myShape2 : myShape1;
412           
413           if(!anOtherS.IsNull()) {
414 //          BRepExtrema_DistShapeShape aDist;
415             aDist.LoadS2(anOtherS);
416             
417             Standard_Boolean bVertexIsOnShape = Standard_False;
418             Standard_Integer ii = 0;
419             TopExp_Explorer anExpV(anEdge, TopAbs_VERTEX);
420             
421             for(; anExpV.More(); anExpV.Next()) {
422               TopoDS_Shape aV = anExpV.Current();
423
424               aDist.LoadS1(aV);
425               aDist.Perform();
426
427               if(aDist.IsDone()) {
428
429                 for(ii = 1; ii <= aDist.NbSolution(); ii++) {
430                   Standard_Real aTolerance = BRep_Tool::Tolerance(TopoDS::Vertex(aV));
431                   TopoDS_Shape aSupportShape = aDist.SupportOnShape2(ii);
432
433                   switch(aSupportShape.ShapeType()) {
434                   case TopAbs_VERTEX: {
435                     aTolerance += BRep_Tool::Tolerance(TopoDS::Vertex(aSupportShape));
436                     break;
437                   }
438                   case TopAbs_EDGE: {
439                     aTolerance += BRep_Tool::Tolerance(TopoDS::Edge(aSupportShape));
440                     break;
441                   }
442                   case TopAbs_FACE: {
443                     aTolerance += BRep_Tool::Tolerance(TopoDS::Face(aSupportShape));
444                     break;
445                   }
446                   default:
447                     break;
448                   }
449                   
450                   if(aDist.Value() < aTolerance) {
451                     bVertexIsOnShape = Standard_True;
452                     break;
453                   }
454                 }
455               }
456             }
457
458             if(!bVertexIsOnShape) {
459               bKeepResult = Standard_False;
460             }
461           }
462         }
463
464         if(bKeepResult) {
465           BOP_CheckResult aResult;
466
467           if(i == 0) {
468             aResult.SetShape1(myShape1);
469             aResult.AddFaultyShape1(anEdge);
470           }
471           else {
472             aResult.SetShape2(myShape2);
473             aResult.AddFaultyShape2(anEdge);
474           }
475           
476           aResult.SetCheckStatus(BOP_TooSmallEdge);
477           myResult.Append(aResult);
478
479           if(myStopOnFirst) {
480             return;
481           }
482         }
483       }
484     }
485   }
486 }
487
488 // ================================================================================
489 // function: TestRebuildFace
490 // purpose:
491 // ================================================================================
492 void BOP_ArgumentAnalyzer::TestRebuildFace() 
493 {
494   if((myOperation == BOP_SECTION) ||
495      (myOperation == BOP_UNKNOWN))
496     return;
497   Standard_Integer i = 0;
498
499   for(i = 0; i < 2; i++) {
500     TopoDS_Shape aS = (i == 0) ? myShape1 : myShape2;
501
502     if(aS.IsNull())
503       continue;
504
505     TopExp_Explorer anExp(aS, TopAbs_FACE);
506
507     for(; anExp.More(); anExp.Next()) {
508       TopoDS_Face aFace = TopoDS::Face(anExp.Current());
509
510       BOP_WireEdgeSet aWES (aFace);
511       TopExp_Explorer anExpE(aFace, TopAbs_EDGE);
512       Standard_Integer nbstartedges = 0;
513
514       for(; anExpE.More(); anExpE.Next()) {
515         aWES.AddStartElement(anExpE.Current());
516         nbstartedges++;
517       }
518       BOP_FaceBuilder aFB;
519       aFB.Do(aWES);
520       const TopTools_ListOfShape& aLF = aFB.NewFaces();
521       Standard_Boolean bBadFace = Standard_False;
522
523       if(aLF.Extent() != 1) {
524         bBadFace = Standard_True;
525       }
526       else {
527         Standard_Integer nbedgeused = 0;
528         anExpE.Init(aLF.First(), TopAbs_EDGE);
529
530         for(; anExpE.More(); anExpE.Next(), nbedgeused++);
531
532         if(nbstartedges != nbedgeused) {
533           bBadFace = Standard_True;
534         }
535       }
536
537       if(bBadFace) {
538         BOP_CheckResult aResult;
539
540         if(i == 0) {
541           aResult.SetShape1(myShape1);
542           aResult.AddFaultyShape1(aFace);
543         }
544         else {
545           aResult.SetShape2(myShape2);
546           aResult.AddFaultyShape2(aFace);
547         }
548           
549         aResult.SetCheckStatus(BOP_NonRecoverableFace);
550         myResult.Append(aResult);
551
552         if(myStopOnFirst) {
553           return;
554         }
555       }
556     }
557   }
558 }
559
560 // ================================================================================
561 // function: TestTangent
562 // purpose:
563 // ================================================================================
564 void BOP_ArgumentAnalyzer::TestTangent() 
565 {
566  // not implemented
567 }
568
569 // ================================================================================
570 // function: TestMergeSubShapes
571 // purpose:
572 // ================================================================================
573  void BOP_ArgumentAnalyzer::TestMergeSubShapes(const TopAbs_ShapeEnum theType) 
574 {
575   if(myShape1.IsNull() || myShape2.IsNull())
576     return;
577
578   BOP_CheckStatus aStatus = BOP_CheckUnknown;
579
580   switch(theType) {
581   case TopAbs_VERTEX: {
582     aStatus = BOP_IncompatibilityOfVertex;
583     break;
584   }
585   case TopAbs_EDGE: {
586     aStatus = BOP_IncompatibilityOfEdge;
587     break;
588   }
589   case TopAbs_FACE: {
590     aStatus = BOP_IncompatibilityOfFace;
591     break;
592   }
593   default: 
594     return;
595   }
596   TopExp_Explorer anExp1(myShape1, theType);
597   TopExp_Explorer anExp2(myShape2, theType);
598   TopTools_SequenceOfShape aSeq1, aSeq2;
599   TopTools_MapOfShape aMap1, aMap2;
600
601   for(; anExp1.More(); anExp1.Next()) {
602     TopoDS_Shape aS1 = anExp1.Current();
603
604     if(aMap1.Contains(aS1))
605       continue;
606     aSeq1.Append(aS1);
607     aMap1.Add(aS1);
608   }
609
610   for(; anExp2.More(); anExp2.Next()) {
611     TopoDS_Shape aS2 = anExp2.Current();
612     if(aMap2.Contains(aS2))
613       continue;
614     aSeq2.Append(aS2);
615     aMap2.Add(aS2);
616   }
617
618   TColStd_Array2OfBoolean anArrayOfFlag(1, aSeq1.Length(), 1, aSeq2.Length());
619   Standard_Integer i = 0, j = 0;
620   for(i = 1; i <= aSeq1.Length(); i++)
621     for(j = 1; j <= aSeq2.Length(); j++)
622       anArrayOfFlag.SetValue(i, j, Standard_False);
623
624   for(i = 1; i <= aSeq1.Length(); i++) {
625     TopoDS_Shape aS1 = aSeq1.Value(i);
626     TopTools_ListOfShape aListOfS2;
627     Standard_Integer nbs = 0;
628
629     for(j = 1; j <= aSeq2.Length(); j++) {
630       TopoDS_Shape aS2 = aSeq2.Value(j);
631       Standard_Boolean bIsEqual = Standard_False;
632
633       if(theType == TopAbs_VERTEX) {
634
635         TopoDS_Vertex aV1 = TopoDS::Vertex(aS1);
636         TopoDS_Vertex aV2 = TopoDS::Vertex(aS2);
637         gp_Pnt aP1 = BRep_Tool::Pnt(aV1);
638         gp_Pnt aP2 = BRep_Tool::Pnt(aV2);
639         Standard_Real aDist = aP1.Distance(aP2);
640
641         if(aDist <= (BRep_Tool::Tolerance(aV1) + BRep_Tool::Tolerance(aV2))) {
642           bIsEqual = Standard_True;
643         }
644       }
645       else if(theType == TopAbs_EDGE) {
646         Standard_Integer aDiscretize = 30;
647         Standard_Real    aDeflection = 0.01;
648         TopoDS_Edge aE1 = TopoDS::Edge(aS1);
649         TopoDS_Edge aE2 = TopoDS::Edge(aS2);
650
651         IntTools_EdgeEdge aEE;
652         aEE.SetEdge1 (aE1);
653         aEE.SetEdge2 (aE2);
654         aEE.SetTolerance1 (BRep_Tool::Tolerance(aE1));
655         aEE.SetTolerance2 (BRep_Tool::Tolerance(aE2));
656         aEE.SetDiscretize (aDiscretize);
657         aEE.SetDeflection (aDeflection);
658
659         Standard_Real f = 0., l = 0.;
660         BRep_Tool::Range(aE1, f, l);
661         aEE.SetRange1(f, l);
662
663         BRep_Tool::Range(aE2, f, l);
664         aEE.SetRange2(f, l);
665
666         aEE.Perform();
667
668         if (aEE.IsDone()) {
669           const IntTools_SequenceOfCommonPrts& aCPrts = aEE.CommonParts();
670           Standard_Integer ii = 0;
671
672           for (ii = 1; ii <= aCPrts.Length(); ii++) {
673             const IntTools_CommonPrt& aCPart = aCPrts(ii);
674
675             if (aCPart.Type() == TopAbs_EDGE) {
676               bIsEqual = Standard_True;
677             }
678           }
679         }
680       }
681       else if(theType == TopAbs_FACE) {
682         // not yet implemented!
683       }
684
685       if(bIsEqual) {
686         anArrayOfFlag.SetValue(i, j, Standard_True );
687         aListOfS2.Append(aS2);
688         nbs++;
689       }
690     }
691
692     if(nbs > 1) {
693       BOP_CheckResult aResult;
694
695       aResult.SetShape1(myShape1);
696       aResult.SetShape2(myShape2);
697       aResult.AddFaultyShape1(aS1);
698       TopTools_ListIteratorOfListOfShape anIt(aListOfS2);
699
700       for(; anIt.More(); anIt.Next()) {
701         aResult.AddFaultyShape2(anIt.Value());
702       }
703
704       aResult.SetCheckStatus(aStatus);
705       myResult.Append(aResult);
706
707       if(myStopOnFirst) {
708         return;
709       }
710     }
711   }
712
713   for(i = 1; i <= aSeq2.Length(); i++) {
714     TopoDS_Shape aS2 = aSeq2.Value(i);
715     TopTools_ListOfShape aListOfS1;
716     Standard_Integer nbs = 0;
717
718     for(j = 1; j <= aSeq1.Length(); j++) {
719       TopoDS_Shape aS1 = aSeq1.Value(j);
720
721       if(anArrayOfFlag.Value(j, i)) {
722         aListOfS1.Append(aS1);
723         nbs++;
724       }
725     }
726
727     if(nbs > 1) {
728       BOP_CheckResult aResult;
729
730       aResult.SetShape1(myShape1);
731       aResult.SetShape2(myShape2);
732       TopTools_ListIteratorOfListOfShape anIt(aListOfS1);
733
734       for(; anIt.More(); anIt.Next()) {
735         aResult.AddFaultyShape1(anIt.Value());
736       }
737       aResult.AddFaultyShape2(aS2);
738
739       aResult.SetCheckStatus(aStatus);
740       myResult.Append(aResult);
741
742       if(myStopOnFirst) {
743         return;
744       }
745     }
746   }
747 }
748
749 // ================================================================================
750 // function: TestMergeVertex
751 // purpose:
752 // ================================================================================
753 void BOP_ArgumentAnalyzer::TestMergeVertex() 
754 {
755   TestMergeSubShapes(TopAbs_VERTEX); 
756 }
757
758 // ================================================================================
759 // function: TestMergeEdge
760 // purpose:
761 // ================================================================================
762 void BOP_ArgumentAnalyzer::TestMergeEdge() 
763 {
764   TestMergeSubShapes(TopAbs_EDGE); 
765 }
766
767 // ================================================================================
768 // function: TestMergeFace
769 // purpose:
770 // ================================================================================
771 // void BOP_ArgumentAnalyzer::TestMergeFace() 
772 // {
773   // not implemented
774 // }
775
776 // ----------------------------------------------------------------------
777 // static function: TestShapeType
778 // purpose:
779 // ----------------------------------------------------------------------
780 Standard_Boolean TestShapeType(const TopoDS_Shape & TheShape)
781 {
782   if(TheShape.IsNull())
783     return Standard_False;
784
785   TopAbs_ShapeEnum aT = TheShape.ShapeType();
786
787   if(aT == TopAbs_COMPOUND && BOPTools_Tools3D::IsEmptyShape(TheShape))
788     return Standard_False;
789
790   TopoDS_Iterator anIt;
791   TopoDS_Shape aSTmp, aShape;
792   Standard_Integer aNbShapes, TreatRes = 0;
793
794   if(aT==TopAbs_COMPOUND || aT==TopAbs_COMPSOLID) {
795     aNbShapes=0;
796     anIt.Initialize(TheShape);
797     for (; anIt.More(); anIt.Next()) {
798       if(!aNbShapes) {
799         aSTmp=anIt.Value();
800       }
801       aNbShapes++;
802       if(aNbShapes>1) {
803         break;
804       }
805     }
806     if(aT == TopAbs_COMPOUND) {
807       if (aNbShapes==1) {
808         TreatRes = BOPTools_DSFiller::TreatCompound(TheShape, aSTmp);
809         if(TreatRes != 0)
810           return Standard_False;
811         aShape=aSTmp;
812         aT = aShape.ShapeType();
813       }
814       else if (aNbShapes>1) {
815         TreatRes = BOPTools_DSFiller::TreatCompound(TheShape, aSTmp);
816         if(TreatRes != 0)
817           return Standard_False;
818         aShape=aSTmp;
819         aT=aShape.ShapeType();
820       }
821     }
822   }
823
824   if(aT==TopAbs_COMPOUND || aT==TopAbs_COMPSOLID) {
825     return Standard_False;
826   }
827
828   return Standard_True;
829 }
830
831 // ----------------------------------------------------------------------
832 // static function: CheckEdge
833 // purpose:
834 // ----------------------------------------------------------------------
835 Standard_Boolean CheckEdge(const TopoDS_Edge& theEdge) 
836 {
837   Handle(IntTools_Context) aContext;
838   TopoDS_Vertex aV1, aV2;
839   //
840   //modified by NIZNHY-PKV Tue Jan 31 15:07:13 2012f
841   aContext=new IntTools_Context;
842   ////modified by NIZNHY-PKV Tue Jan 31 15:07:16 2012t
843   TopExp::Vertices(theEdge, aV1, aV2);
844
845
846   if(aV1.IsNull() || aV2.IsNull() || BRep_Tool::Degenerated(theEdge))
847     return Standard_True;
848   Standard_Real aFirst = 0., aLast = 0.;
849   BRep_Tool::Range(theEdge, aFirst, aLast);
850   IntTools_Range aRange(aFirst, aLast);
851   IntTools_ShrunkRange aSR(theEdge, aV1, aV2, aRange, aContext);
852
853   if (!aSR.IsDone() || aSR.ErrorStatus() == 6) {
854     return Standard_False;
855   }
856   return Standard_True;
857 }
858
859 // ----------------------------------------------------------------------
860 // static function: TestSubShapeType
861 // purpose:
862 // ----------------------------------------------------------------------
863 Standard_Boolean TestSubShapeType(const TopAbs_ShapeEnum theT1,
864                                   const TopAbs_ShapeEnum theT2,
865                                   const BOP_Operation    theOP)
866 {
867   TopAbs_ShapeEnum aT1 = theT1, aT2 = theT2;
868
869   if(aT1==TopAbs_FACE) {
870     if(aT2==TopAbs_SOLID || aT2==TopAbs_SHELL || aT2==TopAbs_FACE ||
871        aT2==TopAbs_WIRE || aT2==TopAbs_EDGE) {
872       aT1=TopAbs_SHELL;
873     }
874   }
875   if(aT2==TopAbs_FACE) {
876     if(aT1==TopAbs_SOLID || aT1==TopAbs_SHELL ||
877        aT1==TopAbs_WIRE || aT1==TopAbs_EDGE) {
878       aT2=TopAbs_SHELL;
879     }
880   }
881   if(aT1==TopAbs_EDGE) {
882     if(aT2==TopAbs_SOLID || aT2==TopAbs_SHELL ||
883        aT2==TopAbs_WIRE || aT2==TopAbs_EDGE) {
884       aT1=TopAbs_WIRE;
885     }
886   }
887   if(aT2==TopAbs_EDGE) {
888     if(aT1==TopAbs_SOLID || aT1==TopAbs_SHELL || aT1==TopAbs_WIRE) {
889       aT2=TopAbs_WIRE;
890     }
891   }
892
893   // test operations
894   if(theOP!=BOP_UNKNOWN) {
895     Standard_Boolean opOk;
896     if(aT1==TopAbs_SHELL && aT2==TopAbs_SHELL)
897       opOk = Standard_True;
898     else if(aT1==TopAbs_SOLID && aT2==TopAbs_SOLID)
899       opOk = Standard_True;
900     else if((aT1==TopAbs_SOLID && aT2==TopAbs_SHELL) ||
901             (aT2==TopAbs_SOLID && aT1==TopAbs_SHELL))
902       opOk = Standard_True;
903     else if(aT1==TopAbs_WIRE && aT2==TopAbs_WIRE)
904       opOk = Standard_True;
905     else if((aT1==TopAbs_WIRE  && aT2==TopAbs_SHELL) ||
906             (aT2==TopAbs_WIRE  && aT1==TopAbs_SHELL))
907       opOk = Standard_True;
908     else if((aT1==TopAbs_WIRE  && aT2==TopAbs_SOLID) ||
909             (aT2==TopAbs_WIRE  && aT1==TopAbs_SOLID))
910       opOk = Standard_True;
911     else 
912       opOk = Standard_False;
913
914     if(!opOk) {
915       return Standard_False;
916     }
917
918     if((aT1==TopAbs_SHELL && aT2==TopAbs_SOLID) ||
919        (aT2==TopAbs_SHELL && aT1==TopAbs_SOLID)) {
920       if(!BOP_ShellSolid::CheckArgTypes(aT1,aT2,theOP)) {
921         return Standard_False;
922       }
923     }
924     if((aT1==TopAbs_WIRE && aT2==TopAbs_SOLID) ||
925        (aT2==TopAbs_WIRE && aT1==TopAbs_SOLID)) {
926       if(!BOP_WireSolid::CheckArgTypes(aT1,aT2,theOP)) {
927         return Standard_False;
928       }
929     }
930     if((aT1==TopAbs_WIRE && aT2==TopAbs_SHELL) ||
931        (aT1==TopAbs_WIRE && aT2==TopAbs_SHELL)) {
932       if(!BOP_WireShell::CheckArgTypes(aT1,aT2,theOP)) {
933         return Standard_False;
934       }
935     }
936   }
937   
938   return Standard_True;
939 }