#ifdef OCCGEOMETRY // GEOM PARTITION : partition algorithm // // Copyright (C) 2003 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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org // // // // File : Partition_Inter3d.cxx // Author : Benedicte MARTIN // Module : GEOM // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Inter3d.cxx,v 1.6 2008/03/31 14:20:28 wabro Exp $ //using namespace std; #include #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 #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 //======================================================================= //function : Partition_Inter3d //purpose : //======================================================================= Partition_Inter3d::Partition_Inter3d() { } //======================================================================= //function : Partition_Inter3d //purpose : //======================================================================= Partition_Inter3d::Partition_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes) :myAsDes(AsDes) { mySectionEdgesAD = new BRepAlgo_AsDes; } //======================================================================= //function : CompletPart3d //purpose : FaceShapeMap is just to know the shape a face belongs to //======================================================================= void Partition_Inter3d::CompletPart3d(const TopTools_ListOfShape& SetOfFaces1, const TopTools_DataMapOfShapeShape& FaceShapeMap) { if (myAsDes.IsNull()) myAsDes = new BRepAlgo_AsDes; TopTools_ListIteratorOfListOfShape it; //--------------------------------------------------------------- // Construction of bounding boxes. //--------------------------------------------------------------- BRep_Builder B; TopoDS_Compound CompOS; B.MakeCompound(CompOS); for (it.Initialize(SetOfFaces1); it.More(); it.Next()) B.Add(CompOS, it.Value()); TopOpeBRepTool_BoxSort BOS; BOS.AddBoxesMakeCOB(CompOS,TopAbs_FACE); for (it.Initialize(SetOfFaces1); it.More(); it.Next()) { TopoDS_Face F1 = TopoDS::Face(it.Value()); // avoid intersecting faces of one shape TopoDS_Shape S1; if (FaceShapeMap.IsBound(F1)) S1 = FaceShapeMap.Find(F1); // 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()) { TopoDS_Face F2 = TopoDS::Face(BOS.TouchedShape(itLI)); if (F1.IsSame(F2) || IsDone(F1,F2)) continue; TopoDS_Shape S2; if (FaceShapeMap.IsBound(F2)) S2 = FaceShapeMap.Find(F2); if (!S1.IsNull() && S1.IsSame(S2)) continue; // descendants of one shape TopExp_Explorer expE (F2, TopAbs_EDGE); for ( ; expE.More(); expE.Next()) if (EM.Contains( expE.Current() )) break; 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); } // mark as modified a face which has at least one new edge if (!myAsDes->HasDescendant( F1 )) continue; TopTools_ListIteratorOfListOfShape itE (myAsDes->Descendant( F1 )); for ( ; itE.More(); itE.Next()) { if (myNewEdges.Contains( itE.Value())) { myTouched.Add( F1 ); break; } } } } //======================================================================= //function : PutInBounds //purpose : //======================================================================= static void PutInBounds (const TopoDS_Face& F, const TopoDS_Edge& E, Handle(Geom2d_Curve)& C2d) { Standard_Real umin,umax,vmin,vmax; Standard_Real f,l; BRep_Tool::Range(E,f,l); TopLoc_Location L; // Recup S avec la location pour eviter la copie. Handle (Geom_Surface) S = BRep_Tool::Surface(F,L); if (S->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { S = (*(Handle_Geom_RectangularTrimmedSurface*)&S)->BasisSurface(); } 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) // V6.3 if (anExtPS.SquareDistance( i ) <= TolE) // V6.5 { 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; 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.; if (minC< umin - eps) { du = (int((umin - minC)/period) + 1)*period; } if (minC > umax + eps) { du = -(int((minC - umax)/period) + 1)*period; } if (du != 0) { gp_Vec2d T1(du,0.); C2d->Translate(T1); minC += du; maxC += du; } // Ajuste au mieux la courbe dans le domaine. if (maxC > umax +100*eps) { Standard_Real d1 = maxC - umax; Standard_Real d2 = umin - minC + period; if (d2 < d1) du =-period; if ( du != 0.) { gp_Vec2d T2(du,0.); C2d->Translate(T2); } } } //------------------ // Recadre en V. //------------------ if (S->IsVPeriodic()) { Standard_Real period = S->VPeriod(); Standard_Real eps = period*1.e-6; 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.; if (minC< vmin - eps) { dv = (int((vmin - minC)/period) + 1)*period; } if (minC > vmax + eps) { dv = -(int((minC - vmax)/period) + 1)*period; } if (dv != 0) { gp_Vec2d T1(0.,dv); C2d->Translate(T1); minC += dv; maxC += dv; } // Ajuste au mieux la courbe dans le domaine. if (maxC > vmax +100*eps) { Standard_Real d1 = maxC - vmax; Standard_Real d2 = vmin - minC + period; if (d2 < d1) dv =-period; if ( dv != 0.) { gp_Vec2d T2(0.,dv); C2d->Translate(T2); } } } } //======================================================================= //function : Inter3D //purpose : //======================================================================= void Partition_Inter3d::Inter3D(const TopoDS_Face& F1, const TopoDS_Face& F2, TopTools_ListOfShape& L) { BRep_Builder B; // fill the data Structure Handle(TopOpeBRepDS_HDataStructure) DatStr = new TopOpeBRepDS_HDataStructure(); TopOpeBRep_DSFiller DSFiller; DSFiller.Insert(F1,F2,DatStr); // define the GeomTool used by the DSFiller : // compute BSpline of degree 1 on intersection curves. Standard_Real tol3dAPPROX = 1e-7; Standard_Real tol2dAPPROX = 1e-7; TopOpeBRepTool_GeomTool GT2 (TopOpeBRepTool_APPROX); GT2.SetTolerances(tol3dAPPROX,tol2dAPPROX); TopOpeBRepDS_BuildTool BT(GT2); // Perform Section TopOpeBRepBuild_Builder TopB(BT); TopB.Perform(DatStr); // =============== // Store new edges // =============== L.Clear(); TopOpeBRepDS_CurveExplorer cex(DatStr->DS()); for (; cex.More(); cex.Next()) { const TopOpeBRepDS_Curve& CDS = cex.Curve(); Standard_Integer ic = cex.Index(); Handle(Geom2d_Curve) pc1 = CDS.Curve1(); Handle(Geom2d_Curve) pc2 = CDS.Curve2(); TopTools_ListIteratorOfListOfShape itLE = TopB.NewEdges(ic); while (itLE.More()) { TopoDS_Edge E = TopoDS::Edge(itLE.Value()); PutInBounds (F1,E,pc1); PutInBounds (F2,E,pc2); B.UpdateEdge (E,pc1,F1,0.); B.UpdateEdge (E,pc2,F2,0.); L.Append (E); itLE.Next(); if (itLE.More()) { pc1 = Handle(Geom2d_Curve)::DownCast(pc1->Copy()); pc2 = Handle(Geom2d_Curve)::DownCast(pc2->Copy()); } } } // ======================== // store same domain faces // ======================== if ( DatStr->HasSameDomain( F1 )) { TopTools_ListOfShape emptyList; if (!mySameDomainFM.IsBound(F1)) mySameDomainFM.Bind(F1,emptyList); if (!mySameDomainFM.IsBound(F2)) 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,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; 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; // 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())); if ( !sde.IsNull() && (V.IsSame(sdeV1) || V.IsSame(sdeV2)) ) oe = sde; V = ReplaceSameDomainV( V , oe ); V.Orientation( TopAbs_INTERNAL); 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); B.UpdateVertex( V, itP.Parameter(), se, DSP.Tolerance()); // make V be on the other edge TopOpeBRepDS_PointIterator itOP (DS.ShapeInterferences( oe )); for (; itOP.More(); itOP.Next()) { const TopOpeBRepDS_Point& ODSP = DS.Point( itOP.Current()); if ( DSP.IsEqual (ODSP)) { B.UpdateVertex( V, itOP.Parameter(), TopoDS::Edge(oe), ODSP.Tolerance()); break; } } } // 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); // equal vertex is already there MV.Add( addedV ); // to ease storage of vertices of ON splits } } // 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_MapOfShape SPM; // map of ON splits TopTools_IndexedMapOfShape ME[2]; TopExp::MapShapes( F1, TopAbs_EDGE, ME[1]); TopExp::MapShapes( F2, TopAbs_EDGE, ME[0]); TopTools_ListIteratorOfListOfShape itSP, itLSE (LSE); while ( itLSE.More() ) { 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 )) { 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( myAsDes->Descendant( F )); if (myAsDes->HasDescendant( F )) { for ( ; itE.More(); itE.Next()) if (se.IsSame( itE.Value() )) break; } 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()) { 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); } Handle(Geom_Curve) C3d = BRep_Tool::Curve( se, f, l); if (umin < umax) // sometimes umin == umax for closed edge C3d = new Geom_TrimmedCurve( C3d, umin, umax); pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol); if (pc.IsNull()) { MESSAGE (" CANT BUILD PCURVE "); } B.UpdateEdge( se, pc, F, tol); } } // to detect splits that do not have same domain pair // 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 (itLSE.Initialize (LSE); itLSE.More(); itLSE.Next()) { const TopoDS_Shape& se = itLSE.Value(); Standard_Integer ancRank = DS.AncestorRank(se); TopoDS_Face F = (ancRank == 1) ? F2 : F1; // add vertices of ON splits which have no same domain pair Standard_Boolean added = Standard_False; 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) { if (mySameDomainVM.IsBound( VS[j] )) VS[j] = TopoDS::Vertex( mySameDomainVM( VS[j] )); if ( !MV.Contains( VS[j] )) { // find equal vertex on se - point interference gp_Pnt P1 = BRep_Tool::Pnt( VS[j] ); 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); VS[j] = V; break; } } 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) mySectionEdgesAD->Add( F, se ); myNewEdges.Add( se ); } } //======================================================================= //function : FacesPartition //purpose : //======================================================================= void Partition_Inter3d::FacesPartition(const TopoDS_Face& F1, const TopoDS_Face& F2) //(const TopTools_DataMapOfShapeListOfShape& /*SetOfFaces2*/) { TopTools_ListOfShape LInt; Inter3D (F1,F2,LInt); StorePart3d (F1,F2,LInt); } //======================================================================= //function : SetDone //purpose : //======================================================================= void Partition_Inter3d::SetDone(const TopoDS_Face& F1, const TopoDS_Face& F2) { if (!myDone.IsBound(F1)) { TopTools_ListOfShape emptyList; myDone.Bind(F1,emptyList); } myDone(F1).Append(F2); if (!myDone.IsBound(F2)) { TopTools_ListOfShape emptyList; myDone.Bind(F2,emptyList); } myDone(F2).Append(F1); } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean Partition_Inter3d::IsDone(const TopoDS_Face& F1, const TopoDS_Face& F2) const { if (myDone.IsBound(F1)) { TopTools_ListIteratorOfListOfShape it (myDone(F1)); for (; it.More(); it.Next()) { if (it.Value().IsSame(F2)) return Standard_True; } } return Standard_False; } //======================================================================= //function : StorePart3d //purpose : //======================================================================= 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); TopTools_ListIteratorOfListOfShape it(LInt); for (; it.More(); it.Next()) { TopoDS_Edge E = TopoDS::Edge(it.Value()); BRep_Builder B; B.SameParameter(E,Standard_False); BRepLib::SameParameter(E,1.0e-7); myNewEdges.Add(E); } } SetDone(F1,F2); } //======================================================================= //function : TouchedFaces //purpose : //======================================================================= TopTools_MapOfShape& Partition_Inter3d::TouchedFaces() { return myTouched; } //======================================================================= //function : AsDes //purpose : //======================================================================= Handle_BRepAlgo_AsDes Partition_Inter3d::AsDes() const { return myAsDes; } //======================================================================= //function : NewEdges //purpose : //======================================================================= TopTools_MapOfShape& Partition_Inter3d::NewEdges() { return myNewEdges; } //======================================================================= //function : Affiche //purpose : //======================================================================= void Partition_Inter3d::Affiche(const TopTools_ListOfShape& SetOfFaces) const { #ifdef DEB char PSection[1024]; char *section=PSection; Standard_Integer i = 0; Standard_Real j=1; TopTools_ListOfShape aList; TopTools_ListIteratorOfListOfShape it; for (it.Initialize(SetOfFaces); it.More(); it.Next()) { const TopoDS_Shape& OS = it.Value(); aList=myAsDes->Descendant(OS); MESSAGE ( " the number of items stored in the list " << j << " : " << aList.Extent() ) j++; TopTools_ListIteratorOfListOfShape itaList; for (itaList.Initialize(aList); itaList.More(); itaList.Next()) { const TopoDS_Shape& SS = itaList.Value(); i++; sprintf(PSection,"section_%d",i); DBRep::Set(section,SS); } } #endif } //======================================================================= //function : SameDomain //purpose : //======================================================================= const TopTools_ListOfShape& Partition_Inter3d::SameDomain(const TopoDS_Face& F) const { if (mySameDomainFM.IsBound( F )) return mySameDomainFM (F); static TopTools_ListOfShape emptyList; return emptyList; } //======================================================================= //function : HasSameDomainF //purpose : Return true if F has same domain faces //======================================================================= Standard_Boolean Partition_Inter3d::HasSameDomainF(const TopoDS_Shape& F) const { return mySameDomainFM.IsBound( F ); } //======================================================================= //function : IsSameDomain //purpose : Return true if F1 and F2 are same domain faces //======================================================================= Standard_Boolean Partition_Inter3d::IsSameDomainF(const TopoDS_Shape& F1, const TopoDS_Shape& F2) const { if (mySameDomainFM.IsBound( F1 )) { TopTools_ListIteratorOfListOfShape it (mySameDomainFM( F1 )); for (; it.More(); it.Next()) if (F2.IsSame( it.Value())) return Standard_True; } return F1.IsSame( F2 ); } //======================================================================= //function : ReplaceSameDomainV //purpose : return same domain vertex of V if it was replaced // and make this vertex to be on E too, else return V //======================================================================= TopoDS_Vertex Partition_Inter3d::ReplaceSameDomainV(const TopoDS_Vertex& V, const TopoDS_Edge& E) const { TopoDS_Vertex SDV = V; if (mySameDomainVM.IsBound( V )) { TopoDS_Vertex V1,V2; TopExp::Vertices(E,V1,V2); Standard_Boolean isClosed = V1.IsSame( V2 ) && V.IsSame(V1); SDV = TopoDS::Vertex( mySameDomainVM(V) ); Standard_Real tol = BRep_Tool::Tolerance( V ); BRep_Builder B; SDV.Orientation( V.Orientation()); if (isClosed) { Standard_Real f, l; BRep_Tool::Range (E, f, l); Standard_Boolean isFirst = IsEqual( BRep_Tool::Parameter(V,E), f ); B.UpdateVertex(SDV, (isFirst ? f : l), E, tol); SDV.Reverse(); B.UpdateVertex(SDV, (isFirst ? l : f), E, tol); } else B.UpdateVertex (SDV, BRep_Tool::Parameter(V,E), E, tol); } return SDV; } //======================================================================= //function : SectionEdgesAD //purpose : //======================================================================= Handle_BRepAlgo_AsDes Partition_Inter3d::SectionEdgesAD() const { return mySectionEdgesAD; } //======================================================================= //function : IsSectionEdge //purpose : return True if E is an edge of a face and it // intersects an other face //======================================================================= Standard_Boolean Partition_Inter3d::IsSectionEdge(const TopoDS_Edge& E) const { return mySectionEdgesAD->HasAscendant(E); } //======================================================================= //function : HasSectionEdge //purpose : return True if an edge of F intersects an other // face or F is intersected by edge of an other face //======================================================================= Standard_Boolean Partition_Inter3d::HasSectionEdge(const TopoDS_Face& F) const { return mySectionEdgesAD->HasDescendant(F); } //======================================================================= //function : IsSplitOn //purpose : return True if NewE is split of OldE on F //======================================================================= Standard_Boolean Partition_Inter3d::IsSplitOn(const TopoDS_Edge& NewE, const TopoDS_Edge& OldE, const TopoDS_Face& F) const { if (! mySectionEdgesAD->HasDescendant(F)) return Standard_False; TopTools_ListIteratorOfListOfShape itE ( mySectionEdgesAD->Descendant(F) ); for ( ; itE.More(); itE.Next()) { if ( itE.Value().ShapeType() != TopAbs_EDGE || ! OldE.IsSame ( itE.Value() )) continue; // an edge encountered, its vertices and a split come next itE.Next(); if (!itE.More()) break; const TopoDS_Shape& V3 = itE.Value(); if (V3.ShapeType() != TopAbs_VERTEX) continue; itE.Next(); if (!itE.More()) break; const TopoDS_Shape& V4 = itE.Value(); if (V4.ShapeType() != TopAbs_VERTEX) continue; TopoDS_Vertex V1, V2; TopExp::Vertices( OldE, V1, V2); if ( V1.IsSame(V2) && (V1.IsSame(V3) || V1.IsSame(V4)) ) { // closed old edge; use the split for the test itE.Next(); if (!itE.More()) break; const TopoDS_Edge& split = TopoDS::Edge( itE.Value() ); // check distance at middle point of NewE Standard_Real f1,l1, f2,l2; Handle(Geom2d_Curve) PC1 = BRep_Tool::CurveOnSurface( split, F ,f1,l1); if (!PC1.IsNull()) { Handle(Geom2d_Curve) PC2 = BRep_Tool::CurveOnSurface(NewE, F ,f2,l2); gp_Pnt2d P = PC2->Value( 0.5*(f2+l2) ); Geom2dAPI_ProjectPointOnCurve proj (P, PC1, f1, l1); if (proj.NbPoints() && proj.LowerDistance() <= Precision::Confusion()) return Standard_True; } else { Handle(Geom_Curve) C1 = BRep_Tool::Curve( split ,f1,l1); Handle(Geom_Curve) C2 = BRep_Tool::Curve( NewE ,f2,l2); gp_Pnt P = C2->Value( 0.5*(f2+l2) ); GeomAPI_ProjectPointOnCurve proj (P, C1, f1, l1); if (proj.NbPoints() && proj.LowerDistance() <= Precision::Confusion()) return Standard_True; } } else { Standard_Real u3 = BRep_Tool::Parameter( TopoDS::Vertex(V3), OldE); Standard_Real u4 = BRep_Tool::Parameter( TopoDS::Vertex(V4), OldE); Standard_Real f,l, u; BRep_Tool::Range( NewE, f,l); u = 0.5*(f+l); f = Min(u3,u4); l = Max(u3,u4); if (u <= l && u >= f) return Standard_True; } } return Standard_False; } //======================================================================= //function : SectionEdgeFaces //purpose : return faces cut by section edge //======================================================================= const TopTools_ListOfShape& Partition_Inter3d::SectionEdgeFaces(const TopoDS_Edge& SecE) const { return mySectionEdgesAD->Ascendant( SecE ); } #endif