-using namespace std;
-// File : Partition_Spliter.cxx
-// Created : Thu Aug 02 16:07:39 2001
-// Author : Benedicte MARTIN
-// Project : SALOME
-// Module : SALOMEGUI
-// Copyright : Open CASCADE
+// Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
+// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// GEOM PARTITION : partition algorithm
+// File : Partition_Spliter.cxx
+// Author : Benedicte MARTIN
+// Module : GEOM
// $Header$
-
-#include "Partition_Spliter.ixx"
+//
#include "Partition_Inter2d.hxx"
#include "Partition_Inter3d.hxx"
#include "Partition_Loop2d.hxx"
#include "Partition_Loop3d.hxx"
+#include "Partition_Spliter.ixx"
#include "utilities.h"
-#include <TopExp_Explorer.hxx>
-#include <TopExp.hxx>
#include <Precision.hxx>
#include <TopAbs_Orientation.hxx>
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
#include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
#include <TopTools_DataMapOfShapeListOfShape.hxx>
#include <TopTools_MapIteratorOfMapOfShape.hxx>
#include <TopTools_SequenceOfShape.hxx>
-#include <gp_Pnt2d.hxx>
-#include <gp_Pnt.hxx>
-#include <gp_Vec.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Surface.hxx>
#include <Geom_TrimmedCurve.hxx>
+#include <gp_Pnt.hxx>
+#include <gp_Pnt2d.hxx>
+#include <gp_Vec.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS_Wire.hxx>
-#include <BRep_Tool.hxx>
-#include <BRepLib.hxx>
#include <BRepBndLib.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+#include <BRepLib.hxx>
+#include <BRep_Tool.hxx>
-#include <stdio.h>
#include <Extrema_ExtPC.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <TopOpeBRepTool_CurveTool.hxx>
#ifdef DEB
-#define DRAW 0
+//# define PART_PERF
+#endif
+
+#ifdef PART_PERF
+# include <OSD_Chronometer.hxx>
#endif
-#ifdef DRAW
-#include <DBRep.hxx>
-Standard_IMPORT Standard_Boolean AffichInter3d ;
-Standard_IMPORT Standard_Boolean AffichInter2d ;
-Standard_IMPORT Standard_Boolean AffichVertex;
-Standard_IMPORT Standard_Boolean AffichFace;
-Standard_IMPORT Standard_Boolean AffichWire;
-Standard_IMPORT Standard_Boolean SelectFace;
+using namespace std;
-static char* names = new char[100];
+//=======================================================================
+//function : isClosed
+//purpose : check id a shape is closed, ie is a solid or a closed shell
+//=======================================================================
-#endif
+static Standard_Boolean isClosed(const TopoDS_Shape& theShape)
+{
+ Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);
+
+ if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {
+ TopTools_IndexedDataMapOfShapeListOfShape MEF;
+ TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);
+ for (Standard_Integer i=1; isClosed && i<=MEF.Extent(); ++i)
+ isClosed = ( MEF(i).Extent() != 1 );
+ }
+
+ return isClosed;
+}
//=======================================================================
//function : Partition_Spliter
void Partition_Spliter::AddTool(const TopoDS_Shape& S)
{
+ if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
+ TopoDS_Iterator it (S);
+ for (; it.More(); it.Next())
+ {
+ AddTool( it.Value());
+ myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
+ }
+ return;
+ }
+
for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next())
+ {
myMapTools.Add(exp.Current());
+ myFaceShapeMap.Bind( exp.Current(), S );
+ }
+ if (isClosed( S ))
+ myClosedShapes.Add( S );
}
//=======================================================================
if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
TopoDS_Iterator it (S);
for (; it.More(); it.Next())
+ {
AddShape( it.Value());
+ myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
+ }
return;
}
//myBuilder.Add( myShape, S );
return;
}
-
- myListShapes.Append(S);
+ Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S
for (; exp.More(); exp.Next()) {
- myFaceShapeMap.Bind( exp.Current(), S );
- myMapFaces.Add(exp.Current());
- myImagesFaces.SetRoot(exp.Current());
+ const TopoDS_Shape & aFace = exp.Current();
+ if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object
+ myFaceShapeMap.Bind( aFace, S );
+ if (myMapFaces.Add( aFace ))
+ myImagesFaces.SetRoot( aFace );
}
+
+ if (nbFacesBefore == myMapFaces.Extent())
+ return;
+
+ // solids must be processed before all
+ if (S.ShapeType() == TopAbs_SOLID)
+ myListShapes.Prepend(S);
+ else
+ myListShapes.Append(S);
+
+ if (isClosed( S ))
+ myClosedShapes.Add( S );
+
}
//=======================================================================
myListShapes.Clear();
myMapFaces.Clear();
myMapTools.Clear();
+ myEqualEdges.Clear();
+ myNewSection.Clear();
+ myClosedShapes.Clear();
+ mySharedFaces.Clear();
+ myWrappingSolid.Clear();
myFaceShapeMap.Clear();
- myNewSection.Clear();
+ myInternalFaces.Clear();
+ myIntNotClFaces.Clear();
myAsDes->Clear();
myImagesFaces.Clear();
myAddedFacesMap.Clear();
- myInternalFaces.Clear();
}
//=======================================================================
TopTools_ListIteratorOfListOfShape itl;
TopExp_Explorer exp;
+#ifdef PART_PERF
+ OSD_Chronometer aCron;
+#endif
+
if (myDoneStep > TopAbs_VERTEX) {
TopTools_ListOfShape aListFaces;
for (it.Initialize(myMapTools); it.More(); it.Next())
aListFaces.Append(it.Key());
+#ifdef PART_PERF
+ aCron.Start();
+#endif
+
//-----------------------------------------------
// Intersection between faces
//-----------------------------------------------
// result is in myAsDes as a map Face - list of new edges;
// special care is done for section edges, same domain faces and vertices:
// data about them is inside myInter3d
-
myInter3d.CompletPart3d(aListFaces, myFaceShapeMap);
- TopTools_MapOfShape& Modif = myInter3d.TouchedFaces();
- TopTools_MapOfShape& NewEdges = myInter3d.NewEdges();
- Handle(BRepAlgo_AsDes) SectionEdgesAD = myInter3d.SectionEdgesAD();
-
-#ifdef DRAW
- if (AffichInter3d) {
- Standard_Integer i=0;
- for (it.Initialize(NewEdges); it.More(); it.Next(), i++) {
- sprintf(names,"e_%d",i);
- cout << "donly " << names << endl;
- DBRep::Set(names,it.Key());
- }
- }
+#ifdef PART_PERF
+ MESSAGE("+++ CompletPart3d()");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
#endif
- //if (Modif.IsEmpty()) return;
-
- // -----------------------------------------------
- // store tools intersecting solids as object shapes,
- // they must split into faces too
- // -----------------------------------------------
-
- // build edge - face map for tool faces
- TopTools_IndexedDataMapOfShapeListOfShape EFM;
- for (it.Initialize(myMapTools); it.More(); it.Next())
- TopExp::MapShapesAndAncestors( it.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
-
- TopTools_MapOfShape checkedEdgeMap;
- for (itl.Initialize( myListShapes ); itl.More(); itl.Next()) {
- TopExp_Explorer expSo (itl.Value(), TopAbs_SOLID);
- for (; expSo.More(); expSo.Next()) {
-
- TopTools_ListOfShape checkFL; // faces to check
- for ( exp.Init( expSo.Current(), TopAbs_FACE); exp.More(); exp.Next())
- checkFL.Append ( exp.Current());
-
- // iterate a list while appending new items
- TopTools_ListIteratorOfListOfShape itF, itCF;
- for (itCF.Initialize (checkFL) ; itCF.More(); itCF.Next()) {
- const TopoDS_Shape& F = itCF.Value();
- if ( myAsDes->HasDescendant( F )) {
- // new edges on face to check
- const TopTools_ListOfShape& NEL = myAsDes->Descendant( F );
- TopTools_ListIteratorOfListOfShape itE (NEL);
- for (; itE.More(); itE.Next()) {
- if (checkedEdgeMap.Add( itE.Value() )) {
- // intersected faces originating an edge
- itF.Initialize (myAsDes->Ascendant( itE.Value() ));
- for (; itF.More(); itF.Next()) {
- if (!myMapFaces.Contains( itF.Value())) {
- AddShape( itF.Value() );
- checkFL.Append( itF.Value() );
- }
- }
- // faces having section edges on F
- if (EFM.Contains( itE.Value()))
- itF.Initialize ( EFM.FindFromKey (itE.Value()));
- for (; itF.More(); itF.Next()) {
- if (!myMapFaces.Contains( itF.Value())) {
- AddShape( itF.Value() );
- checkFL.Append( itF.Value() );
- }
- }
- }
- }
- }
- // find faces cut by edges of F
- TopExp_Explorer expE(F, TopAbs_EDGE);
- for (; expE.More();expE.Next()) {
- if ( SectionEdgesAD->HasAscendant( expE.Current() )
- && checkedEdgeMap.Add( expE.Current() )) {
- itF.Initialize( SectionEdgesAD->Ascendant( expE.Current()) );
- for (; itF.More(); itF.Next()) {
- if (!myMapFaces.Contains( itF.Value())) {
- AddShape( itF.Value() );
- checkFL.Append( itF.Value() );
- }
- }
- }
- }
- }
- }
- }
-
//-----------------------------------------------
// Intersection of edges
//-----------------------------------------------
+ // add tool faces which must be reconstructed to myMapFaces too
+ FindToolsToReconstruct();
+
+#ifdef PART_PERF
+ MESSAGE("+++ FindToolsToReconstruct()");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
+#endif
+
// add existing vertices to edges of object faces in myAsDes
TopTools_MapOfShape DoneEM;
for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
}
// intersect edges that are descendants of a face in myAsDes
+ TopTools_MapOfShape& Modif = myInter3d.TouchedFaces();
for ( it.Initialize(Modif); it.More(); it.Next()) {
const TopoDS_Face& F = TopoDS::Face(it.Key());
- Partition_Inter2d::CompletPart2d (myAsDes, F, NewEdges);
+ Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges());
}
// now myAsDes contains also new vertices made at edge intersection as
// descendant of edges both new and old
myDoneStep = TopAbs_VERTEX;
+#ifdef PART_PERF
+ MESSAGE("+++ CompletPart2d()");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
+#endif
} // if (myDoneStep > TopAbs_VERTEX)
if (Limit == TopAbs_VERTEX) {
return;
}
+
if (myDoneStep > TopAbs_EDGE) {
//-----------------------------------------------
- // Reconstruction of all the edges.
+ //-----------------------------------------------
+ // ------- Reconstruction of all the edges.------
+ //-----------------------------------------------
//-----------------------------------------------
- // Add to myAsDes end vertices of new edges and cut new edges
- int j=1;
- TopTools_MapOfShape& NewEdges = myInter3d.NewEdges();
+ // ==============
+ // cut new edges
+ // ==============
TopTools_ListOfShape LSE; // all edge splits
- for ( it.Initialize(NewEdges); it.More(); it.Next()) {
+ for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) {
TopoDS_Vertex V1,V2;
TopoDS_Edge EE = TopoDS::Edge(it.Key());
if (aListV.IsEmpty())
continue; // new edge does not intersect any other edge
- // one face is Tool, the other is Shape:
- if ( (myMapTools.Contains(aListF.First()) && myMapFaces.Contains(aListF.Last()) ) ||
- ( myMapFaces.Contains(aListF.First()) && myMapTools.Contains(aListF.Last()) ) )
+ // Add end vertices to new edges only if
+ // one face is Tool and the other is Shape
+ Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() );
+ Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() );
+ if (isTool1 || isTool2)
{
TopExp::Vertices(EE,V1,V2);
Standard_Real Tol = Max (BRep_Tool::Tolerance( V1 ),
myAsDes->Add(EE,V2);
}
}
-#ifdef DRAW
- if (AffichVertex) {
- for(itl.Initialize(aListV);itl.More();itl.Next(), j++) {
- sprintf(names,"v_%d",j);
- cout << "donly " << names << endl;
- DBRep::Set(names,itl.Value());
- }
- }
-#endif
+ // cut new edges
Standard_Integer NbV=aListV.Extent() ;
if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) {
- // cut new edges
TopTools_ListOfShape LNE;
MakeEdges (EE,aListV, LNE);
myImagesEdges.Bind(EE,LNE);
}
}
+ // ==============
// cut old edges
+ // ==============
for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) {
const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() );
LSE.Append( LNE );
}
}
+#ifdef PART_PERF
+ MESSAGE("+++ Cut Edges");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
+#endif
+ // process same domain section edges
MergeEqualEdges( LSE );
myDoneStep = TopAbs_EDGE;
+#ifdef PART_PERF
+ MESSAGE("+++ MergeEqualEdges()");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
+#endif
} // if (myDoneStep > TopAbs_EDGE)
if (Limit == TopAbs_EDGE) {
// add splits of old edges
TopTools_ListIteratorOfListOfShape itNE;
for (itl.Initialize( myListShapes );itl.More();itl.Next()) {
+ if (myMapTools.Contains( itl.Value() ))
+ continue; // skip tool faces
for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) {
itNE.Initialize( myImagesEdges.Image( exp.Current() ));
for ( ; itNE.More(); itNE.Next())
return;
}
- // make faces interfering by section edges share the same splits
- //ProcessSectionEdges( SectionEdgesAD );
-
//-----------------------------------------------
// split faces
}
myDoneStep = TopAbs_FACE;
+#ifdef PART_PERF
+ MESSAGE("+++ MakeFaces()");
+ aCron.Show( cout );
+ aCron.Reset();
+ aCron.Start();
+#endif
}
if (Limit == TopAbs_WIRE ||
//-----------------------------------------------
- // split solids
+ // split and add solids and shells
//-----------------------------------------------
-
- // solids must remains closed, so process them first
+
Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE ||
Limit < TopAbs_SHELL);
+ for (itl.Initialize(myListShapes);itl.More();itl.Next())
+ {
+ const TopoDS_Shape & S = itl.Value();
+ if (S.ShapeType() > TopAbs_SHELL)
+ continue;
- for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
- if (itl.Value().ShapeType() == TopAbs_SOLID) {
- TopTools_ListOfShape NSL;
- MakeShells (itl.Value() , NSL);
- TopTools_ListIteratorOfListOfShape itS(NSL);
- for ( ; itS.More(); itS.Next())
- if (makeSolids) {
- // make a solid from a shell
- TopoDS_Solid Solid;
- myBuilder.MakeSolid( Solid );
- myBuilder.Add (Solid, itS.Value());
- myBuilder.Add (myShape, Solid);
- }
- else
- myBuilder.Add (myShape, itS.Value());
- }
- }
-
- //-----------------------------------------------
- // split shells
- //-----------------------------------------------
+ TopTools_ListOfShape NSL; // new shape list
+ MakeShells (S , NSL);
+ if (makeSolids && S.ShapeType() == TopAbs_SOLID )
+ MakeSolids( S, NSL );
- for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
- if (itl.Value().ShapeType() == TopAbs_SHELL) {
- TopTools_ListOfShape NSL;
- MakeShells (itl.Value() , NSL);
- TopTools_ListIteratorOfListOfShape itS(NSL);
- for ( ; itS.More(); itS.Next())
- myBuilder.Add (myShape, itS.Value());
- }
+ // store new shells or solids
+ TopTools_ListIteratorOfListOfShape itNSL (NSL);
+ for ( ; itNSL.More(); itNSL.Next())
+ myBuilder.Add (myShape, itNSL.Value());
}
-
+#ifdef PART_PERF
+ MESSAGE("+++ MakeShells()");
+ aCron.Show( cout );
+#endif
+
//-----------------------------------------------
// add split faces
//-----------------------------------------------
- for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
- const TopoDS_Shape& S = itl.Value();
+ for (itl.Initialize(myListShapes);itl.More();itl.Next())
+ {
+ const TopoDS_Shape & S = itl.Value();
if (S.ShapeType() != TopAbs_FACE ||
- myMapTools.Contains( S ))
+ myMapTools.Contains( S ))
continue;
TopoDS_Iterator itS( myImageShape.Image(S).First() );
for (; itS.More(); itS.Next())
if (! myAddedFacesMap.Contains( itS.Value() ))
- myBuilder.Add (myShape, itS.Value());
+ myBuilder.Add (myShape, itS.Value());
}
-
+
myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL;
}
-
//=======================================================================
-//function : Tri
-//purpose :
+//function : MakeSolids
+//purpose : make solids out of Shells
//=======================================================================
-static void Tri(const TopoDS_Edge& E,
- TopTools_SequenceOfShape& Seq)
+void Partition_Spliter::MakeSolids(const TopoDS_Shape & theSolid,
+ TopTools_ListOfShape & theShellList)
{
- Standard_Boolean Invert = Standard_True;
- Standard_Integer NbPoints = Seq.Length();
- Standard_Real U1,U2;
- TopoDS_Vertex V1,V2;
-
- while (Invert) {
- Invert = Standard_False;
- for ( Standard_Integer i = 1; i < Seq.Length(); i++) {
-
- V1 = TopoDS::Vertex(Seq.Value(i));
- V2 = TopoDS::Vertex(Seq.Value(i+1));
-
- V1.Orientation(TopAbs_INTERNAL);
- V2.Orientation(TopAbs_INTERNAL);
-
- U1 = BRep_Tool::Parameter(V1,E);
- U2 = BRep_Tool::Parameter(V2,E);
-
- if (IsEqual(U1,U2)) {
- Seq.Remove(i);
- i--;
- continue;
- }
- if (U2 < U1) {
- Seq.Exchange(i,i+1);
- Invert = Standard_True;
- }
- }
+ // for a solid wrapping other shells or solids without intersection,
+ // it is necessary to find shells making holes in it
+
+ TopTools_ListOfShape aNewSolids; // result
+ TopTools_ListOfShape aHoleShells;
+ TopoDS_Shape anInfinitePointShape;
+
+ Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid );
+ if (!isWrapping && !theShellList.IsEmpty())
+ {
+ // check if theSolid initially has internal shells
+ TopoDS_Iterator aShellExp (theSolid);
+ aShellExp.Next();
+ isWrapping = aShellExp.More();
}
-}
-
-//=======================================================================
-//function : MakeEdges
-//purpose : cut E by vertices VOnE, return list of new edges NE
-//=======================================================================
-
-void Partition_Spliter::MakeEdges (const TopoDS_Edge& E,
- const TopTools_ListOfShape& VOnE,
- TopTools_ListOfShape& NE ) const
-{
- TopoDS_Edge WE = E;
- WE.Orientation(TopAbs_FORWARD);
-
- TopTools_ListIteratorOfListOfShape itv(VOnE);
- TopTools_SequenceOfShape SV;
-
- Standard_Real U1,U2, f, l;
- TopoDS_Vertex V1,V2,VF,VL;
-
- BRep_Tool::Range(WE,f,l);
- TopExp::Vertices(WE,VF,VL);
+
+ TopTools_ListIteratorOfListOfShape aShellIt(theShellList);
+ for ( ; aShellIt.More(); aShellIt.Next())
+ {
+ const TopoDS_Shape & aShell = aShellIt.Value();
+
+ // check if a shell is a hole
+ if (isWrapping && IsInside (anInfinitePointShape, aShell))
+ aHoleShells.Append( aShell );
+ else
+ {
+ // make a solid from a shell
+ TopoDS_Solid Solid;
+ myBuilder.MakeSolid( Solid );
+ myBuilder.Add (Solid, aShell);
- if (VOnE.Extent() < 3) { // do not rebuild not cut edge
- if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) ||
- VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ) ) {
- NE.Append( E );
- return;
+ aNewSolids.Append (Solid);
}
}
- for (; itv.More(); itv.Next())
- SV.Append(itv.Value());
-
- Tri( WE, SV);
-
- Standard_Integer iVer, NbVer = SV.Length();
-
-
- //----------------------------------------------------------------
- // Construction of the new edges .
- //----------------------------------------------------------------
+ // find an outer shell most close to each hole shell
+ TopTools_DataMapOfShapeShape aInOutMap;
+ for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next())
+ {
+ const TopoDS_Shape & aHole = aShellIt.Value();
+ TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids);
+ for ( ; aSolisIt.More(); aSolisIt.Next())
+ {
+ const TopoDS_Shape & aSolid = aSolisIt.Value();
+ if (! IsInside( aHole, aSolid ))
+ continue;
- if (VF.IsSame(VL)) { // closed edge
- if (NbVer==1)
- SV.Append( SV.First() );
- else if (!SV.First().IsSame(SV.Last())) {
- Standard_Boolean isFirst=0;
- Standard_Real minDU = 1.e10;
- TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU);
- if (endV.IsSame(SV.First()))
- SV.Append(endV);
- else if (endV.IsSame(SV.Last()))
- SV.Prepend(endV);
+ if ( aInOutMap.IsBound (aHole))
+ {
+ const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
+ if ( IsInside( aSolid, aSolid2 ))
+ {
+ aInOutMap.UnBind( aHole );
+ aInOutMap.Bind ( aHole, aSolid );
+ }
+ }
else
- MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE");
- }
- NbVer = SV.Length();
- }
-
- for (iVer=1; iVer < NbVer; iVer++) {
- V1 = TopoDS::Vertex(SV(iVer));
- V2 = TopoDS::Vertex(SV(iVer+1));
-
- TopoDS_Shape NewEdge = WE.EmptyCopied();
- V1.Orientation(TopAbs_FORWARD);
- myBuilder.Add (NewEdge,V1);
- V2.Orientation(TopAbs_REVERSED);
- myBuilder.Add (NewEdge,V2);
-
- if (iVer==1)
- U1 = f;
- else {
- V1.Orientation(TopAbs_INTERNAL);
- U1=BRep_Tool::Parameter(V1,WE);
- }
- if (iVer+1 == NbVer)
- U2 = l;
- else {
- V2.Orientation(TopAbs_INTERNAL);
- U2=BRep_Tool::Parameter(V2,WE);
+ aInOutMap.Bind ( aHole, aSolid );
}
- if (Abs(U1-U2) <= Precision::PConfusion()) {
- MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES");
- continue;
- }
- TopoDS_Edge EE=TopoDS::Edge(NewEdge);
- myBuilder.Range (EE,U1,U2);
-
- TopoDS_Edge NEdge = TopoDS::Edge(NewEdge);
- myBuilder.SameParameter(NEdge,Standard_False);
- Standard_Real tol = 1.0e-2;
- Standard_Boolean flag = BRep_Tool::SameParameter(NEdge);
- if (!flag) {
- BRepLib::SameParameter(NEdge,tol);
- }
- NE.Append(NEdge.Oriented(E.Orientation()));
+ // add aHole to a solid
+ if (aInOutMap.IsBound( aHole ))
+ myBuilder.Add ( aInOutMap( aHole ), aHole );
}
-}
+ theShellList.Clear();
+ theShellList.Append( aNewSolids );
+}
+
//=======================================================================
//function : FindFacesInside
//purpose : return compound of faces of other shapes that are
-// inside <S>.
-// <S> is an object shape.
+// inside <theShape>.
+// <theShape> is an object shape.
// <CheckClosed> makes avoid faces that do not form a
// closed shell
// <All> makes return already added faces
//=======================================================================
-TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& S,
+TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape,
const Standard_Boolean CheckClosed,
const Standard_Boolean All)
{
- if (myInternalFaces.IsBound( S ))
- return myInternalFaces.Find ( S );
-
- TopoDS_Compound C;
- myBuilder.MakeCompound(C);
-
- const TopoDS_Shape& SS = myImageShape.Image(S).First(); // compound of split faces of S
+ // ================================================
+ // check if internal faces have been already found
+ // ================================================
+ TopExp_Explorer expl;
+ if (myInternalFaces.IsBound( theShape ))
+ {
+ TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape );
+ TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape );
+
+ expl.Init( aIntRemFComp, TopAbs_FACE);
+ if (CheckClosed || !expl.More())
+ return aIntFComp;
+
+ TopoDS_Compound C;
+ myBuilder.MakeCompound( C );
+ // add removed faces
+ for (; expl.More(); expl.Next())
+ myBuilder.Add( C, expl.Current() );
+ // add good internal faces
+ for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next())
+ myBuilder.Add( C, expl.Current() );
+ return C;
+ }
+
+ // ===================================
+ // get data for internal faces search
+ // ===================================
- TopTools_MapOfShape MSE, MPF;
- TopTools_DataMapOfShapeListOfShape MEF;
+ // compound of split faces of theShape
+ const TopoDS_Shape& CSF = myImageShape.Image(theShape).First();
+
+ TopTools_MapOfShape MSE, MFP;
+ TopTools_DataMapOfShapeListOfShape DMSEFP;
TopTools_MapIteratorOfMapOfShape itm;
- TopExp_Explorer expl;
- TopTools_ListOfShape Empty;
+ TopTools_ListOfShape EmptyL;
- // MSE filling: map of section edges of SS
- for (expl.Init(SS,TopAbs_EDGE); expl.More(); expl.Next()) {
- TopoDS_Shape resE = expl.Current() ;
- if (myNewSection.Contains( resE ))
+ // MSE filling: map of new section edges of CSF
+ for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) {
+ const TopoDS_Shape & resE = expl.Current() ;
+ if (myNewSection.Contains( resE )) // only new edges
MSE.Add(resE);
}
- // 1. MPF filling: map of resulting faces except those of S,
- // we`ll add to C those of them which are inside SS
- // 2. MEF filling: edge of MSE => faces of MPF
+ // DMEF: map edge of CSF - faces of CSF
+ TopTools_IndexedDataMapOfShapeListOfShape DMEF;
+ TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF);
+
+ // Fill
+ // 1. MFP - a map of faces to process: map of resulting faces except
+ // those of theShape; we`ll add to C those of them which are inside CSF
+ // 2. DMSEFP - edge of MSE => faces of MFP
TopTools_ListIteratorOfListOfShape itl;
for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
- const TopoDS_Shape& SL = itl.Value();
- if ( S.IsSame( SL )) continue;
+ const TopoDS_Shape& aShape = itl.Value();
+ if ( theShape.IsSame( aShape )) continue;
// fill maps
- TopoDS_Iterator itF ( myImageShape.Image(SL).First() );
+ // iterate on split faces of aShape
+ TopoDS_Iterator itF ( myImageShape.Image(aShape).First() );
for ( ; itF.More(); itF.Next()) {
- const TopoDS_Shape& snf = itF.Value();
- MPF.Add(snf);
- for (expl.Init( snf, TopAbs_EDGE ); expl.More(); expl.Next()) {
+ const TopoDS_Shape& sf = itF.Value();
+ MFP.Add(sf);
+ // iterate on edges of split faces of aShape,
+ // add to DMSEFP edges that are new
+ for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) {
TopoDS_Shape se = expl.Current();
if ( MSE.Contains(se)) {// section edge
- if (!MEF.IsBound(se))
- MEF.Bind(se,Empty);
- MEF(se).Append(snf);
+ if (!DMSEFP.IsBound(se))
+ DMSEFP.Bind(se,EmptyL);
+ DMSEFP(se).Append(sf);
}
}
}
}
+
+ // add tool faces having section edges on faces of theShape to MFP and DMSEFP;
+ // such tool faces need not to be reconstructed and so they are not in myListShapes
+ for (itm.Initialize(myMapTools); itm.More(); itm.Next())
+ {
+ const TopoDS_Shape & aToolFace = itm.Key();
+ if (myMapFaces.Contains( aToolFace ))
+ continue;
+ MFP.Add(aToolFace);
+ for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) {
+ TopoDS_Shape se = expl.Current();
+ if ( MSE.Contains( se )) {// section edge
+ if (!DMSEFP.IsBound( se ))
+ DMSEFP.Bind( se, EmptyL );
+ DMSEFP( se ).Append( aToolFace );
+ }
+ }
+ }
- // MSEF: map edge of SS - faces of SS
- TopTools_IndexedDataMapOfShapeListOfShape MSEF;
- TopExp::MapShapesAndAncestors(SS, TopAbs_EDGE, TopAbs_FACE, MSEF);
- // find faces inside S
+ // ===========================
+ // find faces inside theShape
+ // ===========================
Standard_Boolean skipAlreadyAdded = Standard_False;
Standard_Boolean GoodOri, inside;
TopTools_ListOfShape KeepFaces;
TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
- for (Mapit.Initialize(MEF); Mapit.More() ; Mapit.Next() ) {
- TopoDS_Edge E = TopoDS::Edge (Mapit.Key());
- TopoDS_Edge OrigE = TopoDS::Edge ( myImagesEdges.Root( E ));
+ // iterate on section edges, check faces of other shapes
+ // sharing section edges and put internal faces to KeepFaces
+ for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) {
+ // a new edge of theShape
+ const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key());
+ // an original edge of which E is a split
+ const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E ));
+ // does OrigE itself splits a face
Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE );
- TopTools_ListOfShape& EF = MEF.ChangeFind(E);
- itl.Initialize( EF );
+ // split faces of other shapes sharing E
+ TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E);
+ itl.Initialize( LSF );
while (itl.More()) {
- TopoDS_Face face1 = TopoDS::Face(itl.Value());
- EF.Remove( itl ); // == itl.Next();
- if (!MPF.Remove( face1 ))
- continue; // was not is MPF ( i.e already checked)
+ // a split faces of other shape
+ TopoDS_Face aFace1 = TopoDS::Face(itl.Value());
+ // remove aFace1 form DMSEFP and MFP
+ LSF.Remove( itl ); // == itl.Next();
+ if (!MFP.Remove( aFace1 ))
+ continue; // was not is MFP ( i.e already checked)
+ // check if aFace1 was already added to 2 shells
if (!All &&
- myAddedFacesMap.Contains( face1 ) &&
- myAddedFacesMap.Contains( face1.Reversed() )) {
+ myAddedFacesMap.Contains( aFace1 ) &&
+ myAddedFacesMap.Contains( aFace1.Reversed() )) {
skipAlreadyAdded = Standard_True;
- continue; // already added to 2 shells
+ continue;
}
- // find another face which originates from the same face as <face1>
- const TopoDS_Shape& origS = myImagesFaces.Root(face1);
- TopoDS_Shape face2;
+ // find another face which originates from the same face as aFace1:
+ // usually aFace2 is internal if aFace1 is not and vice versa
+
+ TopoDS_Shape anOrigFace = aFace1;
+ if (myImagesFaces.IsImage(aFace1))
+ anOrigFace = myImagesFaces.Root(aFace1);
+ TopoDS_Shape aFace2;
if ( !isSectionE ) {
while (itl.More()) {
- face2 = itl.Value();
- if (!MPF.Contains( face2 )) {
- EF.Remove( itl );
+ aFace2 = itl.Value();
+ if (!MFP.Contains( aFace2 )) {
+ LSF.Remove( itl );
continue;
}
- if (origS.IsSame( myImagesFaces.Root( face2 )))
+ if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 )))
break;
itl.Next();
}
- if (itl.More()) { // face2 found
- EF.Remove( itl );
- MPF.Remove(face2);
+ if (itl.More()) { // aFace2 found, remove it from maps
+ LSF.Remove( itl );
+ MFP.Remove(aFace2);
}
else
- face2.Nullify();
- itl.Initialize( EF );
+ aFace2.Nullify();
+ itl.Initialize( LSF );
}
- // check that origS is not same domain with SS
- Standard_Boolean sameDom1 = 0, sameDom2 = 0;
- const TopTools_ListOfShape& FL = MSEF.FindFromKey(E); //faces of SS sharing E
+ // check that anOrigFace is not same domain with CSF faces it intersects
+
+ const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E
const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First());
const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last());
- if (origS.IsSame( origF1 ))
- sameDom1 = Standard_True;
- if ( origS.IsSame( origF2 ))
- sameDom2 = Standard_True;
- if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( origS )) {
- sameDom1 = myInter3d.IsSameDomainF( origS, origF1);
- sameDom2 = (origF1 == origF2) ? sameDom1 : myInter3d.IsSameDomainF( origS, origF2);
+ Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 );
+ Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 );
+ if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) {
+ sameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1);
+ if (origF1 == origF2)
+ sameDom2 = sameDom1;
+ else
+ myInter3d.IsSameDomainF( anOrigFace, origF2);
}
if (sameDom1 && sameDom2)
continue;
if (inside || (dot + Precision::Angular() >= 1.0))
continue; // E is convex between origF1 and origF2 or they are tangent
}
-
-
+
+
// keep one of found faces
- const TopoDS_Shape& SFace = sameDom1 ? FL.Last() : FL.First(); //face of SS sharing E
- inside = Partition_Loop3d::IsInside (E, TopoDS::Face(SFace), face1,
+
+ //face of CSF sharing E
+ const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First();
+ // analyse aFace1 state
+ inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1,
1, dot, GoodOri);
- if ((dot + Precision::Angular() >= 1.0) &&
- !face2.IsNull()) { // face2 position is not clear, it will be analysed alone
- MPF.Add( face2 );
- EF.Append( face2 );
- face2.Nullify();
+ if (inside && isSectionE)
+ {
+ // aFace1 must be tested with both adjacent faces of CSF
+ const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last();
+ if (aShapeFace2 != aShapeFace)
+ inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1,
+ 1, dot, GoodOri);
+ }
+
+ // store internal face
+ if (inside)
+ KeepFaces.Append(aFace1);
+
+ else if (!aFace2.IsNull())
+ {
+ if (dot + Precision::Angular() >= 1.0)
+ {
+ // aFace2 state is not clear, it will be analysed alone,
+ // put it back to the maps
+ MFP.Add( aFace2 );
+ LSF.Append( aFace2 );
+ }
+ else
+ KeepFaces.Append(aFace2);
}
- if (inside)
- KeepFaces.Append(face1);
- else
- if (!face2.IsNull())
- KeepFaces.Append(face2);
}
}
+ // ===================================================
+ // add not distributed faces connected with KeepFaces
+ // ===================================================
+
+ // ultimate list of internal faces
TopTools_ListOfShape KeptFaces;
- if (MPF.IsEmpty())
- KeptFaces.Append (KeepFaces);
- while (!KeepFaces.IsEmpty()) {
- // add to KeepFaces not distributed faces connected with KeepFaces
+ // add to MFP not split tool faces as well, they may be connected with
+ // tool faces interfering with theShape
+ for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) {
+ const TopoDS_Shape& aToolFace = itm.Key();
+ if (!myImageShape.HasImage(aToolFace))
+ MFP.Add (aToolFace);
+ }
+
+ if (MFP.IsEmpty())
+ KeptFaces.Append (KeepFaces);
- // KeepEdges : map of edges of kept faces
+ while (!KeepFaces.IsEmpty())
+ {
+ // KeepEdges : map of edges of faces kept last time
TopTools_IndexedMapOfShape KeepEdges;
- for (itl.Initialize(KeepFaces);itl.More();itl.Next() )
+ for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) {
TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges);
+ KeptFaces.Append( itl.Value() );
+ }
- KeptFaces.Append (KeepFaces); // == KeepFaces.Clear()
-
- // keep faces connected with already kept faces
- for (itm.Initialize(MPF);itm.More();itm.Next() ) {
- const TopoDS_Shape& PF = itm.Key();
- for (expl.Init(PF,TopAbs_EDGE); expl.More(); expl.Next()) {
- const TopoDS_Shape& se = expl.Current();
- if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {
- KeepFaces.Append(PF);
- MPF.Remove(PF);
- break;
- }
+ KeepFaces.Clear();
+
+ // keep faces connected with already kept faces by KeepEdges
+ for ( itm.Initialize(MFP); itm.More(); itm.Next() ) {
+ const TopoDS_Shape& FP = itm.Key();
+ for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) {
+ const TopoDS_Shape& se = expl.Current();
+ if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {
+ KeepFaces.Append(FP);
+ MFP.Remove(FP);
+ break;
+ }
+ }
+ }
+ }
+
+ // ===============================================================
+ // here MFP contains faces outer of theShape and those of shapes
+ // which do not interfere with theShape at all and between which
+ // there may be those wrapped by theShape and whose faces may be
+ // needed to be returned as well
+ // ===============================================================
+
+ Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID);
+ if (All || isSolid) // All is for sub-result removal
+ {
+ // loop on not used faces; checked faces will be removed from MFP
+ // during the loop
+ for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) {
+ const TopoDS_Shape & aFace = itm.Key();
+
+ // a shape which aFace originates from
+ TopoDS_Shape anOrigShape = GetOriginalShape( aFace );
+
+ // find out if all split faces of anOrigShape are not in MFP
+ // and by the way remove them from MFP
+ Standard_Boolean isAllOut = Standard_True;
+ TopoDS_Shape aSplitFaces = anOrigShape;
+ if (myImageShape.HasImage(anOrigShape))
+ aSplitFaces = myImageShape.Image(anOrigShape).First();
+
+ TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept
+ for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next())
+ {
+ const TopoDS_Shape & aSpFace = expl.Current();
+ // a tool face which became object has image but the whole tool shape has not
+ if (myImageShape.HasImage( aSpFace ))
+ {
+ TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE );
+ for ( ; exF.More(); exF.Next() )
+ {
+ aSplitFaceL.Append( exF.Current() );
+ if ( ! MFP.Remove( exF.Current() ) && isAllOut )
+ // a shared face might be removed from MFP during a prev loop
+ isAllOut = mySharedFaces.Contains( exF.Current() );
+ }
+ }
+ else
+ {
+ aSplitFaceL.Append( aSpFace );
+ if ( ! MFP.Remove( aSpFace ) && isAllOut)
+ // a shared face might be removed from MFP during a prev loop
+ isAllOut = mySharedFaces.Contains( aSpFace );
+ }
+ }
+ itm.Initialize( MFP ); // iterate remaining faces
+ if ( !isAllOut )
+ continue;
+
+ // classify anOrigShape against theShape
+ if (IsInside (anOrigShape, theShape))
+ {
+ if (isSolid && myClosedShapes.Contains( anOrigShape ))
+ // to make a special care at solid reconstruction
+ myWrappingSolid.Add ( theShape );
+
+ // keep faces of an internal shape anOrigShape
+ KeptFaces.Append( aSplitFaceL );
}
}
}
- // check if kept faces make shell without free edges
- MSEF.Clear(); // edge - kept faces
- MPF.Clear(); // wrong faces
+ // ====================================================
+ // check if kept faces form a shell without free edges
+ // ====================================================
+
+ DMEF.Clear(); // edge - kept faces
+ MFP.Clear(); // reuse it for wrong faces
if (CheckClosed) {
for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
- TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, MSEF);
+ TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF);
- Standard_Integer i, nb = MSEF.Extent();
+ Standard_Integer i, nb = DMEF.Extent();
Standard_Boolean isClosed = Standard_False;
while (!isClosed) {
isClosed = Standard_True;
for (i=1; isClosed && i<=nb; ++i) {
- const TopoDS_Shape& E = MSEF.FindKey( i );
- if (! MSE.Contains( E ))
- isClosed = ( MSEF(i).Extent() != 1 );
+ const TopoDS_Shape& E = DMEF.FindKey( i );
+ if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) &&
+ ! MSE.Contains( E ))
+ isClosed = ( DMEF(i).Extent() != 1 );
}
if (!isClosed) {
- const TopoDS_Shape& F = MSEF.FindFromIndex( i-1 ).First(); // bad face
- MPF.Add( F );
- // remove bad face from MSEF
- for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {
+ const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face
+ MFP.Add( F );
+ // remove bad face from DMEF
+ for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {
const TopoDS_Shape& E = expl.Current();
- TopTools_ListOfShape& FL = MSEF.ChangeFromKey( E );
- for (itl.Initialize( FL ); itl.More(); itl.Next() ) {
- if ( F.IsSame( itl.Value() )) {
- FL.Remove( itl );
- break;
- }
- }
- }
+ TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E );
+ for (itl.Initialize( FL ); itl.More(); itl.Next() ) {
+ if ( F.IsSame( itl.Value() )) {
+ FL.Remove( itl );
+ break;
+ }
+ }
+ }
}
}
}
- // add to the compound kept faces except bad ones in MPF
- if (KeptFaces.Extent() > MPF.Extent()) {
- for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
- if (! MPF.Contains( itl.Value() )) {
- myBuilder.Add( C, itl.Value());
- //myBuilder.Add( C, itl.Value().Reversed());
- }
+ // ==============
+ // make a result
+ // ==============
+
+ TopoDS_Compound C;
+ // compound of removed internal faces
+ TopoDS_Compound CNotCl;
+
+ myBuilder.MakeCompound(C);
+ myBuilder.MakeCompound(CNotCl);
+
+ // add to compounds
+ for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
+ {
+ TopoDS_Shape & aIntFace = itl.Value();
+ if (! MFP.Contains( aIntFace ))
+ myBuilder.Add( C, aIntFace);
+ else
+ myBuilder.Add( CNotCl, aIntFace);
+ }
+
+ if (!skipAlreadyAdded && CheckClosed)
+ {
+ myInternalFaces.Bind( theShape, C );
+ myIntNotClFaces.Bind( theShape, CNotCl );
}
- if (!skipAlreadyAdded)
- myInternalFaces.Bind( S, C );
-
return C;
}
//=======================================================================
void Partition_Spliter::MakeShells(const TopoDS_Shape& S,
- TopTools_ListOfShape& NS)
+ TopTools_ListOfShape& NS)
{
- // check if S is closed shape
- Standard_Boolean isClosed = Standard_True;
-
- TopTools_IndexedDataMapOfShapeListOfShape MEF;
- Standard_Integer i;
- if (S.ShapeType() != TopAbs_SOLID) {
- TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF);
- for (i=1; isClosed && i<=MEF.Extent(); ++i)
- isClosed = ( MEF(i).Extent() != 1 );
- }
Partition_Loop3d ShellMaker;
// get compound of split faces of S
const TopoDS_Shape& FacesComp = myImageShape.Image(S).First();
ShellMaker.AddConstFaces( FacesComp );
- // split faces inside S
- if (isClosed) {
+ // add split faces inside S
+ if (myClosedShapes.Contains( S )) {
TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True);
ShellMaker.AddSectionFaces( InternalFacesComp );
-// } else { // a shell may become closed
-// ShellMaker.AddConstFaces( InternalFacesComp );
}
NS = ShellMaker.MakeShells( myAddedFacesMap );
- // 1. Add faces added to new shell to myAddedFacesMap:
+ // Add faces added to new shell to myAddedFacesMap:
// avoid rebuilding twice commont part of 2 solids.
- // 2. Check shell closeness (DEBUG)
TopTools_ListIteratorOfListOfShape itS(NS);
while ( itS.More()) {
-#ifdef DEB
- Standard_Boolean checkCloseness = Standard_True;
-#endif
TopExp_Explorer expF (itS.Value(), TopAbs_FACE);
- for (; expF.More(); expF.Next()) {
-
+ for (; expF.More(); expF.Next())
myAddedFacesMap.Add (expF.Current());
-
-#ifdef DEB
- if (checkCloseness &&
- ! myInter3d.HasSameDomainF( myImagesFaces.Root(expF.Current()) ))
- checkCloseness = Standard_False;
-#endif
- }
-#ifdef DEB
- if (checkCloseness) {
- // if S is closed, a new shell must be closed too;
- if (isClosed) {
- // check that a new shell is closed
- MEF.Clear();
- TopExp::MapShapesAndAncestors(itS.Value(), TopAbs_EDGE, TopAbs_FACE, MEF);
- for (i=1; isClosed && i<=MEF.Extent(); ++i)
- isClosed = ( MEF(i).Extent() != 1 );
- if (!isClosed) { // remove not closed shell
- MESSAGE (" NOT CLOSED SHELL " );
- //NS.Remove( itS );
- itS.Next();
- continue;
- }
- }
- }
-#endif
itS.Next();
- } // loop on new shells
+ }
}
//=======================================================================
//function : findEqual
-//purpose : compare edges form EL1 against edges from EL2,
-// Result is in EMM binding edge form EL1 to list of equal edges
-// Edges are considered equall only if they have same vertices
+//purpose : compare edges of EL1 against edges of EL2,
+// Result is in EMM binding EL1 edges to list of equal edges.
+// Edges are considered equall only if they have same vertices.
// <addSame>==True makes consider same edges as equal
// Put in <AllEqMap> all equal edges
//=======================================================================
itE2.Initialize( VEM(V1) );
for (; itE2.More(); itE2.Next()) {
const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value());
- if (BRep_Tool::Degenerated( E2 ))
+ if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2))
continue;
if (E1.IsSame(E2)) {
TopTools_IndexedMapOfShape EM;
TopExp::MapShapes( F, TopAbs_EDGE, EM);
- TopTools_MapOfShape AddedEqualM;
+ TopTools_MapOfShape AddedEqualM, EqualSeamM;
Standard_Boolean needRebuild = Standard_False;
// add splits to loops
Standard_Boolean isSameE = NE.IsSame ( E );
if ( isNewE || isSectionE || !isSameE) {
- if (AddedEqualM.Contains( NE ))
- continue;
+ if (AddedEqualM.Contains( NE )) {
+ // a seam must be twice in a loop
+ if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE ))
+ continue;
+ }
if (isNewE) {
if (isSectionE) {
}
}
}
- if (myEqualEdges.Contains( NE ) && !AddedEqualM.Add( NE ))
- continue;
+ if (myEqualEdges.Contains( NE ))
+ AddedEqualM.Add( NE );
needRebuild = Standard_True;
}
myImagesFaces.Bind(F,LNF);
// replace the result faces that have already been built
- // during same domain faces reconstruction
- if (myInter3d.HasSameDomainF( F )) {
- // build map edge to same domain faces
+ // during same domain faces reconstruction done earlier
+ if (myInter3d.HasSameDomainF( F ))
+ {
+ // build map edge to same domain faces: EFM
TopTools_IndexedDataMapOfShapeListOfShape EFM;
TopTools_MapOfShape SDFM; // avoid doubling
itl.Initialize( myInter3d.SameDomain( F ));
for (; itl.More(); itl.Next()) {
if ( !myImagesFaces.HasImage( itl.Value() ))
continue;
+ // loop on splits of a SD face
TopTools_ListIteratorOfListOfShape itNF;
itNF.Initialize (myImagesFaces.Image( itl.Value() ));
for ( ; itNF.More(); itNF.Next()) {
TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM);
}
}
- // do replace
+ // do replace faces in the LNF
TopTools_ListOfShape LOF;
if ( !EFM.IsEmpty() )
itl.Initialize( LNF );
Standard_Real dot;
Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF),
1, dot, GoodOri);
- if (dot < 0) {
+ if (dot < 0)
+ {
+ // NF and SDF are on different side of E
if (SDFL.Extent() == 1) {
itl.Next();
continue;
}
else
- SDF = SDFL.Last();
+ SDF = SDFL.Last(); // next face must be on the same side
}
gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF ));
gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF ));
if (!myImagesFaces.HasImage( NF ))
myImagesFaces.Bind( NF, SDF );
+ // mySharedFaces is used in FindFacesInside()
+ mySharedFaces.Add( SDF );
+
LOF.Prepend ( SDF );
LNF.Remove (itl);
}
myImagesFaces.Bind(F,LNF);
}
} // if (myImagesFaces.HasImage( F ))
-
+
+ // fill the resulting compound
for (itl.Initialize(LNF); itl.More(); itl.Next())
myBuilder.Add ( C, itl.Value());
+
} // loop on faces of S
return C;
}
+
+//=======================================================================
+//function : Tri
+//purpose :
+//=======================================================================
+
+static void Tri(const TopoDS_Edge& E,
+ TopTools_SequenceOfShape& Seq,
+ const Partition_Inter3d & theInter3d)
+{
+ Standard_Boolean Invert = Standard_True;
+ Standard_Real U1,U2;
+ TopoDS_Vertex V1,V2;
+
+ while (Invert) {
+ Invert = Standard_False;
+ for ( Standard_Integer i = 1; i < Seq.Length(); i++) {
+
+ V1 = TopoDS::Vertex(Seq.Value(i));
+ V2 = TopoDS::Vertex(Seq.Value(i+1));
+
+ V1.Orientation(TopAbs_INTERNAL);
+ V2.Orientation(TopAbs_INTERNAL);
+
+ U1 = BRep_Tool::Parameter(V1,E);
+ U2 = BRep_Tool::Parameter(V2,E);
+
+ if (IsEqual(U1,U2)) {
+ if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 ))
+ Seq.Remove(i+1); // remove V2
+ else
+ Seq.Remove(i);
+ i--;
+ continue;
+ }
+ if (U2 < U1) {
+ Seq.Exchange(i,i+1);
+ Invert = Standard_True;
+ }
+ }
+ }
+}
+
+//=======================================================================
+//function : MakeEdges
+//purpose : cut E by vertices VOnE, return list of new edges NE
+//=======================================================================
+
+void Partition_Spliter::MakeEdges (const TopoDS_Edge& E,
+ const TopTools_ListOfShape& VOnE,
+ TopTools_ListOfShape& NE ) const
+{
+ TopoDS_Edge WE = E;
+ WE.Orientation(TopAbs_FORWARD);
+
+ Standard_Real U1,U2, f, l;
+ TopoDS_Vertex V1,V2,VF,VL;
+
+ BRep_Tool::Range(WE,f,l);
+ TopExp::Vertices(WE,VF,VL);
+
+ if (VOnE.Extent() < 3) { // do not rebuild not cut edge
+ if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) ||
+ VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ) ) {
+ NE.Append( E );
+ return;
+ }
+ }
+
+ TopTools_SequenceOfShape SV;
+ TopTools_ListIteratorOfListOfShape itv(VOnE);
+ TopTools_MapOfOrientedShape VM( VOnE.Extent() );
+ for (; itv.More(); itv.Next())
+ if ( VM.Add( itv.Value() ))
+ SV.Append(itv.Value());
+
+ Tri( WE, SV, myInter3d );
+
+ if (SV.Length() < 3) { // do not rebuild not cut edge
+ if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) ||
+ VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() ) ) {
+ NE.Append( E );
+ return;
+ }
+ }
+
+ Standard_Integer iVer, NbVer = SV.Length();
+
+
+ //----------------------------------------------------------------
+ // Construction of the new edges .
+ //----------------------------------------------------------------
+
+ if (VF.IsSame(VL)) { // closed edge
+ if (NbVer==1)
+ SV.Append( SV.First() );
+ else if (!SV.First().IsSame(SV.Last())) {
+ Standard_Boolean isFirst=0;
+ Standard_Real minDU = 1.e10;
+ TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU);
+ if (endV.IsSame(SV.First()))
+ SV.Append(endV);
+ else if (endV.IsSame(SV.Last()))
+ SV.Prepend(endV);
+ else
+ MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE");
+ }
+ NbVer = SV.Length();
+ }
+
+ for (iVer=1; iVer < NbVer; iVer++) {
+ V1 = TopoDS::Vertex(SV(iVer));
+ V2 = TopoDS::Vertex(SV(iVer+1));
+
+ TopoDS_Shape NewEdge = WE.EmptyCopied();
+ V1.Orientation(TopAbs_FORWARD);
+ myBuilder.Add (NewEdge,V1);
+ V2.Orientation(TopAbs_REVERSED);
+ myBuilder.Add (NewEdge,V2);
+
+ if (iVer==1)
+ U1 = f;
+ else {
+ V1.Orientation(TopAbs_INTERNAL);
+ U1=BRep_Tool::Parameter(V1,WE);
+ }
+ if (iVer+1 == NbVer)
+ U2 = l;
+ else {
+ V2.Orientation(TopAbs_INTERNAL);
+ U2=BRep_Tool::Parameter(V2,WE);
+ }
+ if (Abs(U1-U2) <= Precision::PConfusion()) {
+ MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES");
+ continue;
+ }
+ TopoDS_Edge EE=TopoDS::Edge(NewEdge);
+ myBuilder.Range (EE,U1,U2);
+
+ TopoDS_Edge NEdge = TopoDS::Edge(NewEdge);
+ myBuilder.SameParameter(NEdge,Standard_False);
+
+ Standard_Real tol = 1.0e-2;
+ Standard_Boolean flag = BRep_Tool::SameParameter(NEdge);
+ if (!flag) {
+ BRepLib::SameParameter(NEdge,tol);
+ }
+ NE.Append(NEdge.Oriented(E.Orientation()));
+ }
+}
+
//=======================================================================
//function : MergeEqualEdges
//purpose : find equal edges, choose ones to keep and make
for ( ; itM.More(); itM.Next()) {
EEL = itM.Value();
EEL.Append( itM.Key() );
+
// choose an edge to keep, section edges have priority
TopoDS_Edge EKeep;
TopTools_ListIteratorOfListOfShape itEE (EEL);
break;
}
+ // update edge images and build pcurves
Standard_Real f,l, tol;
for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) {
const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() );
if ( E.IsSame( EKeep ))
continue;
+
+ // 1. build pcurves of the kept edge on faces where replaced edges exist
const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E ));
TopTools_ListOfShape FL;
- if (myInter3d.IsSectionEdge( EReplOrig ))
- FL = myInter3d.SectionEdgeFaces ( EReplOrig );
- else
- FL = myAsDes->Ascendant( EReplOrig );
-
+ FL = myAsDes->Ascendant( EReplOrig );
+ Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1;
+ // add faces where the replaced edge is a section edge
+ if (myInter3d.IsSectionEdge( EReplOrig )) {
+ TopTools_ListIteratorOfListOfShape seIt;
+ seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig ));
+ for ( ; seIt.More(); seIt.Next())
+ FL.Append( seIt.Value() );
+ }
+ // loop on faces
TopTools_ListIteratorOfListOfShape itF (FL);
- for ( ; itF.More(); itF.Next()) {
+ for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) {
const TopoDS_Face& F = TopoDS::Face( itF.Value());
- // build pcurves
+
Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l);
if (pc.IsNull()) {
Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l);
}
myBuilder.UpdateEdge( EKeep, pc, F, tol);
}
- }
- // replace edges in faces
- if (!myImagesEdges.HasImage( E ))
- myImagesEdges.Bind( E, EKeep );
- }
- }
+
+ if (iFace >= iFirstSectionFace ||
+ !BRep_Tool::IsClosed( EReplOrig, F ))
+ continue;
+
+ // build the second pcurve for a seam
+ TopoDS_Vertex V = TopExp::FirstVertex( EKeep );
+ Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep );
+ Standard_Real Urepl = BRep_Tool::Parameter( V, E );
+
+ TopoDS_Edge EReplRev = E;
+ EReplRev.Reverse();
+ Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l);
+ Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l);
+
+ gp_Pnt2d p1r, p2r, pk;
+ p1r = pcRepl1->Value( Urepl );
+ p2r = pcRepl2->Value( Urepl );
+ pk = pc->Value( Ukeep );
+
+ // suppose that pk is equal to either p1r or p2r
+ Standard_Boolean isUPeriod =
+ ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() ));
+ Standard_Boolean is1Equal;
+ if (isUPeriod)
+ is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() ));
+ else
+ is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() ));
+
+ Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast
+ ( pc->Translated( pk, is1Equal ? p2r : p1r ) );
+
+ if (E.Orientation() == TopAbs_REVERSED)
+ is1Equal = !is1Equal;
+
+ if (is1Equal)
+ myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol);
+ else
+ myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol);
+
+ } // loop on a Faces where a replaced edge exists
+
+
+ // 2. update edge images according to replacement
+ if (myImagesEdges.HasImage( E ))
+ myImagesEdges.Remove( E );
+ myImagesEdges.Bind( E, EKeep );
+
+ } // loop on a list of equal edges EEL
+ } // loop on a map of equal edges EEM
}
//=======================================================================
KeepShapesInside( it.Value());
return;
}
- if (!myImageShape.HasImage( S ) && ! CheckTool( S ))
- return;
-
- TopoDS_Shape InsFacesComp = FindFacesInside( S, Standard_False, Standard_True);
- TopTools_IndexedMapOfShape MIF; // map of internal faces;
- TopExp::MapShapes( InsFacesComp, TopAbs_FACE, MIF );
- if (MIF.IsEmpty()) return;
-
- // leave in the result only those shapes having a face in MIF
+ Standard_Boolean isTool = Standard_False;
+ if (!myImageShape.HasImage( S )) {
+ isTool = CheckTool( S );
+ if (!isTool) return;
+ }
+
+ // build map of internal faces
+ TopTools_IndexedMapOfShape MIF;
+ TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
+ TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF );
+
TopoDS_Compound C;
myBuilder.MakeCompound(C);
-
- for (it.Initialize( myShape ); it.More(); it.Next()) {
- TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
- for (; expResF.More(); expResF.Next()) {
- if ( MIF.Contains( expResF.Current())) {
- myBuilder.Add( C, it.Value() );
- break;
+ TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE;
+ if (!MIF.IsEmpty())
+ {
+ // leave in the result only those shapes having a face in MIF
+ for (it.Initialize( myShape ); it.More(); it.Next()) {
+ const TopoDS_Shape & aResShape = it.Value();
+ TopExp_Explorer expResF( aResShape, TopAbs_FACE );
+ for (; expResF.More(); expResF.Next()) {
+ if ( MIF.Contains( expResF.Current())) {
+ myBuilder.Add( C, aResShape );
+ if (aResShape.ShapeType() < anInternalShapeType)
+ anInternalShapeType = aResShape.ShapeType();
+ break;
+ }
+ }
+ }
+ }
+
+ // may be S was not split by internal faces then it is missing
+ // in myShape, add it
+ if (!isTool &&
+ (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID))
+ {
+ TopTools_IndexedMapOfShape MSF; // map of split faces of S
+ TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF);
+
+ // find a shape having all faces in MSF
+ for (it.Initialize( myShape ); it.More(); it.Next()) {
+ TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
+ for (; expResF.More(); expResF.Next()) {
+ if (! MSF.Contains( expResF.Current()))
+ break;
+ }
+ if (! expResF.More()) {
+ myBuilder.Add( C, it.Value() );
+ break;
}
}
}
isTool = CheckTool( S );
if (!isTool) return;
}
-
- TopoDS_Shape InsFacesComp = FindFacesInside( S, Standard_False, Standard_True);
+
+ TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
TopTools_IndexedMapOfShape MIF; // map of internal faces
- TopExp::MapShapes( InsFacesComp, TopAbs_FACE, MIF);
+ TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF);
if (MIF.IsEmpty()) return;
// add to MIF split faces of S
- if (myImageShape.HasImage( S ))
+ if (myImageShape.HasImage(S))
TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF);
// leave in the result only those shapes not having all face in MIF
for (; expResF.More(); expResF.Next())
if (!MIF.Contains( expResF.Current()))
break;
-
+
if (expResF.More())
// add shape to result
myBuilder.Add( C, it.Value() );
}
if (!isTool) {
+
// rebuild S, it must remain in the result
+
Standard_Boolean isClosed = Standard_False;
switch (S.ShapeType()) {
case TopAbs_SOLID :
isClosed = Standard_True; break;
case TopAbs_SHELL: {
TopTools_IndexedDataMapOfShapeListOfShape MEF;
- Standard_Integer i;
TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF);
+ Standard_Integer i;
for (i=1; isClosed && i<=MEF.Extent(); ++i)
isClosed = ( MEF(i).Extent() != 1 );
break;
isClosed = Standard_False;
}
if (isClosed) {
+
// add to a new shape external faces of removed shapes, ie those in RFM
+
TopoDS_Shell Shell;
myBuilder.MakeShell( Shell );
+ // exclude redundant internal face with edges encounterd only once
+ TopTools_IndexedDataMapOfShapeListOfShape MEF;
TopTools_MapIteratorOfMapOfShape itF (RFM);
for ( ; itF.More(); itF.Next())
- myBuilder.Add( Shell, itF.Key());
+ TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF);
+
+ // add only faces forming a closed shell
+ for (itF.Reset() ; itF.More(); itF.Next())
+ {
+ TopExp_Explorer expE (itF.Key(), TopAbs_EDGE);
+ for (; expE.More(); expE.Next())
+ if (MEF.FindFromKey(expE.Current()).Extent() == 1)
+ break;
+ if (!expE.More())
+ myBuilder.Add( Shell, itF.Key());
+ }
if (S.ShapeType() == TopAbs_SOLID) {
- TopoDS_Solid Solid;
- myBuilder.MakeSolid( Solid );
- myBuilder.Add (Solid, Shell);
- myBuilder.Add (C, Solid);
+ TopoDS_Solid Solid;
+ myBuilder.MakeSolid( Solid );
+ myBuilder.Add (Solid, Shell);
+ myBuilder.Add (C, Solid);
}
else
- myBuilder.Add (C, Shell);
+ myBuilder.Add (C, Shell);
}
else {
if (myImageShape.HasImage( S )) {
- for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next())
- myBuilder.Add (C, it.Value());
+ for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next())
+ myBuilder.Add (C, it.Value());
}
}
}
Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F );
Standard_Boolean hasNewE = myAsDes->HasDescendant( F );
if (!hasSectionE && !hasNewE)
- continue; // F intersects nothing
+ {
+ // F intersects nothing
+ myBuilder.Add( C, F );
+ continue;
+ }
// make an image for F
return isTool;
}
+
+//=======================================================================
+//function : IsInside
+//purpose : Return True if the first vertex of S1 inside S2.
+// If S1.IsNull(), check infinite point against S2.
+//=======================================================================
+
+Standard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1,
+ const TopoDS_Shape& theS2)
+{
+ BRepClass3d_SolidClassifier aClassifier( theS2 );
+
+ TopExp_Explorer expl( theS1, TopAbs_VERTEX );
+ if (!expl.More())
+ aClassifier.PerformInfinitePoint( ::RealSmall());
+ else
+ {
+ const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
+ aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
+ BRep_Tool::Tolerance( aVertex ));
+ }
+
+ return ( aClassifier.State() == TopAbs_IN );
+}
+
+//=======================================================================
+//function : GetOriginalShape
+//purpose : Return the shape aShape originates from. aShape
+// should be a face or more complex result shape
+//=======================================================================
+
+TopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const
+{
+ TopoDS_Shape anOrigShape;
+
+ TopExp_Explorer expl( theShape, TopAbs_FACE);
+ if (expl.More())
+ {
+
+ TopoDS_Shape aFace = expl.Current();
+ if (myImagesFaces.IsImage( aFace ))
+ aFace = myImagesFaces.Root( aFace );
+ anOrigShape = myFaceShapeMap.Find( aFace );
+ }
+ return anOrigShape;
+}
+
+//=======================================================================
+//function : FindToolsToReconstruct
+//purpose : find and store as objects tools which interfere
+// with solids or are inside solids without
+// an interference
+//=======================================================================
+
+void Partition_Spliter::FindToolsToReconstruct()
+{
+ if (myMapTools.IsEmpty())
+ return;
+
+ Standard_Integer nbFoundTools = 0;
+
+ // build edge - face map in order to detect interference with section edges
+ TopTools_IndexedDataMapOfShapeListOfShape EFM;
+ TopTools_MapIteratorOfMapOfShape aMapIt;
+ for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next())
+ TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
+ for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next())
+ TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
+
+ TopTools_MapOfShape aCurrentSolids, aCheckedShapes;
+
+ // faces cut by new edges
+ TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces();
+
+ // keep solids interfering with each other in aCurrentSolids map
+ // and add tool faces intersecting solids as object shapes
+
+ TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE;
+ for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) {
+ TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID);
+ for (; expSo.More(); expSo.Next()) {
+
+ // check if a solid has been already processed
+ const TopoDS_Shape & aSo = expSo.Current();
+ if (!aCheckedShapes.Add( aSo ))
+ continue;
+ aCurrentSolids.Add( aSo );
+
+ // faces to check
+ TopTools_ListOfShape aFacesToCheck;
+ TopExp_Explorer exp( aSo, TopAbs_FACE );
+ for ( ; exp.More(); exp.Next())
+ aFacesToCheck.Append ( exp.Current());
+
+ // add other shapes interefering with a solid.
+ // iterate faces to check while appending new ones
+ for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next())
+ {
+ const TopoDS_Shape& aCheckFace = itCF.Value();
+// if (!aCheckedShapes.Add( aCheckFace ))
+// continue;
+
+ // find faces interfering with aCheckFace
+ TopTools_ListOfShape anIntFaces;
+
+ // ** 1. faces intersecting aCheckFace with creation of new edges on it
+ if ( myAsDes->HasDescendant( aCheckFace ))
+ {
+ // new edges on aCheckFace
+ const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace );
+ for (itE.Initialize( NEL); itE.More(); itE.Next())
+ {
+ const TopoDS_Shape & aNewEdge = itE.Value();
+ if (!aCheckedShapes.Add( aNewEdge ))
+ continue;
+
+ // faces interfering by aNewEdge
+ itF.Initialize (myAsDes->Ascendant( aNewEdge ));
+ for (; itF.More(); itF.Next())
+ if (aCheckFace != itF.Value())
+ anIntFaces.Append( itF.Value() );
+
+ // ** 2. faces having section edge aNewEdge on aFacesToCheck
+ if (EFM.Contains( aNewEdge))
+ {
+ itF.Initialize ( EFM.FindFromKey (itE.Value()));
+ for (; itF.More(); itF.Next())
+ if (aCheckFace != itF.Value())
+ anIntFaces.Append( itF.Value() );
+ }
+ }
+ }
+
+ // ** 3. faces cut by edges of aCheckFace
+ TopExp_Explorer expE (aCheckFace, TopAbs_EDGE);
+ for ( ; expE.More(); expE.Next())
+ {
+ const TopoDS_Shape & aCheckEdge = expE.Current();
+ if (aCheckedShapes.Add( aCheckEdge ) &&
+ myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge )))
+ {
+ itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge )));
+ for (; itF.More(); itF.Next())
+ if (aCheckFace != itF.Value())
+ anIntFaces.Append( itF.Value() );
+ }
+ }
+
+ // process faces interfering with aCheckFace and shapes they
+ // belong to
+ for (itF.Initialize (anIntFaces); itF.More(); itF.Next())
+ {
+ const TopoDS_Shape & F = itF.Value();
+ if (! aCheckedShapes.Add( F ))
+ continue;
+
+ Standard_Boolean isTool = myMapTools.Contains( F );
+ if (isTool &&
+ myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID )
+ {
+ // a tool interfering with a solid
+ if (aSectionFaces.Contains( F ))
+ AddShape( F );
+ ++ nbFoundTools;
+ if (nbFoundTools == myMapTools.Extent())
+ return;
+ }
+
+ const TopoDS_Shape & S = myFaceShapeMap( F );
+ if (aCheckedShapes.Add( S ))
+ {
+ // a new shape interefering with aCurrentSolids is found
+ if (!isTool && S.ShapeType() == TopAbs_SOLID)
+ aCurrentSolids.Add ( S );
+ // add faces to aFacesToCheck list
+ for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next())
+ aFacesToCheck.Append ( exp.Current() );
+ }
+ }
+ } // loop on aFacesToCheck
+
+ // Here aCurrentSolids contains all solids interfering with each other.
+ // aCheckedShapes contains all faces belonging to shapes included
+ // in or interfering with aCurrentSolids or previously checked solids.
+ // Test if tool faces that do not interefere with other shapes are
+ // wrapped by any of aCurrentSolids
+
+ TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids);
+ for ( ; aSolidIt.More(); aSolidIt.Next())
+ {
+ const TopoDS_Shape & aSolid = aSolidIt.Key();
+ TopTools_MapOfShape aCheckedTools( myMapTools.Extent() );
+
+ TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools);
+ for ( ; aToolIt.More(); aToolIt.Next())
+ {
+ const TopoDS_Shape & aToolFace = aToolIt.Key();
+ if (aCheckedShapes.Contains( aToolFace ) || // already found
+ aCheckedTools.Contains( aToolFace )) // checked against aSolid
+ continue;
+
+ const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace );
+ TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE );
+
+ Standard_Boolean isInside = IsInside( aToolShape, aSolid );
+ for ( ; aToolFaceIt.More(); aToolFaceIt.Next() )
+ {
+ const TopoDS_Shape & aTool = aToolFaceIt.Current();
+ aCheckedTools.Add( aTool );
+ if (isInside)
+ {
+ if (aSectionFaces.Contains( aTool ))
+ AddShape( aTool );
+ ++ nbFoundTools;
+ if (nbFoundTools == myMapTools.Extent())
+ return;
+ aCheckedShapes.Add( aTool );
+ }
+ }
+ }
+ }
+
+ } // loop on solid shapes
+ }
+}