Salome HOME
PAL10519: Partition problem in the case of a solids, intersected only by surface...
[modules/geom.git] / src / NMTAlgo / NMTAlgo_Splitter_1.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20 // File:        NMTAlgo_Splitter_1.cxx
21 // Created:     Mon Feb  2 14:58:54 2004
22 // Author:      Peter KURNEV
23 //              <pkv@irinox>
24
25
26 #include <NMTAlgo_Splitter.ixx>
27
28 #include <Precision.hxx>
29
30 #include <gp_Pnt.hxx>
31
32 #include <TopAbs_ShapeEnum.hxx>
33
34 #include <TopoDS.hxx>
35 #include <TopoDS_Edge.hxx>
36 #include <TopoDS_Face.hxx>
37 #include <TopoDS_Shape.hxx>
38 #include <TopoDS_Compound.hxx>
39 #include <TopoDS_Solid.hxx>
40 #include <TopoDS_Iterator.hxx>
41
42 #include <TopExp.hxx>
43 #include <TopExp_Explorer.hxx>
44
45 #include <TopTools_MapOfShape.hxx>
46 #include <TopTools_DataMapOfShapeListOfShape.hxx>
47 #include <TopTools_MapIteratorOfMapOfShape.hxx>
48 #include <TopTools_ListOfShape.hxx>
49 #include <TopTools_ListIteratorOfListOfShape.hxx>
50 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
51 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
54
55 #include <BRep_Tool.hxx>
56 #include <BRepClass3d_SolidClassifier.hxx>
57
58 #include <NMTAlgo_Loop3d.hxx>
59 //
60 #include <BOPTools_Tools2D.hxx>
61 #include <Geom_Curve.hxx>
62 #include <TopAbs_Orientation.hxx>
63 #include <TopTools_ListOfShape.hxx>
64 #include <TopTools_ListIteratorOfListOfShape.hxx>
65 #include <gp_Dir.hxx>
66 #include <gp_Pnt.hxx>
67 #include <BOPTools_Tools3D.hxx>
68 #include <TopoDS.hxx>
69 #include <BRep_Tool.hxx>
70 #include <gp_Pln.hxx>
71 #include <TopAbs_State.hxx>
72
73 //
74 static 
75   void RefineShells(const TopoDS_Shape& ,
76                     TopTools_ListOfShape&);
77 static 
78   void RefineSolids(const TopoDS_Shape& ,
79                     TopTools_ListOfShape&);
80
81 static
82   void GetPlanes (const TopoDS_Edge& anEx,
83                 const TopTools_IndexedDataMapOfShapeListOfShape& anEFMapx,
84                 const TopoDS_Face& aF1,
85                 TopAbs_State& aStPF1);
86
87 //=======================================================================
88 //function : ShellsAndSolids
89 //purpose  : 
90 //=======================================================================
91  void NMTAlgo_Splitter::ShellsAndSolids()
92 {
93   Standard_Boolean bMakeSolids;
94   TopAbs_ShapeEnum aType;
95   TopTools_ListIteratorOfListOfShape aItS;
96   TopTools_ListOfShape aLNS;
97   //
98   myAddedFacesMap.Clear();
99   bMakeSolids=(myLimit==TopAbs_SHAPE || myLimit<TopAbs_SHELL);
100   //
101   myInternalFaces.Clear(); // remove it after all modifs
102   //
103   aItS.Initialize(myListShapes);
104   for ( ;aItS.More(); aItS.Next()) {
105     const TopoDS_Shape& aS=aItS.Value();
106     //
107     if (myToolShapes.Contains(aS)) {
108       continue;
109     }
110     //
111     aType=aS.ShapeType();
112     if (aType > TopAbs_SHELL) {
113       continue;//face,wire,...
114     }
115     //
116     aLNS.Clear();
117     //
118     MakeShells (aS, aLNS);
119     //
120     if (bMakeSolids && aType==TopAbs_SOLID) {
121       MakeSolids(aS, aLNS);
122     }
123     //
124     TopTools_ListIteratorOfListOfShape it (aLNS);
125     for (; it.More(); it.Next()) {
126       myBuilder.Add (myShape, it.Value());
127     }
128   }
129   //
130   // add split faces
131   aItS.Initialize(myListShapes);
132   for ( ;aItS.More(); aItS.Next()) {
133     const TopoDS_Shape& aS=aItS.Value();
134     //
135     aType=aS.ShapeType();
136     if (aType!=TopAbs_FACE || myMapTools.Contains(aS)) {
137       continue; 
138     }
139     //
140     const TopoDS_Shape& aCSF=myImageShape.Image(aS).First();
141     TopoDS_Iterator itS(aCSF);
142     for (; itS.More(); itS.Next()){
143       const TopoDS_Shape& aF=itS.Value();
144       if (!myAddedFacesMap.Contains(aF)){
145         myBuilder.Add (myShape, aF);
146       }
147     }
148   }
149 }
150 //=======================================================================
151 //function : MakeShells
152 //purpose  : split S into compound of shells
153 //=======================================================================
154 void NMTAlgo_Splitter::MakeShells(const TopoDS_Shape& aS,
155                                   TopTools_ListOfShape& aLNS)
156 {
157   NMTAlgo_Loop3d aShellMaker;
158   //
159   // get compound of split faces of aS
160   const TopoDS_Shape& aFC=myImageShape.Image(aS).First();
161   aShellMaker.AddConstFaces(aFC);
162   //
163   // add split faces inside aS
164   TopoDS_Shape aIFC;
165   if (myClosedShapes.Contains(aS)) {
166     //
167     // internal faces compound  
168     aIFC=FindFacesInside(aS, Standard_True);
169     aShellMaker.AddSectionFaces(aIFC);
170   }
171   //
172   aLNS=aShellMaker.MakeShells(myAddedFacesMap);
173   //
174   RefineShells(aS, aLNS);
175   //
176   // Add faces added to new shell to myAddedFacesMap:
177   // avoid rebuilding twice common part of 2 solids.
178   TopTools_ListIteratorOfListOfShape itS(aLNS);
179   TopExp_Explorer expF;
180   for (; itS.More(); itS.Next()) {
181     const TopoDS_Shape& aSh=itS.Value();
182     expF.Init (aSh, TopAbs_FACE);
183     for (; expF.More(); expF.Next()){
184       const TopoDS_Shape& aFx=expF.Current();
185       myAddedFacesMap.Add (aFx);
186     }
187   }
188 }
189 //=======================================================================
190 //function : MakeSolids
191 //purpose  : make solids out of Shells
192 //=======================================================================
193 void NMTAlgo_Splitter::MakeSolids(const TopoDS_Shape&   theSolid,
194                                   TopTools_ListOfShape& theShellList)
195 {
196   // for a solid wrapping other shells or solids without intersection,
197   // it is necessary to find shells making holes in it
198   Standard_Boolean isWrapping;
199   TopTools_ListOfShape aNewSolids; // result
200   TopTools_ListOfShape aHoleShells;
201   TopoDS_Shape anInfinitePointShape;
202   TopTools_DataMapOfShapeShape aInOutMap;
203   TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
204   //
205   isWrapping = myWrappingSolid.Contains(theSolid);
206   if (!isWrapping && !theShellList.IsEmpty())  {
207     // check if theSolid initially has internal shells
208     TopoDS_Iterator aShellExp (theSolid);
209     aShellExp.Next();
210     isWrapping = aShellExp.More();
211   }
212   //
213   aShellIt.Initialize(theShellList);
214   for ( ; aShellIt.More(); aShellIt.Next()) {
215     const TopoDS_Shape & aShell = aShellIt.Value();
216     // check if a shell is a hole of theSolid
217     if (isWrapping && IsInside(anInfinitePointShape, aShell)){
218       aHoleShells.Append(aShell);
219     }
220     else {
221       // make a solid from a shell
222       TopoDS_Solid Solid;
223       myBuilder.MakeSolid( Solid );
224       myBuilder.Add (Solid, aShell);
225       
226       aNewSolids.Append (Solid);
227     }
228   }
229   //
230   // find outer a shell most close to each hole shell
231   aShellIt.Initialize(aHoleShells);
232   for (; aShellIt.More(); aShellIt.Next()){
233     const TopoDS_Shape & aHole = aShellIt.Value();
234     //
235     aSolisIt.Initialize(aNewSolids);
236     for ( ; aSolisIt.More(); aSolisIt.Next())    {
237       const TopoDS_Shape & aSolid = aSolisIt.Value();
238       //
239       if (! IsInside(aHole, aSolid)){
240         continue;
241       }
242       //
243       if ( aInOutMap.IsBound (aHole)){
244         const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
245         if ( IsInside( aSolid, aSolid2 )) {
246           aInOutMap.UnBind( aHole );
247           aInOutMap.Bind ( aHole, aSolid );
248         }
249       }
250       else{
251         aInOutMap.Bind (aHole, aSolid);
252       }
253     }
254     //
255     // add aHole to a solid
256     if (aInOutMap.IsBound( aHole )){
257       TopoDS_Shape & aSolid=aInOutMap(aHole);
258       myBuilder.Add (aSolid, aHole);
259     }
260   }
261   //
262   theShellList.Clear();
263   //
264   RefineSolids(theSolid, aNewSolids);
265   //
266   theShellList.Append(aNewSolids);
267 }
268  
269 //=======================================================================
270 //function : FindFacesInside
271 //purpose  : return compound of faces  of other shapes that are
272 //           inside <theShape>. 
273 //           <theShape> is an object shape.
274 //           <CheckClosed> makes avoid faces that do not form a
275 //           closed shell
276 //           <All> makes return already added faces
277 //=======================================================================
278   TopoDS_Shape NMTAlgo_Splitter::FindFacesInside(const TopoDS_Shape& theShape,
279                                                 const Standard_Boolean CheckClosed,
280                                                 const Standard_Boolean All)
281 {
282   TopExp_Explorer expl;
283   TopAbs_State aState;
284   //
285   // ================================================
286   // check if internal faces have been already found
287   // ================================================
288   if (myInternalFaces.IsBound(theShape)) {
289     TopoDS_Shape aIntFComp = myInternalFaces.Find (theShape);
290     TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find (theShape);
291
292     expl.Init( aIntRemFComp, TopAbs_FACE);
293     if (CheckClosed || !expl.More()){
294       return aIntFComp;
295     }
296     //
297     TopoDS_Compound C;
298     myBuilder.MakeCompound( C );
299     // add removed faces
300     for (; expl.More(); expl.Next()){
301       myBuilder.Add( C, expl.Current() );
302     }
303     // add good internal faces
304     expl.Init( aIntFComp, TopAbs_FACE);
305     for (; expl.More(); expl.Next()) {
306       myBuilder.Add( C, expl.Current() );
307     }
308     //
309     return C;
310   }
311
312   // ===================================
313   // get data for internal faces search
314   // ===================================
315   //
316   // compound of split faces of theShape 
317   const TopoDS_Shape& CSF = myImageShape.Image(theShape).First();
318   //
319   TopTools_MapOfShape MSE, MFP;
320   //xf
321   TopTools_IndexedMapOfShape  aMFCSF;
322   //xt
323   TopTools_DataMapOfShapeListOfShape DMSEFP;
324   TopTools_MapIteratorOfMapOfShape itm;
325   TopTools_ListOfShape EmptyL;
326   TopTools_ListIteratorOfListOfShape itl;
327   TopTools_IndexedDataMapOfShapeListOfShape DMEF;
328   //
329   // MSE filling: map of new section edges of CSF
330   expl.Init(CSF, TopAbs_EDGE);
331   for (; expl.More(); expl.Next()) {
332     const TopoDS_Shape& aE = expl.Current() ;
333     MSE.Add(aE);
334   }
335   //
336   // DMEF: map edge of CSF - faces of CSF
337   TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF);
338   //xf
339   TopExp::MapShapes(CSF, TopAbs_FACE, aMFCSF);
340   //xt
341   //
342   // Fill
343   // 1.  MFP - a map of faces to process: map of resulting faces except
344   // those of theShape; we`ll add to C those of them which are inside CSF
345   // 2.  DMSEFP - edge of MSE => faces of MFP
346   //
347   itl.Initialize(myListShapes);
348   for (;itl.More(); itl.Next()) {
349     const TopoDS_Shape& aShape = itl.Value();
350     //
351     if ( theShape.IsSame(aShape)) {
352       continue;
353     }
354     // fill maps
355     // iterate on split faces of aShape
356     const TopoDS_Shape& CSF1 = myImageShape.Image(aShape).First();
357     TopoDS_Iterator itF (CSF1);
358     for ( ; itF.More(); itF.Next()) {
359       const TopoDS_Shape& aF1 = itF.Value();
360       MFP.Add(aF1);
361       // iterate on edges of split faces of aShape,
362       // add to DMSEFP edges that are new
363       expl.Init(aF1, TopAbs_EDGE);
364       for (; expl.More(); expl.Next()) {
365         TopoDS_Shape aE1 = expl.Current();
366         if ( MSE.Contains(aE1)) {// section edge
367           if (!DMSEFP.IsBound(aE1)) {
368             DMSEFP.Bind(aE1, EmptyL);
369           }
370           DMSEFP(aE1).Append(aF1);
371         }
372       }
373     }
374   }//for (;itl.More(); itl.Next()) 
375   //
376   // add tool faces... (is absent)
377   //
378   // ===========================
379   // find faces inside theShape
380   // ===========================
381   Standard_Boolean sameDom1, sameDom2;
382   Standard_Boolean skipAlreadyAdded = Standard_False;
383   Standard_Boolean GoodOri, inside;
384   Standard_Real dot;
385   TopTools_ListOfShape KeepFaces;
386   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
387
388   // iterate on section edges, check faces of other shapes
389   // sharing section edges and put internal faces to KeepFaces
390   Mapit.Initialize(DMSEFP);
391   for (; Mapit.More() ; Mapit.Next()) {
392     // a new edge of theShape
393     const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key());
394     //
395     //Standard_Boolean isSectionE=IsSectionEdge(E);//(OrigE);  
396     //
397     // split faces of other shapes sharing E
398     TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E);
399     //
400     itl.Initialize( LSF );
401     while (itl.More()) {
402       // a split faces of other shape
403       TopoDS_Face aFace1 = TopoDS::Face(itl.Value());
404       // remove aFace1 form DMSEFP and MFP
405       LSF.Remove( itl ); // == itl.Next();
406       if (!MFP.Remove(aFace1)) {
407         continue; // was not is MFP (i.e already checked)
408       }      
409       //
410       // check if aFace1 was already added to 2 shells
411       if (!All &&
412           myAddedFacesMap.Contains(aFace1) &&
413           myAddedFacesMap.Contains(aFace1.Reversed())) {
414         skipAlreadyAdded = Standard_True;
415       }
416       //
417       //xf 
418       if (aMFCSF.Contains(aFace1)) {
419         // the face aFace1 can not be inside CSF 
420         // if CSF contains the aFace1
421         continue;
422       }
423       //xt
424       //
425       TopoDS_Shape anOrigFace = aFace1;
426       if (myImagesFaces.IsImage(aFace1)){
427         anOrigFace = myImagesFaces.Root(aFace1);
428       }
429       //
430       // <- A was here
431       //
432       // check that anOrigFace is not same domain with CSF faces it intersects
433       //
434       const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E
435       //
436       const TopoDS_Shape& origF1 = myImagesFaces.IsImage(FL.First()) ?
437         myImagesFaces.Root(FL.First()) : FL.First();
438       //
439       const TopoDS_Shape& origF2 = myImagesFaces.IsImage(FL.Last()) ?
440         myImagesFaces.Root(FL.Last()) : FL.Last();
441       //
442       sameDom1 = anOrigFace.IsSame( origF1 );
443       sameDom2 = anOrigFace.IsSame( origF2 );
444       //
445       if (!(sameDom1 || sameDom2) && HasSameDomainF( TopoDS::Face(anOrigFace) )) {       
446         sameDom1 = IsSameDomainF( TopoDS::Face(anOrigFace), TopoDS::Face(origF1));
447         if (origF1 == origF2) {
448           sameDom2 = sameDom1;
449         }
450       }
451       if (sameDom1 && sameDom2){
452         continue;
453       }
454       //
455       if (sameDom1 || sameDom2) {
456         inside = NMTAlgo_Loop3d::IsInside (E,
457                                            TopoDS::Face(FL.First()),
458                                            TopoDS::Face(FL.Last()),
459                                            1, dot, GoodOri);
460         if (inside || (dot + Precision::Angular() >= 1.0)) {
461           continue; // E is convex between origF1 and origF2 or they are tangent
462         }
463       }
464       //
465       GetPlanes(E, DMEF, aFace1, aState);
466       if (aState==TopAbs_IN) {
467         KeepFaces.Append(aFace1);
468       }
469     } //while (itl.More()) {
470   } //for (; Mapit.More() ; Mapit.Next() )
471
472   // ===================================================
473   // add not distributed faces connected with KeepFaces
474   // ===================================================
475
476   // ultimate list of internal faces
477   TopTools_ListOfShape KeptFaces;
478   //
479   // add to MFP not split tool faces as well, they may be connected with
480   // tool faces interfering with theShape
481   /*
482   itm.Initialize(myMapTools);
483   for (; itm.More(); itm.Next() ) {
484     const TopoDS_Shape& aToolFace = itm.Key();
485     if (!myImageShape.HasImage(aToolFace)){
486       MFP.Add (aToolFace);
487     }
488   }
489   */
490   //
491   if (MFP.IsEmpty())
492     KeptFaces.Append (KeepFaces);
493   //
494   while (!KeepFaces.IsEmpty()) {
495     // KeepEdges : map of edges of faces kept last time
496     TopTools_IndexedMapOfShape KeepEdges;
497     for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) {
498       TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges);
499       KeptFaces.Append( itl.Value() );
500     }
501     //
502     KeepFaces.Clear();
503     //
504     // keep faces connected with already kept faces by KeepEdges
505     for ( itm.Initialize(MFP); itm.More(); itm.Next() ) {
506       const TopoDS_Shape& FP = itm.Key();
507       for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) {
508         const TopoDS_Shape& se = expl.Current();
509         if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {
510           KeepFaces.Append(FP);
511           MFP.Remove(FP);
512           break;
513         }
514       }
515     }
516   }
517
518   // ===============================================================
519   // here MFP contains faces outer of theShape and those of shapes
520   // which do not interfere with theShape at all and between which
521   // there may be those wrapped by theShape and whose faces may be
522   // needed to be returned as well
523   // ===============================================================
524
525   Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID);
526   if (All || isSolid)  // All is for sub-result removal
527   {
528     for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) {
529       TopoDS_Shape aFace = itm.Key();
530
531       // find a shape aFace originates from
532       TopoDS_Shape anOrigShape = GetOriginalShape( aFace );
533
534       // find out if all faces of anOrigShape are not in MFP
535       // and by the way remove them from MFP
536       Standard_Boolean isAllOut = Standard_True;
537       TopoDS_Shape aSplitFaces = anOrigShape;
538       if (myImageShape.HasImage(anOrigShape))
539         aSplitFaces = myImageShape.Image(anOrigShape).First();
540
541       TopTools_ListOfShape aSplitFaceL;
542       for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next())
543       {
544         const TopoDS_Shape & aSpFace = expl.Current();
545         // a tool face which become object has image but the whole tool shape has not
546         if (myImageShape.HasImage( aSpFace ))
547         {
548           TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE );
549           for ( ; exF.More(); exF.Next() )
550           {
551             aSplitFaceL.Append( exF.Current() );
552             if ( ! MFP.Remove( exF.Current() ))
553               isAllOut = Standard_False;
554           }
555         }
556         else
557         {
558           aSplitFaceL.Append( aSpFace );
559           if ( ! MFP.Remove( aSpFace ))
560             isAllOut = Standard_False;
561         }
562       }
563       itm.Initialize( MFP );
564       if ( !isAllOut )
565         continue;
566
567       // classify anOrigShape against theShape
568       if (IsInside (anOrigShape, theShape)) {
569         if (isSolid && myClosedShapes.Contains(anOrigShape)) {
570           // to make a special care at solid reconstruction
571           myWrappingSolid.Add ( theShape );
572         }
573         // keep faces of an internal shape anOrigShape
574         KeptFaces.Append( aSplitFaceL );
575       }
576     }
577   }
578
579   // ====================================================
580   // check if kept faces form a shell without free edges
581   // ====================================================
582
583   DMEF.Clear();  // edge - kept faces
584   MFP.Clear(); // reuse it for wrong faces
585   if (CheckClosed) {
586     for (itl.Initialize(KeptFaces); itl.More(); itl.Next() ) 
587       TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF);
588
589     Standard_Integer i, nb = DMEF.Extent();
590     Standard_Boolean isClosed = Standard_False;
591     while (!isClosed) {
592       isClosed = Standard_True;
593       for (i=1;  isClosed && i<=nb;  ++i) {
594         const TopoDS_Shape& E = DMEF.FindKey( i );
595         if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) &&
596             ! MSE.Contains( E ))
597           isClosed = ( DMEF(i).Extent() != 1 );
598       }
599       if (!isClosed) {
600         const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face
601         MFP.Add( F ); 
602         // remove bad face from DMEF
603         for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {
604           const TopoDS_Shape& E = expl.Current();
605           TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E );
606           for (itl.Initialize( FL ); itl.More(); itl.Next() ) {
607             if ( F.IsSame( itl.Value() )) {
608               FL.Remove( itl );
609               break;
610             }
611           }
612         }
613       }
614     }
615   }
616
617   // ==============
618   // make a result
619   // ==============
620
621   TopoDS_Compound C;
622   // compound of removed internal faces
623   TopoDS_Compound CNotCl;
624
625   myBuilder.MakeCompound(C);
626   myBuilder.MakeCompound(CNotCl);
627
628   // add to compounds
629   itl.Initialize(KeptFaces);
630   for (; itl.More(); itl.Next() ) {
631     TopoDS_Shape & aIntFace = itl.Value();
632     //
633     if (!All &&
634         myAddedFacesMap.Contains(aIntFace) &&
635         myAddedFacesMap.Contains(aIntFace.Reversed())) {
636       continue;
637     }
638     //
639     if (! MFP.Contains( aIntFace )){
640       myBuilder.Add(C, aIntFace);
641     }
642     else{
643       myBuilder.Add(CNotCl, aIntFace);
644     }
645   }
646   //
647   if (!skipAlreadyAdded && CheckClosed) {
648     myInternalFaces.Bind(theShape, C);
649     myIntNotClFaces.Bind(theShape, CNotCl);
650   }
651   //
652   //
653   if (!myMapSIFC.IsBound(theShape)) {
654     TopoDS_Compound aCIF;
655     myBuilder.MakeCompound(aCIF);
656     //
657     itl.Initialize(KeptFaces);
658     for (; itl.More(); itl.Next() ) {
659       TopoDS_Shape & aIntFace = itl.Value();
660       if (! MFP.Contains(aIntFace )){
661         myBuilder.Add(aCIF, aIntFace);
662       }
663     }
664     myMapSIFC.Bind(theShape, aCIF);
665   }
666   //
667   return C;
668 }
669 //=======================================================================
670 //function : IsInside
671 //purpose  : Return True if the first vertex of S1 inside S2.
672 //           If S1.IsNull(), check infinite point against S2.
673 //=======================================================================
674 Standard_Boolean NMTAlgo_Splitter::IsInside (const TopoDS_Shape& theS1,
675                                              const TopoDS_Shape& theS2)
676 {
677   BRepClass3d_SolidClassifier aClassifier( theS2 );
678   //
679   TopExp_Explorer expl(theS1, TopAbs_VERTEX);
680   //
681   if (!expl.More()){
682     aClassifier.PerformInfinitePoint( ::RealSmall());
683   }
684   else  {
685     const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
686     aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
687                          BRep_Tool::Tolerance( aVertex ));
688   }
689   //
690   return ( aClassifier.State() == TopAbs_IN );
691 }
692 //=======================================================================
693 //function : GetOriginalShape
694 //purpose  : Return the  shape  aShape  originates from. aShape
695 //           should be a face or more complex result shape
696 //=======================================================================
697 TopoDS_Shape NMTAlgo_Splitter::GetOriginalShape(const TopoDS_Shape& theShape) const
698 {
699   TopoDS_Shape anOrigShape;
700
701   TopExp_Explorer expl( theShape, TopAbs_FACE);
702   if (expl.More()) {
703     TopoDS_Shape aFace = expl.Current();
704     if (myImagesFaces.IsImage( aFace ))
705       aFace = myImagesFaces.Root( aFace );
706     anOrigShape = myFaceShapeMap.Find( aFace );
707   }
708   return anOrigShape;
709 }
710 //=======================================================================
711 //function :RefineShells 
712 //purpose  : 
713 //=======================================================================
714 void RefineShells(const TopoDS_Shape& aS,
715                   TopTools_ListOfShape& aLNS)
716 {
717   Standard_Boolean bFound;
718   Standard_Integer iS, jS, aNbSOrs, aNbSIms, aNbFOrs, aNbFIms, kFOrs, aNb;
719   TopTools_ListIteratorOfListOfShape aIt;
720   TopTools_IndexedMapOfShape aMSOrs, aMSIms, aMFOrs, aMFIms;
721   TopTools_IndexedDataMapOfShapeShape aMImOr;
722   TopTools_ListOfShape aLS;
723   //
724   TopExp::MapShapes(aS, TopAbs_SHELL, aMSOrs);
725   aIt.Initialize(aLNS);
726   for (;aIt.More(); aIt.Next()) {
727     const TopoDS_Shape& aSh=aIt.Value();
728     aMSIms.Add(aSh);
729   }
730   //
731   aNbSOrs=aMSOrs.Extent();
732   aNbSIms=aMSIms.Extent();
733   //
734   for (iS=1; iS<=aNbSOrs; ++iS) {
735     const TopoDS_Shape& aSOr=aMSOrs(iS);
736     aMFOrs.Clear();
737     TopExp::MapShapes(aSOr, TopAbs_FACE, aMFOrs);
738     aNbFOrs=aMFOrs.Extent();
739     //
740     for (jS=1; jS<=aNbSIms; ++jS) {
741       const TopoDS_Shape& aSIm=aMSIms(jS);
742       if (aMImOr.Contains(aSIm)) {
743         continue;
744       }
745       //
746       aMFIms.Clear();
747       TopExp::MapShapes(aSIm, TopAbs_FACE, aMFIms);
748       aNbFIms=aMFIms.Extent();
749       //
750       if (aNbFIms==aNbFOrs) {
751         bFound=Standard_True;
752         for (kFOrs=1; kFOrs<=aNbFOrs; ++kFOrs) {
753           const TopoDS_Shape& aFOr=aMFOrs(kFOrs);
754           if (!aMFIms.Contains(aFOr)) {
755             bFound=Standard_False;
756             break; //next aSIm
757           }
758         }
759         if (bFound){
760           aMImOr.Add(aSIm, aSOr);
761           break; //next aSOr
762         }
763       } //if (aNbFIms==aNbFOrs)
764     }
765   }
766   //
767   aNb=aMImOr.Extent();
768   aIt.Initialize(aLNS);
769   for (;aIt.More(); aIt.Next()) {
770     const TopoDS_Shape& aSh=aIt.Value();
771     if (aMImOr.Contains(aSh)) {
772       const TopoDS_Shape& aSOr=aMImOr.FindFromKey(aSh);
773       aLS.Append(aSOr);
774     }
775     else {
776       aLS.Append(aSh);
777     }
778   }
779   //
780   aLNS.Clear();
781   aLNS.Append(aLS);
782 }
783
784 //=======================================================================
785 //function :RefineSolids 
786 //purpose  : 
787 //=======================================================================
788 void RefineSolids(const TopoDS_Shape& aSolidOr,
789                   TopTools_ListOfShape& aLNS)
790 {
791   Standard_Integer aNb, iS,  aNbSOrs, aNbSIms;
792   TopoDS_Shape aSolidIm;
793   TopTools_IndexedMapOfShape aMSOrs, aMSIms;
794   //
795   aNb=aLNS.Extent();
796   if (aNb!=1) {
797     return;
798   }
799   //
800   aSolidIm=aLNS.First();
801   
802   TopExp::MapShapes(aSolidOr, TopAbs_SHELL, aMSOrs);
803   TopExp::MapShapes(aSolidIm, TopAbs_SHELL, aMSIms);
804   aNbSOrs=aMSOrs.Extent();
805   aNbSIms=aMSIms.Extent();
806   if (aNbSOrs!=aNbSIms) {
807     return;
808   }
809   //
810   for (iS=1; iS<=aNbSOrs; ++iS) {
811     const TopoDS_Shape& aSOr=aMSOrs(iS);
812     if (!aMSIms.Contains(aSOr)) {
813       return;
814     }
815   }
816   //
817   aLNS.Clear();
818   aLNS.Append(aSolidOr);
819 }
820 //=======================================================================
821 //function : GetPlanes
822 //purpose  :
823 //=======================================================================
824 void GetPlanes (const TopoDS_Edge& anEx,
825                 const TopTools_IndexedDataMapOfShapeListOfShape& anEFMapx,
826                 const TopoDS_Face& aF1,
827                 TopAbs_State& aStPF1)
828                 
829 {
830   Standard_Boolean bIsAdjExists;
831   Standard_Real aT, aT1, aT2;
832   TopAbs_Orientation anOrEx, anOr;
833   gp_Dir aDNFx1, aDNFx2, aDNF1; 
834   gp_Pnt aPx, aPx1, aPx2, aPF1;
835   TopoDS_Edge aERight, aSpxSimm;
836   TopoDS_Face aFx1, aFx2, aFF1;
837   TopTools_ListIteratorOfListOfShape anIt;
838   //
839   // Point on Edge
840   Handle(Geom_Curve)aC3D =BRep_Tool::Curve(anEx, aT1, aT2);
841   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
842   
843   aC3D->D0(aT, aPx);
844   //
845   anOrEx=anEx.Orientation();
846   
847   aSpxSimm=anEx;
848   if (anOrEx==TopAbs_FORWARD) {
849     aSpxSimm.Orientation(TopAbs_REVERSED);
850   }
851   else if (anOrEx==TopAbs_REVERSED){
852     aSpxSimm.Orientation(TopAbs_FORWARD);
853   }
854   //
855   const TopTools_ListOfShape& aLF=anEFMapx.FindFromKey(anEx);
856   anIt.Initialize(aLF);
857   for (; anIt.More(); anIt.Next()) {
858     const TopoDS_Shape& aFE=anIt.Value();
859     aFx1=TopoDS::Face(aFE);
860     anOr=BOPTools_Tools3D::Orientation(anEx, aFx1);
861     if (anOr==anOrEx){
862       break;
863     }
864   }
865   //
866   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (anEx, aFx1, aT, aPx1, aDNFx1);
867   //
868   bIsAdjExists=BOPTools_Tools3D::GetAdjacentFace (aFx1, anEx, anEFMapx, aFx2);
869   if (!bIsAdjExists) {
870     BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aSpxSimm, aFx1, aT, aPx2, aDNFx2); 
871   }
872   else {
873     BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aSpxSimm, aFx2, aT, aPx2, aDNFx2);
874   }
875   //
876   aFF1=aF1;
877   aFF1.Orientation(TopAbs_FORWARD);
878   BOPTools_Tools3D::OrientEdgeOnFace (anEx, aFF1, aERight);
879   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aERight, aFF1, aT, aPF1, aDNF1);
880   //
881   {
882     Standard_Real d12, d1, anAlfa12, anAlfa1, aTwoPI;
883     
884     aTwoPI=Standard_PI+Standard_PI;
885     
886     gp_Vec aVx1(aPx, aPx1);
887     gp_Dir aDBx1 (aVx1);
888     gp_Pln aPlnToCompare (aPx, aDNFx1);
889     
890     gp_Vec aVx2(aPx, aPx2);
891     gp_Dir aDBx2 (aVx2);
892     
893     anAlfa12=aDBx1.Angle(aDBx2);
894     d12=BOPTools_Tools3D::SignDistance(aPx2, aPlnToCompare);
895     if (d12 < 0.) {
896       anAlfa12=aTwoPI-anAlfa12;
897     }
898     
899     gp_Vec aVF1(aPx, aPF1);
900     gp_Dir aDBF1 (aVF1);
901     anAlfa1=aDBx1.Angle(aDBF1);
902     d1=BOPTools_Tools3D::SignDistance(aPF1, aPlnToCompare);
903     if (d1 < 0.) {
904       anAlfa1=aTwoPI-anAlfa1;
905     }
906     
907     aStPF1=TopAbs_OUT;
908     if (anAlfa1 > anAlfa12) {
909       aStPF1=TopAbs_IN;
910     }
911   }
912 }
913
914 //modified by NIZNHY-PKV Fri Feb 25 17:00:03 2005t XX 
915 /*
916          A
917       //
918       TopoDS_Shape aFace2;
919       if ( !isSectionE ) {
920         while (itl.More()) {
921           aFace2 = itl.Value();
922           //
923            TopoDS_Shape anOrigFace2 = aFace2;
924           if (myImagesFaces.IsImage(aFace2)) {
925             anOrigFace2 = myImagesFaces.Root(aFace2);
926           }
927           //
928           if (!MFP.Contains( aFace2 )) {
929             LSF.Remove( itl );
930             continue;
931           }
932           //if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 )))
933           if (anOrigFace.IsSame(anOrigFace2)) {
934             break;
935           }
936           itl.Next();
937         }
938         if (itl.More()) { // aFace2 found, remove it from maps
939           LSF.Remove( itl );
940           MFP.Remove(aFace2);
941         }
942         else{
943           aFace2.Nullify();
944         }
945         itl.Initialize( LSF );
946       } 
947       */