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