mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-04-21 10:13:43 +03:00
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
308 lines
10 KiB
C++
308 lines
10 KiB
C++
// Created on: 2016-07-04
|
|
// Copyright (c) 2016 OPEN CASCADE SAS
|
|
// Created by: Oleg AGASHIN
|
|
//
|
|
// 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 <BRepMesh_ModelPreProcessor.hxx>
|
|
#include <BRepMesh_ShapeTool.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <IMeshData_Model.hxx>
|
|
#include <IMeshData_Edge.hxx>
|
|
#include <IMeshData_Wire.hxx>
|
|
#include <IMeshData_PCurve.hxx>
|
|
#include <OSD_Parallel.hxx>
|
|
#include <BRepMesh_ConeRangeSplitter.hxx>
|
|
|
|
namespace
|
|
{
|
|
//! Checks consistency of triangulation stored in topological face.
|
|
class TriangulationConsistency
|
|
{
|
|
public:
|
|
//! Constructor
|
|
TriangulationConsistency(const Handle(IMeshData_Model)& theModel)
|
|
: myModel (theModel)
|
|
{
|
|
}
|
|
|
|
//! Main functor.
|
|
void operator()(const Standard_Integer theFaceIndex) const
|
|
{
|
|
const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
|
|
if (aDFace->IsSet(IMeshData_Outdated))
|
|
{
|
|
return;
|
|
}
|
|
|
|
TopLoc_Location aLoc;
|
|
const Handle(Poly_Triangulation)& aTriangulation =
|
|
BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
|
|
|
|
if (!aTriangulation.IsNull())
|
|
{
|
|
Standard_Boolean isTriangulationConsistent =
|
|
aTriangulation->Deflection() < 1.1 * aDFace->GetDeflection();
|
|
|
|
if (isTriangulationConsistent)
|
|
{
|
|
// #25080: check that indices of links forming triangles are in range.
|
|
const Standard_Integer aNodesNb = aTriangulation->NbNodes();
|
|
const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles();
|
|
|
|
Standard_Integer i = aTriangles.Lower();
|
|
for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i)
|
|
{
|
|
const Poly_Triangle& aTriangle = aTriangles(i);
|
|
|
|
Standard_Integer aNode[3];
|
|
aTriangle.Get(aNode[0], aNode[1], aNode[2]);
|
|
for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
|
|
{
|
|
isTriangulationConsistent = (aNode[j] >= 1 && aNode[j] <= aNodesNb);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isTriangulationConsistent)
|
|
{
|
|
aDFace->SetStatus(IMeshData_Reused);
|
|
aDFace->SetDeflection(aTriangulation->Deflection());
|
|
}
|
|
else
|
|
{
|
|
aDFace->SetStatus(IMeshData_Outdated);
|
|
}
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
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;
|
|
};
|
|
}
|
|
|
|
//=======================================================================
|
|
// Function: Constructor
|
|
// Purpose :
|
|
//=======================================================================
|
|
BRepMesh_ModelPreProcessor::BRepMesh_ModelPreProcessor()
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
// Function: Destructor
|
|
// Purpose :
|
|
//=======================================================================
|
|
BRepMesh_ModelPreProcessor::~BRepMesh_ModelPreProcessor()
|
|
{
|
|
}
|
|
|
|
//=======================================================================
|
|
// Function: Perform
|
|
// Purpose :
|
|
//=======================================================================
|
|
Standard_Boolean BRepMesh_ModelPreProcessor::Perform(
|
|
const Handle(IMeshData_Model)& theModel,
|
|
const IMeshTools_Parameters& theParameters)
|
|
{
|
|
if (theModel.IsNull())
|
|
{
|
|
return Standard_False;
|
|
}
|
|
|
|
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));
|
|
NCollection_Map<IMeshData_Face*> aUsedFaces(1, aTmpAlloc);
|
|
for (Standard_Integer aEdgeIt = 0; aEdgeIt < theModel->EdgesNb(); ++aEdgeIt)
|
|
{
|
|
const IMeshData::IEdgeHandle& aDEdge = theModel->GetEdge(aEdgeIt);
|
|
if (aDEdge->IsFree())
|
|
{
|
|
if (aDEdge->IsSet(IMeshData_Outdated))
|
|
{
|
|
TopLoc_Location aLoc;
|
|
BRep_Tool::Polygon3D(aDEdge->GetEdge(), aLoc);
|
|
BRepMesh_ShapeTool::NullifyEdge(aDEdge->GetEdge(), aLoc);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt)
|
|
{
|
|
// Find adjacent outdated face.
|
|
const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aPCurveIt)->GetFace();
|
|
if (!aUsedFaces.Contains(aDFace.get()))
|
|
{
|
|
aUsedFaces.Add(aDFace.get());
|
|
if (aDFace->IsSet(IMeshData_Outdated))
|
|
{
|
|
TopLoc_Location aLoc;
|
|
const Handle(Poly_Triangulation)& aTriangulation =
|
|
BRep_Tool::Triangulation(aDFace->GetFace(), aLoc);
|
|
|
|
// Clean all edges of oudated face.
|
|
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
|
|
{
|
|
const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
|
|
for (Standard_Integer aWireEdgeIt = 0; aWireEdgeIt < aDWire->EdgesNb(); ++aWireEdgeIt)
|
|
{
|
|
const IMeshData::IEdgeHandle aTmpDEdge = aDWire->GetEdge(aWireEdgeIt);
|
|
BRepMesh_ShapeTool::NullifyEdge(aTmpDEdge->GetEdge(), aTriangulation, aLoc);
|
|
}
|
|
}
|
|
|
|
BRepMesh_ShapeTool::NullifyFace(aDFace->GetFace());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return Standard_True;
|
|
}
|
|
|