diff --git a/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx b/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx index 8900fa870b..da28dd093c 100644 --- a/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx +++ b/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx @@ -17,11 +17,12 @@ #include //======================================================================= -// Function: GenerateSurfaceNodes +// Function: GetSplitSteps // Purpose : //======================================================================= -Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes( - const IMeshTools_Parameters& theParameters) const +std::pair BRepMesh_ConeRangeSplitter::GetSplitSteps( + const IMeshTools_Parameters& theParameters, + std::pair& theStepsNb) const { const std::pair& aRangeU = GetRangeU(); const std::pair& aRangeV = GetRangeV(); @@ -43,15 +44,33 @@ Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes( Du = aDiffU / (nbU + 1); Dv = aDiffV / (nbV + 1); + theStepsNb.first = nbU; + theStepsNb.second = nbV; + return std::make_pair (Du, Dv); +} + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const +{ + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + std::pair aStepsNb; + std::pair aSteps = GetSplitSteps (theParameters, aStepsNb); + const Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); - const Standard_Real aPasMaxV = aRangeV.second - Dv*0.5; - const Standard_Real aPasMaxU = aRangeU.second - Du*0.5; - for (Standard_Real aPasV = aRangeV.first + Dv; aPasV < aPasMaxV; aPasV += Dv) + const Standard_Real aPasMaxV = aRangeV.second - aSteps.second*0.5; + const Standard_Real aPasMaxU = aRangeU.second - aSteps.first *0.5; + for (Standard_Real aPasV = aRangeV.first + aSteps.second; aPasV < aPasMaxV; aPasV += aSteps.second) { - for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du) + for (Standard_Real aPasU = aRangeU.first + aSteps.first; aPasU < aPasMaxU; aPasU += aSteps.first) { aNodes->Append(gp_Pnt2d(aPasU, aPasV)); } diff --git a/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx b/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx index 779c1cadad..e9abf42fec 100644 --- a/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx +++ b/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx @@ -35,6 +35,13 @@ public: { } + //! Returns split intervals along U and V direction. + //! @param theParameters meshing parameters. + //! @param[out] theStepsNb number of steps along corresponding direction. + std::pair GetSplitSteps( + const IMeshTools_Parameters& theParameters, + std::pair& theStepsNb) const; + //! Returns list of nodes generated using surface data and specified parameters. Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; diff --git a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx index a583a9997e..7ec3d4040c 100644 --- a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx +++ b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx @@ -21,6 +21,7 @@ #include #include #include +#include namespace { @@ -88,6 +89,137 @@ namespace Handle(IMeshData_Model) myModel; }; + + //! Adds additional points to seam edges on specific surfaces. + class SeamEdgeAmplifier + { + public: + //! Constructor + SeamEdgeAmplifier(const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) + : myModel (theModel) + , myParameters (theParameters) + { + } + + //! Main functor. + void operator()(const Standard_Integer theFaceIndex) const + { + const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex); + if (aDFace->GetSurface()->GetType() != GeomAbs_Cone) + { + return; + } + + const IMeshData::IWireHandle& aDWire = aDFace->GetWire (0); + for (Standard_Integer aEdgeIdx = 0; aEdgeIdx < aDWire->EdgesNb() - 1; ++aEdgeIdx) + { + const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIdx); + + if (aDEdge->GetPCurve(aDFace.get(), TopAbs_FORWARD) != aDEdge->GetPCurve(aDFace.get(), TopAbs_REVERSED)) + { + if (aDEdge->GetCurve()->ParametersNb() == 2) + { + if (splitEdge (aDEdge, Abs (getConeStep (aDFace)))) + { + TopLoc_Location aLoc; + const Handle (Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation (aDFace->GetFace (), aLoc); + + if (!aTriangulation.IsNull ()) + { + aDFace->SetStatus (IMeshData_Outdated); + } + } + } + return; + } + } + } + + private: + + //! Returns step for splitting seam edge of a cone. + Standard_Real getConeStep(const IMeshData::IFaceHandle& theDFace) const + { + BRepMesh_ConeRangeSplitter aSplitter; + aSplitter.Reset (theDFace, myParameters); + + const IMeshData::IWireHandle& aDWire = theDFace->GetWire (0); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) + { + const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt); + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve( + theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); + + for (Standard_Integer aPointIt = 0; aPointIt < aPCurve->ParametersNb(); ++aPointIt) + { + const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt); + aSplitter.AddPoint(aPnt2d); + } + } + + std::pair aStepsNb; + std::pair aSteps = aSplitter.GetSplitSteps (myParameters, aStepsNb); + return aSteps.second; + } + + //! Splits 3D and all pcurves accoring using the specified step. + Standard_Boolean splitEdge(const IMeshData::IEdgePtr& theDEdge, + const Standard_Real theDU) const + { + if (!splitCurve (theDEdge->GetCurve (), theDU)) + { + return Standard_False; + } + + for (Standard_Integer aPCurveIdx = 0; aPCurveIdx < theDEdge->PCurvesNb(); ++aPCurveIdx) + { + splitCurve (theDEdge->GetPCurve (aPCurveIdx), theDU); + } + + return Standard_True; + } + + //! Splits the given curve using the specified step. + template + Standard_Boolean splitCurve(Curve& theCurve, const Standard_Real theDU) const + { + Standard_Boolean isUpdated = Standard_False; + PointType aDir = theCurve->GetPoint(theCurve->ParametersNb() - 1).Coord() - theCurve->GetPoint(0).Coord(); + const Standard_Real aModulus = aDir.Modulus(); + if (aModulus < gp::Resolution()) + { + return isUpdated; + } + aDir /= aModulus; + + const Standard_Real aLastParam = theCurve->GetParameter(theCurve->ParametersNb() - 1); + const Standard_Boolean isReversed = theCurve->GetParameter(0) > aLastParam; + for (Standard_Integer aPointIdx = 1; ; ++aPointIdx) + { + const Standard_Real aCurrParam = theCurve->GetParameter(0) + aPointIdx * theDU * (isReversed ? -1.0 : 1.0); + if (( isReversed && (aCurrParam < aLastParam)) || + (!isReversed && !(aCurrParam < aLastParam))) + { + break; + } + + theCurve->InsertPoint(theCurve->ParametersNb() - 1, + theCurve->GetPoint(0).Translated (aDir * aPointIdx * theDU), + aCurrParam); + + isUpdated = Standard_True; + } + + return isUpdated; + } + + private: + + Handle(IMeshData_Model) myModel; + IMeshTools_Parameters myParameters; + }; } //======================================================================= @@ -119,7 +251,8 @@ Standard_Boolean BRepMesh_ModelPreProcessor::Perform( return Standard_False; } - OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel); + OSD_Parallel::For(0, theModel->FacesNb(), SeamEdgeAmplifier(theModel, theParameters), !theParameters.InParallel); + OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel); // Clean edges and faces from outdated polygons. Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)); diff --git a/tests/bugs/mesh/bug25042 b/tests/bugs/mesh/bug25042 index 6fa2292bbd..b44908d565 100644 --- a/tests/bugs/mesh/bug25042 +++ b/tests/bugs/mesh/bug25042 @@ -1,6 +1,3 @@ -puts "TODO 0025042 All: Error: Number of triangles = 931 is not equal to expected 957" -puts "TODO 0025042 All: Error: Number of nodes = 532 is not equal to expected 558" - puts "==========" puts "0025042: Cone Meshing: Missing two connecting edges." puts "=========="