1 #ifdef OCCGEOMETRY
2 
3 //  GEOM PARTITION : partition algorithm
4 //
5 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 //
8 //  This library is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU Lesser General Public
10 //  License as published by the Free Software Foundation; either
11 //  version 2.1 of the License.
12 //
13 //  This library is distributed in the hope that it will be useful,
14 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 //  Lesser General Public License for more details.
17 //
18 //  You should have received a copy of the GNU Lesser General Public
19 //  License along with this library; if not, write to the Free Software
20 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21 //
22 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
23 //
24 //
25 //
26 //  File   : Partition_Spliter.cxx
27 //  Author : Benedicte MARTIN
28 //  Module : GEOM
29 //  $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Spliter.cxx,v 1.7 2008/03/31 14:20:28 wabro Exp $
30 
31 //using namespace std;
32 #include <climits>
33 #include "Partition_Inter2d.hxx"
34 #include "Partition_Inter3d.hxx"
35 #include "Partition_Loop2d.hxx"
36 #include "Partition_Loop3d.hxx"
37 #include "Partition_Spliter.ixx"
38 
39 #include "utilities.h"
40 
41 #include <Precision.hxx>
42 #include <TopAbs_Orientation.hxx>
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45 
46 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_DataMapOfShapeListOfShape.hxx>
48 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
49 #include <TopTools_IndexedMapOfShape.hxx>
50 #include <TopTools_ListIteratorOfListOfShape.hxx>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopTools_MapIteratorOfMapOfShape.hxx>
53 #include <TopTools_SequenceOfShape.hxx>
54 
55 #include <Geom2d_Curve.hxx>
56 #include <Geom_Curve.hxx>
57 #include <Geom_Surface.hxx>
58 #include <Geom_TrimmedCurve.hxx>
59 #include <gp_Pnt.hxx>
60 #include <gp_Pnt2d.hxx>
61 #include <gp_Vec.hxx>
62 
63 #include <TopoDS.hxx>
64 #include <TopoDS_Compound.hxx>
65 #include <TopoDS_Edge.hxx>
66 #include <TopoDS_Face.hxx>
67 #include <TopoDS_Iterator.hxx>
68 #include <TopoDS_Shell.hxx>
69 #include <TopoDS_Solid.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <TopoDS_Wire.hxx>
72 
73 #include <BRepBndLib.hxx>
74 #include <BRepClass3d_SolidClassifier.hxx>
75 #include <BRepLib.hxx>
76 #include <BRep_Tool.hxx>
77 
78 #include <Extrema_ExtPC.hxx>
79 #include <GeomAdaptor_Curve.hxx>
80 #include <TopOpeBRepTool_CurveTool.hxx>
81 
82 #ifdef DEB
83 //# define PART_PERF
84 #endif
85 
86 #ifdef PART_PERF
87 # include <OSD_Chronometer.hxx>
88 #endif
89 
90 //=======================================================================
91 //function : isClosed
92 //purpose  : check id a shape is closed, ie is a solid or a closed shell
93 //=======================================================================
94 
isClosed(const TopoDS_Shape & theShape)95 static Standard_Boolean isClosed(const TopoDS_Shape& theShape)
96 {
97   Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);
98 
99   if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {
100     TopTools_IndexedDataMapOfShapeListOfShape MEF;
101     TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);
102     for (Standard_Integer i=1;  isClosed && i<=MEF.Extent();  ++i)
103       isClosed = ( MEF(i).Extent() != 1 );
104   }
105 
106   return isClosed;
107 }
108 
109 //=======================================================================
110 //function : Partition_Spliter
111 //purpose  : constructor
112 //=======================================================================
113 
Partition_Spliter()114 Partition_Spliter::Partition_Spliter()
115 {
116   myAsDes = new BRepAlgo_AsDes;
117   Clear();
118 }
119 
120 //=======================================================================
121 //function : AddTool
122 //purpose  : add cutting tool that will _NOT_ be in result
123 //=======================================================================
124 
AddTool(const TopoDS_Shape & S)125 void Partition_Spliter::AddTool(const TopoDS_Shape& S)
126 {
127   if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
128     TopoDS_Iterator it (S);
129     for (; it.More(); it.Next())
130     {
131       AddTool( it.Value());
132       myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
133     }
134     return;
135   }
136 
137   for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next())
138   {
139     myMapTools.Add(exp.Current());
140     myFaceShapeMap.Bind( exp.Current(), S );
141   }
142   if (isClosed( S ))
143     myClosedShapes.Add( S );
144 }
145 
146 //=======================================================================
147 //function : AddShape
148 //purpose  : add object Shape to be splited
149 //=======================================================================
150 
AddShape(const TopoDS_Shape & S)151 void Partition_Spliter::AddShape(const TopoDS_Shape& S)
152 {
153   if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
154     TopoDS_Iterator it (S);
155     for (; it.More(); it.Next())
156     {
157       AddShape( it.Value());
158       myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
159     }
160     return;
161   }
162 
163   TopExp_Explorer exp(S,TopAbs_FACE);
164   if (!exp.More()) { // do not split edges and vertices
165     //myBuilder.Add( myShape, S );
166     return;
167   }
168 
169   Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S
170   for (; exp.More(); exp.Next()) {
171     const TopoDS_Shape & aFace = exp.Current();
172     if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object
173       myFaceShapeMap.Bind( aFace, S );
174     if (myMapFaces.Add( aFace ))
175       myImagesFaces.SetRoot( aFace );
176   }
177 
178   if (nbFacesBefore == myMapFaces.Extent())
179     return;
180 
181   // solids must be processed before all
182   if (S.ShapeType() == TopAbs_SOLID)
183     myListShapes.Prepend(S);
184   else
185     myListShapes.Append(S);
186 
187   if (isClosed( S ))
188     myClosedShapes.Add( S );
189 
190 }
191 
192 //=======================================================================
193 //function : Shape
194 //purpose  : return resulting compound
195 //=======================================================================
196 
Shape() const197 TopoDS_Shape Partition_Spliter::Shape() const
198 {
199   return myShape;
200 }
201 
202 //=======================================================================
203 //function : Clear
204 //purpose  : clear fields
205 //=======================================================================
206 
Clear()207 void Partition_Spliter::Clear()
208 {
209   myDoneStep = TopAbs_SHAPE;
210 
211   myListShapes.Clear();
212   myMapFaces.Clear();
213   myMapTools.Clear();
214   myEqualEdges.Clear();
215   myNewSection.Clear();
216   myClosedShapes.Clear();
217   mySharedFaces.Clear();
218   myWrappingSolid.Clear();
219   myFaceShapeMap.Clear();
220 
221   myInternalFaces.Clear();
222   myIntNotClFaces.Clear();
223 
224   myAsDes->Clear();
225   myImagesFaces.Clear();
226   myImagesEdges.Clear();
227   myImageShape.Clear();
228 
229   //  myInter3d = Partition_Inter3d(myAsDes);
230   Partition_Inter3d hinter3d (myAsDes);
231   myInter3d = hinter3d;
232 
233   myAddedFacesMap.Clear();
234 
235 }
236 
237 //=======================================================================
238 //function : Compute
239 //purpose  : produce a result
240 //=======================================================================
241 
Compute(const TopAbs_ShapeEnum Limit)242 void Partition_Spliter::Compute(const TopAbs_ShapeEnum Limit)
243 {
244   if ((Limit != TopAbs_SHAPE && myDoneStep == Limit) ||
245       (Limit == TopAbs_SHAPE && myDoneStep == TopAbs_SOLID))
246     return;
247 
248   myBuilder.MakeCompound( myShape );
249 
250   TopTools_MapIteratorOfMapOfShape it;
251   TopTools_ListIteratorOfListOfShape itl;
252   TopExp_Explorer exp;
253 
254 #ifdef PART_PERF
255   OSD_Chronometer aCron;
256 #endif
257 
258   if (myDoneStep > TopAbs_VERTEX) {
259 
260     TopTools_ListOfShape aListFaces;
261     aListFaces = myImagesFaces.Roots();
262     for (it.Initialize(myMapTools); it.More(); it.Next())
263       aListFaces.Append(it.Key());
264 
265 #ifdef PART_PERF
266     aCron.Start();
267 #endif
268 
269     //-----------------------------------------------
270     // Intersection between faces
271     //-----------------------------------------------
272     // result is in myAsDes as a map Face - list of new edges;
273     // special care is done for section edges, same domain faces and vertices:
274     // data about them is inside myInter3d
275     myInter3d.CompletPart3d(aListFaces, myFaceShapeMap);
276 
277 #ifdef PART_PERF
278     MESSAGE("+++ CompletPart3d()");
279     aCron.Show( cout );
280     aCron.Reset();
281     aCron.Start();
282 #endif
283     //-----------------------------------------------
284     // Intersection of edges
285     //-----------------------------------------------
286 
287     // add tool faces which must be reconstructed to myMapFaces too
288     FindToolsToReconstruct();
289 
290 #ifdef PART_PERF
291     MESSAGE("+++ FindToolsToReconstruct()");
292     aCron.Show( cout );
293     aCron.Reset();
294     aCron.Start();
295 #endif
296 
297     // add existing vertices to edges of object faces in myAsDes
298     TopTools_MapOfShape DoneEM;
299     for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
300       const TopoDS_Shape& F  = it.Key();
301       TopoDS_Face FForward = TopoDS::Face(F.Oriented(TopAbs_FORWARD));
302       for (exp.Init(FForward,TopAbs_EDGE); exp.More(); exp.Next()) {
303         const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
304         myAsDes->Add(FForward,E);
305         if (DoneEM.Add(E)) {
306           TopoDS_Iterator itV(E);
307           for (; itV.More(); itV.Next()) {
308             const TopoDS_Vertex& V = TopoDS::Vertex( itV.Value());
309             myAsDes->Add(E, myInter3d.ReplaceSameDomainV( V, E ));
310           }
311         }
312       }
313     }
314 
315     // intersect edges that are descendants of a face in myAsDes
316     TopTools_MapOfShape& Modif = myInter3d.TouchedFaces();
317     for ( it.Initialize(Modif); it.More(); it.Next()) {
318       const TopoDS_Face& F  = TopoDS::Face(it.Key());
319       Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges());
320     }
321     // now myAsDes contains also new vertices made at edge intersection as
322     // descendant of edges both new and old
323 
324     myDoneStep = TopAbs_VERTEX;
325 
326 #ifdef PART_PERF
327     MESSAGE("+++ CompletPart2d()");
328     aCron.Show( cout );
329     aCron.Reset();
330     aCron.Start();
331 #endif
332   } //   if (myDoneStep > TopAbs_VERTEX)
333 
334   if (Limit == TopAbs_VERTEX) {
335     // add new vertices to myShape
336     for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {
337       if (! myAsDes->HasDescendant( it.Key() ))
338         continue;
339       itl.Initialize( myAsDes->Descendant( it.Key() ));
340       for (; itl.More(); itl.Next())
341         myBuilder.Add ( myShape, itl.Value() );
342     }
343     return;
344   }
345 
346 
347   if (myDoneStep > TopAbs_EDGE) {
348 
349     //-----------------------------------------------
350     //-----------------------------------------------
351     // ------- Reconstruction of all the edges.------
352     //-----------------------------------------------
353     //-----------------------------------------------
354 
355     // ==============
356     // cut new edges
357     // ==============
358     TopTools_ListOfShape LSE; // all edge splits
359     for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) {
360 
361       TopoDS_Vertex V1,V2;
362       TopoDS_Edge EE = TopoDS::Edge(it.Key());
363 
364       TopTools_ListOfShape aListV, aListF;
365       aListV = myAsDes->Descendant(EE); // intersection vertices
366       aListF = myAsDes->Ascendant(EE);  // intersected faces
367 
368       if (aListV.IsEmpty())
369         continue;  // new edge does not intersect any other edge
370 
371       // Add end vertices to new edges only if
372       // one face is Tool and the other is Shape
373       Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() );
374       Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() );
375       if (isTool1 || isTool2)
376       {
377         TopExp::Vertices(EE,V1,V2);
378 	Standard_Real Tol = Max (BRep_Tool::Tolerance( V1 ),
379 				 BRep_Tool::Tolerance( V2 ));
380 
381         gp_Pnt P1 = BRep_Tool::Pnt(V1);
382         gp_Pnt P2 = BRep_Tool::Pnt(V2);
383         Standard_Boolean AddV1 = Standard_True;
384         Standard_Boolean AddV2 = Standard_True;
385 
386         // add only if there is no intersection at end vertex
387         for (itl.Initialize(aListV); itl.More(); itl.Next()) {
388           const TopoDS_Vertex& Ve = TopoDS::Vertex(itl.Value()) ;
389           Standard_Real Tol2 = Max ( Tol, BRep_Tool::Tolerance( Ve ));
390           Tol2 *= Tol2;
391           gp_Pnt P = BRep_Tool::Pnt(Ve);
392           if (AddV1 && P.SquareDistance(P1) <= Tol2)
393             AddV1 = Standard_False;
394 
395           if (AddV2 && P.SquareDistance(P2) <= Tol2)
396             AddV2 = Standard_False;
397         }
398 
399         if (AddV1) {
400           aListV.Append(V1);
401           myAsDes->Add(EE,V1);
402         }
403 
404         if (AddV2) {
405           aListV.Append(V2);
406           myAsDes->Add(EE,V2);
407         }
408       }
409 
410       // cut new edges
411       Standard_Integer NbV=aListV.Extent() ;
412       if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) {
413         TopTools_ListOfShape LNE;
414         MakeEdges (EE,aListV, LNE);
415         myImagesEdges.Bind(EE,LNE);
416 	LSE.Append( LNE );
417       }
418     }
419 
420     // ==============
421     // cut old edges
422     // ==============
423     for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
424       for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) {
425         const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() );
426         if ( myImagesEdges.HasImage( EE ))
427           continue;
428         TopTools_ListOfShape  LNE;
429         const TopTools_ListOfShape& aListVV = myAsDes->Descendant(EE);
430         MakeEdges (EE, aListVV, LNE);
431         myImagesEdges.Bind(EE,LNE);
432 	LSE.Append( LNE );
433       }
434     }
435 #ifdef PART_PERF
436     MESSAGE("+++ Cut Edges");
437     aCron.Show( cout );
438     aCron.Reset();
439     aCron.Start();
440 #endif
441 
442     // process same domain section edges
443     MergeEqualEdges( LSE );
444 
445     myDoneStep = TopAbs_EDGE;
446 
447 #ifdef PART_PERF
448     MESSAGE("+++ MergeEqualEdges()");
449     aCron.Show( cout );
450     aCron.Reset();
451     aCron.Start();
452 #endif
453   }  //   if (myDoneStep > TopAbs_EDGE)
454 
455   if (Limit == TopAbs_EDGE) {
456     // add splits of old edges
457     TopTools_ListIteratorOfListOfShape itNE;
458     for (itl.Initialize( myListShapes );itl.More();itl.Next()) {
459       if (myMapTools.Contains( itl.Value() ))
460         continue; // skip tool faces
461       for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) {
462 	itNE.Initialize( myImagesEdges.Image( exp.Current() ));
463 	for ( ; itNE.More(); itNE.Next())
464 	  myBuilder.Add ( myShape, itNE.Value() );
465       }
466     }
467     // add splits of new edges
468     for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {
469       itNE.Initialize( myImagesEdges.Image( it.Key() ));
470       for (; itNE.More(); itNE.Next())
471         myBuilder.Add ( myShape, itNE.Value() );
472     }
473     return;
474   }
475 
476 
477   //-----------------------------------------------
478   // split faces
479   //-----------------------------------------------
480 
481   if (myDoneStep > TopAbs_FACE) {
482 
483     for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
484       TopoDS_Shape FacesComp = MakeFaces ( itl.Value());
485       // there is a cunning here: myImagesFaces keeps faces made by Loop2d
486       // but some of them may be replaced with splits of same domain face
487       // and myImageShape keeps ultimate result
488       myImageShape.Bind( itl.Value(), FacesComp );
489     }
490 
491     myDoneStep = TopAbs_FACE;
492 #ifdef PART_PERF
493     MESSAGE("+++ MakeFaces()");
494     aCron.Show( cout );
495     aCron.Reset();
496     aCron.Start();
497 #endif
498   }
499 
500   if (Limit == TopAbs_WIRE ||
501       Limit == TopAbs_FACE)   {
502     for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
503       if ( myMapTools.Contains( itl.Value() ))
504 	continue; // no result needed for a tool face
505       const TopoDS_Shape& FacesComp = myImageShape.Image( itl.Value() ).First();
506       for ( exp.Init( FacesComp, Limit); exp.More(); exp.Next())
507 	myBuilder.Add ( myShape, exp.Current());
508     }
509     return;
510   }
511 
512 
513   //-----------------------------------------------
514   // split and add solids and shells
515   //-----------------------------------------------
516 
517   Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE ||
518 				 Limit < TopAbs_SHELL);
519   for (itl.Initialize(myListShapes);itl.More();itl.Next())
520   {
521     const TopoDS_Shape & S = itl.Value();
522     if (S.ShapeType() > TopAbs_SHELL)
523       continue;
524 
525     TopTools_ListOfShape NSL; // new shape list
526     MakeShells (S , NSL);
527     if (makeSolids && S.ShapeType() == TopAbs_SOLID )
528       MakeSolids( S, NSL );
529 
530     // store new shells or solids
531     TopTools_ListIteratorOfListOfShape itNSL (NSL);
532     for ( ; itNSL.More(); itNSL.Next())
533       myBuilder.Add (myShape, itNSL.Value());
534   }
535 #ifdef PART_PERF
536     MESSAGE("+++ MakeShells()");
537     aCron.Show( cout );
538 #endif
539 
540   //-----------------------------------------------
541   // add split faces
542   //-----------------------------------------------
543 
544   for (itl.Initialize(myListShapes);itl.More();itl.Next())
545   {
546     const TopoDS_Shape & S = itl.Value();
547     if (S.ShapeType() != TopAbs_FACE ||
548         myMapTools.Contains( S ))
549       continue;
550     TopoDS_Iterator itS( myImageShape.Image(S).First() );
551     for (; itS.More(); itS.Next())
552       if (! myAddedFacesMap.Contains( itS.Value() ))
553         myBuilder.Add (myShape, itS.Value());
554   }
555 
556   myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL;
557 
558 }
559 
560 //=======================================================================
561 //function : MakeSolids
562 //purpose  : make solids out of Shells
563 //=======================================================================
564 
MakeSolids(const TopoDS_Shape & theSolid,TopTools_ListOfShape & theShellList)565 void Partition_Spliter::MakeSolids(const TopoDS_Shape &   theSolid,
566                                    TopTools_ListOfShape & theShellList)
567 {
568   // for a solid wrapping other shells or solids without intersection,
569   // it is necessary to find shells making holes in it
570 
571   TopTools_ListOfShape aNewSolids; // result
572   TopTools_ListOfShape aHoleShells;
573   TopoDS_Shape anInfinitePointShape;
574 
575   Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid );
576   if (!isWrapping && !theShellList.IsEmpty())
577   {
578     // check if theSolid initially has internal shells
579     TopoDS_Iterator aShellExp (theSolid);
580     aShellExp.Next();
581     isWrapping = aShellExp.More();
582   }
583 
584   TopTools_ListIteratorOfListOfShape aShellIt(theShellList);
585   for ( ; aShellIt.More(); aShellIt.Next())
586   {
587     const TopoDS_Shape & aShell = aShellIt.Value();
588 
589     // check if a shell is a hole
590     if (isWrapping && IsInside (anInfinitePointShape, aShell))
591       aHoleShells.Append( aShell );
592     else
593     {
594       // make a solid from a shell
595       TopoDS_Solid Solid;
596       myBuilder.MakeSolid( Solid );
597       myBuilder.Add (Solid, aShell);
598 
599       aNewSolids.Append (Solid);
600     }
601   }
602 
603   // find an outer shell most close to each hole shell
604   TopTools_DataMapOfShapeShape aInOutMap;
605   for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next())
606   {
607     const TopoDS_Shape & aHole = aShellIt.Value();
608     TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids);
609     for ( ; aSolisIt.More(); aSolisIt.Next())
610     {
611       const TopoDS_Shape & aSolid = aSolisIt.Value();
612       if (! IsInside( aHole, aSolid ))
613         continue;
614 
615       if ( aInOutMap.IsBound (aHole))
616       {
617         const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
618         if ( IsInside( aSolid, aSolid2 ))
619         {
620           aInOutMap.UnBind( aHole );
621           aInOutMap.Bind ( aHole, aSolid );
622         }
623       }
624       else
625         aInOutMap.Bind ( aHole, aSolid );
626     }
627 
628     // add aHole to a solid
629     if (aInOutMap.IsBound( aHole ))
630       myBuilder.Add ( aInOutMap( aHole ), aHole );
631   }
632 
633   theShellList.Clear();
634   theShellList.Append( aNewSolids );
635 }
636 
637 //=======================================================================
638 //function : FindFacesInside
639 //purpose  : return compound of faces  of other shapes that are
640 //           inside <theShape>.
641 //           <theShape> is an object shape.
642 //           <CheckClosed> makes avoid faces that do not form a
643 //           closed shell
644 //           <All> makes return already added faces
645 //=======================================================================
646 
FindFacesInside(const TopoDS_Shape & theShape,const Standard_Boolean CheckClosed,const Standard_Boolean All)647 TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape,
648 						const Standard_Boolean CheckClosed,
649 						const Standard_Boolean All)
650 {
651   // ================================================
652   // check if internal faces have been already found
653   // ================================================
654   TopExp_Explorer expl;
655   if (myInternalFaces.IsBound( theShape ))
656   {
657     TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape );
658     TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape );
659 
660     expl.Init( aIntRemFComp, TopAbs_FACE);
661     if (CheckClosed || !expl.More())
662       return aIntFComp;
663 
664     TopoDS_Compound C;
665     myBuilder.MakeCompound( C );
666     // add removed faces
667     for (; expl.More(); expl.Next())
668       myBuilder.Add( C, expl.Current() );
669     // add good internal faces
670     for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next())
671       myBuilder.Add( C, expl.Current() );
672     return C;
673   }
674 
675   // ===================================
676   // get data for internal faces search
677   // ===================================
678 
679   // compound of split faces of theShape
680   const TopoDS_Shape& CSF = myImageShape.Image(theShape).First();
681 
682   TopTools_MapOfShape MSE, MFP;
683   TopTools_DataMapOfShapeListOfShape DMSEFP;
684   TopTools_MapIteratorOfMapOfShape itm;
685   TopTools_ListOfShape EmptyL;
686 
687   // MSE filling: map of new section edges of CSF
688   for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) {
689     const TopoDS_Shape & resE = expl.Current() ;
690     if (myNewSection.Contains( resE )) // only new edges
691       MSE.Add(resE);
692   }
693 
694   // DMEF: map edge of CSF - faces of CSF
695   TopTools_IndexedDataMapOfShapeListOfShape DMEF;
696   TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF);
697 
698   // Fill
699   // 1.  MFP - a map of faces to process: map of resulting faces except
700   // those of theShape; we`ll add to C those of them which are inside CSF
701   // 2.  DMSEFP - edge of MSE => faces of MFP
702   TopTools_ListIteratorOfListOfShape itl;
703   for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
704     const TopoDS_Shape& aShape = itl.Value();
705     if ( theShape.IsSame( aShape )) continue;
706     // fill maps
707     // iterate on split faces of aShape
708     TopoDS_Iterator itF ( myImageShape.Image(aShape).First() );
709     for ( ; itF.More(); itF.Next()) {
710       const TopoDS_Shape& sf = itF.Value();
711       MFP.Add(sf);
712       // iterate on edges of split faces of aShape,
713       // add to DMSEFP edges that are new
714       for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) {
715 	TopoDS_Shape se = expl.Current();
716 	if ( MSE.Contains(se)) {// section edge
717 	  if (!DMSEFP.IsBound(se))
718 	    DMSEFP.Bind(se,EmptyL);
719 	  DMSEFP(se).Append(sf);
720 	}
721       }
722     }
723   }
724 
725   // add tool faces having section edges on faces of theShape to MFP and DMSEFP;
726   // such tool faces need not to be reconstructed and so they are not in myListShapes
727   for (itm.Initialize(myMapTools); itm.More(); itm.Next())
728   {
729     const TopoDS_Shape & aToolFace = itm.Key();
730     if (myMapFaces.Contains( aToolFace ))
731       continue;
732     MFP.Add(aToolFace);
733     for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) {
734       TopoDS_Shape se = expl.Current();
735       if ( MSE.Contains( se )) {// section edge
736         if (!DMSEFP.IsBound( se ))
737           DMSEFP.Bind( se, EmptyL );
738         DMSEFP( se ).Append( aToolFace );
739       }
740     }
741   }
742 
743 
744   // ===========================
745   // find faces inside theShape
746   // ===========================
747 
748   Standard_Boolean skipAlreadyAdded = Standard_False;
749   Standard_Boolean GoodOri, inside;
750   Standard_Real dot;
751   TopTools_ListOfShape KeepFaces;
752   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
753 
754   // iterate on section edges, check faces of other shapes
755   // sharing section edges and put internal faces to KeepFaces
756   for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) {
757     // a new edge of theShape
758     const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key());
759     // an original edge of which E is a split
760     const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E ));
761     // does OrigE itself splits a face
762     Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE );
763 
764     // split faces of other shapes sharing E
765     TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E);
766     itl.Initialize( LSF );
767     while (itl.More()) {
768       // a split faces of other shape
769       TopoDS_Face aFace1 = TopoDS::Face(itl.Value());
770       // remove aFace1 form DMSEFP and MFP
771       LSF.Remove( itl ); // == itl.Next();
772       if (!MFP.Remove( aFace1 ))
773 	continue; // was not is MFP ( i.e already checked)
774       // check if aFace1 was already added to 2 shells
775       if (!All &&
776 	  myAddedFacesMap.Contains( aFace1 ) &&
777 	  myAddedFacesMap.Contains( aFace1.Reversed() )) {
778 	skipAlreadyAdded = Standard_True;
779 	continue;
780       }
781 
782       // find another face which originates from the same face as aFace1:
783       // usually aFace2 is internal if aFace1 is not and vice versa
784 
785       TopoDS_Shape anOrigFace = aFace1;
786       if (myImagesFaces.IsImage(aFace1))
787         anOrigFace = myImagesFaces.Root(aFace1);
788       TopoDS_Shape aFace2;
789       if ( !isSectionE ) {
790         while (itl.More()) {
791           aFace2 = itl.Value();
792           if (!MFP.Contains( aFace2 )) {
793             LSF.Remove( itl );
794             continue;
795           }
796           if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 )))
797             break;
798           itl.Next();
799         }
800         if (itl.More()) { // aFace2 found, remove it from maps
801           LSF.Remove( itl );
802           MFP.Remove(aFace2);
803         }
804         else
805           aFace2.Nullify();
806         itl.Initialize( LSF );
807       }
808 
809       // check that anOrigFace is not same domain with CSF faces it intersects
810 
811       const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E
812       const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First());
813       const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last());
814       Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 );
815       Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 );
816       if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) {
817 	sameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1);
818         if (origF1 == origF2)
819           sameDom2 = sameDom1;
820         else
821           myInter3d.IsSameDomainF( anOrigFace, origF2);
822       }
823       if (sameDom1 && sameDom2)
824 	continue;
825       if ((sameDom1 || sameDom2)) {
826 	inside = Partition_Loop3d::IsInside (E,
827 					     TopoDS::Face(FL.First()),
828 					     TopoDS::Face(FL.Last()),
829 					     1, dot, GoodOri);
830 	if (inside || (dot + Precision::Angular() >= 1.0))
831 	  continue; // E is convex between origF1 and origF2 or they are tangent
832       }
833 
834 
835       // keep one of found faces
836 
837       //face of CSF sharing E
838       const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First();
839       // analyse aFace1 state
840       inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1,
841 					   1, dot, GoodOri);
842       if (inside && isSectionE)
843       {
844         // aFace1 must be tested with both adjacent faces of CSF
845         const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last();
846         if (aShapeFace2 != aShapeFace)
847           inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1,
848                                                1, dot, GoodOri);
849       }
850 
851       // store internal face
852       if (inside)
853         KeepFaces.Append(aFace1);
854 
855       else if (!aFace2.IsNull())
856       {
857         if (dot + Precision::Angular() >= 1.0)
858         {
859           // aFace2 state is not clear, it will be analysed alone,
860           // put it back to the maps
861           MFP.Add( aFace2 );
862           LSF.Append( aFace2 );
863         }
864         else
865           KeepFaces.Append(aFace2);
866       }
867     }
868   }
869 
870   // ===================================================
871   // add not distributed faces connected with KeepFaces
872   // ===================================================
873 
874   // ultimate list of internal faces
875   TopTools_ListOfShape KeptFaces;
876 
877   // add to MFP unsplit tool faces as well, they may be connected with
878   // tool faces interfering with theShape
879   for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) {
880     const TopoDS_Shape& aToolFace = itm.Key();
881     if (!myImageShape.HasImage(aToolFace))
882       MFP.Add (aToolFace);
883   }
884 
885   if (MFP.IsEmpty())
886     KeptFaces.Append (KeepFaces);
887 
888   while (!KeepFaces.IsEmpty())
889   {
890     // KeepEdges : map of edges of faces kept last time
891     TopTools_IndexedMapOfShape KeepEdges;
892     for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) {
893       TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges);
894       KeptFaces.Append( itl.Value() );
895     }
896 
897     KeepFaces.Clear();
898 
899     // keep faces connected with already kept faces by KeepEdges
900     for ( itm.Initialize(MFP); itm.More(); itm.Next() ) {
901       const TopoDS_Shape& FP = itm.Key();
902       for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) {
903         const TopoDS_Shape& se = expl.Current();
904         if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {
905           KeepFaces.Append(FP);
906           MFP.Remove(FP);
907           break;
908         }
909       }
910     }
911   }
912 
913   // ===============================================================
914   // here MFP contains faces outer of theShape and those of shapes
915   // which do not interfere with theShape at all and between which
916   // there may be those wrapped by theShape and whose faces may be
917   // needed to be returned as well
918   // ===============================================================
919 
920   Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID);
921   if (All || isSolid)  // All is for sub-result removal
922   {
923     // loop on not used faces; checked faces will be removed from MFP
924     // during the loop
925     for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) {
926       const TopoDS_Shape & aFace = itm.Key();
927 
928       // a shape which aFace originates from
929       TopoDS_Shape anOrigShape = GetOriginalShape( aFace );
930 
931       // find out if all split faces of anOrigShape are not in MFP
932       // and by the way remove them from MFP
933       Standard_Boolean isAllOut = Standard_True;
934       TopoDS_Shape aSplitFaces = anOrigShape;
935       if (myImageShape.HasImage(anOrigShape))
936         aSplitFaces = myImageShape.Image(anOrigShape).First();
937 
938       TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept
939       for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next())
940       {
941         const TopoDS_Shape & aSpFace = expl.Current();
942         // a tool face which became object has image but the whole tool shape has not
943         if (myImageShape.HasImage( aSpFace ))
944         {
945           TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE );
946           for ( ; exF.More(); exF.Next() )
947           {
948             aSplitFaceL.Append( exF.Current() );
949             if ( ! MFP.Remove( exF.Current() ) && isAllOut )
950               // a shared face might be removed from MFP during a prev loop
951               isAllOut = mySharedFaces.Contains( exF.Current() );
952           }
953         }
954         else
955         {
956           aSplitFaceL.Append( aSpFace );
957           if ( ! MFP.Remove( aSpFace ) && isAllOut)
958             // a shared face might be removed from MFP during a prev loop
959             isAllOut = mySharedFaces.Contains( aSpFace );
960         }
961       }
962       itm.Initialize( MFP ); // iterate remaining faces
963       if ( !isAllOut )
964         continue;
965 
966       // classify anOrigShape against theShape
967       if (IsInside (anOrigShape, theShape))
968       {
969         if (isSolid && myClosedShapes.Contains( anOrigShape ))
970           // to make a special care at solid reconstruction
971           myWrappingSolid.Add ( theShape );
972 
973         // keep faces of an internal shape anOrigShape
974         KeptFaces.Append( aSplitFaceL );
975       }
976     }
977   }
978 
979   // ====================================================
980   // check if kept faces form a shell without free edges
981   // ====================================================
982 
983   DMEF.Clear();  // edge - kept faces
984   MFP.Clear(); // reuse it for wrong faces
985   if (CheckClosed) {
986     for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
987       TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF);
988 
989     Standard_Integer i, nb = DMEF.Extent();
990     Standard_Boolean isClosed = Standard_False;
991     while (!isClosed) {
992       isClosed = Standard_True;
993       for (i=1;  isClosed && i<=nb;  ++i) {
994         const TopoDS_Shape& E = DMEF.FindKey( i );
995         if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) &&
996             ! MSE.Contains( E ))
997           isClosed = ( DMEF(i).Extent() != 1 );
998       }
999       if (!isClosed) {
1000         const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face
1001         MFP.Add( F );
1002         // remove bad face from DMEF
1003         for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {
1004 	  const TopoDS_Shape& E = expl.Current();
1005           TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E );
1006           for (itl.Initialize( FL ); itl.More(); itl.Next() ) {
1007             if ( F.IsSame( itl.Value() )) {
1008               FL.Remove( itl );
1009               break;
1010             }
1011           }
1012         }
1013       }
1014     }
1015   }
1016 
1017   // ==============
1018   // make a result
1019   // ==============
1020 
1021   TopoDS_Compound C;
1022   // compound of removed internal faces
1023   TopoDS_Compound CNotCl;
1024 
1025   myBuilder.MakeCompound(C);
1026   myBuilder.MakeCompound(CNotCl);
1027 
1028   // add to compounds
1029   for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
1030   {
1031     TopoDS_Shape & aIntFace = itl.Value();
1032     if (! MFP.Contains( aIntFace ))
1033       myBuilder.Add( C, aIntFace);
1034     else
1035       myBuilder.Add( CNotCl, aIntFace);
1036   }
1037 
1038   if (!skipAlreadyAdded && CheckClosed)
1039   {
1040     myInternalFaces.Bind( theShape, C );
1041     myIntNotClFaces.Bind( theShape, CNotCl );
1042   }
1043 
1044   return C;
1045 }
1046 
1047 //=======================================================================
1048 //function : MakeShell
1049 //purpose  : split S into compound of shells
1050 //=======================================================================
1051 
MakeShells(const TopoDS_Shape & S,TopTools_ListOfShape & NS)1052 void Partition_Spliter::MakeShells(const TopoDS_Shape& S,
1053                                    TopTools_ListOfShape& NS)
1054 {
1055   Partition_Loop3d ShellMaker;
1056   // get compound of split faces of S
1057   const TopoDS_Shape& FacesComp = myImageShape.Image(S).First();
1058   ShellMaker.AddConstFaces( FacesComp );
1059   // add split faces inside S
1060   if (myClosedShapes.Contains( S )) {
1061     TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True);
1062     ShellMaker.AddSectionFaces( InternalFacesComp );
1063   }
1064 
1065   NS = ShellMaker.MakeShells( myAddedFacesMap );
1066 
1067   // Add faces added to new shell to myAddedFacesMap:
1068   // avoid rebuilding twice commont part of 2 solids.
1069   TopTools_ListIteratorOfListOfShape itS(NS);
1070   while ( itS.More()) {
1071     TopExp_Explorer expF (itS.Value(), TopAbs_FACE);
1072     for (; expF.More(); expF.Next())
1073       myAddedFacesMap.Add (expF.Current());
1074 
1075     itS.Next();
1076   }
1077 }
1078 
1079 //=======================================================================
1080 //function : findEqual
1081 //purpose  : compare edges of EL1 against edges of EL2,
1082 //           Result is in EMM binding EL1 edges to list of equal edges.
1083 //           Edges are considered equall only if they have same vertices.
1084 //           <addSame>==True makes consider same edges as equal
1085 //           Put in <AllEqMap> all equal edges
1086 //=======================================================================
1087 
findEqual(const TopTools_ListOfShape & EL1,const TopTools_ListOfShape & EL2,const Standard_Boolean addSame,TopTools_DataMapOfShapeListOfShape & EEM,TopTools_MapOfShape & AllEqMap)1088 static void findEqual (const TopTools_ListOfShape& EL1,
1089 		       const TopTools_ListOfShape& EL2,
1090 		       const Standard_Boolean addSame,
1091 		       TopTools_DataMapOfShapeListOfShape& EEM,
1092 		       TopTools_MapOfShape& AllEqMap)
1093 {
1094   // map vertices to edges for EL2
1095   TopTools_DataMapOfShapeListOfShape VEM;
1096   TopTools_ListIteratorOfListOfShape itE1, itE2(EL2);
1097   TopoDS_Iterator itV;
1098   TopTools_ListOfShape emptyL;
1099   for (; itE2.More(); itE2.Next()) {
1100     for (itV.Initialize( itE2.Value() ); itV.More(); itV.Next()) {
1101       const TopoDS_Shape& V = itV.Value();
1102       if (! VEM.IsBound( V ) )
1103 	VEM.Bind( V, emptyL);
1104       VEM( V ).Append( itE2.Value());
1105     }
1106   }
1107 
1108   gp_Vec D1, D2;
1109   gp_Pnt P;
1110   Standard_Real f,l,u,tol;
1111   Handle(Geom_Curve) C1, C2;
1112   Extrema_ExtPC Extrema;
1113   TopoDS_Vertex V1, V2, V3, V4;
1114 
1115   AllEqMap.Clear();
1116 
1117   for (itE1.Initialize(EL1); itE1.More(); itE1.Next()) {
1118     const TopoDS_Edge& E1 = TopoDS::Edge( itE1.Value());
1119     if (BRep_Tool::Degenerated( E1 ) || AllEqMap.Contains (E1))
1120       continue;
1121     TopExp::Vertices( E1, V1, V2 );
1122 
1123     if (VEM.IsBound(V1))
1124       itE2.Initialize( VEM(V1) );
1125     for (; itE2.More(); itE2.Next()) {
1126       const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value());
1127       if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2))
1128         continue;
1129 
1130       if (E1.IsSame(E2)) {
1131 	if (!addSame)
1132 	  continue;
1133       }
1134       else {
1135 	TopExp::Vertices( E2, V3, V4);
1136 	if (!V2.IsSame(V4) && !V2.IsSame(V3))
1137 	  continue;
1138 	// E1 and E2 have same vertices
1139 	// check D1 at end points.
1140         C2 = BRep_Tool::Curve( E2, f,l);
1141         C1 = BRep_Tool::Curve( E1, f,l);
1142 	u = BRep_Tool::Parameter(V1,E1);
1143         C1->D1(u, P, D1);
1144 	u = BRep_Tool::Parameter(V1.IsSame(V3) ? V3 : V4, E2);
1145 	C2->D1(u, P, D2);
1146         D1.Normalize(); D2.Normalize();
1147         if (Abs(D1*D2) + Precision::Angular() < 1.0)
1148           continue;
1149 	if (! V1.IsSame(V2)) {
1150 	  u = BRep_Tool::Parameter(V2,E1);
1151 	  C1->D1(u, P, D1);
1152 	  u = BRep_Tool::Parameter(V2.IsSame(V3) ? V3 : V4, E2);
1153 	  C2->D1(u, P, D2);
1154 	  D1.Normalize(); D2.Normalize();
1155 	  if (Abs(D1*D2) + Precision::Angular() < 1.0)
1156 	    continue;
1157 	}
1158         // check distance at a couple of internal points
1159         tol = Max(BRep_Tool::Tolerance(E1),
1160                   BRep_Tool::Tolerance(E2));
1161         GeomAdaptor_Curve AC1(C1);
1162         Extrema.Initialize(AC1,f,l);
1163 	Standard_Boolean ok = Standard_True, hasMin = Standard_False;
1164 	BRep_Tool::Range( E2, f, l);
1165         Standard_Integer i=1, nbi=3;
1166         for (; i<nbi && ok; ++i) {
1167           Extrema.Perform( C2->Value( f+(l-f)*i/nbi ));
1168           Standard_Integer j=1, nbj=Extrema.NbExt();
1169           for (; j<=nbj && ok; ++j) {
1170             if (Extrema.IsMin(j)) {
1171 	      hasMin = Standard_True;
1172 	      // ok = Extrema.Value(j) <= tol;  // V6.3
1173 	      ok = Extrema.SquareDistance(j) <= tol;  // V6.5
1174 	    }
1175           }
1176         }
1177         if ( !hasMin || !ok)
1178           continue;
1179       }
1180       // bind E2 to E1 in EEM
1181       if (!EEM.IsBound(E1)) {
1182         EEM.Bind (E1, emptyL);
1183 	AllEqMap.Add (E1);
1184       }
1185       EEM(E1).Append(E2);
1186       AllEqMap.Add (E2);
1187     }
1188   }
1189 }
1190 
1191 //=======================================================================
1192 //function : MakeFaces
1193 //purpose  : split faces of S, return compound of new faces
1194 //=======================================================================
1195 
MakeFaces(const TopoDS_Shape & S)1196 TopoDS_Shape Partition_Spliter::MakeFaces (const TopoDS_Shape& S)
1197 {
1198   TopoDS_Compound C;
1199   myBuilder.MakeCompound(C);
1200 
1201   TopTools_ListIteratorOfListOfShape itl, itNE;
1202 
1203   TopExp_Explorer exp(S,TopAbs_FACE);
1204   for (; exp.More(); exp.Next()) {
1205 
1206     const TopoDS_Face& F = TopoDS::Face(exp.Current());
1207 
1208     TopTools_ListOfShape LNF;
1209 
1210     if (myImagesFaces.HasImage( F )) {
1211       myImagesFaces.LastImage( F, LNF );
1212       TopAbs_Orientation oriF = F.Orientation();
1213       for ( itl.Initialize( LNF ); itl.More(); itl.Next())
1214 	itl.Value().Orientation( oriF );
1215     }
1216     else {
1217 
1218       Partition_Loop2d loops;
1219       loops.Init(F);
1220 
1221       TopTools_IndexedMapOfShape EM;
1222       TopExp::MapShapes( F, TopAbs_EDGE, EM);
1223 
1224       TopTools_MapOfShape AddedEqualM, EqualSeamM;
1225       Standard_Boolean needRebuild = Standard_False;
1226 
1227       // add splits to loops
1228 
1229       // LE: old edges + new unsplit edges
1230       const TopTools_ListOfShape& LE = myAsDes->Descendant(F);
1231       for (itl.Initialize(LE); itl.More(); itl.Next()) {
1232 	const TopoDS_Edge& E = TopoDS::Edge( itl.Value() );
1233 
1234 	Standard_Boolean isSectionE = myInter3d.IsSectionEdge(E);
1235 	Standard_Boolean isNewE = !EM.Contains( E );
1236 
1237 	// LSE: list of split edges
1238 	TopTools_ListOfShape LSE;
1239 	myImagesEdges.LastImage(E,LSE); // splits of E or E itself
1240 
1241 	for (itNE.Initialize(LSE); itNE.More(); itNE.Next()) {
1242 
1243 	  TopoDS_Edge NE = TopoDS::Edge( itNE.Value() );
1244 	  Standard_Boolean isSameE = NE.IsSame ( E );
1245 
1246 	  if ( isNewE || isSectionE || !isSameE) {
1247 	    if (AddedEqualM.Contains( NE )) {
1248               // a seam must be twice in a loop
1249               if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE ))
1250                 continue;
1251             }
1252 
1253 	    if (isNewE) {
1254 	      if (isSectionE) {
1255 		if ( ! myInter3d.IsSplitOn( NE, E, F) )
1256 		  continue;
1257 	      }
1258 	      else {
1259 		TopoDS_Vertex V1,V2;
1260 		TopExp::Vertices(NE,V1,V2);
1261 		const TopTools_ListOfShape& EL1 = myAsDes->Ascendant(V1);
1262 		const TopTools_ListOfShape& EL2 = myAsDes->Ascendant(V2);
1263 		if ( EL1.Extent() < 2 && EL2.Extent() < 2 )
1264 		  continue;
1265 	      }
1266 	    }
1267 	    else {
1268 	      NE.Orientation( E.Orientation());
1269 	      if (!isSameE) {
1270 		// orient NE because it may be a split of other edge
1271 		Standard_Real f,l,u;
1272 		Handle(Geom_Curve) C3d  = BRep_Tool::Curve( E,f,l );
1273 		Handle(Geom_Curve) NC3d = BRep_Tool::Curve( NE,f,l);
1274 		if ( C3d != NC3d) {
1275 		  gp_Vec D1, ND1;  gp_Pnt P;
1276 		  TopoDS_Vertex V = TopExp::FirstVertex(NE);
1277 		  u = BRep_Tool::Parameter(V,NE);
1278 		  NC3d->D1 (u, P, ND1);
1279 		  u = BRep_Tool::Parameter(V,E);
1280 		  C3d ->D1 (u, P, D1);
1281 		  if (ND1.Dot(D1) < 0)
1282 		    NE.Reverse();
1283 		}
1284 	      }
1285 	    }
1286 	    if (myEqualEdges.Contains( NE ))
1287               AddedEqualM.Add( NE );
1288 
1289 	    needRebuild = Standard_True;
1290 	  }
1291 
1292 	  if (isNewE || isSectionE)
1293 	    myNewSection.Add( NE );
1294 
1295 	  if (isNewE)
1296 	    loops.AddSectionEdge(NE);
1297 	  else
1298 	    loops.AddConstEdge(NE);
1299 	}
1300       }
1301 
1302       //-------------------
1303       // Build the faces.
1304       //-------------------
1305 
1306       if (needRebuild) {
1307 
1308         loops.Perform();
1309         loops.WiresToFaces(myImagesEdges);
1310 
1311         LNF = loops.NewFaces();
1312 
1313         myImagesFaces.Bind(F,LNF);
1314 
1315         // replace the result faces that have already been built
1316         // during same domain faces reconstruction done earlier
1317         if (myInter3d.HasSameDomainF( F ))
1318         {
1319           // build map edge to same domain faces: EFM
1320           TopTools_IndexedDataMapOfShapeListOfShape EFM;
1321           TopTools_MapOfShape SDFM; // avoid doubling
1322           itl.Initialize( myInter3d.SameDomain( F ));
1323           for (; itl.More(); itl.Next()) {
1324             if ( !myImagesFaces.HasImage( itl.Value() ))
1325               continue;
1326             // loop on splits of a SD face
1327             TopTools_ListIteratorOfListOfShape itNF;
1328             itNF.Initialize (myImagesFaces.Image( itl.Value() ));
1329             for ( ; itNF.More(); itNF.Next()) {
1330               TopoDS_Shape SDF = itNF.Value();
1331               if (myImagesFaces.HasImage( SDF )) // already replaced
1332                 SDF = myImagesFaces.Image( SDF ).First();
1333               if (SDFM.Add (SDF))
1334                 TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM);
1335             }
1336           }
1337           // do replace faces in the LNF
1338           TopTools_ListOfShape LOF;
1339           if ( !EFM.IsEmpty() )
1340             itl.Initialize( LNF );
1341           while (itl.More()) {
1342             const TopoDS_Shape& NF = itl.Value();
1343             TopExp_Explorer expE ( NF, TopAbs_EDGE );
1344             const TopoDS_Edge& E  = TopoDS::Edge (expE.Current());
1345             if (EFM.Contains( E )) {
1346               const TopTools_ListOfShape& SDFL = EFM.FindFromKey( E );
1347               TopoDS_Shape SDF = SDFL.First();
1348               Standard_Boolean GoodOri;
1349               Standard_Real dot;
1350               Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF),
1351                                           1, dot, GoodOri);
1352               if (dot < 0)
1353               {
1354                 // NF and SDF are on different side of E
1355                 if (SDFL.Extent() == 1) {
1356                   itl.Next();
1357                   continue;
1358                 }
1359                 else
1360                   SDF = SDFL.Last(); // next face must be on the same side
1361               }
1362               gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF ));
1363               gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF ));
1364               if (V1*V2 < 0)
1365                 SDF.Reverse();
1366 
1367               if (!myImagesFaces.HasImage( NF ))
1368                 myImagesFaces.Bind( NF, SDF );
1369 
1370               // mySharedFaces is used in FindFacesInside()
1371               mySharedFaces.Add( SDF );
1372 
1373               LOF.Prepend ( SDF );
1374               LNF.Remove (itl);
1375             }
1376             else
1377               itl.Next();
1378           }
1379 
1380           LNF.Append (LOF);
1381         }
1382       } // if (needRebuild)
1383 
1384       else {
1385 	LNF.Append( F );
1386 	myImagesFaces.Bind(F,LNF);
1387       }
1388     } // if (myImagesFaces.HasImage( F ))
1389 
1390     // fill the resulting compound
1391     for (itl.Initialize(LNF); itl.More(); itl.Next())
1392       myBuilder.Add ( C, itl.Value());
1393 
1394   } // loop on faces of S
1395 
1396   return C;
1397 }
1398 
1399 
1400 //=======================================================================
1401 //function : Tri
1402 //purpose  :
1403 //=======================================================================
1404 
Tri(const TopoDS_Edge & E,TopTools_SequenceOfShape & Seq,const Partition_Inter3d & theInter3d)1405 static void Tri(const TopoDS_Edge&        E,
1406 		TopTools_SequenceOfShape& Seq,
1407                 const Partition_Inter3d & theInter3d)
1408 {
1409   Standard_Boolean Invert   = Standard_True;
1410   Standard_Real    U1,U2;
1411   TopoDS_Vertex    V1,V2;
1412 
1413   while (Invert) {
1414     Invert = Standard_False;
1415     for ( Standard_Integer i = 1; i < Seq.Length(); i++) {
1416 
1417       V1 = TopoDS::Vertex(Seq.Value(i));
1418       V2 = TopoDS::Vertex(Seq.Value(i+1));
1419 
1420       V1.Orientation(TopAbs_INTERNAL);
1421       V2.Orientation(TopAbs_INTERNAL);
1422 
1423       U1 = BRep_Tool::Parameter(V1,E);
1424       U2 = BRep_Tool::Parameter(V2,E);
1425 
1426       if (IsEqual(U1,U2)) {
1427         if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 ))
1428           Seq.Remove(i+1); // remove V2
1429         else
1430           Seq.Remove(i);
1431 	i--;
1432 	continue;
1433       }
1434       if (U2 < U1) {
1435 	Seq.Exchange(i,i+1);
1436 	Invert = Standard_True;
1437       }
1438     }
1439   }
1440 }
1441 
1442 //=======================================================================
1443 //function : MakeEdges
1444 //purpose  : cut E by vertices VOnE, return list of new edges NE
1445 //=======================================================================
1446 
MakeEdges(const TopoDS_Edge & E,const TopTools_ListOfShape & VOnE,TopTools_ListOfShape & NE) const1447 void Partition_Spliter::MakeEdges (const TopoDS_Edge& E,
1448                                    const TopTools_ListOfShape& VOnE,
1449                                    TopTools_ListOfShape& NE   ) const
1450 {
1451   TopoDS_Edge WE = E;
1452   WE.Orientation(TopAbs_FORWARD);
1453 
1454   Standard_Real    U1,U2, f, l;
1455   TopoDS_Vertex    V1,V2,VF,VL;
1456 
1457   BRep_Tool::Range(WE,f,l);
1458   TopExp::Vertices(WE,VF,VL);
1459 
1460   if (VOnE.Extent() < 3) { // do not rebuild not cut edge
1461     if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) ||
1462 	VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() )  ) {
1463       NE.Append( E );
1464       return;
1465     }
1466   }
1467 
1468   TopTools_SequenceOfShape SV;
1469   TopTools_ListIteratorOfListOfShape itv(VOnE);
1470   TopTools_MapOfOrientedShape VM( VOnE.Extent() );
1471   for (; itv.More(); itv.Next())
1472     if ( VM.Add( itv.Value() ))
1473       SV.Append(itv.Value());
1474 
1475   Tri( WE, SV, myInter3d );
1476 
1477   if (SV.Length() < 3) { // do not rebuild not cut edge
1478     if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) ||
1479 	VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() )  ) {
1480       NE.Append( E );
1481       return;
1482     }
1483   }
1484 
1485   Standard_Integer iVer, NbVer = SV.Length();
1486 
1487 
1488   //----------------------------------------------------------------
1489   // Construction of the new edges .
1490   //----------------------------------------------------------------
1491 
1492   if (VF.IsSame(VL)) { // closed edge
1493     if (NbVer==1)
1494       SV.Append( SV.First() );
1495     else if (!SV.First().IsSame(SV.Last())) {
1496       Standard_Boolean isFirst=0;
1497       Standard_Real    minDU = 1.e10;
1498       TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU);
1499       if (endV.IsSame(SV.First()))
1500 	SV.Append(endV);
1501       else if (endV.IsSame(SV.Last()))
1502 	SV.Prepend(endV);
1503       else
1504 	MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE");
1505     }
1506     NbVer = SV.Length();
1507   }
1508 
1509   for (iVer=1; iVer < NbVer; iVer++) {
1510     V1  = TopoDS::Vertex(SV(iVer));
1511     V2  = TopoDS::Vertex(SV(iVer+1));
1512 
1513     TopoDS_Shape NewEdge = WE.EmptyCopied();
1514     V1.Orientation(TopAbs_FORWARD);
1515     myBuilder.Add  (NewEdge,V1);
1516     V2.Orientation(TopAbs_REVERSED);
1517     myBuilder.Add  (NewEdge,V2);
1518 
1519     if (iVer==1)
1520       U1 = f;
1521     else 	{
1522       V1.Orientation(TopAbs_INTERNAL);
1523       U1=BRep_Tool::Parameter(V1,WE);
1524     }
1525     if (iVer+1 == NbVer)
1526       U2 = l;
1527     else	{
1528       V2.Orientation(TopAbs_INTERNAL);
1529       U2=BRep_Tool::Parameter(V2,WE);
1530     }
1531     if (Abs(U1-U2) <= Precision::PConfusion()) {
1532       MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES");
1533       continue;
1534     }
1535     TopoDS_Edge EE=TopoDS::Edge(NewEdge);
1536     myBuilder.Range (EE,U1,U2);
1537 
1538     TopoDS_Edge NEdge = TopoDS::Edge(NewEdge);
1539     myBuilder.SameParameter(NEdge,Standard_False);
1540 
1541     Standard_Real tol = 1.0e-2;
1542     Standard_Boolean flag = BRep_Tool::SameParameter(NEdge);
1543     if (!flag) {
1544       BRepLib::SameParameter(NEdge,tol);
1545     }
1546     NE.Append(NEdge.Oriented(E.Orientation()));
1547   }
1548 }
1549 
1550 //=======================================================================
1551 //function : MergeEqualEdges
1552 //purpose  : find equal edges,  choose  ones  to  keep and make
1553 //           them have pcurves on all faces they are shared by
1554 //=======================================================================
1555 
MergeEqualEdges(const TopTools_ListOfShape & LSE)1556 void Partition_Spliter::MergeEqualEdges (const TopTools_ListOfShape& LSE)
1557 {
1558   // find equal edges
1559   // map: edge - equal edges
1560   TopTools_DataMapOfShapeListOfShape EEM( LSE.Extent() );
1561   findEqual (LSE, LSE, 0, EEM, myEqualEdges);
1562 
1563   TopTools_ListOfShape EEL; // list of equal edges
1564   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itM (EEM);
1565   for ( ; itM.More(); itM.Next()) {
1566     EEL = itM.Value();
1567     EEL.Append( itM.Key() );
1568 
1569     // choose an edge to keep, section edges have priority
1570     TopoDS_Edge EKeep;
1571     TopTools_ListIteratorOfListOfShape itEE (EEL);
1572     for (; itEE.More(); itEE.Next()) {
1573       EKeep = TopoDS::Edge( itEE.Value() );
1574       const TopoDS_Edge& EKeepOrig = TopoDS::Edge( myImagesEdges.Root( EKeep ));
1575       if (myInter3d.IsSectionEdge( EKeepOrig ))
1576         break;
1577     }
1578 
1579     // update edge images and build pcurves
1580     Standard_Real f,l, tol;
1581     for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) {
1582       const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() );
1583       if ( E.IsSame( EKeep ))
1584         continue;
1585 
1586       // 1. build pcurves of the kept edge on faces where replaced edges exist
1587       const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E ));
1588       TopTools_ListOfShape FL;
1589       FL = myAsDes->Ascendant( EReplOrig );
1590       Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1;
1591       // add faces where the replaced edge is a section edge
1592       if (myInter3d.IsSectionEdge( EReplOrig )) {
1593         TopTools_ListIteratorOfListOfShape seIt;
1594         seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig ));
1595         for ( ; seIt.More(); seIt.Next())
1596           FL.Append( seIt.Value() );
1597       }
1598       // loop on faces
1599       TopTools_ListIteratorOfListOfShape itF (FL);
1600       for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) {
1601         const TopoDS_Face& F = TopoDS::Face( itF.Value());
1602 
1603         Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l);
1604         if (pc.IsNull()) {
1605           Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l);
1606           C3d = new Geom_TrimmedCurve( C3d, f,l);
1607           pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol);
1608           if (pc.IsNull()) {
1609             MESSAGE (" CANNOT BUILD PCURVE ");
1610           }
1611           myBuilder.UpdateEdge( EKeep, pc, F, tol);
1612         }
1613 
1614         if (iFace >= iFirstSectionFace ||
1615             !BRep_Tool::IsClosed( EReplOrig, F ))
1616           continue;
1617 
1618         // build the second pcurve for a seam
1619         TopoDS_Vertex V = TopExp::FirstVertex( EKeep );
1620         Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep );
1621         Standard_Real Urepl = BRep_Tool::Parameter( V, E );
1622 
1623         TopoDS_Edge EReplRev = E;
1624         EReplRev.Reverse();
1625         Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l);
1626         Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l);
1627 
1628         gp_Pnt2d p1r, p2r, pk;
1629         p1r = pcRepl1->Value( Urepl );
1630         p2r = pcRepl2->Value( Urepl );
1631         pk  = pc->Value( Ukeep );
1632 
1633         // suppose that pk is equal to either p1r or p2r
1634         Standard_Boolean isUPeriod =
1635           ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() ));
1636         Standard_Boolean is1Equal;
1637         if (isUPeriod)
1638           is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() ));
1639         else
1640           is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() ));
1641 
1642         Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast
1643           ( pc->Translated( pk, is1Equal ? p2r : p1r ) );
1644 
1645         if (E.Orientation() == TopAbs_REVERSED)
1646           is1Equal = !is1Equal;
1647 
1648         if (is1Equal)
1649           myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol);
1650         else
1651           myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol);
1652 
1653       } // loop on a Faces where a replaced edge exists
1654 
1655 
1656       // 2. update edge images according to replacement
1657       if (myImagesEdges.HasImage( E ))
1658         myImagesEdges.Remove( E );
1659       myImagesEdges.Bind( E, EKeep );
1660 
1661     } // loop on a list of equal edges EEL
1662   } // loop on a map of equal edges EEM
1663 }
1664 
1665 //=======================================================================
1666 //function : KeepShapesInside
1667 //purpose  : remove shapes that are outside of S from resul
1668 //=======================================================================
1669 
KeepShapesInside(const TopoDS_Shape & S)1670 void Partition_Spliter::KeepShapesInside (const TopoDS_Shape& S)
1671 {
1672   TopoDS_Iterator it;
1673   if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
1674     for (it.Initialize( S ); it.More(); it.Next())
1675       KeepShapesInside( it.Value());
1676     return;
1677   }
1678 
1679   Standard_Boolean isTool = Standard_False;
1680   if (!myImageShape.HasImage( S )) {
1681     isTool = CheckTool( S );
1682     if (!isTool) return;
1683   }
1684 
1685   // build map of internal faces
1686   TopTools_IndexedMapOfShape MIF;
1687   TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
1688   TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF );
1689 
1690   TopoDS_Compound C;
1691   myBuilder.MakeCompound(C);
1692 
1693   TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE;
1694   if (!MIF.IsEmpty())
1695   {
1696     // leave in the result only those shapes having a face in MIF
1697     for (it.Initialize( myShape ); it.More(); it.Next()) {
1698       const TopoDS_Shape & aResShape = it.Value();
1699       TopExp_Explorer expResF( aResShape, TopAbs_FACE );
1700       for (; expResF.More(); expResF.Next()) {
1701         if ( MIF.Contains( expResF.Current())) {
1702           myBuilder.Add( C, aResShape );
1703           if (aResShape.ShapeType() < anInternalShapeType)
1704             anInternalShapeType = aResShape.ShapeType();
1705           break;
1706         }
1707       }
1708     }
1709   }
1710 
1711   // may be S was not split by internal faces then it is missing
1712   // in myShape, add it
1713   if (!isTool &&
1714       (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID))
1715   {
1716     TopTools_IndexedMapOfShape MSF; // map of split faces of S
1717     TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF);
1718 
1719     // find a shape having all faces in MSF
1720     for (it.Initialize( myShape ); it.More(); it.Next()) {
1721       TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
1722       for (; expResF.More(); expResF.Next()) {
1723         if (! MSF.Contains( expResF.Current()))
1724           break;
1725       }
1726       if (! expResF.More()) {
1727         myBuilder.Add( C, it.Value() );
1728         break;
1729       }
1730     }
1731   }
1732 
1733   myShape = C;
1734 }
1735 
1736 //=======================================================================
1737 //function : RemoveShapesInside
1738 //purpose  : remove shapes that are inside S from resul
1739 //=======================================================================
1740 
RemoveShapesInside(const TopoDS_Shape & S)1741 void Partition_Spliter::RemoveShapesInside (const TopoDS_Shape& S)
1742 {
1743   TopoDS_Iterator it;
1744   if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
1745     for (it.Initialize( S ); it.More(); it.Next())
1746       RemoveShapesInside( it.Value());
1747     return;
1748   }
1749   Standard_Boolean isTool = Standard_False;
1750   if (!myImageShape.HasImage( S )) {
1751     isTool = CheckTool( S );
1752     if (!isTool) return;
1753   }
1754 
1755   TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
1756   TopTools_IndexedMapOfShape MIF; // map of internal faces
1757   TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF);
1758 
1759   if (MIF.IsEmpty()) return;
1760 
1761   // add to MIF split faces of S
1762   if (myImageShape.HasImage(S))
1763     TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF);
1764 
1765   // leave in the result only those shapes not having all face in MIF
1766 
1767   TopoDS_Compound C;
1768   myBuilder.MakeCompound(C);
1769 
1770   // RMF : faces of removed shapes that encounter once
1771   TopTools_MapOfShape RFM;
1772 
1773   for (it.Initialize( myShape ); it.More(); it.Next()) {
1774 
1775     TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
1776     for (; expResF.More(); expResF.Next())
1777       if (!MIF.Contains( expResF.Current()))
1778 	break;
1779 
1780     if (expResF.More())
1781       // add shape to result
1782       myBuilder.Add( C, it.Value() );
1783     else
1784       // add faces of a removed shape to RFM
1785       for (expResF.ReInit(); expResF.More(); expResF.Next()) {
1786 	const TopoDS_Shape& F = expResF.Current();
1787 	if ( ! RFM.Remove ( F ))
1788 	  RFM.Add( F );
1789       }
1790   }
1791 
1792   if (!isTool) {
1793 
1794     // rebuild S, it must remain in the result
1795 
1796     Standard_Boolean isClosed = Standard_False;
1797     switch (S.ShapeType()) {
1798     case TopAbs_SOLID :
1799       isClosed = Standard_True; break;
1800     case TopAbs_SHELL: {
1801       TopTools_IndexedDataMapOfShapeListOfShape MEF;
1802       TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF);
1803       Standard_Integer i;
1804       for (i=1;  isClosed && i<=MEF.Extent();  ++i)
1805         isClosed = ( MEF(i).Extent() != 1 );
1806       break;
1807     }
1808     default:
1809       isClosed = Standard_False;
1810     }
1811     if (isClosed) {
1812 
1813       // add to a new shape external faces of removed shapes, ie those in RFM
1814 
1815       TopoDS_Shell Shell;
1816       myBuilder.MakeShell( Shell );
1817 
1818       // exclude redundant internal face with edges encounterd only once
1819       TopTools_IndexedDataMapOfShapeListOfShape MEF;
1820       TopTools_MapIteratorOfMapOfShape itF (RFM);
1821       for ( ; itF.More(); itF.Next())
1822         TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF);
1823 
1824       // add only faces forming a closed shell
1825       for (itF.Reset() ; itF.More(); itF.Next())
1826       {
1827         TopExp_Explorer expE (itF.Key(), TopAbs_EDGE);
1828         for (; expE.More(); expE.Next())
1829           if (MEF.FindFromKey(expE.Current()).Extent() == 1)
1830             break;
1831         if (!expE.More())
1832           myBuilder.Add( Shell, itF.Key());
1833       }
1834 
1835       if (S.ShapeType() == TopAbs_SOLID) {
1836         TopoDS_Solid Solid;
1837         myBuilder.MakeSolid( Solid );
1838         myBuilder.Add (Solid, Shell);
1839         myBuilder.Add (C, Solid);
1840       }
1841       else
1842         myBuilder.Add (C, Shell);
1843     }
1844     else {
1845       if (myImageShape.HasImage( S )) {
1846         for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next())
1847           myBuilder.Add (C, it.Value());
1848       }
1849     }
1850   }
1851 
1852   myShape = C;
1853 }
1854 
1855 //=======================================================================
1856 //function : CheckTool
1857 //purpose  : Return True if <S>  is  a tool shape. Prepare tool
1858 //           faces of <S> for the search of internal faces.
1859 //=======================================================================
1860 
CheckTool(const TopoDS_Shape & S)1861 Standard_Boolean Partition_Spliter::CheckTool(const TopoDS_Shape& S)
1862 {
1863   // suppose S has not an image
1864 
1865   Standard_Boolean isTool = Standard_False;
1866   TopoDS_Compound C;
1867   myBuilder.MakeCompound( C );
1868 
1869   TopExp_Explorer expF( S, TopAbs_FACE);
1870   for (; expF.More(); expF.Next()) {
1871 
1872     const TopoDS_Face& F = TopoDS::Face( expF.Current() );
1873     if (myMapTools.Contains( F ))
1874       isTool = Standard_True;
1875     else
1876       continue;
1877 
1878     if (myImagesFaces.HasImage( F )) {
1879       // F has been reconstructed
1880       TopAbs_Orientation Fori = F.Orientation();
1881       TopTools_ListOfShape LNF;
1882       myImagesFaces.LastImage( F, LNF);
1883       TopTools_ListIteratorOfListOfShape itF (LNF);
1884       for ( ; itF.More(); itF.Next())
1885 	myBuilder.Add( C, itF.Value().Oriented(Fori) );
1886       continue;
1887     }
1888 
1889     Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F );
1890     Standard_Boolean hasNewE     = myAsDes->HasDescendant( F );
1891     if (!hasSectionE && !hasNewE)
1892     {
1893       // F intersects nothing
1894       myBuilder.Add( C, F );
1895       continue;
1896     }
1897 
1898     // make an image for F
1899 
1900     TopoDS_Face NF = F;
1901     NF.Orientation(TopAbs_FORWARD);
1902     NF = TopoDS::Face( NF.EmptyCopied() ); // make a copy
1903     TopoDS_Wire NW;
1904     myBuilder.MakeWire( NW );
1905 
1906     // add edges, as less as possible
1907     TopTools_ListOfShape NEL;
1908     TopTools_ListIteratorOfListOfShape itNE;
1909     if (hasSectionE) {
1910       // add section edges
1911       TopExp_Explorer expE;
1912       for ( ; expE.More(); expE.Next()) {
1913 	if (! myImagesEdges.HasImage( expE.Current() ))
1914 	  continue;
1915 	myImagesEdges.LastImage( expE.Current(), NEL );
1916 	for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next())
1917 	  myBuilder.Add ( NW, itNE.Value());
1918       }
1919     }
1920     if (hasNewE) {
1921       // add new edges
1922       NEL = myAsDes->Descendant( F );
1923       for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) {
1924 	TopTools_ListOfShape SEL; // splits
1925 	myImagesEdges.LastImage( itNE.Value(), SEL );
1926 	TopTools_ListIteratorOfListOfShape itSE (SEL);
1927 	for ( ; itSE.More(); itSE.Next())
1928 	  myBuilder.Add ( NW, itSE.Value());
1929       }
1930     }
1931     myBuilder.Add( NF, NW );
1932     myBuilder.Add (C, NF);
1933 
1934     NF.Orientation( F.Orientation() ); // NF is most probably invalid
1935     myImagesFaces.Bind (F, NF);
1936   }
1937   if (isTool)
1938     myImageShape.Bind (S, C);
1939 
1940   return isTool;
1941 }
1942 
1943 //=======================================================================
1944 //function : IsInside
1945 //purpose  : Return True if the first vertex of S1 inside S2.
1946 //           If S1.IsNull(), check infinite point against S2.
1947 //=======================================================================
1948 
IsInside(const TopoDS_Shape & theS1,const TopoDS_Shape & theS2)1949 Standard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1,
1950                                               const TopoDS_Shape& theS2)
1951 {
1952   BRepClass3d_SolidClassifier aClassifier( theS2 );
1953 
1954   TopExp_Explorer expl( theS1, TopAbs_VERTEX );
1955   if (!expl.More())
1956     aClassifier.PerformInfinitePoint( ::RealSmall());
1957   else
1958   {
1959     const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
1960     aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
1961                          BRep_Tool::Tolerance( aVertex ));
1962   }
1963 
1964   return ( aClassifier.State() == TopAbs_IN );
1965 }
1966 
1967 //=======================================================================
1968 //function : GetOriginalShape
1969 //purpose  : Return the  shape  aShape  originates from. aShape
1970 //           should be a face or more complex result shape
1971 //=======================================================================
1972 
GetOriginalShape(const TopoDS_Shape & theShape) const1973 TopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const
1974 {
1975   TopoDS_Shape anOrigShape;
1976 
1977   TopExp_Explorer expl( theShape, TopAbs_FACE);
1978   if (expl.More())
1979   {
1980 
1981     TopoDS_Shape aFace = expl.Current();
1982     if (myImagesFaces.IsImage( aFace ))
1983       aFace = myImagesFaces.Root( aFace );
1984     anOrigShape = myFaceShapeMap.Find( aFace );
1985   }
1986   return anOrigShape;
1987 }
1988 
1989 //=======================================================================
1990 //function : FindToolsToReconstruct
1991 //purpose  : find and store  as  objects  tools which interfere
1992 //           with  solids   or   are   inside   solids  without
1993 //           an interference
1994 //=======================================================================
1995 
FindToolsToReconstruct()1996 void Partition_Spliter::FindToolsToReconstruct()
1997 {
1998   if (myMapTools.IsEmpty())
1999     return;
2000 
2001   Standard_Integer nbFoundTools = 0;
2002 
2003   // build edge - face map in order to detect interference with section edges
2004   TopTools_IndexedDataMapOfShapeListOfShape EFM;
2005   TopTools_MapIteratorOfMapOfShape aMapIt;
2006   for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next())
2007     TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
2008   for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next())
2009     TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
2010 
2011   TopTools_MapOfShape aCurrentSolids, aCheckedShapes;
2012 
2013   // faces cut by new edges
2014   TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces();
2015 
2016   // keep solids interfering with each other in aCurrentSolids map
2017   // and add tool faces intersecting solids as object shapes
2018 
2019   TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE;
2020   for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) {
2021     TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID);
2022     for (; expSo.More(); expSo.Next()) {
2023 
2024       // check if a solid has been already processed
2025       const TopoDS_Shape & aSo = expSo.Current();
2026       if (!aCheckedShapes.Add( aSo ))
2027         continue;
2028       aCurrentSolids.Add( aSo );
2029 
2030       // faces to check
2031       TopTools_ListOfShape aFacesToCheck;
2032       TopExp_Explorer exp( aSo, TopAbs_FACE );
2033       for ( ; exp.More(); exp.Next())
2034         aFacesToCheck.Append ( exp.Current());
2035 
2036       // add other shapes interefering with a solid.
2037       // iterate faces to check while appending new ones
2038       for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next())
2039       {
2040         const TopoDS_Shape& aCheckFace = itCF.Value();
2041 //         if (!aCheckedShapes.Add( aCheckFace ))
2042 //           continue;
2043 
2044         // find faces interfering with aCheckFace
2045         TopTools_ListOfShape anIntFaces;
2046 
2047         // ** 1. faces intersecting aCheckFace with creation of new edges on it
2048         if ( myAsDes->HasDescendant( aCheckFace ))
2049         {
2050           // new edges on aCheckFace
2051           const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace );
2052           for (itE.Initialize( NEL); itE.More(); itE.Next())
2053           {
2054             const TopoDS_Shape & aNewEdge = itE.Value();
2055             if (!aCheckedShapes.Add( aNewEdge ))
2056               continue;
2057 
2058             // faces interfering by aNewEdge
2059             itF.Initialize (myAsDes->Ascendant( aNewEdge ));
2060             for (; itF.More(); itF.Next())
2061               if (aCheckFace != itF.Value())
2062                 anIntFaces.Append( itF.Value() );
2063 
2064             // ** 2. faces having section edge aNewEdge on aFacesToCheck
2065             if (EFM.Contains( aNewEdge))
2066             {
2067               itF.Initialize ( EFM.FindFromKey (itE.Value()));
2068               for (; itF.More(); itF.Next())
2069                 if (aCheckFace != itF.Value())
2070                   anIntFaces.Append( itF.Value() );
2071             }
2072           }
2073         }
2074 
2075         // ** 3. faces cut by edges of aCheckFace
2076         TopExp_Explorer expE (aCheckFace, TopAbs_EDGE);
2077         for ( ; expE.More(); expE.Next())
2078         {
2079           const TopoDS_Shape & aCheckEdge = expE.Current();
2080           if (aCheckedShapes.Add( aCheckEdge ) &&
2081               myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge )))
2082           {
2083             itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge )));
2084             for (; itF.More(); itF.Next())
2085               if (aCheckFace != itF.Value())
2086                 anIntFaces.Append( itF.Value() );
2087           }
2088         }
2089 
2090         // process faces interfering with aCheckFace and shapes they
2091         // belong to
2092         for (itF.Initialize (anIntFaces); itF.More(); itF.Next())
2093         {
2094           const TopoDS_Shape & F = itF.Value();
2095           if (! aCheckedShapes.Add( F ))
2096             continue;
2097 
2098           Standard_Boolean isTool = myMapTools.Contains( F );
2099           if (isTool &&
2100               myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID )
2101           {
2102             // a tool interfering with a solid
2103             if (aSectionFaces.Contains( F ))
2104               AddShape( F );
2105             ++ nbFoundTools;
2106             if (nbFoundTools == myMapTools.Extent())
2107               return;
2108           }
2109 
2110           const TopoDS_Shape & S = myFaceShapeMap( F );
2111           if (aCheckedShapes.Add( S ))
2112           {
2113             // a new shape interefering with aCurrentSolids is found
2114             if (!isTool && S.ShapeType() == TopAbs_SOLID)
2115               aCurrentSolids.Add ( S );
2116             // add faces to aFacesToCheck list
2117             for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next())
2118               aFacesToCheck.Append ( exp.Current() );
2119           }
2120         }
2121       } // loop on aFacesToCheck
2122 
2123       // Here aCurrentSolids contains all solids interfering with each other.
2124       // aCheckedShapes contains all faces belonging to shapes included
2125       // in or interfering with aCurrentSolids or previously checked solids.
2126       // Test if tool faces that do not interefere with other shapes are
2127       // wrapped by any of aCurrentSolids
2128 
2129       TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids);
2130       for ( ; aSolidIt.More(); aSolidIt.Next())
2131       {
2132         const TopoDS_Shape & aSolid = aSolidIt.Key();
2133         TopTools_MapOfShape aCheckedTools( myMapTools.Extent() );
2134 
2135         TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools);
2136         for ( ; aToolIt.More(); aToolIt.Next())
2137         {
2138           const TopoDS_Shape & aToolFace = aToolIt.Key();
2139           if (aCheckedShapes.Contains( aToolFace ) || // already found
2140               aCheckedTools.Contains( aToolFace ))    // checked against aSolid
2141             continue;
2142 
2143           const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace );
2144           TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE );
2145 
2146           Standard_Boolean isInside = IsInside( aToolShape, aSolid );
2147           for ( ; aToolFaceIt.More(); aToolFaceIt.Next() )
2148           {
2149             const TopoDS_Shape & aTool = aToolFaceIt.Current();
2150             aCheckedTools.Add( aTool );
2151             if (isInside)
2152             {
2153               if (aSectionFaces.Contains( aTool ))
2154                 AddShape( aTool );
2155               ++ nbFoundTools;
2156               if (nbFoundTools == myMapTools.Extent())
2157                 return;
2158               aCheckedShapes.Add( aTool );
2159             }
2160           }
2161         }
2162       }
2163 
2164     } // loop on solid shapes
2165   }
2166 }
2167 
2168 #endif
2169