// Created on: 1993-01-21 // Created by: Remi LEQUETTE // Copyright (c) 1993-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. #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 //======================================================================= //function : UVBounds //purpose : //======================================================================= void BRepTools::UVBounds(const TopoDS_Face& F, Standard_Real& UMin, Standard_Real& UMax, Standard_Real& VMin, Standard_Real& VMax) { Bnd_Box2d B; AddUVBounds(F,B); if (!B.IsVoid()) { B.Get(UMin,VMin,UMax,VMax); } else { UMin = UMax = VMin = VMax = 0.0; } } //======================================================================= //function : UVBounds //purpose : //======================================================================= void BRepTools::UVBounds(const TopoDS_Face& F, const TopoDS_Wire& W, Standard_Real& UMin, Standard_Real& UMax, Standard_Real& VMin, Standard_Real& VMax) { Bnd_Box2d B; AddUVBounds(F,W,B); if (!B.IsVoid()) { B.Get(UMin,VMin,UMax,VMax); } else { UMin = UMax = VMin = VMax = 0.0; } } //======================================================================= //function : UVBounds //purpose : //======================================================================= void BRepTools::UVBounds(const TopoDS_Face& F, const TopoDS_Edge& E, Standard_Real& UMin, Standard_Real& UMax, Standard_Real& VMin, Standard_Real& VMax) { Bnd_Box2d B; AddUVBounds(F,E,B); if (!B.IsVoid()) { B.Get(UMin,VMin,UMax,VMax); } else { UMin = UMax = VMin = VMax = 0.0; } } //======================================================================= //function : AddUVBounds //purpose : //======================================================================= void BRepTools::AddUVBounds(const TopoDS_Face& FF, Bnd_Box2d& B) { TopoDS_Face F = FF; F.Orientation(TopAbs_FORWARD); TopExp_Explorer ex(F,TopAbs_EDGE); // fill box for the given face Bnd_Box2d aBox; for (;ex.More();ex.Next()) { BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),aBox); } // if the box is empty (face without edges or without pcurves), // get natural bounds if (aBox.IsVoid()) { Standard_Real UMin,UMax,VMin,VMax; TopLoc_Location L; const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(F, L); if (aSurf.IsNull()) { return; } aSurf->Bounds(UMin,UMax,VMin,VMax); aBox.Update(UMin,VMin,UMax,VMax); } // add face box to result B.Add ( aBox ); } //======================================================================= //function : AddUVBounds //purpose : //======================================================================= void BRepTools::AddUVBounds(const TopoDS_Face& F, const TopoDS_Wire& W, Bnd_Box2d& B) { TopExp_Explorer ex; for (ex.Init(W,TopAbs_EDGE);ex.More();ex.Next()) { BRepTools::AddUVBounds(F,TopoDS::Edge(ex.Current()),B); } } //======================================================================= //function : AddUVBounds //purpose : //======================================================================= void BRepTools::AddUVBounds(const TopoDS_Face& aF, const TopoDS_Edge& aE, Bnd_Box2d& aB) { Standard_Real aT1, aT2, aXmin = 0.0, aYmin = 0.0, aXmax = 0.0, aYmax = 0.0; Standard_Real aUmin, aUmax, aVmin, aVmax; Bnd_Box2d aBoxC, aBoxS; TopLoc_Location aLoc; // const Handle(Geom2d_Curve) aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2); if (aC2D.IsNull()) { return; } // BndLib_Add2dCurve::Add(aC2D, aT1, aT2, 0., aBoxC); if (!aBoxC.IsVoid()) { aBoxC.Get(aXmin, aYmin, aXmax, aYmax); } // Handle(Geom_Surface) aS = BRep_Tool::Surface(aF, aLoc); aS->Bounds(aUmin, aUmax, aVmin, aVmax); if(aS->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) { const Handle(Geom_RectangularTrimmedSurface) aSt = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS); aS = aSt->BasisSurface(); } // if(!aS->IsUPeriodic()) { Standard_Boolean isUPeriodic = Standard_False; // Additional verification for U-periodicity for B-spline surfaces // 1. Verify that the surface is U-closed (if such flag is false). Verification uses 2 points // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points. if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) && (aXmin < aUmin || aXmax > aUmax)) { Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion(); isUPeriodic = Standard_True; gp_Pnt P1, P2; // 1. Verify that the surface is U-closed if (!aS->IsUClosed()) { Standard_Real aVStep = aVmax - aVmin; for (Standard_Real aV = aVmin; aV <= aVmax; aV += aVStep) { P1 = aS->Value(aUmin, aV); P2 = aS->Value(aUmax, aV); if (P1.SquareDistance(P2) > aTol2) { isUPeriodic = Standard_False; break; } } } // 2. Verify periodicity of surface inside UV-bounds of the edge if (isUPeriodic) // the flag still not changed { Standard_Real aV = (aVmin + aVmax) * 0.5; Standard_Real aU[6]; // values of U lying out of surface boundaries Standard_Real aUpp[6]; // corresponding U-values plus/minus period Standard_Integer aNbPnt = 0; if (aXmin < aUmin) { aU[0] = aXmin; aU[1] = (aXmin + aUmin) * 0.5; aU[2] = aUmin; aUpp[0] = aU[0] + aUmax - aUmin; aUpp[1] = aU[1] + aUmax - aUmin; aUpp[2] = aU[2] + aUmax - aUmin; aNbPnt += 3; } if (aXmax > aUmax) { aU[aNbPnt] = aUmax; aU[aNbPnt + 1] = (aXmax + aUmax) * 0.5; aU[aNbPnt + 2] = aXmax; aUpp[aNbPnt] = aU[aNbPnt] - aUmax + aUmin; aUpp[aNbPnt + 1] = aU[aNbPnt + 1] - aUmax + aUmin; aUpp[aNbPnt + 2] = aU[aNbPnt + 2] - aUmax + aUmin; aNbPnt += 3; } for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++) { P1 = aS->Value(aU[anInd], aV); P2 = aS->Value(aUpp[anInd], aV); if (P1.SquareDistance(P2) > aTol2) { isUPeriodic = Standard_False; break; } } } } if (!isUPeriodic) { if((aXminIsVPeriodic()) { Standard_Boolean isVPeriodic = Standard_False; // Additional verification for V-periodicity for B-spline surfaces // 1. Verify that the surface is V-closed (if such flag is false). Verification uses 2 points // 2. Verify periodicity of surface inside UV-bounds of the edge. Verification uses 3 or 6 points. if (aS->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface) && (aYmin < aVmin || aYmax > aVmax)) { Standard_Real aTol2 = 100 * Precision::Confusion() * Precision::Confusion(); isVPeriodic = Standard_True; gp_Pnt P1, P2; // 1. Verify that the surface is V-closed if (!aS->IsVClosed()) { Standard_Real aUStep = aUmax - aUmin; for (Standard_Real aU = aUmin; aU <= aUmax; aU += aUStep) { P1 = aS->Value(aU, aVmin); P2 = aS->Value(aU, aVmax); if (P1.SquareDistance(P2) > aTol2) { isVPeriodic = Standard_False; break; } } } // 2. Verify periodicity of surface inside UV-bounds of the edge if (isVPeriodic) // the flag still not changed { Standard_Real aU = (aUmin + aUmax) * 0.5; Standard_Real aV[6]; // values of V lying out of surface boundaries Standard_Real aVpp[6]; // corresponding V-values plus/minus period Standard_Integer aNbPnt = 0; if (aYmin < aVmin) { aV[0] = aYmin; aV[1] = (aYmin + aVmin) * 0.5; aV[2] = aVmin; aVpp[0] = aV[0] + aVmax - aVmin; aVpp[1] = aV[1] + aVmax - aVmin; aVpp[2] = aV[2] + aVmax - aVmin; aNbPnt += 3; } if (aYmax > aVmax) { aV[aNbPnt] = aVmax; aV[aNbPnt + 1] = (aYmax + aVmax) * 0.5; aV[aNbPnt + 2] = aYmax; aVpp[aNbPnt] = aV[aNbPnt] - aVmax + aVmin; aVpp[aNbPnt + 1] = aV[aNbPnt + 1] - aVmax + aVmin; aVpp[aNbPnt + 2] = aV[aNbPnt + 2] - aVmax + aVmin; aNbPnt += 3; } for (Standard_Integer anInd = 0; anInd < aNbPnt; anInd++) { P1 = aS->Value(aU, aV[anInd]); P2 = aS->Value(aU, aVpp[anInd]); if (P1.SquareDistance(P2) > aTol2) { isVPeriodic = Standard_False; break; } } } } if (!isVPeriodic) { if((aYminChecked(Standard_True); } } //======================================================================= //function : Update //purpose : //======================================================================= void BRepTools::Update(const TopoDS_Shell& S) { TopExp_Explorer ex(S,TopAbs_FACE); while (ex.More()) { Update(TopoDS::Face(ex.Current())); ex.Next(); } } //======================================================================= //function : Update //purpose : //======================================================================= void BRepTools::Update(const TopoDS_Solid& S) { TopExp_Explorer ex(S,TopAbs_FACE); while (ex.More()) { Update(TopoDS::Face(ex.Current())); ex.Next(); } } //======================================================================= //function : Update //purpose : //======================================================================= void BRepTools::Update(const TopoDS_CompSolid& CS) { TopExp_Explorer ex(CS,TopAbs_FACE); while (ex.More()) { Update(TopoDS::Face(ex.Current())); ex.Next(); } } //======================================================================= //function : Update //purpose : //======================================================================= void BRepTools::Update(const TopoDS_Compound& C) { TopExp_Explorer ex(C,TopAbs_FACE); while (ex.More()) { Update(TopoDS::Face(ex.Current())); ex.Next(); } } //======================================================================= //function : Update //purpose : //======================================================================= void BRepTools::Update(const TopoDS_Shape& S) { switch (S.ShapeType()) { case TopAbs_VERTEX : Update(TopoDS::Vertex(S)); break; case TopAbs_EDGE : Update(TopoDS::Edge(S)); break; case TopAbs_WIRE : Update(TopoDS::Wire(S)); break; case TopAbs_FACE : Update(TopoDS::Face(S)); break; case TopAbs_SHELL : Update(TopoDS::Shell(S)); break; case TopAbs_SOLID : Update(TopoDS::Solid(S)); break; case TopAbs_COMPSOLID : Update(TopoDS::CompSolid(S)); break; case TopAbs_COMPOUND : Update(TopoDS::Compound(S)); break; default: break; } } //======================================================================= //function : UpdateFaceUVPoints //purpose : Reset the UV points of edges on the Face //======================================================================= void BRepTools::UpdateFaceUVPoints(const TopoDS_Face& theF) { // For each edge of the face reset the UV points to the bounding // points of the parametric curve of the edge on the face. // Get surface of the face TopLoc_Location aLoc; const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(theF, aLoc); // Iterate on edges and reset UV points TopExp_Explorer anExpE(theF, TopAbs_EDGE); for (; anExpE.More(); anExpE.Next()) { const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current()); const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape()); if (TE->Locked()) return; const TopLoc_Location aELoc = aLoc.Predivided(aE.Location()); // Edge representations BRep_ListOfCurveRepresentation& aLCR = TE->ChangeCurves(); BRep_ListIteratorOfListOfCurveRepresentation itLCR(aLCR); for (; itLCR.More(); itLCR.Next()) { Handle(BRep_GCurve) GC = Handle(BRep_GCurve)::DownCast(itLCR.Value()); if (!GC.IsNull() && GC->IsCurveOnSurface(aSurf, aELoc)) { // Update UV points GC->Update(); break; } } } } //======================================================================= //function : Compare //purpose : //======================================================================= Standard_Boolean BRepTools::Compare(const TopoDS_Vertex& V1, const TopoDS_Vertex& V2) { if (V1.IsSame(V2)) return Standard_True; gp_Pnt p1 = BRep_Tool::Pnt(V1); gp_Pnt p2 = BRep_Tool::Pnt(V2); Standard_Real l = p1.Distance(p2); if (l <= BRep_Tool::Tolerance(V1)) return Standard_True; if (l <= BRep_Tool::Tolerance(V2)) return Standard_True; return Standard_False; } //======================================================================= //function : Compare //purpose : //======================================================================= Standard_Boolean BRepTools::Compare(const TopoDS_Edge& E1, const TopoDS_Edge& E2) { if (E1.IsSame(E2)) return Standard_True; return Standard_False; } //======================================================================= //function : OuterWire //purpose : //======================================================================= TopoDS_Wire BRepTools::OuterWire(const TopoDS_Face& F) { TopoDS_Wire Wres; TopExp_Explorer expw (F,TopAbs_WIRE); if (expw.More()) { Wres = TopoDS::Wire(expw.Current()); expw.Next(); if (expw.More()) { Standard_Real UMin, UMax, VMin, VMax; Standard_Real umin, umax, vmin, vmax; BRepTools::UVBounds(F,Wres,UMin,UMax,VMin,VMax); while (expw.More()) { const TopoDS_Wire& W = TopoDS::Wire(expw.Current()); BRepTools::UVBounds(F,W,umin, umax, vmin, vmax); if (((umin - UMin) <= Precision::PConfusion()) && ((umax - UMax) >= -Precision::PConfusion()) && ((vmin - VMin) <= Precision::PConfusion()) && ((vmax - VMax) >= -Precision::PConfusion())) { Wres = W; UMin = umin; UMax = umax; VMin = vmin; VMax = vmax; } expw.Next(); } } } return Wres; } //======================================================================= //function : Map3DEdges //purpose : //======================================================================= void BRepTools::Map3DEdges(const TopoDS_Shape& S, TopTools_IndexedMapOfShape& M) { TopExp_Explorer Ex; for (Ex.Init(S,TopAbs_EDGE); Ex.More(); Ex.Next()) { if (!BRep_Tool::Degenerated(TopoDS::Edge(Ex.Current()))) M.Add(Ex.Current()); } } //======================================================================= //function : Dump //purpose : //======================================================================= void BRepTools::Dump(const TopoDS_Shape& Sh, Standard_OStream& S) { BRepTools_ShapeSet SS; SS.Add(Sh); SS.Dump(Sh,S); SS.Dump(S); } //======================================================================= //function : Write //purpose : //======================================================================= void BRepTools::Write (const TopoDS_Shape& theShape, Standard_OStream& theStream, const Standard_Boolean theWithTriangles, const Standard_Boolean theWithNormals, const TopTools_FormatVersion theVersion, const Message_ProgressRange& theProgress) { BRepTools_ShapeSet aShapeSet (theWithTriangles, theWithNormals); aShapeSet.SetFormatNb (theVersion); aShapeSet.Add (theShape); aShapeSet.Write (theStream, theProgress); aShapeSet.Write (theShape, theStream); } //======================================================================= //function : Read //purpose : //======================================================================= void BRepTools::Read(TopoDS_Shape& Sh, std::istream& S, const BRep_Builder& B, const Message_ProgressRange& theProgress) { BRepTools_ShapeSet SS(B); SS.Read(S, theProgress); SS.Read(Sh,S); } //======================================================================= //function : Write //purpose : //======================================================================= Standard_Boolean BRepTools::Write (const TopoDS_Shape& theShape, const Standard_CString theFile, const Standard_Boolean theWithTriangles, const Standard_Boolean theWithNormals, const TopTools_FormatVersion theVersion, const Message_ProgressRange& theProgress) { const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem(); std::shared_ptr aStream = aFileSystem->OpenOStream (theFile, std::ios::out | std::ios::binary); if (aStream.get() == NULL || !aStream->good()) { return Standard_False; } Standard_Boolean isGood = (aStream->good() && !aStream->eof()); if(!isGood) return isGood; BRepTools_ShapeSet SS (theWithTriangles, theWithNormals); SS.SetFormatNb (theVersion); SS.Add (theShape); *aStream << "DBRep_DrawableShape\n"; // for easy Draw read SS.Write (*aStream, theProgress); isGood = aStream->good(); if (isGood) { SS.Write (theShape, *aStream); } aStream->flush(); isGood = aStream->good(); errno = 0; isGood = aStream->good() && isGood && !errno; aStream.reset(); return isGood; } //======================================================================= //function : Read //purpose : //======================================================================= Standard_Boolean BRepTools::Read(TopoDS_Shape& Sh, const Standard_CString File, const BRep_Builder& B, const Message_ProgressRange& theProgress) { const Handle(OSD_FileSystem)& aFileSystem = OSD_FileSystem::DefaultFileSystem(); std::shared_ptr aStream = aFileSystem->OpenIStream (File, std::ios::in); if (aStream.get() == NULL) { return Standard_False; } BRepTools_ShapeSet SS(B); SS.Read (*aStream, theProgress); if(!SS.NbShapes()) return Standard_False; SS.Read (Sh,*aStream); return Standard_True; } //======================================================================= //function : Clean //purpose : //======================================================================= void BRepTools::Clean (const TopoDS_Shape& theShape, const Standard_Boolean theForce) { if (theShape.IsNull()) return; BRep_Builder aBuilder; Handle(Poly_Triangulation) aNullTriangulation; Handle(Poly_PolygonOnTriangulation) aNullPoly; TopTools_MapOfShape aShapeMap; const TopLoc_Location anEmptyLoc; TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); for (; aFaceIt.More(); aFaceIt.Next()) { TopoDS_Shape aFaceNoLoc = aFaceIt.Value(); aFaceNoLoc.Location (anEmptyLoc); if (!aShapeMap.Add (aFaceNoLoc)) { // the face has already been processed continue; } const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current()); if (!BRep_Tool::IsGeometric (aFace)) { // Do not remove triangulation as there is no surface to recompute it. continue; } TopLoc_Location aLoc; const Handle(Poly_Triangulation)& aTriangulation = BRep_Tool::Triangulation(aFace, aLoc); if (aTriangulation.IsNull()) continue; // Nullify edges // Theoretically, the edges on the face (with surface) may have no geometry // (no curve 3d or 2d or both). Such faces should be considered as invalid and // are not supported by current implementation. So, both triangulation of the face // and polygon on triangulation of the edges are removed unconditionally. TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); for (; aEdgeIt.More(); aEdgeIt.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current()); aBuilder.UpdateEdge(anEdge, aNullPoly, aTriangulation, aLoc); } aBuilder.UpdateFace(aFace, aNullTriangulation); } // Iterate over all edges seeking for 3d polygons Handle (Poly_Polygon3D) aNullPoly3d; TopExp_Explorer aEdgeIt (theShape, TopAbs_EDGE); for (; aEdgeIt.More (); aEdgeIt.Next ()) { TopoDS_Edge anEdge = TopoDS::Edge(aEdgeIt.Value()); anEdge.Location(anEmptyLoc); if (!aShapeMap.Add(anEdge)) { // the edge has already been processed continue; } if (!BRep_Tool::IsGeometric(TopoDS::Edge(anEdge))) { // Do not remove polygon 3d as there is no curve to recompute it. continue; } TopLoc_Location aLoc; Handle(Poly_Polygon3D) aPoly3d = BRep_Tool::Polygon3D(anEdge, aLoc); if (!aPoly3d.IsNull()) { aBuilder.UpdateEdge(anEdge, aNullPoly3d); } if (theForce) { Handle(BRep_CurveRepresentation) aCR; BRep_TEdge* aTE = static_cast(anEdge.TShape().get()); BRep_ListOfCurveRepresentation& aLCR = aTE->ChangeCurves(); BRep_ListIteratorOfListOfCurveRepresentation anIterCR(aLCR); // find and remove all representations while (anIterCR.More()) { aCR = anIterCR.Value(); if (aCR->IsPolygonOnTriangulation()) { aLCR.Remove(anIterCR); } else { anIterCR.Next(); } } aTE->Modified(Standard_True); } } } //======================================================================= //function : CleanGeometry //purpose : //======================================================================= void BRepTools::CleanGeometry(const TopoDS_Shape& theShape) { if (theShape.IsNull()) return; BRep_Builder aBuilder; for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next()) { TopLoc_Location aLocation; const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current()); const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface(aFace, aLocation); for (TopExp_Explorer aEdgeIt(aFace, TopAbs_EDGE); aEdgeIt.More(); aEdgeIt.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Current()); aBuilder.UpdateEdge(anEdge, Handle(Geom2d_Curve)(), aSurface, aLocation, BRep_Tool::Tolerance(anEdge)); } aBuilder.UpdateFace(aFace, Handle(Geom_Surface)(), aFace.Location(), BRep_Tool::Tolerance(aFace)); } for (TopExp_Explorer aEdgeIt2(theShape, TopAbs_EDGE); aEdgeIt2.More(); aEdgeIt2.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt2.Current()); aBuilder.UpdateEdge(anEdge, Handle(Geom_Curve)(), TopLoc_Location(), BRep_Tool::Tolerance(anEdge)); } RemoveUnusedPCurves(theShape); } //======================================================================= //function : RemoveUnusedPCurves //purpose : //======================================================================= void BRepTools::RemoveUnusedPCurves(const TopoDS_Shape& S) { TColStd_MapOfTransient UsedSurfaces; TopExp_Explorer Explo(S, TopAbs_FACE); for (; Explo.More(); Explo.Next()) { TopoDS_Face aFace = TopoDS::Face(Explo.Current()); TopLoc_Location aLoc; Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace, aLoc); UsedSurfaces.Add(aSurf); } TopTools_IndexedMapOfShape Emap; TopExp::MapShapes(S, TopAbs_EDGE, Emap); Standard_Integer i; for (i = 1; i <= Emap.Extent(); i++) { const Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*) &Emap(i).TShape()); BRep_ListOfCurveRepresentation& lcr = TE -> ChangeCurves(); BRep_ListIteratorOfListOfCurveRepresentation itrep(lcr ); while (itrep.More()) { Standard_Boolean ToRemove = Standard_False; Handle(BRep_CurveRepresentation) CurveRep = itrep.Value(); if (CurveRep->IsCurveOnSurface()) { Handle(Geom_Surface) aSurface = CurveRep->Surface(); if (!UsedSurfaces.Contains(aSurface)) ToRemove = Standard_True; } else if (CurveRep->IsRegularity()) { Handle(Geom_Surface) Surf1 = CurveRep->Surface(); Handle(Geom_Surface) Surf2 = CurveRep->Surface2(); ToRemove = (!UsedSurfaces.Contains(Surf1) || !UsedSurfaces.Contains(Surf2)); } if (ToRemove) lcr.Remove(itrep); else itrep.Next(); } } } //======================================================================= //function : Triangulation //purpose : //======================================================================= Standard_Boolean BRepTools::Triangulation(const TopoDS_Shape& theShape, const Standard_Real theLinDefl, const Standard_Boolean theToCheckFreeEdges) { TopExp_Explorer anEdgeIter; TopLoc_Location aDummyLoc; for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); const Handle(Poly_Triangulation)& aTri = BRep_Tool::Triangulation (aFace, aDummyLoc); if (aTri.IsNull() || aTri->Deflection() > theLinDefl) { return Standard_False; } for (anEdgeIter.Init (aFace, TopAbs_EDGE); anEdgeIter.More(); anEdgeIter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, aTri, aDummyLoc); if (aPoly.IsNull()) { return Standard_False; } } } if (!theToCheckFreeEdges) { return Standard_True; } Handle(Poly_Triangulation) anEdgeTri; for (anEdgeIter.Init (theShape, TopAbs_EDGE, TopAbs_FACE); anEdgeIter.More(); anEdgeIter.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge (anEdgeIter.Current()); const Handle(Poly_Polygon3D)& aPolygon = BRep_Tool::Polygon3D (anEdge, aDummyLoc); if (!aPolygon.IsNull()) { if (aPolygon->Deflection() > theLinDefl) { return Standard_False; } } else { const Handle(Poly_PolygonOnTriangulation)& aPoly = BRep_Tool::PolygonOnTriangulation (anEdge, anEdgeTri, aDummyLoc); if (aPoly.IsNull() || anEdgeTri.IsNull() || anEdgeTri->Deflection() > theLinDefl) { return Standard_False; } } } return Standard_True; } //======================================================================= //function : LoadTriangulation //purpose : //======================================================================= Standard_Boolean BRepTools::LoadTriangulation (const TopoDS_Shape& theShape, const Standard_Integer theTriangulationIdx, const Standard_Boolean theToSetAsActive, const Handle(OSD_FileSystem)& theFileSystem) { Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!"); Standard_Boolean wasLoaded = false; BRep_Builder aBuilder; TopLoc_Location aDummyLoc; const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem(); for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); Handle(Poly_Triangulation) aTriangulation; if (theTriangulationIdx == -1) { // load an active triangulation aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc); } else { const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc); if (theTriangulationIdx >= aTriangulations.Size()) { // triangulation index is out of range continue; } Standard_Integer aTriangulationIdx = 0; for (Poly_ListOfTriangulation::Iterator anIter(aTriangulations); anIter.More(); anIter.Next(), aTriangulationIdx++) { if (aTriangulationIdx != theTriangulationIdx) { continue; } aTriangulation = anIter.Value(); break; } } if (aTriangulation.IsNull() || !aTriangulation->HasDeferredData()) { // NULL triangulation, already loaded triangulation or triangulation without deferred storage // cannot be loaded continue; } if (aTriangulation->LoadDeferredData (aFileSystem)) { wasLoaded = true; if (theToSetAsActive && (theTriangulationIdx != -1)) // triangulation is already active { aBuilder.UpdateFace (aFace, aTriangulation, false); } } } return wasLoaded; } //======================================================================= //function : LoadAllTriangulation //purpose : //======================================================================= Standard_Boolean BRepTools::LoadAllTriangulations (const TopoDS_Shape& theShape, const Handle(OSD_FileSystem)& theFileSystem) { Standard_Boolean wasLoaded = false; TopLoc_Location aDummyLoc; const Handle(OSD_FileSystem)& aFileSystem = !theFileSystem.IsNull() ? theFileSystem : OSD_FileSystem::DefaultFileSystem(); for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc)); anIter.More(); anIter.Next()) { const Handle(Poly_Triangulation)& aTriangulation = anIter.Value(); if (aTriangulation.IsNull() || !aTriangulation->HasDeferredData()) { // NULL triangulation, already loaded triangulation or triangulation without deferred storage // cannot be loaded continue; } wasLoaded = aTriangulation->LoadDeferredData (aFileSystem); } } return wasLoaded; } //======================================================================= //function : UnloadTriangulation //purpose : //======================================================================= Standard_Boolean BRepTools::UnloadTriangulation (const TopoDS_Shape& theShape, const Standard_Integer theTriangulationIdx) { Standard_ASSERT_RAISE (theTriangulationIdx >= -1, "Invalid negative triangulation index!"); Standard_Boolean wasUnloaded = false; TopLoc_Location aDummyLoc; for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); Handle(Poly_Triangulation) aTriangulation; if (theTriangulationIdx == -1) { // unload an active triangulation aTriangulation = BRep_Tool::Triangulation (aFace, aDummyLoc); } else { Standard_Integer aTriangulationIdx = 0; const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc); if (theTriangulationIdx >= aTriangulations.Size()) { // triangulation index is out of range continue; } for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations); anIter.More(); anIter.Next(), aTriangulationIdx++) { if (aTriangulationIdx != theTriangulationIdx) { continue; } aTriangulation = anIter.Value(); break; } } if (aTriangulation.IsNull() || !aTriangulation->HasDeferredData()) { // NULL triangulation or triangulation without deferred storage cannot be unloaded continue; } wasUnloaded = aTriangulation->UnloadDeferredData(); } return wasUnloaded; } //======================================================================= //function : UnloadAllTriangulations //purpose : //======================================================================= Standard_Boolean BRepTools::UnloadAllTriangulations (const TopoDS_Shape& theShape) { Standard_Boolean wasUnloaded = false; TopLoc_Location aDummyLoc; for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); Handle(Poly_Triangulation) aTriangulation; for (Poly_ListOfTriangulation::Iterator anIter (BRep_Tool::Triangulations (aFace, aDummyLoc)); anIter.More(); anIter.Next()) { aTriangulation = anIter.Value(); if (aTriangulation.IsNull() || !aTriangulation->HasDeferredData()) { // NULL triangulation or triangulation without deferred storage cannot be unloaded continue; } wasUnloaded = aTriangulation->UnloadDeferredData(); } } return wasUnloaded; } //======================================================================= //function : ActivateTriangulation //purpose : //======================================================================= Standard_Boolean BRepTools::ActivateTriangulation (const TopoDS_Shape& theShape, const Standard_Integer theTriangulationIdx, const Standard_Boolean theToActivateStrictly) { Standard_ASSERT_RAISE (theTriangulationIdx > -1, "Invalid negative triangulation index!"); Standard_Boolean wasActivated = false; BRep_Builder aBuilder; TopLoc_Location aDummyLoc; for (TopExp_Explorer aFaceIter (theShape, TopAbs_FACE); aFaceIter.More(); aFaceIter.Next()) { const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Current()); Standard_Integer aTriangulationIdx = theTriangulationIdx; const Poly_ListOfTriangulation& aTriangulations = BRep_Tool::Triangulations (aFace, aDummyLoc); const Standard_Integer aTriangulationsNb = aTriangulations.Size(); if (theTriangulationIdx >= aTriangulationsNb) { // triangulation index is out of range if (theToActivateStrictly) { // skip activation continue; } // use last available aTriangulationIdx = aTriangulationsNb - 1; } Handle(Poly_Triangulation) anActiveTriangulation; Standard_Integer aTriangulationIter = 0; for (Poly_ListOfTriangulation::Iterator anIter (aTriangulations); anIter.More(); anIter.Next(), aTriangulationIter++) { if (aTriangulationIter != aTriangulationIdx) { continue; } anActiveTriangulation = anIter.Value(); break; } if (anActiveTriangulation.IsNull()) { continue; } aBuilder.UpdateFace (aFace, anActiveTriangulation, false); wasActivated = true; } return wasActivated; } //======================================================================= //function : IsReallyClosed //purpose : //======================================================================= Standard_Boolean BRepTools::IsReallyClosed(const TopoDS_Edge& E, const TopoDS_Face& F) { if (!BRep_Tool::IsClosed(E,F)) { return Standard_False; } Standard_Integer nbocc = 0; TopExp_Explorer exp; for (exp.Init(F,TopAbs_EDGE);exp.More();exp.Next()) { if (exp.Current().IsSame(E)) { nbocc++; } } return nbocc == 2; } //======================================================================= //function : DetectClosedness //purpose : //======================================================================= void BRepTools::DetectClosedness(const TopoDS_Face& theFace, Standard_Boolean& theUclosed, Standard_Boolean& theVclosed) { theUclosed = theVclosed = Standard_False; TopExp_Explorer Explo(theFace, TopAbs_EDGE); for (; Explo.More(); Explo.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); if (BRep_Tool::IsClosed(anEdge, theFace) && BRepTools::IsReallyClosed(anEdge, theFace)) { Standard_Real fpar, lpar; Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar); Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(anEdge.Reversed()), theFace, fpar, lpar); gp_Pnt2d Point1 = PCurve1->Value(fpar); gp_Pnt2d Point2 = PCurve2->Value(fpar); Standard_Boolean IsUiso = (Abs(Point1.X() - Point2.X()) > Abs(Point1.Y() - Point2.Y())); if (IsUiso) theUclosed = Standard_True; else theVclosed = Standard_True; } } } //======================================================================= //function : EvalAndUpdateTol //purpose : //======================================================================= Standard_Real BRepTools::EvalAndUpdateTol(const TopoDS_Edge& theE, const Handle(Geom_Curve)& C3d, const Handle(Geom2d_Curve)& C2d, const Handle(Geom_Surface)& S, const Standard_Real f, const Standard_Real l) { Standard_Real newtol = 0.; Standard_Real first = f, last = l; //Set first, last to avoid ErrosStatus = 2 because of //too strong checking of limits in class CheckCurveOnSurface // if(!C3d->IsPeriodic()) { first = Max(first, C3d->FirstParameter()); last = Min(last, C3d->LastParameter()); } if(!C2d->IsPeriodic()) { first = Max(first, C2d->FirstParameter()); last = Min(last, C2d->LastParameter()); } const Handle(Adaptor3d_Curve) aGeomAdaptorCurve = new GeomAdaptor_Curve(C3d, first, last); Handle(Adaptor2d_Curve2d) aGeom2dAdaptorCurve = new Geom2dAdaptor_Curve(C2d, first, last); Handle(GeomAdaptor_Surface) aGeomAdaptorSurface = new GeomAdaptor_Surface(S); Handle(Adaptor3d_CurveOnSurface) anAdaptor3dCurveOnSurface = new Adaptor3d_CurveOnSurface(aGeom2dAdaptorCurve, aGeomAdaptorSurface); GeomLib_CheckCurveOnSurface CT(aGeomAdaptorCurve); CT.Perform(anAdaptor3dCurveOnSurface); if(CT.IsDone()) { newtol = CT.MaxDistance(); } else { if(CT.ErrorStatus() == 3 || (CT.ErrorStatus() == 2 && (C3d->IsPeriodic() || C2d->IsPeriodic()))) { //Try to estimate by sample points Standard_Integer nbint = 22; Standard_Real dt = (last - first) / nbint; dt = Max(dt, Precision::Confusion()); Standard_Real d, dmax = 0.; gp_Pnt2d aP2d; gp_Pnt aPC, aPS; Standard_Integer cnt = 0; Standard_Real t = first; for(; t <= last; t += dt) { cnt++; C2d->D0(t, aP2d); C3d->D0(t, aPC); S->D0(aP2d.X(), aP2d.Y(), aPS); d = aPS.SquareDistance(aPC); if(d > dmax) { dmax = d; } } if(cnt < nbint + 1) { t = last; C2d->D0(t, aP2d); C3d->D0(t, aPC); S->D0(aP2d.X(), aP2d.Y(), aPS); d = aPS.SquareDistance(aPC); if(d > dmax) { dmax = d; } } newtol = 1.2 * Sqrt(dmax); } } Standard_Real Tol = BRep_Tool::Tolerance(theE); if(newtol > Tol) { Tol = newtol; BRep_Builder B; B.UpdateEdge(theE, Tol); } return Tol; } //======================================================================= //function : OriEdgeInFace //purpose : //======================================================================= TopAbs_Orientation BRepTools::OriEdgeInFace (const TopoDS_Edge& E, const TopoDS_Face& F ) { TopExp_Explorer Exp(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE); for (; Exp.More() ;Exp.Next()) { if (Exp.Current().IsSame(E)) { return Exp.Current().Orientation(); } } throw Standard_ConstructionError("BRepTools::OriEdgeInFace"); } namespace { //======================================================================= //function : findInternalsToKeep //purpose : Looks for internal sub-shapes which has to be kept to preserve // topological connectivity. //======================================================================= static void findInternalsToKeep (const TopoDS_Shape& theS, TopTools_MapOfShape& theAllNonInternals, TopTools_MapOfShape& theAllInternals, TopTools_MapOfShape& theShapesToKeep) { for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next()) { const TopoDS_Shape& aSS = it.Value(); findInternalsToKeep (aSS, theAllNonInternals, theAllInternals, theShapesToKeep); if (aSS.Orientation() == TopAbs_INTERNAL) theAllInternals.Add (aSS); else theAllNonInternals.Add (aSS); if (theAllNonInternals.Contains(aSS) && theAllInternals.Contains (aSS)) theShapesToKeep.Add (aSS); } } //======================================================================= //function : removeShapes //purpose : Removes sub-shapes from the shape //======================================================================= static void removeShapes (TopoDS_Shape& theS, const TopTools_ListOfShape& theLS) { BRep_Builder aBB; Standard_Boolean isFree = theS.Free(); theS.Free (Standard_True); for (TopTools_ListOfShape::Iterator it (theLS); it.More(); it.Next()) { aBB.Remove (theS, it.Value()); } theS.Free (isFree); } //======================================================================= //function : removeInternals //purpose : Removes recursively all internal sub-shapes from the given shape. // Returns true if all sub-shapes have been removed from the shape. //======================================================================= static Standard_Boolean removeInternals (TopoDS_Shape& theS, const TopTools_MapOfShape* theShapesToKeep) { TopTools_ListOfShape aLRemove; for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next()) { const TopoDS_Shape& aSS = it.Value(); if (aSS.Orientation() == TopAbs_INTERNAL) { if (!theShapesToKeep || !theShapesToKeep->Contains (aSS)) aLRemove.Append (aSS); } else { if (removeInternals (*(TopoDS_Shape*)&aSS, theShapesToKeep)) aLRemove.Append (aSS); } } Standard_Integer aNbSToRemove = aLRemove.Extent(); if (aNbSToRemove) { removeShapes (theS, aLRemove); return (theS.NbChildren() == 0); } return Standard_False; } } //======================================================================= //function : RemoveInternals //purpose : //======================================================================= void BRepTools::RemoveInternals (TopoDS_Shape& theS, const Standard_Boolean theForce) { TopTools_MapOfShape *pMKeep = NULL, aMKeep; if (!theForce) { // Find all internal sub-shapes which has to be kept to preserve topological connectivity. // Note that if the multi-connected shape is not directly contained in some shape, // but as a part of bigger sub-shape which will be removed, the multi-connected // shape is going to be removed also, breaking topological connectivity. // For instance, is a compound of the face and edge, which does not // belong to the face. The face contains internal wire and the edge shares // the vertex with one of the vertices of that wire. The vertex is not directly // contained in the face, thus will be removed as part of internal wire, and topological // connectivity between edge and face will be lost. TopTools_MapOfShape anAllNonInternals, anAllInternals; findInternalsToKeep (theS, anAllNonInternals, anAllInternals, aMKeep); if (aMKeep.Extent()) pMKeep = &aMKeep; } removeInternals (theS, pMKeep); } //======================================================================= //function : CheckLocations //purpose : //======================================================================= void BRepTools::CheckLocations(const TopoDS_Shape& theS, TopTools_ListOfShape& theProblemShapes) { if (theS.IsNull()) return; TopTools_IndexedMapOfShape aMapS; TopExp::MapShapes(theS, aMapS, Standard_False, Standard_False); Standard_Integer i; for (i = 1; i <= aMapS.Extent(); ++i) { const TopoDS_Shape& anS = aMapS(i); const TopLoc_Location& aLoc = anS.Location(); const gp_Trsf& aTrsf = aLoc.Transformation(); Standard_Boolean isBadTrsf = aTrsf.IsNegative() || (Abs(Abs(aTrsf.ScaleFactor()) - 1.) > TopLoc_Location::ScalePrec()); if (isBadTrsf) { theProblemShapes.Append(anS); } } }