X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPARTITION%2FPartition_Inter3d.cxx;h=87de801359b9aeb93a0896dd5e2e2ed5ad3440c6;hb=4df412f5db44d67db5ad624250c204b44b1ba217;hp=d7156f83c626376fc6e30a919872aa5cf8f8f708;hpb=ecb53a73db547cbbb50f2df55faa344e3ad41594;p=modules%2Fgeom.git diff --git a/src/PARTITION/Partition_Inter3d.cxx b/src/PARTITION/Partition_Inter3d.cxx index d7156f83c..87de80135 100644 --- a/src/PARTITION/Partition_Inter3d.cxx +++ b/src/PARTITION/Partition_Inter3d.cxx @@ -1,64 +1,88 @@ -using namespace std; -// File : Partition_Inter3d.cxx -// Created : Thu Aug 02 16:20:37 2001 -// Author : Benedicte MARTIN -// Project : SALOME -// Module : PARTITION -// 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_Inter3d.cxx +// Author : Benedicte MARTIN +// Module : GEOM // $Header$ - -#include "Partition_Inter3d.ixx" +// #include "Partition_Inter2d.hxx" +#include "Partition_Inter3d.ixx" #include "utilities.h" -#include -#include -#include #include #include #include +#include +#include +#include #include #include +#include +#include +#include +#include #include -#include +#include #include #include -#include -#include -#include -#include -#include +#include #ifdef DEB #include #endif -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include -#include +#include +#include #include #include -#include #include -#include +#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include + +using namespace std; //======================================================================= //function : Partition_Inter3d @@ -111,10 +135,10 @@ void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1, // avoid intersecting faces of one shape TopoDS_Shape S1; if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1); - // avoid intersecting faces sharing vertices, suppose they belong to - // shapes sharing same faces - TopTools_IndexedMapOfShape VM; - TopExp::MapShapes( F1, TopAbs_VERTEX, VM); + + // to filter faces sharing an edge + TopTools_IndexedMapOfShape EM; + TopExp::MapShapes( F1, TopAbs_EDGE, EM); TColStd_ListIteratorOfListOfInteger itLI = BOS.Compare(F1); for (; itLI.More(); itLI.Next()) { @@ -127,13 +151,22 @@ void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1, if (!S1.IsNull() && S1.IsSame(S2)) continue; // descendants of one shape - TopExp_Explorer expV (F2, TopAbs_VERTEX); - for ( ; expV.More(); expV.Next()) - if (VM.Contains( expV.Current() )) + TopExp_Explorer expE (F2, TopAbs_EDGE); + for ( ; expE.More(); expE.Next()) + if (EM.Contains( expE.Current() )) break; - if (expV.More()) - continue; // faces have a common edge - + if (expE.More()) + { + // faces have a common edge, check if they are a tool and a face + // generated by the tool in another shape; in that case they are + // to be intersected + TopLoc_Location L1, L2; + Handle(Geom_Surface) S1 = BRep_Tool::Surface( F1, L1 ); + Handle(Geom_Surface) S2 = BRep_Tool::Surface( F2, L2 ); + if ( S1 != S2 || L1 != L2 ) + continue; + } + F1.Orientation(TopAbs_FORWARD); F2.Orientation(TopAbs_FORWARD); FacesPartition(F1,F2); @@ -171,19 +204,61 @@ static void PutInBounds (const TopoDS_Face& F, if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { S = (*(Handle_Geom_RectangularTrimmedSurface*)&S)->BasisSurface(); } - //--------------- - // Recadre en U. - //--------------- - if (!S->IsUPeriodic() && !S->IsVPeriodic()) return; + if (!S->IsUPeriodic() && !S->IsVPeriodic()) + return; BRepTools::UVBounds(F,umin,umax,vmin,vmax); + gp_Pnt2d Pf = C2d->Value(f); + gp_Pnt2d Pl = C2d->Value(l); + const Standard_Real Um = 0.34*f + 0.66*l; + gp_Pnt2d Pm = C2d->Value( Um ); + + // sometimes on shpere, pcurve is out of domain by V though S is + // UPeriodic, sometimes it is in domain but nontheless it has + // wrong position. + // Check pcurve position by 3D point + if (S->IsKind(STANDARD_TYPE( Geom_SphericalSurface ))) + { + // get point on the surface + gp_Pnt Ps = S->Value( Pm.X(), Pm.Y() ); + // get point on the edge + Handle(Geom_Curve) C = BRep_Tool::Curve( E, f, l ); + gp_Pnt Pc = C->Value( Um ); + // compare points + Standard_Real TolE = BRep_Tool::Tolerance( E ); + if ( Pc.SquareDistance( Ps ) * 0.95 < TolE * TolE ) + return; // OK + + // find good UV for Pc: project Pc on S + GeomAdaptor_Surface SA (S); + Extrema_ExtPS anExtPS (Pc, SA, + SA.UResolution( TolE ), SA.VResolution( TolE )); + if (anExtPS.IsDone()) + { + Standard_Integer i, nbExt = anExtPS.NbExt(); + Extrema_POnSurf aPOnSurf; + for (i = 1; i <= nbExt; ++i ) + if (anExtPS.Value( i ) <= TolE) { + aPOnSurf = anExtPS.Point( i ); + break; + } + if (i <= nbExt) { + // a point found + Standard_Real u, v; + aPOnSurf.Parameter( u, v ); + gp_Pnt2d aGoodPm ( u, v ); + C2d->Translate( Pm , aGoodPm ); + } + } + } + + //--------------- + // Recadre en U. + //--------------- if (S->IsUPeriodic()) { Standard_Real period = S->UPeriod(); Standard_Real eps = period*1.e-6; - gp_Pnt2d Pf = C2d->Value(f); - gp_Pnt2d Pl = C2d->Value(l); - gp_Pnt2d Pm = C2d->Value(0.34*f + 0.66*l); Standard_Real minC = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X()); Standard_Real maxC = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X()); Standard_Real du = 0.; @@ -215,9 +290,6 @@ static void PutInBounds (const TopoDS_Face& F, if (S->IsVPeriodic()) { Standard_Real period = S->VPeriod(); Standard_Real eps = period*1.e-6; - gp_Pnt2d Pf = C2d->Value(f); - gp_Pnt2d Pl = C2d->Value(l); - gp_Pnt2d Pm = C2d->Value(0.34*f + 0.66*l); Standard_Real minC = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y()); Standard_Real maxC = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y()); Standard_Real dv = 0.; @@ -289,8 +361,6 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, while (itLE.More()) { TopoDS_Edge E = TopoDS::Edge(itLE.Value()); -// Standard_Real f,l; -// BRep_Tool::Range(E,f,l); PutInBounds (F1,E,pc1); PutInBounds (F2,E,pc2); @@ -307,48 +377,59 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, } } - // =================================================== - // Store section edges, same domain faces and verives - // =================================================== + // ======================== + // store same domain faces + // ======================== - TopTools_ListOfShape empty, LSP, LSE; - if ( DatStr->HasSameDomain( F1 )) { // same domain faces + if ( DatStr->HasSameDomain( F1 )) + { + TopTools_ListOfShape emptyList; if (!mySameDomainFM.IsBound(F1)) - mySameDomainFM.Bind(F1,empty); + mySameDomainFM.Bind(F1,emptyList); if (!mySameDomainFM.IsBound(F2)) - mySameDomainFM.Bind(F2,empty); + mySameDomainFM.Bind(F2,emptyList); mySameDomainFM(F1).Append(F2); mySameDomainFM(F2).Append(F1); } + // ==================== + // Store section edges + // ==================== + const TopOpeBRepDS_DataStructure& DS = DatStr->DS(); - Standard_Integer j,i,nes = DS.NbSectionEdges(); - if (!nes) return; + Standard_Integer j,i,nse = DS.NbSectionEdges(); + if (nse == 0) return; TopoDS_Vertex V, sdeV1, sdeV2; TopTools_MapOfShape MV; + TopTools_ListOfShape LSE; // list of section edges + TopoDS_Face dummyF; - // put vertices on section edges - for (i=1;i<=nes;i++) { - - TopoDS_Edge se, sde, oe; // section, same domain, other edge - se = DS.SectionEdge(i); + for (i = 1; i <= nse; i++) + { + const TopoDS_Edge & se = DS.SectionEdge(i); if (! TopB.IsSplit(se,TopAbs_ON)) continue; + LSE.Append( se ); + // add vertices where section edges interferes with other + // edges as its descendant in myAsDes + + TopoDS_Edge sde, oe; // same domain, other edge if (DatStr->HasSameDomain(se)) { sde = TopoDS::Edge( DatStr->SameDomain(se).Value() ); TopExp::Vertices( sde, sdeV1, sdeV2); } - - TColStd_MapOfInteger MIV; + TColStd_MapOfInteger MIV; // indices of added edges TopOpeBRepDS_PointIterator itP (DS.ShapeInterferences( se )); itP.SupportKind( TopOpeBRepDS_EDGE ); + // loop on intersections of se for (; itP.More(); itP.Next()) { oe = TopoDS::Edge( DS.Shape( itP.Support())); if (itP.IsVertex()) { + // there is a vertex at intersection if ( !MIV.Add( itP.Current() )) continue; V = TopoDS::Vertex( DS.Shape( itP.Current())); @@ -356,9 +437,10 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, oe = sde; V = ReplaceSameDomainV( V , oe ); V.Orientation( TopAbs_INTERNAL); - B.UpdateVertex( V, itP.Parameter(), se, 0.); + B.UpdateVertex( V, itP.Parameter(), se, 0.); // AddVonE() sets real U } else { + // create a new vertex at the intersection point const TopOpeBRepDS_Point& DSP = DS.Point( itP.Current()); V = BRepLib_MakeVertex( DSP.Point() ); V.Orientation( TopAbs_INTERNAL); @@ -373,50 +455,62 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, } } } - TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes); + // add V on the both intersecting edges + TopoDS_Vertex addedV = Partition_Inter2d::AddVonE( V,se,oe,myAsDes,dummyF); if (!addedV.IsSame( V )) - mySameDomainVM.Bind (V, addedV); - MV.Add( addedV ); + mySameDomainVM.Bind (V, addedV); // equal vertex is already there + + MV.Add( addedV ); // to ease storage of vertices of ON splits } } - TopB.SplitSectionEdges(); + // add section edge to the face it intersects and find + // splits ON that do not have same domain pair + + TopB.SplitSectionEdges(); // let TopB find ON splits - TopTools_DataMapOfShapeShape SEM; // map split - section edge + TopTools_MapOfShape SPM; // map of ON splits TopTools_IndexedMapOfShape ME[2]; TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]); TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]); - // add section edge to the face it intersects and find - // splits ON that do not have same domain pair - - for (i=1;i<=nes;i++) { + TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE); + while ( itLSE.More() ) { - const TopoDS_Edge& se = DS.SectionEdge(i); - if (! TopB.IsSplit(se,TopAbs_ON)) - continue; + TopoDS_Edge se = TopoDS::Edge( itLSE.Value() ); + // move itLSE to the next se Standard_Integer ancRank = DS.AncestorRank(se); if (ME[ancRank-1].Contains( se )) - continue; // se is an edge of face it intersects + { + LSE.Remove( itLSE ); // se is an edge of face it intersects + continue; + } + else + { + itLSE.Next(); + } const TopoDS_Face& F = (ancRank == 1) ? F2 : F1; // add se to face but dont add twice - TopTools_ListIteratorOfListOfShape itE; + TopTools_ListIteratorOfListOfShape itE( myAsDes->Descendant( F )); if (myAsDes->HasDescendant( F )) { - for (itE.Initialize( (myAsDes->Descendant( F )) ); itE.More(); itE.Next()) + for ( ; itE.More(); itE.Next()) if (se.IsSame( itE.Value() )) break; } - if (!itE.More()) { + if (!itE.More()) + { myAsDes->Add( F, se ); + + // check se pcurve on F Standard_Real tol, f,l, umin=1e100, umax=-1e100; Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( se, F, f,l); if (pc.IsNull()) { - TopTools_ListIteratorOfListOfShape it( TopB.Splits(se,TopAbs_ON) ); - for ( ;it.More();it.Next()) { - const TopoDS_Edge& E = TopoDS::Edge ( it.Value()); + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) { + const TopoDS_Edge& E = TopoDS::Edge ( itSP.Value()); BRep_Tool::Range(E, f, l); umin = Min( umin, f); umax = Max( umax, l); @@ -431,45 +525,43 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, B.UpdateEdge( se, pc, F, tol); } } - + // to detect splits that do not have same domain pair - TopTools_ListIteratorOfListOfShape it( TopB.Splits(se,TopAbs_ON) ); - for ( ;it.More();it.Next()) { - const TopoDS_Edge& S = TopoDS::Edge ( it.Value()); - if (SEM.IsBound( S )) - SEM.UnBind( S ); - else - SEM.Bind( S, se); + // ie which split a face into parts and not pass by its boundary + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) { + const TopoDS_Shape& SP = itSP.Value(); + if (!SPM.Add( SP )) + SPM.Remove( SP ); } } // store vertices of ON splits and bind section edges to faces - for (i=1;i<=nes;i++) { - - const TopoDS_Edge& se = DS.SectionEdge(i); - if (! TopB.IsSplit(se,TopAbs_ON)) - continue; + + for (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next()) + { + const TopoDS_Shape& se = itLSE.Value(); Standard_Integer ancRank = DS.AncestorRank(se); - if (ME[ancRank-1].Contains( se )) - continue; // se is an edge of face it intersects - TopoDS_Face F = (ancRank == 1) ? F2 : F1; - // add vertices of splits + // add vertices of ON splits which have no same domain pair Standard_Boolean added = Standard_False; - TopTools_ListIteratorOfListOfShape it( TopB.Splits(se,TopAbs_ON) ); - for ( ;it.More();it.Next()) { - const TopoDS_Edge& S = TopoDS::Edge ( it.Value()); - if (!SEM.IsBound( S )) + itSP.Initialize( TopB.Splits(se,TopAbs_ON) ); + for ( ; itSP.More(); itSP.Next()) + { + if (!SPM.Contains( itSP.Value() )) continue; + + const TopoDS_Edge& S = TopoDS::Edge ( itSP.Value()); added = Standard_True; mySectionEdgesAD->Add( F, se ); TopoDS_Vertex VS[2]; TopExp::Vertices (S, VS[0], VS[1]); - for (j=0; j<2; ++j) { + for (j=0; j<2; ++j) + { if (mySameDomainVM.IsBound( VS[j] )) VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] )); if ( !MV.Contains( VS[j] )) { @@ -478,6 +570,8 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, TopTools_ListIteratorOfListOfShape itV( myAsDes->Descendant(se) ); for (; itV.More(); itV.Next()) { V = TopoDS::Vertex( itV.Value() ); + if ( V.IsSame( VS[j] )) + break; gp_Pnt P2 = BRep_Tool::Pnt( V ); if (P1.IsEqual( P2, Precision::Confusion())) { mySameDomainVM.Bind (VS[j], V); @@ -488,8 +582,13 @@ void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, if (!itV.More()) // no interferences with edges myAsDes->Add( se, VS[j]); } + + // add ends of ON splits to F in order to detect later + // if a split is on face in IsSplitOn() mySectionEdgesAD->Add( F, VS[j]); } + // in the descendants of F, first go ends of an ON split and + // then a split itself mySectionEdgesAD->Add( F, S ); } if (!added) @@ -524,13 +623,13 @@ void Partition_Inter3d::SetDone(const TopoDS_Face& F1, const TopoDS_Face& F2) { if (!myDone.IsBound(F1)) { - TopTools_ListOfShape empty; - myDone.Bind(F1,empty); + TopTools_ListOfShape emptyList; + myDone.Bind(F1,emptyList); } myDone(F1).Append(F2); if (!myDone.IsBound(F2)) { - TopTools_ListOfShape empty; - myDone.Bind(F2,empty); + TopTools_ListOfShape emptyList; + myDone.Bind(F2,emptyList); } myDone(F2).Append(F1); } @@ -563,7 +662,6 @@ void Partition_Inter3d::StorePart3d(const TopoDS_Face& F1, const TopoDS_Face& F2, const TopTools_ListOfShape& LInt) { - if (!LInt.IsEmpty()) { myAsDes->Add( F1,LInt); myAsDes->Add( F2,LInt); @@ -653,8 +751,8 @@ const TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) if (mySameDomainFM.IsBound( F )) return mySameDomainFM (F); - static TopTools_ListOfShape empty; - return empty; + static TopTools_ListOfShape emptyList; + return emptyList; } //=======================================================================