1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0028379: BRepMesh produces mangled mesh for a cone

Split seam edge of a cone according to the specified parameters.
Seam edge functor is called before check of triangulation consistency in order to keep face status consistent.
The cause is that split seam edge can set Outdated flag when Reused is set by another functor without reset which can lead to refusement of such face by triangulation procedure.
Fix compilation error on VS2008
This commit is contained in:
oan 2018-11-02 16:50:47 +03:00 committed by apn
parent 9d083161b6
commit dc57476a0e
4 changed files with 167 additions and 11 deletions

View File

@ -17,11 +17,12 @@
#include <GCPnts_TangentialDeflection.hxx>
//=======================================================================
// Function: GenerateSurfaceNodes
// Function: GetSplitSteps
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& theParameters) const
std::pair<Standard_Real, Standard_Real> BRepMesh_ConeRangeSplitter::GetSplitSteps(
const IMeshTools_Parameters& theParameters,
std::pair<Standard_Integer, Standard_Integer>& theStepsNb) const
{
const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& 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<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
std::pair<Standard_Integer, Standard_Integer> aStepsNb;
std::pair<Standard_Real, Standard_Real> 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));
}

View File

@ -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<Standard_Real, Standard_Real> GetSplitSteps(
const IMeshTools_Parameters& theParameters,
std::pair<Standard_Integer, Standard_Integer>& 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;

View File

@ -21,6 +21,7 @@
#include <IMeshData_Wire.hxx>
#include <IMeshData_PCurve.hxx>
#include <OSD_Parallel.hxx>
#include <BRepMesh_ConeRangeSplitter.hxx>
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<Standard_Integer, Standard_Integer> aStepsNb;
std::pair<Standard_Real, Standard_Real> 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<gp_XYZ> (theDEdge->GetCurve (), theDU))
{
return Standard_False;
}
for (Standard_Integer aPCurveIdx = 0; aPCurveIdx < theDEdge->PCurvesNb(); ++aPCurveIdx)
{
splitCurve<gp_XY> (theDEdge->GetPCurve (aPCurveIdx), theDU);
}
return Standard_True;
}
//! Splits the given curve using the specified step.
template<class PointType, class Curve>
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));

View File

@ -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 "=========="