0023024: Update headers of OCCT files
[occt.git] / src / BOP / BOP_SolidSolid.cxx
1 // Created on: 2001-05-25
2 // Created by: Peter KURNEV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20
21
22 #include <BOP_SolidSolid.ixx>
23
24 #include <Standard_Failure.hxx>
25 #include <Standard_ErrorHandler.hxx>
26
27
28 #include <TColStd_IndexedMapOfInteger.hxx>
29 #include <TColStd_MapOfInteger.hxx>
30
31 #include <TopAbs_Orientation.hxx>
32 #include <TopLoc_Location.hxx>
33
34 #include <TopoDS.hxx>
35 #include <TopoDS_Shape.hxx>
36 #include <TopoDS_Vertex.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Face.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopoDS_Shell.hxx>
41 #include <TopoDS_Solid.hxx>
42 #include <TopoDS_Compound.hxx>
43
44 #include <TopTools_ListOfShape.hxx>
45 #include <TopTools_ListIteratorOfListOfShape.hxx>
46 #include <TopTools_IndexedMapOfShape.hxx>
47 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
48
49 #include <TopExp.hxx>
50
51 #include <BRep_Tool.hxx>
52 #include <BRep_Builder.hxx>
53
54 #include <BooleanOperations_ShapesDataStructure.hxx>
55 #include <BooleanOperations_StateOfShape.hxx>
56 #include <BooleanOperations_IndexedDataMapOfShapeInteger.hxx>
57
58 #include <BOPTColStd_Dump.hxx>
59 #include <BOPTColStd_IndexedDataMapOfIntegerIndexedMapOfInteger.hxx>
60
61 #include <BOPTools_SSInterference.hxx>
62 #include <BOPTools_InterferencePool.hxx>
63 #include <BOPTools_CArray1OfSSInterference.hxx>
64 #include <BOPTools_SequenceOfCurves.hxx>
65 #include <BOPTools_ListOfPaveBlock.hxx>
66 #include <BOPTools_ListIteratorOfListOfPaveBlock.hxx>
67 #include <BOPTools_PaveBlock.hxx>
68 #include <BOPTools_PaveFiller.hxx>
69 #include <BOPTools_DSFiller.hxx>
70 #include <BOPTools_CommonBlockPool.hxx>
71 #include <BOPTools_ListOfCommonBlock.hxx>
72 #include <BOPTools_ListIteratorOfListOfCommonBlock.hxx>
73 #include <BOPTools_CommonBlock.hxx>
74 #include <BOPTools_PaveBlock.hxx>
75
76 #include <BOP_WireEdgeSet.hxx>
77 #include <BOP_ShellFaceSet.hxx>
78 #include <BOP_SolidBuilder.hxx>
79 #include <BOP_Draw.hxx>
80 #include <BOP_FaceBuilder.hxx>
81 #include <BOP_CorrectTolerances.hxx>
82 #include <BOP_BuilderTools.hxx>
83 #include <BOP_Refiner.hxx>
84
85 #include <BOPTools_Curve.hxx>
86 #include <BOPTools_Tools3D.hxx>
87 #include <BOPTools_Tools2D.hxx>
88 #include <IntTools_Context.hxx>
89 #include <BRepTools.hxx>
90 #include <Geom_Surface.hxx>
91 #include <Geom_Curve.hxx>
92 #include <gp_Pln.hxx>
93 #include <BOP_SDFWESFiller.hxx>
94
95 #include <TColStd_ListIteratorOfListOfInteger.hxx>
96
97 #include <BOP_SolidSolidHistoryCollector.hxx>
98
99 static Standard_Boolean CheckFaceIntersection(const Standard_Integer   theFaceIndex,
100                                               const BOPTools_DSFiller* theDSFiller);
101
102 static Standard_Boolean BuildWESForCommonZone(const Standard_Integer                           theFaceIndex,
103                                               const TColStd_IndexedMapOfInteger&               theFFIndicesMap,
104                                               const BOPTools_DSFiller*                         theDSFiller,
105                                               const BOP_Operation&                             theOperation,
106                                               BOP_WireEdgeSet&                                 theWES,
107                                               BOP_WireEdgeSet&                                 theWESAvoid);
108
109 static void LocalAddPartsEFSo (const Standard_Integer nF1, 
110                                const Standard_Integer iFF,
111                                const TopTools_IndexedDataMapOfShapeListOfShape& aMEFObj,
112                                const TopTools_IndexedDataMapOfShapeListOfShape& aMEFTool,
113                                const BOPTools_DSFiller*                         theDSFiller,
114                                const BOP_Operation&                             theOperation,
115                                const TopTools_ListOfShape&                      theListOfSDFace,
116                                TopTools_IndexedMapOfShape& anEMap,
117                                BOP_WireEdgeSet& aWES);
118
119 static Standard_Boolean LocalIsKeepTwice(const TopoDS_Face&          aF1,
120                                          const TopoDS_Face&          aF2,
121                                          const TopoDS_Face&          aF2Adj,
122                                          const TopoDS_Edge&          aSpEF2,
123                                          const TopTools_ListOfShape& theFacesToAvoid2,
124                                          const TopTools_ListOfShape& theFacesToAvoidAdj);
125
126 //=======================================================================
127 // function: BOP_SolidSolid::BOP_SolidSolid
128 // purpose: 
129 //=======================================================================
130   BOP_SolidSolid::BOP_SolidSolid()
131 {
132 }
133 //=======================================================================
134 // function: Destroy
135 // purpose: 
136 //=======================================================================
137   void BOP_SolidSolid::Destroy() {}
138
139 //=======================================================================
140 // function: DoDoWithFiller
141 // purpose: 
142 //=======================================================================
143   void BOP_SolidSolid::DoWithFiller(const BOPTools_DSFiller& aDSFiller) 
144 {
145   myErrorStatus=0;
146   myIsDone=Standard_False;
147   //
148   myResultMap.Clear();
149   myModifiedMap.Clear();
150   //
151   myDSFiller=(BOPTools_DSFiller*) &aDSFiller;
152   //
153   try {
154     OCC_CATCH_SIGNALS
155
156     // modified by NIZHNY-MKK  Fri Sep  3 15:14:17 2004.BEGIN
157     if(!myDSFiller->IsDone()) {
158       myErrorStatus = 1;
159       BOPTColStd_Dump::PrintMessage("DSFiller is invalid: Can not build result\n");
160       return;
161     }
162     // modified by NIZHNY-MKK  Fri Sep  3 15:14:20 2004.END
163     Standard_Boolean bIsNewFiller;
164     bIsNewFiller=aDSFiller.IsNewFiller();
165     
166     if (bIsNewFiller) {
167       Prepare();
168
169       PrepareFaceSplits();
170
171       aDSFiller.SetNewFiller(!bIsNewFiller);
172     }
173     //
174     DoNewFaces();
175     //
176     BuildResult();
177     //
178     // Treat of internals
179     CollectInternals();
180     BOP_Refiner aRefiner;
181     aRefiner.SetShape(myResult);
182     aRefiner.SetInternals(myInternals);
183     aRefiner.Do();
184     //
185     BOP_CorrectTolerances::CorrectTolerances(myResult, 0.01);
186     //
187     FillModified();
188
189     if(!myHistory.IsNull()) {
190       Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = 
191         Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory);
192       aSolidHistory->SetResult(myResult, myDSFiller);
193     }
194
195     myIsDone=Standard_True;
196   }
197   catch ( Standard_Failure ) {
198     myErrorStatus = 1;
199     BOPTColStd_Dump::PrintMessage("Can not build result\n");
200   }
201 }
202
203 //=================================================================================
204 // function: BuildResult
205 // purpose: 
206 //=================================================================================
207   void BOP_SolidSolid::BuildResult() 
208 {
209   BOP_ShellFaceSet theSFS(TopoDS::Solid(myShape1));
210
211   PrepareSFS(myNewFaces, theSFS);
212   //
213   BOP_SolidBuilder aSOBU;
214   
215   BRep_Builder aBB;
216   TopoDS_Solid aNewSolid;
217   TopoDS_Shell aNewShell;
218   TopTools_ListOfShape aListOfResult;
219
220   aSOBU.InitSolidBuilder(theSFS, Standard_True);
221   for(aSOBU.InitSolid(); aSOBU.MoreSolid(); aSOBU.NextSolid()) {
222     aBB.MakeSolid(aNewSolid);
223
224     for(aSOBU.InitShell(); aSOBU.MoreShell(); aSOBU.NextShell()) {
225
226       if(aSOBU.IsOldShell()) {
227         aNewShell = aSOBU.OldShell();
228       }
229       else {
230         aBB.MakeShell(aNewShell);
231
232         for(aSOBU.InitFace(); aSOBU.MoreFace(); aSOBU.NextFace()) {
233           TopoDS_Face aFace = aSOBU.Face();
234           aBB.Add(aNewShell, aFace);
235         }
236
237         Standard_Boolean isclosed = Standard_False;
238         TopTools_IndexedDataMapOfShapeListOfShape aMap;
239         TopExp::MapShapesAndAncestors(aNewShell, TopAbs_EDGE, TopAbs_FACE, aMap);
240         Standard_Integer nbedge = aMap.Extent();
241
242         for(Standard_Integer eiterator = 1; eiterator <= nbedge; eiterator++) {
243           const TopoDS_Shape& aShape = aMap.FindKey(eiterator);
244           TopAbs_Orientation anOrientation = aShape.Orientation();
245
246           if((anOrientation == TopAbs_INTERNAL) ||
247              (anOrientation == TopAbs_EXTERNAL) ||
248              (BRep_Tool::Degenerated(TopoDS::Edge(aShape))))
249             continue;
250           Standard_Integer nbface = aMap(eiterator).Extent();
251
252           if(nbface < 2) { // (here should be additional condition)
253             isclosed = Standard_False;
254             break;
255           }
256         }
257         aNewShell.Closed(isclosed);
258       } // end else of if(aSOBU.IsOldShell())
259       aBB.Add(aNewSolid, aNewShell);
260     }
261     aListOfResult.Append(aNewSolid);
262   }
263
264   TopoDS_Compound aCompound;
265   aBB.MakeCompound(aCompound);
266   
267   TopTools_ListIteratorOfListOfShape aResultIt(aListOfResult);
268   
269   for(; aResultIt.More(); aResultIt.Next()) {
270     aBB.Add(aCompound, aResultIt.Value());
271   }
272   
273   myResult=aCompound;
274 }
275
276 //=======================================================================
277 // function: DoNewFaces
278 // purpose: 
279 //=======================================================================
280   void BOP_SolidSolid::DoNewFaces() 
281 {
282   const BooleanOperations_ShapesDataStructure& aDS=myDSFiller->DS();
283   BOPTools_InterferencePool* pIntrPool=(BOPTools_InterferencePool*)&myDSFiller->InterfPool();
284   BOPTools_CArray1OfSSInterference& aFFs=pIntrPool->SSInterferences();
285   //
286   // EF Maps
287   const TopoDS_Shape& anObj=aDS.Object();
288   const TopoDS_Shape& aTool=aDS.Tool();
289   
290   TopTools_IndexedMapOfShape anEMap;
291   TopTools_IndexedDataMapOfShapeListOfShape aMEFObj, aMEFTool;
292   TopExp::MapShapesAndAncestors (anObj, TopAbs_EDGE , TopAbs_FACE , aMEFObj);
293   TopExp::MapShapesAndAncestors (aTool, TopAbs_EDGE , TopAbs_FACE , aMEFTool);
294   //
295   Standard_Boolean bIsTouchCase, bIsTouch, bToReverseFace;    
296   Standard_Integer i, aNb, j, aNbj, iFF, nF1, iRank;
297   TopTools_ListOfShape aListOfNewFaces;
298   TopAbs_Orientation anOriF1;
299   TopTools_ListIteratorOfListOfShape anIt;
300
301   const TColStd_DataMapOfIntegerListOfInteger& aMapOfFaceSplits = myDSFiller->SplitFacePool();
302
303   //
304   // DoMap
305   BOPTColStd_IndexedDataMapOfIntegerIndexedMapOfInteger aFFMap;
306   BOP_BuilderTools::DoMap(aFFs, aFFMap);
307   //
308   aNb=aFFMap.Extent();
309   for (i=1; i<=aNb; i++) {
310     // 
311     // a. Prepare info about the Face nF1 and create WES for nF1
312     nF1=aFFMap.FindKey(i);
313     const TopoDS_Face& aF1=TopoDS::Face(aDS.Shape(nF1));
314     
315     anOriF1=aF1.Orientation();
316     iRank=aDS.Rank(nF1);
317
318     if(aMapOfFaceSplits.IsBound(nF1)) {
319       TopoDS_Face aFace = aF1;
320       TopTools_ListOfShape aLF;
321
322       const TColStd_ListOfInteger& aListOfSplitIndex = aMapOfFaceSplits.Find(nF1);
323       TColStd_ListIteratorOfListOfInteger aSplIt(aListOfSplitIndex);
324
325       for(; aSplIt.More(); aSplIt.Next()) {
326         Standard_Integer nFSpl = aSplIt.Value();
327         Standard_Boolean bAddFace = Standard_False;
328
329         BooleanOperations_StateOfShape aSt = aDS.GetState(nFSpl);
330
331         if(aSt != BooleanOperations_ON) {
332           BooleanOperations_StateOfShape aStateComp = BOP_BuilderTools::StateToCompare(iRank, myOperation);
333           
334           if(aStateComp == aSt) {
335             bAddFace = Standard_True;
336           }
337         }
338         else {
339            if(iRank == 1) {
340              bAddFace = TakeOnSplit(nFSpl, nF1);
341           }
342         }
343
344         if(bAddFace) {
345           const TopoDS_Shape& aFaceSpl = aDS.Shape(nFSpl);
346           aLF.Append(aFaceSpl);
347         }
348       }
349
350       TopTools_ListOfShape aLFx;
351       anIt.Initialize(aLF);
352
353       for (; anIt.More(); anIt.Next()) {
354         TopoDS_Shape& aFx=anIt.Value();
355         aFx.Orientation(anOriF1);
356         bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation);
357
358         if (bToReverseFace) {
359           aFx.Reverse();
360         }
361         aListOfNewFaces.Append(aFx);
362         aLFx.Append(aFx);
363
364         if(!myHistory.IsNull()) {
365           Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = 
366             Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory);
367           aSolidHistory->AddNewShape(aFace, aFx, myDSFiller);
368         }
369       }
370       //
371       // Fill "Modified"
372       FillModified(aFace, aLFx); 
373       continue;
374     }
375
376     myFace=aF1;
377     myFace.Orientation(TopAbs_FORWARD);
378     BOP_WireEdgeSet aWES (myFace);
379     
380     const TColStd_IndexedMapOfInteger& aFFIndicesMap=aFFMap.FindFromIndex(i);
381     aNbj=aFFIndicesMap.Extent();
382     // 
383     // b. The Switch: Same Domain Faces or Non-Same Domain Faces 
384     bIsTouchCase=Standard_False;
385     for (j=1; j<=aNbj; j++) {
386       iFF=aFFIndicesMap(j);
387       BOPTools_SSInterference& aFF=aFFs(iFF);
388       bIsTouchCase=aFF.IsTangentFaces();
389       if (bIsTouchCase) {
390         break;
391       }
392     }
393
394     // modified by NIZHNY-MKK  Tue Sep 16 11:11:22 2003.BEGIN
395     Standard_Boolean bIsCommonalgo = CheckFaceIntersection(nF1, myDSFiller);
396     BOP_WireEdgeSet atmpWES (myFace);
397     BOP_WireEdgeSet atmpWESAvoid (myFace);
398
399     if(!bIsCommonalgo) {
400       bIsCommonalgo = !BuildWESForCommonZone(nF1, aFFIndicesMap, myDSFiller, 
401                                             myOperation, atmpWES, atmpWESAvoid);
402     }
403
404     if(bIsCommonalgo) {
405       //
406       // c. Filling the WES for nF1
407       if (bIsTouchCase) { 
408         //                                               XXXXXXXXXXXXXXXXXXXXXXXXXX
409         //                                               X   nF1 has SD face(s)   X
410         //                                               XXXXXXXXXXXXXXXXXXXXXXXXXX
411         //
412         // 1. Add Split Parts having states in accordance with operation
413         AddSplitPartsINOUT (nF1, aWES);
414         //
415         // 2. Add Section Edges to the WES 
416         for (j=1; j<=aNbj; j++) {
417           iFF=aFFIndicesMap(j);
418           BOPTools_SSInterference& aFF=aFFs(iFF);
419           bIsTouch=aFF.IsTangentFaces();
420
421           if (!bIsTouch) {
422             AddSectionPartsSo(nF1, iFF, aWES);
423           }
424         }
425         //
426         // 3. Add IN2D, ON2D Parts to the WES 
427         for (j=1; j<=aNbj; j++) {
428           iFF = aFFIndicesMap(j);
429           BOPTools_SSInterference& aFF=aFFs(iFF);
430           bIsTouch = aFF.IsTangentFaces();
431
432           if (bIsTouch) {
433             Standard_Integer nF2;
434             nF2 = aFF.OppositeIndex(nF1);
435             AddINON2DPartsSo(iFF, nF1, nF2, aWES);
436             AddPartsEFSDSo(nF1, iFF, aMEFObj, aMEFTool, aWES);
437             AddPartsEESDSo(nF1, iFF, aMEFObj, aMEFTool, aWES);
438           }
439         }
440         //
441         // 4. On3D parts
442         for (j=1; j<=aNbj; j++) {
443           iFF=aFFIndicesMap(j);
444           BOPTools_SSInterference& aFF=aFFs(iFF);
445           bIsTouch=aFF.IsTangentFaces();
446
447           if (!bIsTouch) {
448             AddSplitPartsON3DSo (nF1, iFF, aWES);
449           }
450         }
451
452         // 5. Add EF parts (E (from F2) on F1 ),
453         // where F2 is non-same-domain face to F1
454         anEMap.Clear();
455         //
456         // anEMap will contain all Split parts that has already in aWES
457         const TopTools_ListOfShape& aLE=aWES.StartElements();
458         anIt.Initialize (aLE);
459
460         for (; anIt.More(); anIt.Next()) {
461           TopoDS_Shape& anE=anIt.Value();
462           anEMap.Add(anE);
463         }
464         //
465         for (j=1; j<=aNbj; j++) {
466           iFF = aFFIndicesMap(j);
467           BOPTools_SSInterference& aFF=aFFs(iFF);
468           bIsTouch = aFF.IsTangentFaces();
469
470           if (!bIsTouch) {
471             AddPartsEFNonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES);
472             AddPartsEENonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES);
473           }
474         }
475       } // end of  if (bIsTouchCase)
476       //
477       else {
478         //                                  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
479         //                                  X   nF1 does not have SD face(s)   X
480         //                                  XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
481         //
482         // 1. Add Split Parts having states in accordance with operation
483         AddSplitPartsINOUT (nF1, aWES);
484         //
485         // 2. Add Split Parts with state ON
486         AddSplitPartsONSo (nF1, aMEFObj, aMEFTool, aWES);
487         //
488         // 3. Add Section Edges to the WES 
489       
490         for (j=1; j<=aNbj; j++) {
491           iFF=aFFIndicesMap(j);
492           AddSectionPartsSo(nF1, iFF, aWES);
493         }
494         //
495         // 4. Add EF parts (E (from F2) on F1 )
496         anEMap.Clear();
497         for (j=1; j<=aNbj; j++) {
498           iFF=aFFIndicesMap(j);
499           AddPartsEFSo(nF1, iFF, aMEFObj, aMEFTool, anEMap, aWES);
500         }
501       }
502     } // end of if(bIsCommonalgo)
503     else {
504       TopTools_IndexedMapOfOrientedShape aMapOfSDFaceEdges;
505       BOP_WireEdgeSet aSDWES(myFace);
506
507       if (bIsTouchCase) {
508         // Add IN2D, ON2D Parts to the WES 
509         for (j=1; j<=aNbj; j++) {
510           iFF = aFFIndicesMap(j);
511           BOPTools_SSInterference& aFF = aFFs(iFF);
512           bIsTouch = aFF.IsTangentFaces();
513
514           if (bIsTouch) {
515             Standard_Integer nF2 = aFF.OppositeIndex(nF1);
516             AddINON2DPartsSo(iFF, nF1, nF2, aSDWES);
517             AddPartsEFSDSo(nF1, iFF, aMEFObj, aMEFTool, aSDWES);
518             AddPartsEESDSo(nF1, iFF, aMEFObj, aMEFTool, aSDWES);
519           }
520         }
521         //
522         // On3D parts
523         for (j=1; j<=aNbj; j++) {
524           iFF = aFFIndicesMap(j);
525           BOPTools_SSInterference& aFF = aFFs(iFF);
526           bIsTouch = aFF.IsTangentFaces();
527
528           if (!bIsTouch) {
529             AddSplitPartsON3DSo (nF1, iFF, aSDWES);
530           }
531         }
532
533         TopTools_IndexedMapOfOrientedShape aMapOfWESEdges;
534
535         for(aSDWES.InitStartElements(); aSDWES.MoreStartElements(); aSDWES.NextStartElement()) {
536           aMapOfWESEdges.Add(aSDWES.StartElement());
537         }
538
539         // Build SameDomain faces.
540         // Only edges from aMapOfWESEdges are represented in these faces
541         TopTools_ListOfShape aListOfSDFaces;
542
543         for (j = 1; j <= aNbj; j++) {
544           iFF = aFFIndicesMap(j);
545           BOPTools_SSInterference& aFF = aFFs(iFF);
546           bIsTouch = aFF.IsTangentFaces();
547
548           if (bIsTouch) {
549
550             Standard_Integer nF2 = aFF.OppositeIndex(nF1);
551             TopoDS_Face aF1FWD = aF1;
552             aF1FWD.Orientation (TopAbs_FORWARD);
553       
554             BOP_WireEdgeSet aWEScommon (aF1FWD);
555             BOP_SDFWESFiller aWESFiller(nF1, nF2, *myDSFiller);
556             aWESFiller.SetSenseFlag(aFF.SenseFlag());
557             aWESFiller.SetOperation(BOP_COMMON);
558             aWESFiller.Do(aWEScommon);
559
560             BOP_FaceBuilder aFB;
561             aFB.Do(aWEScommon);
562             const TopTools_ListOfShape& aLF = aFB.NewFaces();
563             TopTools_ListIteratorOfListOfShape anItLF(aLF);
564
565             for (; anItLF.More(); anItLF.Next()) {
566               const TopoDS_Shape& aFR = anItLF.Value();
567
568               if (aFR.ShapeType()==TopAbs_FACE) {
569                 const TopoDS_Face& aFaceResult=TopoDS::Face(aFR);
570                 //
571                 Standard_Boolean bIsValidIn2D  = Standard_False;
572                 Standard_Boolean bNegativeFlag = Standard_False;
573                 bIsValidIn2D = BOPTools_Tools3D::IsValidArea (aFaceResult, bNegativeFlag);
574
575                 if (bIsValidIn2D) {
576
577                   //            if(CheckSameDomainFaceInside(aFaceResult, aF2)) {
578                   Standard_Boolean bfound = Standard_True;
579                   TopExp_Explorer anExp(aFaceResult, TopAbs_EDGE);
580
581                   for(; anExp.More(); anExp.Next()) {
582                     if(!aMapOfWESEdges.Contains(anExp.Current())) {
583                       bfound = Standard_False;
584                       break;
585                     }
586                   }
587
588                   if(bfound)
589                     aListOfSDFaces.Append(aFaceResult);
590                   //            }
591                 }
592               }
593             }
594           }
595         }
596         // end  for (j = 1; j <= aNbj...
597
598         TopTools_ListIteratorOfListOfShape anItSD(aListOfSDFaces);
599
600         for(; anItSD.More(); anItSD.Next()) {
601           const TopoDS_Shape& aShape = anItSD.Value();
602           TopoDS_Face aFx = TopoDS::Face(aShape);
603           TopExp_Explorer anExp(aFx, TopAbs_EDGE);
604
605           for(; anExp.More(); anExp.Next()) {
606             aMapOfSDFaceEdges.Add(anExp.Current());
607           }
608           aFx.Orientation(anOriF1);
609           bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation);
610
611           if (bToReverseFace) {
612             aFx.Reverse();
613           }
614           aListOfNewFaces.Append(aFx);
615         }
616       }
617
618       // Build Common Zone faces, based on intersection lines and
619       // splits with state ON (see BuildWESForCommonZone()).
620       TopTools_ListOfShape aListOfCommonZoneFace;
621       Standard_Integer awesit = 0;
622
623       for(awesit = 0; awesit < 2; awesit++) {
624         BOP_WireEdgeSet& aCurWEStmp = (awesit == 0) ? atmpWES : atmpWESAvoid;
625         BOP_WireEdgeSet aCurWES(myFace);
626
627         for(aCurWEStmp.InitStartElements(); aCurWEStmp.MoreStartElements(); aCurWEStmp.NextStartElement()) {
628           if(!aMapOfSDFaceEdges.Contains(aCurWEStmp.StartElement())) {
629             aCurWES.AddStartElement(aCurWEStmp.StartElement());
630           }
631         }
632
633         if(!aCurWES.StartElements().IsEmpty()) {
634           BOP_FaceBuilder aFB;
635     
636           aFB.SetTreatment(0); // 0 -Do internal edges, 1 -No Internal Edges
637           aFB.SetTreatSDScales(1);
638           aFB.Do(aCurWES);
639           const TopTools_ListOfShape& aLF = aFB.NewFaces();
640           anIt.Initialize(aLF);
641
642           for (; anIt.More(); anIt.Next()) {
643             TopoDS_Shape& aFx=anIt.Value();
644             aFx.Orientation(anOriF1);
645
646             if(awesit == 0) {
647               bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation);
648
649               if (bToReverseFace) {
650                 aFx.Reverse();
651               }
652               aListOfNewFaces.Append(aFx);
653             }
654             aListOfCommonZoneFace.Append(aFx);
655           }
656         }
657       }
658       // end for(awesit = ...
659
660       // Construct WES to build faces out of common zone
661       BOP_WireEdgeSet aWES2 (myFace);
662       AddSplitPartsINOUT (nF1, aWES2);
663       //
664
665       if(!bIsTouchCase) {
666         AddSplitPartsONSo (nF1, aMEFObj, aMEFTool, aWES2);
667       }
668       //
669       for (j=1; j<=aNbj; j++) {
670         iFF=aFFIndicesMap(j);
671         AddSectionPartsSo(nF1, iFF, aWES2);
672       }
673       anEMap.Clear();
674
675       if(bIsTouchCase) {
676         for(aSDWES.InitStartElements(); aSDWES.MoreStartElements(); aSDWES.NextStartElement()) {
677           aWES2.AddStartElement(aSDWES.StartElement());
678         }
679
680         for(aWES2.InitStartElements(); aWES2.MoreStartElements(); aWES2.NextStartElement()) {
681           anEMap.Add(aWES2.StartElement());
682         }
683       }
684
685       for (j=1; j<=aNbj; j++) {
686         iFF = aFFIndicesMap(j);
687
688         if(!bIsTouchCase) {
689           LocalAddPartsEFSo(nF1, iFF, aMEFObj, aMEFTool, myDSFiller, 
690                             myOperation, aListOfCommonZoneFace, anEMap, aWES2);
691         }
692         else {
693           BOPTools_SSInterference& aFF = aFFs(iFF);
694           bIsTouch = aFF.IsTangentFaces();
695
696           if (!bIsTouch) {
697             AddPartsEFNonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES2);
698             AddPartsEENonSDSo (nF1, iFF, aMEFObj, aMEFTool, aFFIndicesMap, anEMap, aWES2);
699           }
700         }
701       }
702
703       aWES.ClearContents();
704
705       aWES2.InitStartElements();
706
707       for (; aWES2.MoreStartElements(); aWES2.NextStartElement()) {
708         if(aMapOfSDFaceEdges.Contains(aWES2.StartElement()))
709           continue;
710         Standard_Boolean bisequal = Standard_False;
711         Standard_Integer wesit = 0;
712
713         for(wesit = 0; wesit < 2; wesit++) {
714           BOP_WireEdgeSet& acurwes = (wesit == 0) ? atmpWES : atmpWESAvoid;
715           acurwes.InitStartElements();
716
717           for (; !bisequal && acurwes.MoreStartElements(); acurwes.NextStartElement()) {
718             const TopoDS_Shape& anE = acurwes.StartElement();
719             bisequal = anE.IsEqual(aWES2.StartElement());
720           }
721         }
722
723         if(!bisequal) {
724           aWES.AddStartElement(aWES2.StartElement());
725         }
726       }
727       //end for (; aWES2.MoreStartElements...
728     }
729     // modified by NIZHNY-MKK  Tue Sep 16 11:11:33 2003.END
730     
731     //
732     //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
733     // Display the WES
734     if (myDraw)  {
735       const TopTools_ListOfShape& aWESL=aWES.StartElements();
736       BOP_Draw::DrawListOfEdgesWithPC (myFace, aWESL, i, "ew_"); 
737       BOP_Draw::Wait();
738     }
739     //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
740     //
741     // d. Build new Faces from myFace
742     BOP_FaceBuilder aFB;
743     
744     aFB.SetTreatment(0); // 0 -Do internal edges, 1 -No Internal Edges
745     aFB.SetTreatSDScales(1);
746     aFB.Do(aWES);
747
748     const TopTools_ListOfShape& aLF=aFB.NewFaces();
749     //
750     // e. Do Internal Vertices
751     DoInternalVertices(nF1, aLF);
752     // 
753     // f. Orient new faces
754     TopTools_ListOfShape aLFx;
755     anIt.Initialize(aLF);
756     for (; anIt.More(); anIt.Next()) {
757       TopoDS_Shape& aFx=anIt.Value();
758       aFx.Orientation(anOriF1);
759       bToReverseFace=BOP_BuilderTools::ToReverseFace(iRank, myOperation);
760       if (bToReverseFace) {
761         aFx.Reverse();
762       }
763       aListOfNewFaces.Append(aFx);
764       aLFx.Append(aFx);
765
766       if(!myHistory.IsNull()) {
767         Handle(BOP_SolidSolidHistoryCollector) aSolidHistory = 
768           Handle(BOP_SolidSolidHistoryCollector)::DownCast(myHistory);
769         aSolidHistory->AddNewShape(aF1, aFx, myDSFiller);
770       }
771     }
772     //
773     // Fill "Modified"
774     FillModified(aF1, aLFx); 
775     //
776   }// for (i=1; i<=aNb; i++)
777
778   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
779   // Display the new Faces
780   if (myDraw) { 
781     BOP_Draw::DrawListOfShape(aListOfNewFaces, "fn_");
782   }
783   //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
784   myNewFaces.Clear();
785   myNewFaces.Append(aListOfNewFaces);
786 }
787
788 //=================================================================================
789 // function: PrepareSFS
790 // purpose: 
791 //=================================================================================
792   void BOP_SolidSolid::PrepareSFS(const TopTools_ListOfShape& theNewFaces,
793                                   BOP_ShellFaceSet& theSFS) 
794 {
795   
796   const BooleanOperations_ShapesDataStructure& theDS=myDSFiller->DS();
797
798   Standard_Integer iRank, lastindex, firstindex, i, a;
799   BooleanOperations_StateOfShape aChoosenState;
800
801   for(iRank = 1; iRank <= 2; iRank++) {
802     aChoosenState = BOP_BuilderTools::StateToCompare(iRank, myOperation);
803     //
804     const TopoDS_Shape& aSolid = (iRank==1) ? myShape1 : myShape2;
805     
806     firstindex=1;
807     lastindex=theDS.NumberOfShapesOfTheObject();
808     if (iRank==2) {
809       firstindex=lastindex+1;
810       lastindex=theDS.NumberOfSourceShapes();
811     }
812     
813     for(i = firstindex; i <= lastindex; i++) {
814
815       if((theDS.GetShapeType(i) != TopAbs_FACE) || (theDS.GetState(i) != aChoosenState))
816         continue;
817
818       
819       // compute orientation
820       TopoDS_Shape aFace=theDS.Shape(i);
821
822       TopAbs_Orientation anOri = TopAbs_FORWARD;
823       
824       for(a = 1; a <= theDS.NumberOfAncestors(i); a++) {
825         const TopoDS_Shape& aShell = theDS.GetShape(theDS.GetAncestor(i, a));
826
827         TopAbs_Orientation anAncestorOrientation = aShell.Orientation();
828         Standard_Boolean found = Standard_False;
829         
830         TopExp_Explorer aSolidExp(aSolid, TopAbs_SHELL);
831         for(;  !found && aSolidExp.More(); aSolidExp.Next()) {
832           
833           if(aShell.IsSame(aSolidExp.Current())) {
834             anAncestorOrientation = aSolidExp.Current().Orientation();
835             found = Standard_True;
836           }
837         }
838         
839         if(!found) {
840           // raise the exception: programming error
841           BOPTColStd_Dump::PrintMessage
842             ("BOP_SolidSolid::PrepareSFS(). Raises the exception: programming error...\n");
843           continue;
844         }
845         
846         TopoDS_Shape anOrientedShell = aShell;
847         anOrientedShell.Orientation(anAncestorOrientation);
848         
849         TopExp_Explorer aShellExp(anOrientedShell, TopAbs_FACE); 
850         for(; aShellExp.More(); aShellExp.Next()) { 
851           
852           if(!aFace.IsSame(aShellExp.Current()))
853             continue;
854
855           anOri = aShellExp.Current().Orientation();
856           
857           if(BOP_BuilderTools::ToReverseFace(iRank, myOperation)) {
858             anOri = TopAbs::Complement(anOri);
859           }
860           aFace.Orientation(anOri);
861           
862           theSFS.AddStartElement(aFace);
863         } // end shell explorer
864       }
865     } // end source shapes explorer
866   }
867
868   TopTools_ListIteratorOfListOfShape anIt(theNewFaces);
869
870   for(;anIt.More(); anIt.Next()) {
871     theSFS.AddStartElement(anIt.Value());
872   }
873 }
874
875 // --------------------------------------------------------------------------------------------------------
876 // static function: CheckFaceIntersection
877 // purpose: Returns Standard_True if there are no any common zone for given face,
878 //          Returns Standard_False if there are common zones or probability of existance of the common zone
879 //          is high.
880 // --------------------------------------------------------------------------------------------------------
881 Standard_Boolean CheckFaceIntersection(const Standard_Integer   theFaceIndex,
882                                        const BOPTools_DSFiller* theDSFiller) {
883
884   const BooleanOperations_ShapesDataStructure& aDS              = theDSFiller->DS();
885   const BOPTools_PaveFiller&                   aPaveFiller      = theDSFiller->PaveFiller();
886   BOPTools_PaveFiller*                         pPaveFiller      = (BOPTools_PaveFiller*)&aPaveFiller;
887   BOPTools_CommonBlockPool&                    aCBPool          = pPaveFiller->ChangeCommonBlockPool();
888 //   const BOPTools_SplitShapesPool&              aSplitShapesPool = aPaveFiller.SplitShapesPool();
889
890   BOPTools_InterferencePool* pIntrPool=
891     (BOPTools_InterferencePool*)&theDSFiller->InterfPool();
892   
893   BOPTools_CArray1OfSSInterference& aFFs = pIntrPool->SSInterferences();
894   Standard_Integer i = 0;
895
896   for(i = 1; i <= aFFs.Length(); i++) {
897     BOPTools_SSInterference& aFF = aFFs(i);
898
899     if((aFF.Index1() != theFaceIndex) && (aFF.Index2() != theFaceIndex))
900       continue;
901
902     Standard_Integer otherindex = aFF.OppositeIndex(theFaceIndex);
903
904     BOPTools_SequenceOfCurves& aSC = aFF.Curves();
905     Standard_Integer aNbCurves = aSC.Length();
906
907     if(aNbCurves > 0) {
908       TopoDS_Shape aF1 = aDS.Shape(theFaceIndex);
909       TopoDS_Shape aF2 = aDS.Shape(otherindex);
910       TopExp_Explorer anExp;
911
912       for(Standard_Integer j = 0; j < 2; j++) {
913         Standard_Integer afaceindextocompare = (j == 0) ? otherindex : theFaceIndex;
914         Standard_Integer aFaceRank = 1;
915         if(j == 0) {
916           anExp.Init(aF1, TopAbs_EDGE);
917           aFaceRank = aDS.Rank(theFaceIndex);
918         }
919         else {
920           anExp.Init(aF2, TopAbs_EDGE);
921           aFaceRank = aDS.Rank(otherindex);
922         }
923
924         for(; anExp.More(); anExp.Next()) {
925           const TopoDS_Edge& aEF = TopoDS::Edge(anExp.Current());
926           Standard_Integer nEF = aDS.ShapeIndex(aEF, aFaceRank);
927           BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(nEF));
928           BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
929
930           for (; anItCB.More(); anItCB.Next()) {
931             BOPTools_CommonBlock& aCB=anItCB.Value();
932             Standard_Integer nFace = aCB.Face();
933
934             if(nFace == afaceindextocompare)
935               return Standard_False;
936           }
937         }
938       }
939     }
940   }
941
942   return Standard_True;
943 }
944
945 // ----------------------------------------------------------------------------------------------------------------
946 // static function: BuildWESForCommonZone
947 // purpose: Finds common zones which contains boundaries represented by new geometry
948 //          Fills theWES if zones could be included in result,
949 //          Fills theWESAvoid if zones could not be included in result.
950 //          Returns true if common zones are found, otherwise returns false.
951 // ----------------------------------------------------------------------------------------------------------------
952 Standard_Boolean BuildWESForCommonZone(const Standard_Integer                           theFaceIndex,
953                                        const TColStd_IndexedMapOfInteger&               theFFIndicesMap,
954                                        const BOPTools_DSFiller*                         theDSFiller,
955                                        const BOP_Operation&                             theOperation,
956                                        BOP_WireEdgeSet&                                 theWES,
957                                        BOP_WireEdgeSet&                                 theWESAvoid) {
958
959   const BooleanOperations_ShapesDataStructure& aDS              = theDSFiller->DS();
960 //   const BOPTools_PaveFiller&                   aPaveFiller      = theDSFiller->PaveFiller();
961 //   BOPTools_PaveFiller*                         pPaveFiller      = (BOPTools_PaveFiller*)&aPaveFiller;
962 //   BOPTools_CommonBlockPool&                    aCBPool          = pPaveFiller->ChangeCommonBlockPool();
963 //   const BOPTools_SplitShapesPool&              aSplitShapesPool = aPaveFiller.SplitShapesPool();
964   
965   BOPTools_InterferencePool* pIntrPool=
966     (BOPTools_InterferencePool*)&theDSFiller->InterfPool();
967   
968   BOPTools_CArray1OfSSInterference& aFFs = pIntrPool->SSInterferences();
969
970   TopoDS_Face aFace = TopoDS::Face(aDS.Shape(theFaceIndex));
971   TopoDS_Face myFace = aFace;
972   myFace.Orientation(TopAbs_FORWARD);
973 //   Standard_Integer iFaceRank = aDS.Rank(theFaceIndex);
974   TopTools_IndexedDataMapOfShapeListOfShape aMapFCommonZones, aMapFCommonZones2;
975   Standard_Integer j = 0, k = 0;
976
977   for (j = 1; j <= theFFIndicesMap.Extent(); j++) {
978     BOP_WireEdgeSet atmpWES(myFace);
979
980     Standard_Integer iFF= theFFIndicesMap(j);
981     BOPTools_SSInterference& aFF = aFFs(iFF);
982     Standard_Integer aFaceIndex2 = aFF.OppositeIndex(theFaceIndex);
983     TopoDS_Face aFace2 = TopoDS::Face(aDS.Shape(aFaceIndex2));
984 //     Standard_Integer iFaceRank2 = aDS.Rank(aFaceIndex2);
985
986     BOPTools_SequenceOfCurves& aSC = aFF.Curves();
987     Standard_Integer aNbCurves = aSC.Length();
988     Standard_Integer i = 0;
989
990     for (i = 1; i <= aNbCurves; i++) {
991       const BOPTools_Curve& aBC = aSC(i);
992       const BOPTools_ListOfPaveBlock& aLPB = aBC.NewPaveBlocks();
993       BOPTools_ListIteratorOfListOfPaveBlock anIt(aLPB);
994
995       for (; anIt.More(); anIt.Next()) {
996         const BOPTools_PaveBlock& aPB=anIt.Value();
997         Standard_Integer nE = aPB.Edge();
998         const TopoDS_Edge& aE = TopoDS::Edge(aDS.Shape(nE));
999
1000         TopoDS_Edge aES=aE;
1001         atmpWES.AddStartElement(aES);
1002         aES.Reverse();
1003         atmpWES.AddStartElement(aES);
1004       }
1005     }
1006     BOP_SDFWESFiller aWESFiller(theFaceIndex, aFaceIndex2, *theDSFiller);
1007     Standard_Integer iSenseFlag = 0;
1008     Standard_Integer iRankF1 = aDS.Rank(theFaceIndex);
1009
1010     // compute iSenseFlag. begin
1011     gp_Dir aDNF1, aDNF2;
1012     const BOPTools_ListOfPaveBlock& aLPB = aFF.PaveBlocks();
1013
1014     if (aLPB.IsEmpty()) {
1015       continue;
1016     }
1017     const BOPTools_PaveBlock& aPB = aLPB.First();
1018     const TopoDS_Edge& aSpE = TopoDS::Edge(aDS.Shape(aPB.Edge()));
1019     BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpE, aFace, aDNF1); 
1020     BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpE, aFace2, aDNF2);
1021     Standard_Real aScPr = aDNF1*aDNF2;
1022
1023     if (aScPr<0.) {
1024       iSenseFlag = -1;
1025     }
1026     else if (aScPr>0.) {
1027       iSenseFlag = 1;
1028     }
1029     // compute iSenseFlag. end
1030
1031     aWESFiller.SetSenseFlag(iSenseFlag);
1032     aWESFiller.SetOperation(BOP_COMMON);
1033     aWESFiller.Do(atmpWES);
1034
1035     BOP_FaceBuilder aFB;
1036     aFB.Do(atmpWES);
1037     const TopTools_ListOfShape& aLF = aFB.NewFaces();
1038     
1039     if(aLF.IsEmpty()) {
1040       continue;
1041     }
1042
1043     TopTools_ListIteratorOfListOfShape anIt(aLF);
1044     
1045     for(; anIt.More(); anIt.Next()) {
1046       const TopoDS_Face& aCurFace = TopoDS::Face(anIt.Value());
1047       // check common zone.begin
1048       Standard_Boolean IsSameDomain = Standard_True;
1049       Standard_Boolean bIsValidIn2D = Standard_False, bNegativeFlag = Standard_False;
1050       bIsValidIn2D = BOPTools_Tools3D::IsValidArea (aCurFace, bNegativeFlag);
1051
1052       if(bIsValidIn2D) {
1053         Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aCurFace);
1054         Standard_Real aTolerance = BRep_Tool::Tolerance(aFace) + BRep_Tool::Tolerance(aFace2);
1055         IntTools_Context aContext;
1056         Standard_Real umin, umax, vmin, vmax;
1057         BRepTools::UVBounds(aCurFace, umin, umax, vmin, vmax);
1058         Standard_Real deltau = (umax - umin) * 0.1;
1059         Standard_Real deltav = (vmax - vmin) * 0.1;
1060
1061         for(Standard_Integer uit = 1; IsSameDomain && (uit < 9); uit++) {
1062           Standard_Real U = umin + uit * deltau;
1063
1064           for(Standard_Integer vit = 1; vit < 9; vit++) {
1065             Standard_Real V = vmin + vit * deltav;
1066
1067             if(aContext.IsPointInOnFace(aCurFace, gp_Pnt2d(U, V))) {
1068               gp_Pnt aCurPoint = aSurface->Value(U, V);
1069
1070               if(!aContext.IsValidPointForFace(aCurPoint, aFace2, aTolerance)) {
1071                 IsSameDomain = Standard_False;
1072                 break;
1073               }
1074             }
1075           }
1076         }
1077       }
1078       // check common zone.end
1079
1080       if(IsSameDomain) {
1081         Standard_Integer addcommonzone = Standard_False;
1082
1083         if (iSenseFlag==1) {
1084           switch (theOperation) {
1085           
1086           case BOP_FUSE: 
1087             if (iRankF1==1) {
1088               addcommonzone = Standard_True;
1089             }
1090             break;
1091           
1092           case BOP_COMMON:
1093             if (iRankF1==1) {
1094               addcommonzone = Standard_True;
1095             }
1096             break;
1097       
1098           case BOP_CUT:   
1099           case BOP_CUT21: 
1100             break;
1101           
1102           default:
1103             break;
1104           }
1105         }
1106         else if (iSenseFlag==-1) { // iSenseFlag<0
1107           switch (theOperation) {
1108           
1109           case BOP_FUSE:   
1110           case BOP_COMMON: 
1111             break;
1112           
1113           case BOP_CUT: 
1114             if (iRankF1==1) {
1115               addcommonzone = Standard_True;
1116             }
1117             break;
1118
1119           case BOP_CUT21:
1120             if (iRankF1==2) {
1121               addcommonzone = Standard_True;
1122             }
1123           default:
1124             break;
1125           }
1126         }
1127         TopTools_ListOfShape thelist;
1128         if(addcommonzone) {
1129           if(!aMapFCommonZones.Contains(aFace2))            
1130             aMapFCommonZones.Add(aFace2, thelist);
1131           aMapFCommonZones.ChangeFromKey(aFace2).Append(aCurFace);
1132         }
1133         else {
1134           if(!aMapFCommonZones2.Contains(aFace2))
1135             aMapFCommonZones2.Add(aFace2, thelist);
1136           aMapFCommonZones2.ChangeFromKey(aFace2).Append(aCurFace);
1137         }
1138       }
1139     }
1140   }
1141
1142   if(aMapFCommonZones.IsEmpty() && aMapFCommonZones2.IsEmpty()) {
1143     return Standard_False;
1144   }
1145   Standard_Integer amapit = 0;
1146
1147   for(amapit = 0; amapit < 2; amapit++) {
1148     const TopTools_IndexedDataMapOfShapeListOfShape& aMap = 
1149       (amapit == 0) ? aMapFCommonZones : aMapFCommonZones2;
1150     BOP_WireEdgeSet& aWES = (amapit == 0) ? theWES : theWESAvoid;
1151
1152     for(k = 1; k <= aMap.Extent(); k++) {
1153       const TopTools_ListOfShape& alf = aMap(k);
1154       TopTools_ListIteratorOfListOfShape anIt(alf);
1155
1156       for(; anIt.More(); anIt.Next()) {
1157         TopExp_Explorer anExp(anIt.Value(), TopAbs_EDGE);
1158
1159         for(; anExp.More(); anExp.Next()) {
1160           aWES.AddStartElement(anExp.Current());
1161         }
1162       }
1163     }
1164   }
1165   //end for(amapit = ...
1166
1167   return Standard_True;
1168 }
1169
1170 // ----------------------------------------------------------------------------------------------------------------
1171 // static function: LocalAddPartsEFSo
1172 // purpose: Adds split parts of edges, which lay on face nF1, to theWES.
1173 //          It uses found common zones (theListOfSDFace) to check
1174 //          if a split part should be represented in theWES twice or not.
1175 // ----------------------------------------------------------------------------------------------------------------
1176 void LocalAddPartsEFSo (const Standard_Integer nF1, 
1177                         const Standard_Integer iFF,
1178                         const TopTools_IndexedDataMapOfShapeListOfShape& theMEFObj,
1179                         const TopTools_IndexedDataMapOfShapeListOfShape& theMEFTool,
1180                         const BOPTools_DSFiller*                         theDSFiller,
1181                         const BOP_Operation&                             theOperation,
1182                         const TopTools_ListOfShape&                      theListOfSDFace,
1183                         TopTools_IndexedMapOfShape&                      theEMap,
1184                         BOP_WireEdgeSet&                                 theWES) {
1185
1186   const BooleanOperations_ShapesDataStructure& aDS = theDSFiller->DS();
1187   BOPTools_InterferencePool* pIntrPool=(BOPTools_InterferencePool*)&theDSFiller->InterfPool();
1188   BOPTools_CArray1OfSSInterference& aFFs=pIntrPool->SSInterferences();
1189   
1190   const BOPTools_PaveFiller& aPF    = theDSFiller->PaveFiller();
1191   BOPTools_PaveFiller* pPaveFiller  =(BOPTools_PaveFiller*)&aPF;
1192   BOPTools_CommonBlockPool& aCBPool = pPaveFiller->ChangeCommonBlockPool();
1193   BOPTools_SSInterference& aFF=aFFs(iFF);
1194   Standard_Integer nF2 = aFF.OppositeIndex(nF1);
1195   const TopoDS_Face& aFace  =TopoDS::Face(aDS.Shape(nF1));
1196   const TopoDS_Face& aFace2 =TopoDS::Face(aDS.Shape(nF2));
1197
1198   Standard_Integer anindextocompare = nF1;
1199   Standard_Integer iFaceRank1, iFaceRank2;
1200   iFaceRank1 = aDS.Rank(nF1);
1201   iFaceRank2 = aDS.Rank(nF2);
1202   Standard_Integer aFaceRank = iFaceRank2;
1203   const TopTools_IndexedDataMapOfShapeListOfShape& aMEF = (aFaceRank == 1) ? theMEFObj : theMEFTool;
1204   TopExp_Explorer anExp(aFace2, TopAbs_EDGE);
1205
1206   for(; anExp.More(); anExp.Next()) {
1207     const TopoDS_Edge& aEF = TopoDS::Edge(anExp.Current());
1208     Standard_Integer nEF   = aDS.ShapeIndex(aEF, aFaceRank);
1209     BOPTools_ListOfCommonBlock& aLCB = aCBPool(aDS.RefEdge(nEF));
1210     BOPTools_ListIteratorOfListOfCommonBlock anItCB(aLCB);
1211
1212     for (; anItCB.More(); anItCB.Next()) {
1213       BOPTools_CommonBlock& aCB=anItCB.Value();
1214       Standard_Integer nFace = aCB.Face();
1215
1216       if (nFace == anindextocompare) {
1217         BOPTools_PaveBlock& aPB = aCB.PaveBlock1(nEF);
1218
1219         Standard_Integer nSplit = aPB.Edge();
1220         const TopoDS_Shape& aSplit = aDS.Shape(nSplit);
1221
1222         if (theEMap.Contains(aSplit)) {
1223           continue;// next CB
1224         }
1225         theEMap.Add(aSplit);
1226         TopoDS_Edge aSS = TopoDS::Edge(aSplit);
1227         //
1228         TopoDS_Face aFAdj;
1229         Standard_Boolean bIsAdjExists = Standard_False;
1230
1231         bIsAdjExists = BOPTools_Tools3D::GetAdjacentFace(aFace2, aEF, aMEF, aFAdj);
1232         Standard_Boolean bIsKeepTwice = Standard_False;
1233
1234         if(bIsAdjExists) {
1235           bIsKeepTwice = LocalIsKeepTwice(aFace, aFace2, aFAdj, aSS, theListOfSDFace, theListOfSDFace);
1236         }
1237         else {
1238           bIsKeepTwice = BOPTools_Tools3D::IsTouchCase(aSS, aFace, aFace2);
1239         }
1240         
1241         if(bIsKeepTwice) {
1242           theWES.AddStartElement(aSS);
1243           aSS.Reverse();
1244           theWES.AddStartElement(aSS);
1245         }
1246         else {
1247           aSS.Orientation(TopAbs_FORWARD);
1248           TopoDS_Face myFace = aFace;
1249           myFace.Orientation(TopAbs_FORWARD);
1250           BOP_BuilderTools::OrientSectionEdgeOnF1
1251             (myFace, aFace2, iFaceRank1, theOperation, aSS);
1252
1253           theWES.AddStartElement(aSS);
1254         }
1255       }
1256     }
1257   }
1258 }
1259
1260 // --------------------------------------------------------------------------------------------------------
1261 // static function: LocalIsKeepTwice
1262 // purpose:
1263 // --------------------------------------------------------------------------------------------------------
1264 Standard_Boolean LocalIsKeepTwice(const TopoDS_Face&          aF1,
1265                                   const TopoDS_Face&          aF2,
1266                                   const TopoDS_Face&          aF2Adj,
1267                                   const TopoDS_Edge&          aSpEF2,
1268                                   const TopTools_ListOfShape& theFacesToAvoid2,
1269                                   const TopTools_ListOfShape& theFacesToAvoidAdj) {
1270
1271   Standard_Real aT1, aT2, aT, dt=1.e-7, A, B, C, D, d2, d2Adj;
1272   gp_Dir aDNF1, aDNF2, DBF2, aDNF2Adj, DBF2Adj;
1273   gp_Vec aD1Sp;
1274   gp_Pnt aP, aPF2, aPF2Adj;
1275
1276   Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aSpEF2, aT1, aT2);
1277   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
1278   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF1, aT, aDNF1);
1279   
1280   //
1281   aC3D->D1(aT, aP, aD1Sp);
1282   gp_Dir aDD1Sp(aD1Sp); 
1283   
1284   if (aSpEF2.Orientation()==TopAbs_REVERSED) {
1285     aDD1Sp.Reverse();
1286   }
1287   // Split Normal on F2
1288   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2, aT, aDNF2);
1289   if (aF2.Orientation()==TopAbs_REVERSED) {
1290     aDNF2.Reverse();
1291   }
1292   // Binormal on F2
1293   DBF2=aDNF2^aDD1Sp;
1294
1295   TopTools_ListIteratorOfListOfShape anIt;
1296   IntTools_Context aContext;
1297   Standard_Boolean dtfound = Standard_False;
1298   Standard_Real acurdt = dt;
1299
1300   while(!dtfound) {
1301     dtfound = Standard_True;
1302
1303     aPF2.SetCoord(aP.X() + acurdt*DBF2.X(), 
1304                   aP.Y() + acurdt*DBF2.Y(),
1305                   aP.Z() + acurdt*DBF2.Z());
1306     
1307     for(anIt.Initialize(theFacesToAvoid2); anIt.More(); anIt.Next()) {
1308       const TopoDS_Face& aFace = TopoDS::Face(anIt.Value());
1309
1310       if(aContext.IsValidPointForFace(aPF2, aFace, BRep_Tool::Tolerance(aFace))) {
1311         dtfound = Standard_False;
1312         break;
1313       }
1314     }
1315
1316     if(!aContext.IsValidPointForFace(aPF2, aF2, BRep_Tool::Tolerance(aF2))) {
1317       acurdt = dt;
1318       break;
1319     }
1320     acurdt *= 2.;
1321   }
1322
1323   if(!dtfound) {
1324     dt = 1.e-07;
1325     // Point near aP
1326     aPF2.SetCoord(aP.X()+dt*DBF2.X(), 
1327                   aP.Y()+dt*DBF2.Y(),
1328                   aP.Z()+dt*DBF2.Z());
1329   }
1330   //
1331   aDD1Sp.Reverse();
1332
1333   // Split Normal on F2Adj
1334   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2Adj, aT, aDNF2Adj);
1335   if (aF2Adj.Orientation()==TopAbs_REVERSED) {
1336     aDNF2Adj.Reverse();
1337   }
1338   // Binormal on F2Adj
1339   DBF2Adj=aDNF2Adj^aDD1Sp;
1340
1341   dt = 1.e-07;
1342   acurdt = dt;
1343   dtfound = Standard_False;
1344
1345   while(!dtfound) {
1346     dtfound = Standard_True;
1347     aPF2Adj.SetCoord(aP.X() + acurdt*DBF2Adj.X(), 
1348                      aP.Y() + acurdt*DBF2Adj.Y(),
1349                      aP.Z() + acurdt*DBF2Adj.Z());
1350     
1351     for(anIt.Initialize(theFacesToAvoidAdj); anIt.More(); anIt.Next()) {
1352       const TopoDS_Face& aFace = TopoDS::Face(anIt.Value());
1353
1354       if(aContext.IsValidPointForFace(aPF2Adj, aFace, BRep_Tool::Tolerance(aFace))) {
1355         dtfound = Standard_False;
1356         break;
1357       }
1358     }
1359
1360     if(!aContext.IsValidPointForFace(aPF2Adj, aF2Adj, BRep_Tool::Tolerance(aF2Adj))) {
1361       acurdt = dt;
1362       break;
1363     }
1364     acurdt *= 2.;
1365   }
1366
1367   if(!dtfound) {
1368     dt = 1.e-07;
1369     aPF2Adj.SetCoord(aP.X()+dt*DBF2Adj.X(), 
1370                      aP.Y()+dt*DBF2Adj.Y(),
1371                      aP.Z()+dt*DBF2Adj.Z());
1372   }
1373   //
1374   // Tangent Plane on F1
1375   gp_Pln aPlnN1(aP, aDNF1);
1376   aPlnN1.Coefficients(A, B, C, D);
1377   //
1378   d2   = A*aPF2.X()    + B*aPF2.Y()   + C*aPF2.Z()    + D;
1379   d2Adj= A*aPF2Adj.X() + B*aPF2Adj.Y()+ C*aPF2Adj.Z() + D;
1380   //
1381   if (fabs(d2)<1.e-10) {
1382     d2=0.;
1383   }
1384   if (fabs(d2Adj)<1.e-10) {
1385     d2Adj=0.;
1386   }
1387   //
1388   aT=d2*d2Adj;
1389   //
1390   return  (aT >= 0.);
1391 }
1392
1393 //=================================================================================
1394 // function: SetHistoryCollector
1395 // purpose: 
1396 //=================================================================================
1397 void BOP_SolidSolid::SetHistoryCollector(const Handle(BOP_HistoryCollector)& theHistory) 
1398 {
1399   if(theHistory.IsNull() ||
1400      !theHistory->IsKind(STANDARD_TYPE(BOP_SolidSolidHistoryCollector)))
1401     myHistory.Nullify();
1402   else
1403     myHistory = theHistory;
1404 }