1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-09-08 14:17:06 +03:00

Update BRepMesh component according to OCCT's 7.4.0

Includes #26106 patch
This commit is contained in:
oan
2023-01-16 14:57:12 +03:00
parent 906412a658
commit 6a2c30cdbf
149 changed files with 12531 additions and 7265 deletions

View File

@@ -105,6 +105,7 @@ n BRepIntCurveSurface
n BRepLib
n BRepMAT2d
n BRepMesh
n BRepMeshData
n BRepOffset
n BRepOffsetAPI
n BRepPrim
@@ -141,6 +142,8 @@ n HLRTopoBRep
n HLRAppli
n Hatch
n HatchGen
n IMeshData
n IMeshTools
n IntCurve
n IntCurveSurface
n IntCurvesFace

View File

@@ -296,13 +296,13 @@ Standard_Boolean AIS_RubberBand::fillTriangles()
Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator);
Standard_Integer aPtsLower = myPoints.Lower();
Standard_Integer aPtsUpper = myPoints.Upper();
BRepMesh::Array1OfInteger anIndexes (0, myPoints.Length() - 1);
IMeshData::VectorOfInteger anIndexes (myPoints.Length());
for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx)
{
gp_XY aP ((Standard_Real)myPoints.Value (aPtIdx).x(),
(Standard_Real)myPoints.Value (aPtIdx).y());
BRepMesh_Vertex aVertex (aP, aPtIdx, BRepMesh_Frontier);
anIndexes.ChangeValue (aPtIdx - aPtsLower) = aMeshStructure->AddNode (aVertex);
anIndexes.Append (aMeshStructure->AddNode (aVertex));
}
Standard_Real aPtSum = 0;
@@ -325,7 +325,7 @@ Standard_Boolean AIS_RubberBand::fillTriangles()
}
BRepMesh_Delaun aTriangulation (aMeshStructure, anIndexes);
const BRepMesh::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
const IMeshData::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain();
if (aTriangles.Extent() < 1)
return Standard_False;
@@ -338,7 +338,7 @@ Standard_Boolean AIS_RubberBand::fillTriangles()
}
Standard_Integer aVertexIndex = 1;
BRepMesh::MapOfInteger::Iterator aTriangleIt (aTriangles);
IMeshData::IteratorOfMapOfInteger aTriangleIt (aTriangles);
for (; aTriangleIt.More(); aTriangleIt.Next())
{
const Standard_Integer aTriangleId = aTriangleIt.Key();

View File

@@ -1,147 +0,0 @@
// 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.
#ifndef _BRepMesh_HeaderFile
#define _BRepMesh_HeaderFile
#include <gp_Pnt.hxx>
#include <gp_XYZ.hxx>
#include <gp_XY.hxx>
#include <Bnd_B2d.hxx>
#include <Bnd_Box2d.hxx>
#include <Standard.hxx>
#include <NCollection_List.hxx>
#include <NCollection_Map.hxx>
#include <NCollection_Vector.hxx>
#include <NCollection_Handle.hxx>
#include <NCollection_DataMap.hxx>
#include <NCollection_IndexedMap.hxx>
#include <NCollection_IndexedDataMap.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Sequence.hxx>
#include <NCollection_CellFilter.hxx>
#include <NCollection_IncAllocator.hxx>
#include <NCollection_EBTree.hxx>
#include <NCollection_UBTreeFiller.hxx>
#include <BRepMesh_Edge.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
#include <BRepMesh_PairOfIndex.hxx>
#include <BRepMesh_Circle.hxx>
#include <TopTools_ShapeMapHasher.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <vector>
class BRepMesh_Vertex;
class TopoDS_Edge;
class TopoDS_Vertex;
class BRepMesh_FaceAttribute;
class BRepMesh_VertexInspector;
class BRepMesh_CircleInspector;
class BRepMesh_Classifier;
class Poly_Triangulation;
class BRepMesh_VertexTool;
namespace BRepMesh
{
//! Default size for memory block allocated by IncAllocator.
/**
* The idea here is that blocks of the given size are returned to the system
* rather than retained in the malloc heap, at least on WIN32 and WIN64 platforms.
*/
#ifdef _WIN64
const size_t MEMORY_BLOCK_SIZE_HUGE = 1024 * 1024;
#else
const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024;
#endif
//! Structure keeping parameters of segment.
struct Segment
{
gp_XY StartPnt;
gp_XY EndPnt;
};
//! Sequences
typedef NCollection_Sequence<Bnd_B2d> SequenceOfBndB2d;
typedef NCollection_Sequence<Standard_Integer> SequenceOfInteger;
typedef NCollection_Sequence<Standard_Real> SequenceOfReal;
//! Vectors
typedef NCollection_Vector<BRepMesh_Vertex> VectorOfVertex;
typedef NCollection_Vector<Standard_Integer> VectorOfInteger;
typedef NCollection_Vector<BRepMesh_Circle> VectorOfCircle;
//! Trees
typedef NCollection_EBTree<Standard_Integer, Bnd_Box2d> BndBox2dTree;
typedef NCollection_UBTreeFiller<Standard_Integer, Bnd_Box2d> BndBox2dTreeFiller;
//! Arrays
typedef NCollection_Array1<BRepMesh_Vertex> Array1OfVertexOfDelaun;
typedef NCollection_Array1<Standard_Integer> Array1OfInteger;
typedef NCollection_Array1<Standard_Real> Array1OfReal;
typedef NCollection_Array1<Segment> Array1OfSegments;
//! Lists
typedef NCollection_List<gp_XY> ListOfXY;
typedef NCollection_List<BRepMesh_Vertex> ListOfVertex;
typedef NCollection_List<Standard_Integer> ListOfInteger;
//! Maps
typedef NCollection_Map<Standard_Real> MapOfReal;
typedef NCollection_Map<Standard_Integer> MapOfInteger;
typedef NCollection_DataMap<Handle(Poly_Triangulation), Standard_Boolean> DMapOfTriangulationBool;
typedef NCollection_Map<TopoDS_Shape, TopTools_ShapeMapHasher> MapOfShape;
typedef NCollection_DataMap<Standard_Integer, Standard_Integer> MapOfIntegerInteger;
typedef NCollection_DataMap<TopoDS_Vertex, Standard_Integer, TopTools_ShapeMapHasher> DMapOfVertexInteger;
typedef NCollection_DataMap<TopoDS_Face, Handle(BRepMesh_FaceAttribute), TopTools_ShapeMapHasher> DMapOfFaceAttribute;
typedef NCollection_DataMap<TopoDS_Shape, BRepMesh_PairOfPolygon, TopTools_ShapeMapHasher> DMapOfShapePairOfPolygon;
typedef NCollection_DataMap<Standard_Integer, gp_Pnt> DMapOfIntegerPnt;
typedef NCollection_DataMap<Standard_Integer, ListOfXY> DMapOfIntegerListOfXY;
typedef NCollection_DataMap<Standard_Integer, ListOfInteger> DMapOfIntegerListOfInteger;
typedef NCollection_DataMap<TopoDS_Edge, DMapOfTriangulationBool, TopTools_ShapeMapHasher> DMapOfEdgeListOfTriangulationBool;
typedef NCollection_IndexedMap<Standard_Integer> IMapOfInteger;
typedef NCollection_IndexedMap<Standard_Real> IMapOfReal;
typedef NCollection_IndexedMap<BRepMesh_Triangle> IMapOfElement;
typedef NCollection_IndexedDataMap<BRepMesh_Edge, BRepMesh_PairOfIndex> IDMapOfLink;
//! CellFilters
typedef NCollection_CellFilter<BRepMesh_CircleInspector> CircleCellFilter;
typedef NCollection_CellFilter<BRepMesh_VertexInspector> VertexCellFilter;
//! Handles
typedef NCollection_Handle<VectorOfVertex> HVectorOfVertex;
typedef NCollection_Handle<MapOfInteger> HMapOfInteger;
typedef NCollection_Handle<IMapOfInteger> HIMapOfInteger;
typedef NCollection_Handle<DMapOfShapePairOfPolygon> HDMapOfShapePairOfPolygon;
typedef NCollection_Handle<DMapOfIntegerPnt> HDMapOfIntegerPnt;
typedef NCollection_Handle<BRepMesh_Classifier> HClassifier;
typedef NCollection_Handle<BndBox2dTree> HBndBox2dTree;
typedef NCollection_Handle<Array1OfSegments> HArray1OfSegments;
typedef NCollection_Handle<DMapOfVertexInteger> HDMapOfVertexInteger;
typedef NCollection_Handle<DMapOfIntegerListOfXY> HDMapOfIntegerListOfXY;
typedef NCollection_Handle<BRepMesh_VertexTool> HVertexTool;
typedef NCollection_Handle<SequenceOfBndB2d> HSequenceOfBndB2d;
typedef NCollection_Handle<SequenceOfInteger> HSequenceOfInteger;
//! Other data structures
typedef std::pair<HArray1OfSegments, HBndBox2dTree> SegmentsTree;
typedef NCollection_Array1<SegmentsTree> Array1OfSegmentsTree;
} // namespace BRepMesh
#endif

View File

@@ -0,0 +1,316 @@
// Created on: 2016-04-19
// 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_BaseMeshAlgo.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <IMeshData_Curve.hxx>
#include <BRepMesh_Delaun.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <Standard_ErrorHandler.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_BaseMeshAlgo::BRepMesh_BaseMeshAlgo()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_BaseMeshAlgo::~BRepMesh_BaseMeshAlgo()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
void BRepMesh_BaseMeshAlgo::Perform(
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters)
{
try
{
OCC_CATCH_SIGNALS
myDFace = theDFace;
myParameters = theParameters;
myAllocator = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator);
myNodesMap = new VectorOfPnt(256, myAllocator);
myUsedNodes = new DMapOfIntegerInteger(1, myAllocator);
if (initDataStructure())
{
generateMesh();
commitSurfaceTriangulation();
}
}
catch (Standard_Failure const& /*theExeption*/)
{
}
myDFace.Nullify(); // Do not hold link to face.
myStructure.Nullify();
myNodesMap .Nullify();
myUsedNodes.Nullify();
myAllocator.Nullify();
}
//=======================================================================
//function : initDataStructure
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_BaseMeshAlgo::initDataStructure()
{
for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
{
const IMeshData::IWireHandle& aDWire = myDFace->GetWire(aWireIt);
if (aDWire->IsSet(IMeshData_SelfIntersectingWire))
{
// TODO: here we can add points of self-intersecting wire as fixed points
// in order to keep consistency of nodes with adjacent faces.
continue;
}
for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
{
const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt);
const IMeshData::ICurveHandle& aCurve = aDEdge->GetCurve();
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
const TopAbs_Orientation aOri = fixSeamEdgeOrientation(aDEdge, aPCurve);
Standard_Integer aPrevNodeIndex = -1;
const Standard_Integer aLastPoint = aPCurve->ParametersNb() - 1;
for (Standard_Integer aPointIt = 0; aPointIt <= aLastPoint; ++aPointIt)
{
const Standard_Integer aNodeIndex = registerNode(
aCurve ->GetPoint(aPointIt),
aPCurve->GetPoint(aPointIt),
BRepMesh_Frontier, Standard_False/*aPointIt > 0 && aPointIt < aLastPoint*/);
aPCurve->GetIndex(aPointIt) = aNodeIndex;
myUsedNodes->Bind(aNodeIndex, aNodeIndex);
if (aPrevNodeIndex != -1 && aPrevNodeIndex != aNodeIndex)
{
const Standard_Integer aLinksNb = myStructure->NbLinks();
const Standard_Integer aLinkIndex = addLinkToMesh(aPrevNodeIndex, aNodeIndex, aOri);
if (aWireIt != 0 && aLinkIndex <= aLinksNb)
{
// Prevent holes around wire of zero area.
BRepMesh_Edge& aLink = const_cast<BRepMesh_Edge&>(myStructure->GetLink(aLinkIndex));
aLink.SetMovability(BRepMesh_Fixed);
}
}
aPrevNodeIndex = aNodeIndex;
}
}
}
return Standard_True;
}
//=======================================================================
// Function: registerNode
// Purpose :
//=======================================================================
Standard_Integer BRepMesh_BaseMeshAlgo::registerNode(
const gp_Pnt& thePoint,
const gp_Pnt2d& thePoint2d,
const BRepMesh_DegreeOfFreedom theMovability,
const Standard_Boolean isForceAdd)
{
const Standard_Integer aNodeIndex = addNodeToStructure(
thePoint2d, myNodesMap->Size(), theMovability, isForceAdd);
if (aNodeIndex > myNodesMap->Size())
{
myNodesMap->Append(thePoint);
}
return aNodeIndex;
}
//=======================================================================
// Function: addNode
// Purpose :
//=======================================================================
Standard_Integer BRepMesh_BaseMeshAlgo::addNodeToStructure(
const gp_Pnt2d& thePoint,
const Standard_Integer theLocation3d,
const BRepMesh_DegreeOfFreedom theMovability,
const Standard_Boolean isForceAdd)
{
BRepMesh_Vertex aNode(thePoint.XY(), theLocation3d, theMovability);
return myStructure->AddNode(aNode, isForceAdd);
}
//=======================================================================
//function : addLinkToMesh
//purpose :
//=======================================================================
Standard_Integer BRepMesh_BaseMeshAlgo::addLinkToMesh(
const Standard_Integer theFirstNodeId,
const Standard_Integer theLastNodeId,
const TopAbs_Orientation theOrientation)
{
Standard_Integer aLinkIndex;
if (theOrientation == TopAbs_REVERSED)
aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier));
else if (theOrientation == TopAbs_INTERNAL)
aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed));
else
aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier));
return Abs(aLinkIndex);
}
//=======================================================================
//function : fixSeamEdgeOrientation
//purpose :
//=======================================================================
TopAbs_Orientation BRepMesh_BaseMeshAlgo::fixSeamEdgeOrientation(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IPCurveHandle& thePCurve) const
{
for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
{
const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
if (aPCurve->GetFace() == myDFace && thePCurve != aPCurve)
{
// Simple check that another pcurve of seam edge does not coincide with reference one.
const gp_Pnt2d& aPnt1_1 = thePCurve->GetPoint(0);
const gp_Pnt2d& aPnt2_1 = thePCurve->GetPoint(thePCurve->ParametersNb() - 1);
const gp_Pnt2d& aPnt1_2 = aPCurve->GetPoint(0);
const gp_Pnt2d& aPnt2_2 = aPCurve->GetPoint(aPCurve->ParametersNb() - 1);
const Standard_Real aSqDist1 = Min(aPnt1_1.SquareDistance(aPnt1_2), aPnt1_1.SquareDistance(aPnt2_2));
const Standard_Real aSqDist2 = Min(aPnt2_1.SquareDistance(aPnt1_2), aPnt2_1.SquareDistance(aPnt2_2));
if (aSqDist1 < Precision::SquareConfusion() &&
aSqDist2 < Precision::SquareConfusion())
{
return TopAbs_INTERNAL;
}
}
}
return thePCurve->GetOrientation();
}
//=======================================================================
//function : commitSurfaceTriangulation
//purpose :
//=======================================================================
void BRepMesh_BaseMeshAlgo::commitSurfaceTriangulation()
{
Handle(Poly_Triangulation) aTriangulation = collectTriangles();
if (aTriangulation.IsNull())
{
myDFace->SetStatus(IMeshData_Failure);
return;
}
collectNodes(aTriangulation);
aTriangulation->Deflection(myDFace->GetDeflection());
BRepMesh_ShapeTool::AddInFace(myDFace->GetFace(), aTriangulation);
}
//=======================================================================
//function : collectTriangles
//purpose :
//=======================================================================
Handle(Poly_Triangulation) BRepMesh_BaseMeshAlgo::collectTriangles()
{
const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
if (aTriangles.IsEmpty())
{
return Handle(Poly_Triangulation)();
}
Poly_Array1OfTriangle aPolyTrianges(1, aTriangles.Extent());
IMeshData::IteratorOfMapOfInteger aTriIt(aTriangles);
for (Standard_Integer aTriangeId = 1; aTriIt.More(); aTriIt.Next(), ++aTriangeId)
{
const BRepMesh_Triangle& aCurElem = myStructure->GetElement(aTriIt.Key());
Standard_Integer aNode[3];
myStructure->ElementNodes(aCurElem, aNode);
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!myUsedNodes->IsBound(aNode[i]))
{
myUsedNodes->Bind(aNode[i], myUsedNodes->Size() + 1);
}
aNode[i] = myUsedNodes->Find(aNode[i]);
}
aPolyTrianges(aTriangeId).Set(aNode[0], aNode[1], aNode[2]);
}
Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation(
myUsedNodes->Extent(), aTriangles.Extent(), Standard_True);
aTriangulation->ChangeTriangles() = aPolyTrianges;
return aTriangulation;
}
//=======================================================================
//function : collectNodes
//purpose :
//=======================================================================
void BRepMesh_BaseMeshAlgo::collectNodes(
const Handle(Poly_Triangulation)& theTriangulation)
{
// Store mesh nodes
TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes();
TColgp_Array1OfPnt2d& aNodes2d = theTriangulation->ChangeUVNodes();
for (Standard_Integer i = 1; i <= myNodesMap->Size(); ++i)
{
if (myUsedNodes->IsBound(i))
{
const BRepMesh_Vertex& aVertex = myStructure->GetNode(i);
const Standard_Integer aNodeIndex = myUsedNodes->Find(i);
aNodes(aNodeIndex) = myNodesMap->Value(aVertex.Location3d());
aNodes2d(aNodeIndex) = getNodePoint2d(aVertex);
}
}
}
//=======================================================================
// Function: getNodePoint2d
// Purpose :
//=======================================================================
gp_Pnt2d BRepMesh_BaseMeshAlgo::getNodePoint2d(
const BRepMesh_Vertex& theVertex) const
{
return theVertex.Coord();
}

View File

@@ -0,0 +1,143 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_BaseMeshAlgo_HeaderFile
#define _BRepMesh_BaseMeshAlgo_HeaderFile
#include <IMeshTools_MeshAlgo.hxx>
#include <NCollection_Shared.hxx>
#include <IMeshTools_Parameters.hxx>
#include <BRepMesh_DegreeOfFreedom.hxx>
#include <Poly_Triangulation.hxx>
class BRepMesh_DataStructureOfDelaun;
class BRepMesh_Delaun;
//! Class provides base fuctionality for algorithms building face triangulation.
//! Performs initialization of BRepMesh_DataStructureOfDelaun and nodes map structures.
class BRepMesh_BaseMeshAlgo : public IMeshTools_MeshAlgo
{
public:
typedef NCollection_Shared<NCollection_Vector<gp_Pnt> > VectorOfPnt;
//! Constructor.
Standard_EXPORT BRepMesh_BaseMeshAlgo();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_BaseMeshAlgo();
//! Performs processing of the given face.
Standard_EXPORT virtual void Perform(
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_BaseMeshAlgo, IMeshTools_MeshAlgo)
protected:
//! Gets discrete face.
inline const IMeshData::IFaceHandle& getDFace() const
{
return myDFace;
}
//! Gets meshing parameters.
inline const IMeshTools_Parameters& getParameters() const
{
return myParameters;
}
//! Gets common allocator.
inline const Handle(NCollection_IncAllocator)& getAllocator() const
{
return myAllocator;
}
//! Gets mesh structure.
inline const Handle(BRepMesh_DataStructureOfDelaun)& getStructure() const
{
return myStructure;
}
//! Gets 3d nodes map.
inline const Handle(VectorOfPnt)& getNodesMap() const
{
return myNodesMap;
}
protected:
//! Registers the given point in vertex map and adds 2d point to mesh data structure.
//! Returns index of node in the structure.
Standard_EXPORT virtual Standard_Integer registerNode(
const gp_Pnt& thePoint,
const gp_Pnt2d& thePoint2d,
const BRepMesh_DegreeOfFreedom theMovability,
const Standard_Boolean isForceAdd);
//! Adds the given 2d point to mesh data structure.
//! Returns index of node in the structure.
Standard_EXPORT virtual Standard_Integer addNodeToStructure(
const gp_Pnt2d& thePoint,
const Standard_Integer theLocation3d,
const BRepMesh_DegreeOfFreedom theMovability,
const Standard_Boolean isForceAdd);
//! Returns 2d point associated to the given vertex.
Standard_EXPORT virtual gp_Pnt2d getNodePoint2d(const BRepMesh_Vertex& theVertex) const;
//! Performs initialization of data structure using existing model data.
Standard_EXPORT virtual Standard_Boolean initDataStructure();
//! Generates mesh for the contour stored in data structure.
Standard_EXPORT virtual void generateMesh() = 0;
private:
//! If the given edge has another pcurve for current face coinsiding with specified one,
//! returns TopAbs_INTERNAL flag. Elsewhere returns orientation of specified pcurve.
TopAbs_Orientation fixSeamEdgeOrientation(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IPCurveHandle& thePCurve) const;
//! Adds new link to the mesh data structure.
//! Movability of the link and order of nodes depend on orientation parameter.
Standard_Integer addLinkToMesh(
const Standard_Integer theFirstNodeId,
const Standard_Integer theLastNodeId,
const TopAbs_Orientation theOrientation);
//! Commits generated triangulation to TopoDS face.
void commitSurfaceTriangulation();
//! Collects triangles to output data.
Handle(Poly_Triangulation) collectTriangles();
//! Collects nodes to output data.
void collectNodes(const Handle(Poly_Triangulation)& theTriangulation);
private:
typedef NCollection_Shared<NCollection_DataMap<Standard_Integer, Standard_Integer> > DMapOfIntegerInteger;
IMeshData::IFaceHandle myDFace;
IMeshTools_Parameters myParameters;
Handle(NCollection_IncAllocator) myAllocator;
Handle(BRepMesh_DataStructureOfDelaun) myStructure;
Handle(VectorOfPnt) myNodesMap;
Handle(DMapOfIntegerInteger) myUsedNodes;
};
#endif

View File

@@ -0,0 +1,54 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile
#define _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile
#include <BRepMesh_NURBSRangeSplitter.hxx>
//! Auxiliary class extending UV range splitter in order to generate
//! internal nodes for NURBS surface.
class BRepMesh_BoundaryParamsRangeSplitter : public BRepMesh_NURBSRangeSplitter
{
public:
//! Constructor.
BRepMesh_BoundaryParamsRangeSplitter()
{
}
//! Destructor.
virtual ~BRepMesh_BoundaryParamsRangeSplitter()
{
}
//! Registers border point.
virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE
{
BRepMesh_NURBSRangeSplitter::AddPoint(thePoint);
GetParametersU().Add(thePoint.X());
GetParametersV().Add(thePoint.Y());
}
protected:
//! Initializes U and V parameters lists using CN continuity intervals.
virtual Standard_Boolean initParameters() const Standard_OVERRIDE
{
return Standard_True;
}
};
#endif

View File

@@ -16,7 +16,7 @@
#ifndef BRepMesh_CircleInspector_Header
#define BRepMesh_CircleInspector_Header
#include <BRepMesh.hxx>
#include <IMeshData_Types.hxx>
#include <BRepMesh_Circle.hxx>
#include <Precision.hxx>
#include <gp_XY.hxx>
@@ -37,9 +37,9 @@ public:
const Standard_Real theTolerance,
const Standard_Integer theReservedSize,
const Handle(NCollection_IncAllocator)& theAllocator)
: myTolerance(theTolerance*theTolerance),
: mySqTolerance(theTolerance*theTolerance),
myResIndices(theAllocator),
myCircles(theReservedSize)
myCircles(theReservedSize, theAllocator)
{
}
@@ -53,7 +53,7 @@ public:
}
//! Resutns vector of registered circles.
inline const BRepMesh::VectorOfCircle& Circles() const
inline const IMeshData::VectorOfCircle& Circles() const
{
return myCircles;
}
@@ -75,7 +75,7 @@ public:
}
//! Returns list of circles shot by the reference point.
inline BRepMesh::ListOfInteger& GetShotCircles()
inline IMeshData::ListOfInteger& GetShotCircles()
{
return myResIndices;
}
@@ -83,8 +83,41 @@ public:
//! Performs inspection of a circle with the given index.
//! @param theTargetIndex index of a circle to be checked.
//! @return status of the check.
Standard_EXPORT NCollection_CellFilter_Action Inspect(
const Standard_Integer theTargetIndex);
inline NCollection_CellFilter_Action Inspect(
const Standard_Integer theTargetIndex)
{
BRepMesh_Circle& aCircle = myCircles(theTargetIndex);
const Standard_Real& aRadius = aCircle.Radius();
if (aRadius < 0.)
return CellFilter_Purge;
gp_XY& aLoc = const_cast<gp_XY&>(aCircle.Location());
const Standard_Real aDX = myPoint.ChangeCoord(1) - aLoc.ChangeCoord(1);
const Standard_Real aDY = myPoint.ChangeCoord(2) - aLoc.ChangeCoord(2);
//This check is wrong. It is better to use
//
// const Standard_Real aR = aRadius + aToler;
// if ((aDX * aDX + aDY * aDY) <= aR * aR)
// {
// ...
// }
//where aToler = sqrt(mySqTolerance). Taking into account the fact
//that the input parameter of the class (see constructor) is linear
//(not quadratic) tolerance there is no point in square root computation.
//Simply, we do not need to compute square of the input tolerance and to
//assign it to mySqTolerance. The input linear tolerance is needed to be used.
//However, this change leads to hangs the test case "perf mesh bug27119".
//So, this correction is better to be implemented in the future.
if ((aDX * aDX + aDY * aDY) - (aRadius * aRadius) <= mySqTolerance)
myResIndices.Append(theTargetIndex);
return CellFilter_Keep;
}
//! Checks indices for equlity.
static Standard_Boolean IsEqual(
@@ -95,9 +128,9 @@ public:
}
private:
Standard_Real myTolerance;
BRepMesh::ListOfInteger myResIndices;
BRepMesh::VectorOfCircle myCircles;
Standard_Real mySqTolerance;
IMeshData::ListOfInteger myResIndices;
IMeshData::VectorOfCircle myCircles;
gp_XY myPoint;
};

View File

@@ -21,34 +21,13 @@
#include <BRepMesh_Circle.hxx>
#include <BRepMesh_CircleInspector.hxx>
//=======================================================================
//function : Inspect
//purpose :
//=======================================================================
NCollection_CellFilter_Action BRepMesh_CircleInspector::Inspect(
const Standard_Integer theTargetIndex)
{
const BRepMesh_Circle& aCircle = myCircles(theTargetIndex);
Standard_Real aRadius = aCircle.Radius();
if(aRadius < 0.)
return CellFilter_Purge;
const gp_XY& aLoc = aCircle.Location();
if ((myPoint - aLoc).SquareModulus() - (aRadius * aRadius) <= myTolerance)
myResIndices.Append(theTargetIndex);
return CellFilter_Keep;
}
//=======================================================================
//function : BRepMesh_CircleTool
//purpose :
//=======================================================================
BRepMesh_CircleTool::BRepMesh_CircleTool(
const Handle(NCollection_IncAllocator)& theAllocator)
: myTolerance (Precision::PConfusion() * Precision::PConfusion()),
: myTolerance (Precision::PConfusion()),
myAllocator (theAllocator),
myCellFilter(10.0, theAllocator),
mySelector (myTolerance, 64, theAllocator)
@@ -62,7 +41,7 @@ BRepMesh_CircleTool::BRepMesh_CircleTool(
BRepMesh_CircleTool::BRepMesh_CircleTool(
const Standard_Integer theReservedSize,
const Handle(NCollection_IncAllocator)& theAllocator)
: myTolerance (Precision::PConfusion() * Precision::PConfusion()),
: myTolerance (Precision::PConfusion()),
myAllocator (theAllocator),
myCellFilter(10.0, theAllocator),
mySelector (myTolerance, Max(theReservedSize, 64), theAllocator)
@@ -117,42 +96,43 @@ Standard_Boolean BRepMesh_CircleTool::MakeCircle(const gp_XY& thePoint1,
static const Standard_Real aPrecision = Precision::PConfusion();
static const Standard_Real aSqPrecision = aPrecision * aPrecision;
if ((thePoint1 - thePoint3).SquareModulus() < aSqPrecision)
return Standard_False;
gp_XY aLink1(thePoint2 - thePoint1);
gp_XY aLink1(const_cast<gp_XY&>(thePoint3).ChangeCoord(1) - const_cast<gp_XY&>(thePoint2).ChangeCoord(1),
const_cast<gp_XY&>(thePoint2).ChangeCoord(2) - const_cast<gp_XY&>(thePoint3).ChangeCoord(2));
if (aLink1.SquareModulus() < aSqPrecision)
return Standard_False;
gp_XY aLink2(thePoint3 - thePoint2);
gp_XY aLink2(const_cast<gp_XY&>(thePoint1).ChangeCoord(1) - const_cast<gp_XY&>(thePoint3).ChangeCoord(1),
const_cast<gp_XY&>(thePoint3).ChangeCoord(2) - const_cast<gp_XY&>(thePoint1).ChangeCoord(2));
if (aLink2.SquareModulus() < aSqPrecision)
return Standard_False;
gp_XY aMidPnt1 = (thePoint1 + thePoint2) / 2.;
gp_XY aNorm1 = gp_XY(aLink1.Y(), -aLink1.X());
aNorm1.Add(aMidPnt1);
if (aLink2.SquareModulus() < aSqPrecision)
gp_XY aLink3(const_cast<gp_XY&>(thePoint2).ChangeCoord(1) - const_cast<gp_XY&>(thePoint1).ChangeCoord(1),
const_cast<gp_XY&>(thePoint1).ChangeCoord(2) - const_cast<gp_XY&>(thePoint2).ChangeCoord(2));
if (aLink3.SquareModulus() < aSqPrecision)
return Standard_False;
gp_XY aMidPnt2 = (thePoint2 + thePoint3) / 2.;
gp_XY aNorm2 = gp_XY(aLink2.Y(), -aLink2.X());
aNorm2.Add(aMidPnt2);
const Standard_Real aD = 2 * (const_cast<gp_XY&>(thePoint1).ChangeCoord(1) * aLink1.Y() +
const_cast<gp_XY&>(thePoint2).ChangeCoord(1) * aLink2.Y() +
const_cast<gp_XY&>(thePoint3).ChangeCoord(1) * aLink3.Y());
gp_XY aIntPnt;
Standard_Real aParam[2];
BRepMesh_GeomTool::IntFlag aIntFlag =
BRepMesh_GeomTool::IntLinLin(aMidPnt1, aNorm1,
aMidPnt2, aNorm2, aIntPnt, aParam);
if (aIntFlag != BRepMesh_GeomTool::Cross)
if (Abs(aD) < gp::Resolution())
return Standard_False;
theLocation = aIntPnt;
const Standard_Real aInvD = 1. / aD;
const Standard_Real aSqMod1 = thePoint1.SquareModulus();
const Standard_Real aSqMod2 = thePoint2.SquareModulus();
const Standard_Real aSqMod3 = thePoint3.SquareModulus();
theLocation.ChangeCoord(1) = (aSqMod1 * aLink1.Y() +
aSqMod2 * aLink2.Y() +
aSqMod3 * aLink3.Y()) * aInvD;
theRadius = Sqrt(Max(Max((thePoint1 - aIntPnt).SquareModulus(),
(thePoint2 - aIntPnt).SquareModulus()),
(thePoint3 - aIntPnt).SquareModulus())) + 2 * RealEpsilon();
theLocation.ChangeCoord(2) = (aSqMod1 * aLink1.X() +
aSqMod2 * aLink2.X() +
aSqMod3 * aLink3.X()) * aInvD;
theRadius = Sqrt(Max(Max((thePoint1 - theLocation).SquareModulus(),
(thePoint2 - theLocation).SquareModulus()),
(thePoint3 - theLocation).SquareModulus())) + 2 * RealEpsilon();
return Standard_True;
}
@@ -190,7 +170,7 @@ void BRepMesh_CircleTool::Delete(const Standard_Integer theIndex)
//function : Select
//purpose :
//=======================================================================
BRepMesh::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
IMeshData::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint)
{
mySelector.SetPoint(thePoint);
myCellFilter.Inspect(thePoint, mySelector);

View File

@@ -24,7 +24,7 @@
#include <gp_XYZ.hxx>
#include <Standard_Integer.hxx>
#include <Standard_Boolean.hxx>
#include <BRepMesh.hxx>
#include <IMeshData_Types.hxx>
#include <NCollection_Array1.hxx>
class gp_Circ2d;
@@ -52,7 +52,7 @@ public:
//! @param theReservedSize size to be reserved for vector of circles.
inline void Init(const Standard_Integer /*theReservedSize*/)
{
myTolerance = Precision::PConfusion() * Precision::PConfusion();
myTolerance = Precision::PConfusion();
}
//! Sets new size for cell filter.
@@ -83,6 +83,12 @@ public:
myFaceMax = theMax;
}
//! Retruns true if cell filter contains no circle.
inline Standard_Boolean IsEmpty () const
{
return mySelector.Circles ().IsEmpty ();
}
//! Binds the circle to the tool.
//! @param theIndex index a circle should be bound with.
//! @param theCircle circle to be bound.
@@ -125,7 +131,7 @@ public:
//! Select the circles shot by the given point.
//! @param thePoint bullet point.
Standard_EXPORT BRepMesh::ListOfInteger& Select(const gp_XY& thePoint);
Standard_EXPORT IMeshData::ListOfInteger& Select(const gp_XY& thePoint);
private:
@@ -141,7 +147,7 @@ private:
Standard_Real myTolerance;
Handle(NCollection_IncAllocator) myAllocator;
BRepMesh::CircleCellFilter myCellFilter;
IMeshData::CircleCellFilter myCellFilter;
BRepMesh_CircleInspector mySelector;
gp_XY myFaceMax;
gp_XY myFaceMin;

View File

@@ -1,7 +1,6 @@
// Created on: 1997-06-26
// Created by: Laurent PAINNOT
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
// Created on: 2016-07-07
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
@@ -29,6 +28,14 @@ BRepMesh_Classifier::BRepMesh_Classifier()
{
}
//=======================================================================
//function : Destructor
//purpose :
//=======================================================================
BRepMesh_Classifier::~BRepMesh_Classifier()
{
}
//=======================================================================
//function : Perform
//purpose :
@@ -38,20 +45,24 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const
Standard_Boolean isOut = Standard_False;
Standard_Integer aNb = myTabClass.Length();
for (Standard_Integer i = 1; i <= aNb; i++)
for (Standard_Integer i = 0; i < aNb; i++)
{
Standard_Integer aCur = ((CSLib_Class2d*)myTabClass(i))->SiDans(thePoint);
const Standard_Integer aCur = myTabClass(i)->SiDans(thePoint);
if (aCur == 0)
{
// Point is ON, but mark it as OUT
isOut = Standard_True;
}
else
{
isOut = myTabOrient(i) ? (aCur == -1) : (aCur == 1);
}
if (isOut)
{
return TopAbs_OUT;
}
}
return TopAbs_IN;
}
@@ -61,23 +72,23 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const
//purpose :
//=======================================================================
void BRepMesh_Classifier::RegisterWire(
const NCollection_Sequence<gp_Pnt2d>& theWire,
const Standard_Real theTolUV,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax)
const NCollection_Sequence<const gp_Pnt2d*>& theWire,
const std::pair<Standard_Real, Standard_Real>& theTolUV,
const std::pair<Standard_Real, Standard_Real>& theRangeU,
const std::pair<Standard_Real, Standard_Real>& theRangeV)
{
const Standard_Integer aNbPnts = theWire.Length();
if (aNbPnts < 2)
{
return;
}
// Accumulate angle
TColgp_Array1OfPnt2d aPClass(1, aNbPnts);
Standard_Real anAngle = 0.0;
gp_Pnt2d p1 = theWire(1), p2 = theWire(2), p3;
aPClass(1) = p1;
aPClass(2) = p2;
const gp_Pnt2d *p1 = theWire(1), *p2 = theWire(2), *p3;
aPClass(1) = *p1;
aPClass(2) = *p2;
const Standard_Real aAngTol = Precision::Angular();
const Standard_Real aSqConfusion =
@@ -88,15 +99,15 @@ void BRepMesh_Classifier::RegisterWire(
Standard_Integer ii = i + 2;
if (ii > aNbPnts)
{
p3 = aPClass(ii - aNbPnts);
p3 = &aPClass(ii - aNbPnts);
}
else
{
p3 = theWire.Value(ii);
aPClass(ii) = p3;
aPClass(ii) = *p3;
}
gp_Vec2d A(p1,p2), B(p2,p3);
const gp_Vec2d A(*p1,*p2), B(*p2,*p3);
if (A.SquareMagnitude() > aSqConfusion &&
B.SquareMagnitude() > aSqConfusion)
{
@@ -115,27 +126,10 @@ void BRepMesh_Classifier::RegisterWire(
if (Abs(anAngle) < aAngTol)
anAngle = 0.0;
myTabClass.Append( (void *)new CSLib_Class2d(aPClass,
theTolUV, theTolUV, theUmin, theVmin, theUmax, theVmax) );
myTabClass.Append(new CSLib_Class2d(
aPClass, theTolUV.first, theTolUV.second,
theRangeU.first, theRangeV.first,
theRangeU.second, theRangeV.second));
myTabOrient.Append( !(anAngle < 0.0) );
}
//=======================================================================
//function : Destroy
//purpose :
//=======================================================================
void BRepMesh_Classifier::Destroy()
{
Standard_Integer aNb = myTabClass.Length();
for (Standard_Integer i = 1; i <= aNb; i++)
{
if (myTabClass(i))
{
delete ((CSLib_Class2d*)myTabClass(i));
myTabClass(i) = NULL;
}
}
myTabClass.Clear();
myTabOrient.Clear();
}

View File

@@ -1,7 +1,6 @@
// Created on: 2014-06-03
// Created on: 2016-07-07
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
// Copyright (c) 1997-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -18,38 +17,31 @@
#define _BRepMesh_Classifier_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <BRepTopAdaptor_SeqOfPtr.hxx>
#include <TColStd_SequenceOfBoolean.hxx>
#include <TopAbs_State.hxx>
#include <NCollection_Sequence.hxx>
#include <gp_Pnt2d.hxx>
#include <IMeshData_Types.hxx>
#include <NCollection_Handle.hxx>
//! Auxilary class contains information about correctness of discretized
//! face and used for classification of points regarding face internals.
class BRepMesh_Classifier
#include <memory>
class gp_Pnt2d;
class CSLib_Class2d;
//! Auxilary class intended for classification of points
//! regarding internals of discrete face.
class BRepMesh_Classifier : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
Standard_EXPORT BRepMesh_Classifier();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_Classifier()
{
Destroy();
}
//! Method is called on destruction.
//! Clears internal data structures.
Standard_EXPORT void Destroy();
Standard_EXPORT virtual ~BRepMesh_Classifier();
//! Performs classification of the given point regarding to face internals.
//! @param thePoint Point in parametric space to be classified.
//! @return
//! @return TopAbs_IN if point lies within face boundaries and TopAbs_OUT elsewhere.
Standard_EXPORT TopAbs_State Perform(const gp_Pnt2d& thePoint) const;
//! Registers wire specified by sequence of points for
@@ -61,17 +53,17 @@ public:
//! @param theVmin Lower V boundary of the face in parametric space.
//! @param theVmax Upper V boundary of the face in parametric space.
Standard_EXPORT void RegisterWire(
const NCollection_Sequence<gp_Pnt2d>& theWire,
const Standard_Real theTolUV,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax);
const NCollection_Sequence<const gp_Pnt2d*>& theWire,
const std::pair<Standard_Real, Standard_Real>& theTolUV,
const std::pair<Standard_Real, Standard_Real>& theRangeU,
const std::pair<Standard_Real, Standard_Real>& theRangeV);
DEFINE_STANDARD_RTTI_INLINE (BRepMesh_Classifier, Standard_Transient)
private:
BRepTopAdaptor_SeqOfPtr myTabClass;
TColStd_SequenceOfBoolean myTabOrient;
NCollection_Vector<NCollection_Handle<CSLib_Class2d> > myTabClass;
IMeshData::VectorOfBoolean myTabOrient;
};
#endif

View File

@@ -0,0 +1,80 @@
// Created on: 2016-07-07
// 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_ConeRangeSplitter.hxx>
#include <GCPnts_TangentialDeflection.hxx>
//=======================================================================
// Function: GetSplitSteps
// Purpose :
//=======================================================================
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();
gp_Cone aCone = GetDFace()->GetSurface()->Cone();
Standard_Real aRefR = aCone.RefRadius();
Standard_Real aSAng = aCone.SemiAngle();
Standard_Real aRadius = Max(Abs(aRefR + aRangeV.first * Sin(aSAng)),
Abs(aRefR + aRangeV.second * Sin(aSAng)));
Standard_Real Dv, Du = GCPnts_TangentialDeflection::ArcAngularStep(
aRadius, GetDFace()->GetDeflection(),
theParameters.Angle, theParameters.MinSize);
const Standard_Real aDiffU = aRangeU.second - aRangeU.first;
const Standard_Real aDiffV = aRangeV.second - aRangeV.first;
Standard_Integer nbU = (Standard_Integer) (aDiffU / Du);
Standard_Integer nbV = (Standard_Integer) (nbU * (aDiffV) / (aDiffU * aRadius));
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 - 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 + aSteps.first; aPasU < aPasMaxU; aPasU += aSteps.first)
{
aNodes->Append(gp_Pnt2d(aPasU, aPasV));
}
}
return aNodes;
}

View File

@@ -0,0 +1,50 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_ConeRangeSplitter_HeaderFile
#define _BRepMesh_ConeRangeSplitter_HeaderFile
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <IMeshTools_Parameters.hxx>
//! Auxiliary class extending default range splitter in
//! order to generate internal nodes for conical surface.
class BRepMesh_ConeRangeSplitter : public BRepMesh_DefaultRangeSplitter
{
public:
//! Constructor.
BRepMesh_ConeRangeSplitter()
{
}
//! Destructor.
virtual ~BRepMesh_ConeRangeSplitter()
{
}
//! 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;
};
#endif

View File

@@ -0,0 +1,60 @@
// Created on: 2019-07-08
// Copyright (c) 2019 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.
#ifndef _BRepMesh_ConstrainedBaseMeshAlgo_HeaderFile
#define _BRepMesh_ConstrainedBaseMeshAlgo_HeaderFile
#include <BRepMesh_BaseMeshAlgo.hxx>
#include <NCollection_Shared.hxx>
#include <IMeshTools_Parameters.hxx>
class BRepMesh_DataStructureOfDelaun;
class BRepMesh_Delaun;
//! Class provides base fuctionality to build face triangulation using Dealunay approach.
//! Performs generation of mesh using raw data from model.
class BRepMesh_ConstrainedBaseMeshAlgo : public BRepMesh_BaseMeshAlgo
{
public:
//! Constructor.
BRepMesh_ConstrainedBaseMeshAlgo ()
{
}
//! Destructor.
virtual ~BRepMesh_ConstrainedBaseMeshAlgo ()
{
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ConstrainedBaseMeshAlgo, BRepMesh_BaseMeshAlgo)
protected:
//! Returns size of cell to be used by acceleration circles grid structure.
virtual std::pair<Standard_Integer, Standard_Integer> getCellsCount (const Standard_Integer /*theVerticesNb*/)
{
return std::pair<Standard_Integer, Standard_Integer> (-1, -1);
}
//! Perfroms processing of generated mesh.
//! By default does nothing.
//! Expected to be called from method generateMesh() in successor classes.
virtual void postProcessMesh (BRepMesh_Delaun& /*theMesher*/)
{
}
};
#endif

View File

@@ -0,0 +1,45 @@
// Created on: 2016-04-07
// 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_Context.hxx>
#include <BRepMesh_ModelBuilder.hxx>
#include <BRepMesh_EdgeDiscret.hxx>
#include <BRepMesh_ModelHealer.hxx>
#include <BRepMesh_FaceDiscret.hxx>
#include <BRepMesh_ModelPreProcessor.hxx>
#include <BRepMesh_ModelPostProcessor.hxx>
#include <BRepMesh_MeshAlgoFactory.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_Context::BRepMesh_Context ()
{
SetModelBuilder (new BRepMesh_ModelBuilder);
SetEdgeDiscret (new BRepMesh_EdgeDiscret);
SetModelHealer (new BRepMesh_ModelHealer);
SetPreProcessor (new BRepMesh_ModelPreProcessor);
SetFaceDiscret (new BRepMesh_FaceDiscret(new BRepMesh_MeshAlgoFactory));
SetPostProcessor(new BRepMesh_ModelPostProcessor);
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_Context::~BRepMesh_Context ()
{
}

View File

@@ -1,6 +1,6 @@
// Created on: 2011-05-17
// Created on: 2016-04-07
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -13,18 +13,24 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _BRepMesh_Status_HeaderFile
#define _BRepMesh_Status_HeaderFile
#ifndef _BRepMesh_Context_HeaderFile
#define _BRepMesh_Context_HeaderFile
//! Discribes the wires discretisation.
enum BRepMesh_Status
#include <IMeshTools_Context.hxx>
//! Class implemeting default context of BRepMesh algorithm.
//! Initializes context by default algorithms.
class BRepMesh_Context : public IMeshTools_Context
{
BRepMesh_NoError = 0x0,
BRepMesh_OpenWire = 0x1,
BRepMesh_SelfIntersectingWire = 0x2,
BRepMesh_Failure = 0x4,
BRepMesh_ReMesh = 0x8,
BRepMesh_UserBreak = 0x16
public:
//! Constructor.
Standard_EXPORT BRepMesh_Context ();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_Context ();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Context, IMeshTools_Context)
};
#endif

View File

@@ -0,0 +1,342 @@
// Created on: 2016-04-19
// 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_CurveTessellator.hxx>
#include <gp_Pnt.hxx>
#include <BRep_Tool.hxx>
#include <TopoDS_Edge.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <IMeshTools_Parameters.hxx>
#include <TopExp_Explorer.hxx>
#include <Geom_Plane.hxx>
#include <TopExp.hxx>
#include <Adaptor3d_HCurveOnSurface.hxx>
#include <Adaptor2d_HCurve2d.hxx>
#include <Standard_Failure.hxx>
#include <GCPnts_AbscissaPoint.hxx>
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_CurveTessellator::BRepMesh_CurveTessellator(
const IMeshData::IEdgeHandle& theEdge,
const IMeshTools_Parameters& theParameters)
: myDEdge(theEdge),
myParameters(theParameters),
myEdge(theEdge->GetEdge()),
myCurve(myEdge)
{
init();
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_CurveTessellator::BRepMesh_CurveTessellator (
const IMeshData::IEdgeHandle& theEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters)
: myDEdge(theEdge),
myParameters(theParameters),
myEdge(TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation))),
myCurve(myEdge, theFace->GetFace())
{
init();
}
//=======================================================================
//function : init
//purpose :
//=======================================================================
void BRepMesh_CurveTessellator::init()
{
if (myParameters.MinSize <= 0.0)
{
Standard_Failure::Raise ("The structure \"myParameters\" is not initialized");
}
TopExp::Vertices(myEdge, myFirstVertex, myLastVertex);
Standard_Real aPreciseAngDef = 0.5 * myDEdge->GetAngularDeflection();
Standard_Real aPreciseLinDef = 0.5 * myDEdge->GetDeflection();
if (myEdge.Orientation() == TopAbs_INTERNAL)
{
aPreciseLinDef *= 0.5;
}
aPreciseLinDef = Max (aPreciseLinDef, Precision::Confusion());
aPreciseAngDef = Max (aPreciseAngDef, Precision::Angular());
Standard_Real aMinSize = myParameters.MinSize;
if (myParameters.AdjustMinSize)
{
aMinSize = Min (aMinSize, myParameters.RelMinSize() * GCPnts_AbscissaPoint::Length (
myCurve, myCurve.FirstParameter(), myCurve.LastParameter(), aPreciseLinDef));
}
mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
mySquareMinSize = Max (mySquareEdgeDef, aMinSize * aMinSize);
myEdgeSqTol = BRep_Tool::Tolerance (myEdge);
myEdgeSqTol *= myEdgeSqTol;
const Standard_Integer aMinPntNb = (myCurve.GetType() == GeomAbs_Circle) ? 4 : 2; //OCC287
myDiscretTool.Initialize (myCurve,
myCurve.FirstParameter(), myCurve.LastParameter(),
aPreciseAngDef, aPreciseLinDef, aMinPntNb,
Precision::PConfusion(), aMinSize);
if (myCurve.IsCurveOnSurface())
{
const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
const Standard_Real aTol = Precision::Confusion();
const Standard_Real aDu = aSurface->UResolution(aTol);
const Standard_Real aDv = aSurface->VResolution(aTol);
myFaceRangeU[0] = aSurface->FirstUParameter() - aDu;
myFaceRangeU[1] = aSurface->LastUParameter() + aDu;
myFaceRangeV[0] = aSurface->FirstVParameter() - aDv;
myFaceRangeV[1] = aSurface->LastVParameter() + aDv;
}
addInternalVertices();
splitByDeflection2d();
}
//=======================================================================
//function : Destructor
//purpose :
//=======================================================================
BRepMesh_CurveTessellator::~BRepMesh_CurveTessellator ()
{
}
//=======================================================================
//function : NbPoints
//purpose :
//=======================================================================
Standard_Integer BRepMesh_CurveTessellator::PointsNb () const
{
return myDiscretTool.NbPoints ();
}
//=======================================================================
//function : splitByDeflection2d
//purpose :
//=======================================================================
void BRepMesh_CurveTessellator::splitByDeflection2d ()
{
const Standard_Integer aNodesNb = myDiscretTool.NbPoints ();
if (!myDEdge->IsFree () &&
myDEdge->GetSameParam () &&
myDEdge->GetSameRange () &&
aNodesNb > 1)
{
for (Standard_Integer aPCurveIt = 0; aPCurveIt < myDEdge->PCurvesNb (); ++aPCurveIt)
{
TopLoc_Location aLoc;
const IMeshData::IPCurveHandle& aPCurve = myDEdge->GetPCurve(aPCurveIt);
const TopoDS_Face& aFace = aPCurve->GetFace ()->GetFace ();
const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (aFace, aLoc);
if (aSurface->IsInstance(STANDARD_TYPE(Geom_Plane)))
{
continue;
}
const TopoDS_Edge aCurrEdge = TopoDS::Edge(myEdge.Oriented(aPCurve->GetOrientation()));
Standard_Real aF, aL;
Handle (Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface (aCurrEdge, aFace, aF, aL);
TColStd_Array1OfReal aParamArray (1, aNodesNb);
for (Standard_Integer i = 1; i <= aNodesNb; ++i)
aParamArray.SetValue (i, myDiscretTool.Parameter (i));
for (Standard_Integer i = 1; i < aNodesNb; ++i)
splitSegment (aSurface, aCurve2d, aParamArray (i), aParamArray (i + 1), 1);
}
}
}
//=======================================================================
//function : addInternalVertices
//purpose :
//=======================================================================
void BRepMesh_CurveTessellator::addInternalVertices ()
{
// PTv, chl/922/G9, Take into account internal vertices
// it is necessary for internal edges, which do not split other edges, by their vertex
TopExp_Explorer aVertexIt (myEdge, TopAbs_VERTEX);
for (; aVertexIt.More (); aVertexIt.Next ())
{
const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexIt.Current ());
if (aVertex.Orientation() != TopAbs_INTERNAL)
{
continue;
}
myDiscretTool.AddPoint (BRep_Tool::Pnt (aVertex),
BRep_Tool::Parameter (aVertex, myEdge), Standard_True);
}
}
//=======================================================================
//function : isInToleranceOfVertex
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_CurveTessellator::isInToleranceOfVertex (
const gp_Pnt& thePoint,
const TopoDS_Vertex& theVertex) const
{
const gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
const Standard_Real aTolerance = BRep_Tool::Tolerance(theVertex);
return (thePoint.SquareDistance (aPoint) < aTolerance * aTolerance);
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_CurveTessellator::Value (
const Standard_Integer theIndex,
gp_Pnt& thePoint,
Standard_Real& theParameter) const
{
thePoint = myDiscretTool.Value (theIndex);
theParameter = myDiscretTool.Parameter (theIndex);
/*if (!isInToleranceOfVertex(thePoint, myFirstVertex) &&
!isInToleranceOfVertex(thePoint, myLastVertex))
{*/
if (!myCurve.IsCurveOnSurface())
{
return Standard_True;
}
// If point coordinates are out of surface range,
// it is necessary to re-project point.
const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface();
const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface();
if (aSurface->GetType() != GeomAbs_BSplineSurface &&
aSurface->GetType() != GeomAbs_BezierSurface &&
aSurface->GetType() != GeomAbs_OtherSurface)
{
return Standard_True;
}
// Let skip periodic case.
if (aSurface->IsUPeriodic() || aSurface->IsVPeriodic())
{
return Standard_True;
}
gp_Pnt2d aUV;
aCurve.GetCurve()->D0(theParameter, aUV);
// Point lies within the surface range - nothing to do.
if (aUV.X() > myFaceRangeU[0] && aUV.X() < myFaceRangeU[1] &&
aUV.Y() > myFaceRangeV[0] && aUV.Y() < myFaceRangeV[1])
{
return Standard_True;
}
gp_Pnt aPntOnSurf;
aSurface->D0(aUV.X(), aUV.Y(), aPntOnSurf);
return (thePoint.SquareDistance(aPntOnSurf) < myEdgeSqTol);
/*}
return Standard_False;*/
}
//=======================================================================
//function : splitSegment
//purpose :
//=======================================================================
void BRepMesh_CurveTessellator::splitSegment (
const Handle (Geom_Surface)& theSurf,
const Handle (Geom2d_Curve)& theCurve2d,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Integer theNbIter)
{
// limit iteration depth
if (theNbIter > 10)
{
return;
}
gp_Pnt2d uvf, uvl, uvm;
gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
Standard_Real midpar;
if (Abs(theLast - theFirst) < 2 * Precision::PConfusion())
{
return;
}
if ((theCurve2d->FirstParameter() - theFirst > Precision::PConfusion()) ||
(theLast - theCurve2d->LastParameter() > Precision::PConfusion()))
{
// E.g. test bugs moddata_3 bug30133
return;
}
theCurve2d->D0 (theFirst, uvf);
theCurve2d->D0 (theLast, uvl);
P3dF = theSurf->Value (uvf.X (), uvf.Y ());
P3dL = theSurf->Value (uvl.X (), uvl.Y ());
if (P3dF.SquareDistance(P3dL) < mySquareMinSize)
{
return;
}
uvm = gp_Pnt2d ((uvf.XY () + uvl.XY ())*0.5);
midP3dFromSurf = theSurf->Value (uvm.X (), uvm.Y ());
gp_XYZ Vec1 = midP3dFromSurf.XYZ () - P3dF.XYZ ();
if (Vec1.SquareModulus() < mySquareMinSize)
{
return;
}
gp_XYZ aVec = P3dL.XYZ () - P3dF.XYZ ();
aVec.Normalize ();
Standard_Real aModulus = Vec1.Dot (aVec);
gp_XYZ aProj = aVec * aModulus;
gp_XYZ aDist = Vec1 - aProj;
if (aDist.SquareModulus() < mySquareEdgeDef)
{
return;
}
midpar = (theFirst + theLast) * 0.5;
myCurve.D0 (midpar, midP3d);
myDiscretTool.AddPoint (midP3d, midpar, Standard_False);
splitSegment (theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
splitSegment (theSurf, theCurve2d, midpar, theLast, theNbIter + 1);
}

View File

@@ -0,0 +1,110 @@
// Created on: 2016-04-19
// 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.
#ifndef _BRepMesh_EdgeTessellator_HeaderFile
#define _BRepMesh_EdgeTessellator_HeaderFile
#include <IMeshTools_CurveTessellator.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <IMeshData_Types.hxx>
class TopoDS_Face;
class Geom_Surface;
class Geom2d_Curve;
struct IMeshTools_Parameters;
//! Auxiliary class performing tessellation of passed edge according to specified parameters.
class BRepMesh_CurveTessellator : public IMeshTools_CurveTessellator
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_CurveTessellator(
const IMeshData::IEdgeHandle& theEdge,
const IMeshTools_Parameters& theParameters);
//! Constructor.
Standard_EXPORT BRepMesh_CurveTessellator (
const IMeshData::IEdgeHandle& theEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters);
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_CurveTessellator ();
//! Returns number of tessellation points.
Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE;
//! Returns parameters of solution with the given index.
//! @param theIndex index of tessellation point.
//! @param theParameter parameters on PCurve corresponded to the solution.
//! @param thePoint tessellation point.
//! @return True in case of valid result, false elewhere.
Standard_EXPORT virtual Standard_Boolean Value (
const Standard_Integer theIndex,
gp_Pnt& thePoint,
Standard_Real& theParameter) const Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_CurveTessellator, IMeshTools_CurveTessellator)
private:
//! Performs initialization of this tool.
void init();
//! Adds internal vertices to discrete polygon.
void addInternalVertices ();
//Check deflection in 2d space for improvement of edge tesselation.
void splitByDeflection2d ();
void splitSegment (
const Handle (Geom_Surface)& theSurf,
const Handle (Geom2d_Curve)& theCurve2d,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Integer theNbIter);
//! Checks whether the given point lies within tolerance of the vertex.
Standard_Boolean isInToleranceOfVertex (
const gp_Pnt& thePoint,
const TopoDS_Vertex& theVertex) const;
private:
BRepMesh_CurveTessellator (const BRepMesh_CurveTessellator& theOther);
void operator=(const BRepMesh_CurveTessellator& theOther);
private:
const IMeshData::IEdgeHandle& myDEdge;
const IMeshTools_Parameters& myParameters;
TopoDS_Edge myEdge;
BRepAdaptor_Curve myCurve;
GCPnts_TangentialDeflection myDiscretTool;
TopoDS_Vertex myFirstVertex;
TopoDS_Vertex myLastVertex;
Standard_Real mySquareEdgeDef;
Standard_Real mySquareMinSize;
Standard_Real myEdgeSqTol;
Standard_Real myFaceRangeU[2];
Standard_Real myFaceRangeV[2];
};
#endif

View File

@@ -0,0 +1,70 @@
// Created on: 2019-06-07
// Copyright (c) 2019 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.
#ifndef _BRepMesh_CustomBaseMeshAlgo_HeaderFile
#define _BRepMesh_CustomBaseMeshAlgo_HeaderFile
#include <BRepMesh_ConstrainedBaseMeshAlgo.hxx>
#include <NCollection_Shared.hxx>
#include <IMeshTools_Parameters.hxx>
#include <BRepMesh_Delaun.hxx>
#include <BRepMesh_MeshTool.hxx>
class BRepMesh_DataStructureOfDelaun;
//! Class provides base fuctionality to build face triangulation using custom triangulation algorithm.
//! Performs generation of mesh using raw data from model.
class BRepMesh_CustomBaseMeshAlgo : public BRepMesh_ConstrainedBaseMeshAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_CustomBaseMeshAlgo ()
{
}
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_CustomBaseMeshAlgo ()
{
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_CustomBaseMeshAlgo, BRepMesh_ConstrainedBaseMeshAlgo)
protected:
//! Generates mesh for the contour stored in data structure.
Standard_EXPORT virtual void generateMesh () Standard_OVERRIDE
{
const Handle (BRepMesh_DataStructureOfDelaun)& aStructure = this->getStructure ();
buildBaseTriangulation ();
std::pair<Standard_Integer, Standard_Integer> aCellsCount = this->getCellsCount (aStructure->NbNodes ());
BRepMesh_Delaun aMesher (aStructure, aCellsCount.first, aCellsCount.second, Standard_False);
aMesher.ProcessConstraints ();
BRepMesh_MeshTool aCleaner (aStructure);
aCleaner.EraseFreeLinks ();
postProcessMesh (aMesher);
}
protected:
//! Builds base triangulation using custom triangulation algorithm.
Standard_EXPORT virtual void buildBaseTriangulation() = 0;
};
#endif

View File

@@ -0,0 +1,53 @@
// Created on: 2019-06-07
// Copyright (c) 2019 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.
#ifndef _BRepMesh_CustomDelaunayBaseMeshAlgo_HeaderFile
#define _BRepMesh_CustomDelaunayBaseMeshAlgo_HeaderFile
class BRepMesh_DataStructureOfDelaun;
class BRepMesh_Delaun;
//! Class provides base fuctionality to build face triangulation using custom
//! triangulation algorithm with possibility to modify final mesh.
//! Performs generation of mesh using raw data from model.
template<class BaseAlgo>
class BRepMesh_CustomDelaunayBaseMeshAlgo : public BaseAlgo
{
public:
//! Constructor.
BRepMesh_CustomDelaunayBaseMeshAlgo ()
{
}
//! Destructor.
virtual ~BRepMesh_CustomDelaunayBaseMeshAlgo ()
{
}
protected:
//! Perfroms processing of generated mesh.
virtual void postProcessMesh(BRepMesh_Delaun& theMesher)
{
BaseAlgo::postProcessMesh (theMesher);
const Handle(BRepMesh_DataStructureOfDelaun)& aStructure = this->getStructure();
std::pair<Standard_Integer, Standard_Integer> aCellsCount = this->getCellsCount (aStructure->NbNodes());
theMesher.InitCirclesTool (aCellsCount.first, aCellsCount.second);
}
};
#endif

View File

@@ -0,0 +1,98 @@
// Created on: 2016-07-07
// 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_CylinderRangeSplitter.hxx>
#include <GCPnts_TangentialDeflection.hxx>
//=======================================================================
// Function: Reset
// Purpose :
//=======================================================================
void BRepMesh_CylinderRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters)
{
BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters);
const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius();
myDu = GCPnts_TangentialDeflection::ArcAngularStep(
aRadius, GetDFace()->GetDeflection(),
theParameters.Angle, theParameters.MinSize);
}
//=======================================================================
// Function: GenerateSurfaceNodes
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_CylinderRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& /*theParameters*/) const
{
const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius();
Standard_Integer nbU = 0;
Standard_Integer nbV = 0;
const Standard_Real su = aRangeU.second - aRangeU.first;
const Standard_Real sv = aRangeV.second - aRangeV.first;
const Standard_Real aArcLen = su * aRadius;
if (aArcLen > GetDFace()->GetDeflection())
{
// Calculate parameters for iteration in U direction
nbU = (Standard_Integer) (su / myDu);
/*
// Calculate parameters for iteration in V direction
const Standard_Real aDv = nbU*sv / aArcLen;
// Protection against overflow during casting to int in case
// of long cylinder with small radius.
nbV = aDv > static_cast<Standard_Real> (IntegerLast()) ?
0 : (Standard_Integer) (aDv);
nbV = Min(nbV, 100 * nbU);
*/
}
const Standard_Real Du = su / (nbU + 1);
const Standard_Real Dv = sv / (nbV + 1);
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)
{
for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du)
{
aNodes->Append(gp_Pnt2d(aPasU, aPasV));
}
}
return aNodes;
}
//=======================================================================
// Function: computeDelta
// Purpose :
//=======================================================================
void BRepMesh_CylinderRangeSplitter::computeDelta(
const Standard_Real /*theLengthU*/,
const Standard_Real theLengthV)
{
const std::pair<double, double>& aRangeV = GetRangeV();
myDelta.first = myDu / Max(theLengthV, aRangeV.second - aRangeV.first);
myDelta.second = 1.;
}

View File

@@ -0,0 +1,59 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_CylinderRangeSplitter_HeaderFile
#define _BRepMesh_CylinderRangeSplitter_HeaderFile
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <IMeshTools_Parameters.hxx>
//! Auxiliary class extending default range splitter in
//! order to generate internal nodes for cylindrical surface.
class BRepMesh_CylinderRangeSplitter : public BRepMesh_DefaultRangeSplitter
{
public:
//! Constructor.
BRepMesh_CylinderRangeSplitter()
: myDu(1.)
{
}
//! Destructor.
virtual ~BRepMesh_CylinderRangeSplitter()
{
}
//! Resets this splitter. Must be called before first use.
Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
//! 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;
protected:
//! Computes parametric delta taking length along U and V into account.
Standard_EXPORT virtual void computeDelta(
const Standard_Real theLengthU,
const Standard_Real theLengthV) Standard_OVERRIDE;
private:
Standard_Real myDu;
};
#endif

View File

@@ -15,18 +15,15 @@
// commercial license or contractual agreement.
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_PairOfIndex.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepMesh_Edge.hxx>
#include <TopoDS_Compound.hxx>
#include <BRep_Builder.hxx>
#include <BRepTools.hxx>
#include <Standard_ErrorHandler.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient)
//=======================================================================
//function : BRepMesh_DataStructureOfDelaun
//purpose :
@@ -39,9 +36,7 @@ BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun(
myNodeLinks (theReservedNodeSize * 3, myAllocator),
myLinks (theReservedNodeSize * 3, myAllocator),
myDelLinks (myAllocator),
myElements (theReservedNodeSize * 2, myAllocator),
myElementsOfDomain(theReservedNodeSize * 2, myAllocator),
myLinksOfDomain (theReservedNodeSize * 2, myAllocator)
myElements (theReservedNodeSize * 2, myAllocator)
{
}
@@ -55,7 +50,7 @@ Standard_Integer BRepMesh_DataStructureOfDelaun::AddNode(
{
const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd);
if (!myNodeLinks.IsBound(aNodeId))
myNodeLinks.Bind(aNodeId, BRepMesh::ListOfInteger(myAllocator));
myNodeLinks.Bind(aNodeId, IMeshData::ListOfInteger(myAllocator));
return aNodeId;
}
@@ -174,8 +169,8 @@ void BRepMesh_DataStructureOfDelaun::cleanLink(
const Standard_Integer aNodeId = (i == 0) ?
theLink.FirstNode() : theLink.LastNode();
BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aNodeId);
IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for(; aLinkIt.More(); aLinkIt.Next())
{
if (aLinkIt.Value() == theIndex)
@@ -194,16 +189,11 @@ void BRepMesh_DataStructureOfDelaun::cleanLink(
Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement(
const BRepMesh_Triangle& theElement)
{
Standard_Integer aElementIndex = IndexOf(theElement);
if (aElementIndex > 0)
return aElementIndex;
aElementIndex = myElements.Add(theElement);
myElements.Append(theElement);
Standard_Integer aElementIndex = myElements.Size();
myElementsOfDomain.Add(aElementIndex);
Standard_Integer e[3];
Standard_Boolean o[3];
theElement.Edges(e, o);
const Standard_Integer (&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(aElementIndex);
@@ -237,10 +227,7 @@ void BRepMesh_DataStructureOfDelaun::cleanElement(
if (theElement.Movability() != BRepMesh_Free)
return;
Standard_Integer e[3];
Standard_Boolean o[3];
theElement.Edges(e, o);
const Standard_Integer(&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
removeElementIndex(theIndex, myLinks(e[i]));
}
@@ -274,20 +261,15 @@ Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement(
const BRepMesh_Triangle& aElement = GetElement(theIndex);
if (aElement.Movability() == BRepMesh_Deleted)
{
myElements.Substitute(theIndex, theNewElement);
myElements(theIndex) = theNewElement;
return Standard_True;
}
if (IndexOf(theNewElement) != 0)
return Standard_False;
cleanElement(theIndex, aElement);
// Warning: here new element and old element should have different Hash code
myElements.Substitute(theIndex, theNewElement);
myElements(theIndex) = theNewElement;
Standard_Integer e[3];
Standard_Boolean o[3];
theNewElement.Edges(e, o);
const Standard_Integer(&e)[3] = theNewElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
myLinks(e[i]).Append(theIndex);
@@ -302,9 +284,8 @@ void BRepMesh_DataStructureOfDelaun::ElementNodes(
const BRepMesh_Triangle& theElement,
Standard_Integer (&theNodes)[3])
{
Standard_Integer e[3];
Standard_Boolean o[3];
theElement.Edges(e, o);
const Standard_Integer(&e)[3] = theElement.myEdges;
const Standard_Boolean(&o)[3] = theElement.myOrientations;
const BRepMesh_Edge& aLink1 = GetLink(e[0]);
if (o[0])
@@ -331,16 +312,14 @@ void BRepMesh_DataStructureOfDelaun::ElementNodes(
//=======================================================================
void BRepMesh_DataStructureOfDelaun::ClearDomain()
{
BRepMesh::MapOfInteger aFreeEdges;
BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain);
IMeshData::MapOfInteger aFreeEdges;
IMeshData::IteratorOfMapOfInteger aElementIt(myElementsOfDomain);
for (; aElementIt.More(); aElementIt.Next())
{
const Standard_Integer aElementId = aElementIt.Key();
BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId);
Standard_Integer e[3];
Standard_Boolean o[3];
aElement.Edges(e, o);
const Standard_Integer(&e)[3] = aElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
aFreeEdges.Add(e[i]);
@@ -350,7 +329,7 @@ void BRepMesh_DataStructureOfDelaun::ClearDomain()
}
myElementsOfDomain.Clear();
BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges);
IMeshData::IteratorOfMapOfInteger aEdgeIt(aFreeEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
RemoveLink(aEdgeIt.Key());
}
@@ -390,7 +369,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
--aLastLiveItem;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
BRepMesh::ListOfInteger::Iterator aLinkIt;
IMeshData::ListOfInteger::Iterator aLinkIt;
// update link references
for (Standard_Integer i = 0; i < 2; ++i)
{
@@ -411,10 +390,9 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
// update elements references
for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j)
{
const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
Standard_Integer e[3];
Standard_Boolean o[3];
const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j));
aElement.Edges(e, o);
for (Standard_Integer i = 0; i < 3; ++i)
{
@@ -425,8 +403,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
}
}
myElements.Substitute(aLinkIt.Value(),
BRepMesh_Triangle(e, o, aElement.Movability()));
myElements(aLinkIt.Value()) = BRepMesh_Triangle(e, o, aElement.Movability());
}
}
}
@@ -437,8 +414,8 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks()
//=======================================================================
void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
{
BRepMesh::ListOfInteger& aDelNodes =
(BRepMesh::ListOfInteger&)myNodes->GetListOfDelNodes();
IMeshData::ListOfInteger& aDelNodes =
(IMeshData::ListOfInteger&)myNodes->GetListOfDelNodes();
Standard_Integer aLastLiveItem = NbNodes();
while (!aDelNodes.IsEmpty())
@@ -459,7 +436,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
continue;
BRepMesh_Vertex aNode = GetNode(aLastLiveItem);
BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem);
myNodes->RemoveLast();
--aLastLiveItem;
@@ -468,7 +445,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedNodes()
myNodeLinks.ChangeFind(aDelItem) = aLinkList;
const Standard_Integer aLastLiveItemId = aLastLiveItem + 1;
BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList);
IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList);
for (; aLinkIt.More(); aLinkIt.Next())
{
const Standard_Integer aLinkId = aLinkIt.Value();
@@ -495,14 +472,14 @@ void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) con
{
theStream << " Map of nodes : \n";
myNodes->Statistics(theStream);
theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << endl;
theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << std::endl;
theStream << "\n\n Map of Links : \n";
myLinks.Statistics(theStream);
theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
theStream << "\n Deleted links : " << myDelLinks.Extent() << std::endl;
theStream << "\n\n Map of elements : \n";
myElements.Statistics(theStream);
theStream << "\n Elements : " << myElements.Size() << std::endl;
}
//=======================================================================
@@ -547,10 +524,10 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
}
else
{
BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain());
IMeshData::IteratorOfMapOfInteger aLinksIt(aMeshData->LinksOfDomain());
for (; aLinksIt.More(); aLinksIt.Next())
{
const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value());
const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Key());
gp_Pnt aPnt[2];
for (Standard_Integer i = 0; i < 2; ++i)
{
@@ -578,3 +555,9 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
return theFileNameStr;
}
void BRepMesh_DataStructureOfDelaun::Dump(Standard_CString theFileNameStr)
{
Handle(BRepMesh_DataStructureOfDelaun) aMeshData (this);
BRepMesh_Dump((void*)&aMeshData, theFileNameStr);
}

View File

@@ -14,17 +14,14 @@
#ifndef _BRepMesh_DataStructureOfDelaun_HeaderFile
#define _BRepMesh_DataStructureOfDelaun_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <BRepMesh_VertexTool.hxx>
#include <Standard_Transient.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_PairOfIndex.hxx>
#include <Standard_OStream.hxx>
#include <BRepMesh.hxx>
#include <IMeshData_Types.hxx>
#include <BRepMesh_VertexTool.hxx>
class BRepMesh_Vertex;
class BRepMesh_VertexTool;
class BRepMesh_Edge;
//! Describes the data structure necessary for the mesh algorithms in
@@ -101,14 +98,14 @@ public: //! @name API for accessing mesh nodes.
if (isForce || myNodes->FindKey(theIndex).Movability() == BRepMesh_Free)
{
if (LinksConnectedTo(theIndex).Extent()==0)
myNodes->Delete(theIndex);
myNodes->DeleteVertex(theIndex);
}
}
//! Get list of links attached to the node with the given index.
//! @param theIndex index of node whose links should be retrieved.
//! @return list of links attached to the node.
inline const BRepMesh::ListOfInteger& LinksConnectedTo(
inline const IMeshData::ListOfInteger& LinksConnectedTo(
const Standard_Integer theIndex) const
{
return linksConnectedTo(theIndex);
@@ -145,7 +142,7 @@ public: //! @name API for accessing mesh links.
}
//! Returns map of indices of links registered in mesh.
inline const BRepMesh::MapOfInteger& LinksOfDomain() const
inline const IMeshData::MapOfInteger& LinksOfDomain() const
{
return myLinksOfDomain;
}
@@ -181,7 +178,7 @@ public: //! @name API for accessing mesh elements.
//! Returns number of links.
inline Standard_Integer NbElements() const
{
return myElements.Extent();
return myElements.Size();
}
//! Adds element to the mesh if it is not already in the mesh.
@@ -189,24 +186,16 @@ public: //! @name API for accessing mesh elements.
//! @return index of the element in the structure.
Standard_EXPORT Standard_Integer AddElement(const BRepMesh_Triangle& theElement);
//! Finds the index of the given element.
//! @param theElement element to find.
//! @return index of the given element of zero if element is not in the mesh.
Standard_Integer IndexOf(const BRepMesh_Triangle& theElement) const
{
return myElements.FindIndex(theElement);
}
//! Get element by the index.
//! @param theIndex index of an element.
//! @return element with the given index.
const BRepMesh_Triangle& GetElement(const Standard_Integer theIndex)
{
return myElements.FindKey(theIndex);
return myElements.ChangeValue(theIndex - 1);
}
//! Returns map of indices of elements registered in mesh.
inline const BRepMesh::MapOfInteger& ElementsOfDomain() const
inline const IMeshData::MapOfInteger& ElementsOfDomain() const
{
return myElementsOfDomain;
}
@@ -229,6 +218,8 @@ public: //! @name API for accessing mesh elements.
const BRepMesh_Triangle& theElement,
Standard_Integer (&theNodes)[3]);
Standard_EXPORT void Dump(Standard_CString theFileNameStr);
public: //! @name Auxilary API
@@ -244,7 +235,7 @@ public: //! @name Auxilary API
}
//! Gives the data structure for initialization of cell size and tolerance.
inline BRepMesh::HVertexTool& Data()
inline const Handle(BRepMesh_VertexTool)& Data()
{
return myNodes;
}
@@ -260,17 +251,17 @@ public: //! @name Auxilary API
clearDeletedNodes();
}
DEFINE_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient)
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DataStructureOfDelaun, Standard_Transient)
private:
//! Get list of links attached to the node with the given index.
//! @param theIndex index of node whose links should be retrieved.
//! @return list of links attached to the node.
inline BRepMesh::ListOfInteger& linksConnectedTo(
inline IMeshData::ListOfInteger& linksConnectedTo(
const Standard_Integer theIndex) const
{
return (BRepMesh::ListOfInteger&)myNodeLinks.Find(theIndex);
return (IMeshData::ListOfInteger&)myNodeLinks.Find(theIndex);
}
//! Substitutes deleted links by the last one from corresponding map
@@ -305,15 +296,13 @@ private:
private:
Handle(NCollection_IncAllocator) myAllocator;
BRepMesh::HVertexTool myNodes;
BRepMesh::DMapOfIntegerListOfInteger myNodeLinks;
BRepMesh::IDMapOfLink myLinks;
BRepMesh::ListOfInteger myDelLinks;
BRepMesh::IMapOfElement myElements;
BRepMesh::MapOfInteger myElementsOfDomain;
BRepMesh::MapOfInteger myLinksOfDomain;
Handle(BRepMesh_VertexTool) myNodes;
IMeshData::DMapOfIntegerListOfInteger myNodeLinks;
IMeshData::IDMapOfLink myLinks;
IMeshData::ListOfInteger myDelLinks;
IMeshData::VectorOfElements myElements;
IMeshData::MapOfInteger myElementsOfDomain;
IMeshData::MapOfInteger myLinksOfDomain;
};
DEFINE_STANDARD_HANDLE(BRepMesh_DataStructureOfDelaun,Standard_Transient)
#endif

View File

@@ -0,0 +1,252 @@
// Created on: 2016-07-07
// 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_DefaultRangeSplitter.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomAbs_IsoType.hxx>
//=======================================================================
// Function: Reset
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& /*theParameters*/)
{
myDFace = theDFace;
myRangeU.first = myRangeV.first = 1.e100;
myRangeU.second = myRangeV.second = -1.e100;
myDelta.first = myDelta.second = 1.;
myTolerance.first = myTolerance.second = Precision::Confusion();
}
//=======================================================================
// Function: AddPoint
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
{
myRangeU.first = Min(thePoint.X(), myRangeU.first);
myRangeU.second = Max(thePoint.X(), myRangeU.second);
myRangeV.first = Min(thePoint.Y(), myRangeV.first);
myRangeV.second = Max(thePoint.Y(), myRangeV.second);
}
//=======================================================================
// Function: AdjustRange
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::AdjustRange()
{
const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface();
updateRange(aSurface->FirstUParameter(), aSurface->LastUParameter(),
aSurface->IsUPeriodic(), myRangeU.first, myRangeU.second);
if (myRangeU.second < myRangeU.first)
{
myIsValid = Standard_False;
return;
}
updateRange(aSurface->FirstVParameter(), aSurface->LastVParameter(),
aSurface->IsVPeriodic(), myRangeV.first, myRangeV.second);
if (myRangeV.second < myRangeV.first)
{
myIsValid = Standard_False;
return;
}
const Standard_Real aLengthU = computeLengthU();
const Standard_Real aLengthV = computeLengthV();
myIsValid = aLengthU > Precision::PConfusion () && aLengthV > Precision::PConfusion ();
if (myIsValid)
{
computeTolerance(aLengthU, aLengthV);
computeDelta (aLengthU, aLengthV);
}
}
//=======================================================================
// Function: IsValid
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_DefaultRangeSplitter::IsValid()
{
return myIsValid;
}
//=======================================================================
// Function: Scale
// Purpose :
//=======================================================================
gp_Pnt2d BRepMesh_DefaultRangeSplitter::Scale(const gp_Pnt2d& thePoint,
const Standard_Boolean isToFaceBasis) const
{
return isToFaceBasis ?
gp_Pnt2d ((thePoint.X () - myRangeU.first) / myDelta.first,
(thePoint.Y () - myRangeV.first) / myDelta.second) :
gp_Pnt2d (thePoint.X () * myDelta.first + myRangeU.first,
thePoint.Y () * myDelta.second + myRangeV.first);
}
//=======================================================================
// Function: GenerateSurfaceNodes
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_DefaultRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& /*theParameters*/) const
{
return Handle(IMeshData::ListOfPnt2d)();
}
//=======================================================================
// Function: computeTolerance
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::computeTolerance(
const Standard_Real /*theLenU*/,
const Standard_Real /*theLenV*/)
{
const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
const Standard_Real aDeflectionUV = 1.e-05;
myTolerance.first = Max(Min(aDeflectionUV, 0.1 * aDiffU), 1e-7 * aDiffU);
myTolerance.second = Max(Min(aDeflectionUV, 0.1 * aDiffV), 1e-7 * aDiffV);
}
//=======================================================================
// Function: computeDelta
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::computeDelta(
const Standard_Real theLengthU,
const Standard_Real theLengthV)
{
const Standard_Real aDiffU = myRangeU.second - myRangeU.first;
const Standard_Real aDiffV = myRangeV.second - myRangeV.first;
myDelta.first = aDiffU / (theLengthU < myTolerance.first ? 1. : theLengthU);
myDelta.second = aDiffV / (theLengthV < myTolerance.second ? 1. : theLengthV);
}
//=======================================================================
// Function: computeLengthU
// Purpose :
//=======================================================================
Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthU()
{
Standard_Real longu = 0.0;
gp_Pnt P11, P12, P21, P22, P31, P32;
Standard_Real du = 0.05 * (myRangeU.second - myRangeU.first);
Standard_Real dfvave = 0.5 * (myRangeV.second + myRangeV.first);
Standard_Real dfucur;
Standard_Integer i1;
const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
gFace->D0(myRangeU.first, myRangeV.first, P11);
gFace->D0(myRangeU.first, dfvave, P21);
gFace->D0(myRangeU.first, myRangeV.second, P31);
for (i1 = 1, dfucur = myRangeU.first + du; i1 <= 20; i1++, dfucur += du)
{
gFace->D0(dfucur, myRangeV.first, P12);
gFace->D0(dfucur, dfvave, P22);
gFace->D0(dfucur, myRangeV.second, P32);
longu += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
P11 = P12;
P21 = P22;
P31 = P32;
}
return longu / 3.;
}
//=======================================================================
// Function: computeLengthV
// Purpose :
//=======================================================================
Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthV()
{
Standard_Real longv = 0.0;
gp_Pnt P11, P12, P21, P22, P31, P32;
Standard_Real dv = 0.05 * (myRangeV.second - myRangeV.first);
Standard_Real dfuave = 0.5 * (myRangeU.second + myRangeU.first);
Standard_Real dfvcur;
Standard_Integer i1;
const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
gFace->D0(myRangeU.first, myRangeV.first, P11);
gFace->D0(dfuave, myRangeV.first, P21);
gFace->D0(myRangeU.second, myRangeV.first, P31);
for (i1 = 1, dfvcur = myRangeV.first + dv; i1 <= 20; i1++, dfvcur += dv)
{
gFace->D0(myRangeU.first, dfvcur, P12);
gFace->D0(dfuave, dfvcur, P22);
gFace->D0(myRangeU.second, dfvcur, P32);
longv += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32));
P11 = P12;
P21 = P22;
P31 = P32;
}
return longv / 3.;
}
//=======================================================================
// Function: updateRange
// Purpose :
//=======================================================================
void BRepMesh_DefaultRangeSplitter::updateRange(
const Standard_Real theGeomFirst,
const Standard_Real theGeomLast,
const Standard_Boolean isPeriodic,
Standard_Real& theDiscreteFirst,
Standard_Real& theDiscreteLast)
{
if (theDiscreteFirst < theGeomFirst ||
theDiscreteLast > theGeomLast)
{
if (isPeriodic)
{
if ((theDiscreteLast - theDiscreteFirst) > (theGeomLast - theGeomFirst))
{
theDiscreteLast = theDiscreteFirst + (theGeomLast - theGeomFirst);
}
}
else
{
if ((theDiscreteFirst < theGeomLast) && (theDiscreteLast > theGeomFirst))
{
//Protection against the faces whose pcurve is out of the surface's domain
//(see issue #23675 and test cases "bugs iges buc60820*")
if (theGeomFirst > theDiscreteFirst)
{
theDiscreteFirst = theGeomFirst;
}
if (theGeomLast < theDiscreteLast)
{
theDiscreteLast = theGeomLast;
}
}
}
}
}

View File

@@ -0,0 +1,150 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_DefaultRangeSplitter_HeaderFile
#define _BRepMesh_DefaultRangeSplitter_HeaderFile
#include <Standard_Type.hxx>
#include <gp_Pnt2d.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <IMeshData_Types.hxx>
#include <IMeshData_Face.hxx>
struct IMeshTools_Parameters;
//! Default tool to define range of discrete face model and
//! obtain grid points distributed within this range.
class BRepMesh_DefaultRangeSplitter
{
public:
//! Constructor.
BRepMesh_DefaultRangeSplitter()
: myIsValid (Standard_True)
{
}
//! Destructor.
virtual ~BRepMesh_DefaultRangeSplitter()
{
}
//! Resets this splitter. Must be called before first use.
Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters);
//! Registers border point.
Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint);
//! Updates discrete range of surface according to its geometric range.
Standard_EXPORT virtual void AdjustRange();
//! Returns True if computed range is valid.
Standard_EXPORT virtual Standard_Boolean IsValid();
//! Scales the given point from real parametric space
//! to face basis and otherwise.
//! @param thePoint point to be scaled.
//! @param isToFaceBasis if TRUE converts point to face basis,
//! otherwise performs reverse conversion.
//! @return scaled point.
Standard_EXPORT gp_Pnt2d Scale(const gp_Pnt2d& thePoint,
const Standard_Boolean isToFaceBasis) const;
//! Returns list of nodes generated using surface data and specified parameters.
//! By default returns null ptr.
Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes(
const IMeshTools_Parameters& theParameters) const;
//! Returns point in 3d space corresponded to the given
//! point defined in parameteric space of surface.
inline gp_Pnt Point(const gp_Pnt2d& thePoint2d) const
{
return GetSurface()->Value(thePoint2d.X(), thePoint2d.Y());
}
protected:
//! Computes parametric tolerance taking length along U and V into account.
virtual void computeTolerance(
const Standard_Real theLenU,
const Standard_Real theLenV);
//! Computes parametric delta taking length along U and V and value of tolerance into account.
virtual void computeDelta(
const Standard_Real theLengthU,
const Standard_Real theLengthV);
public:
//! Returns face model.
inline const IMeshData::IFaceHandle& GetDFace() const
{
return myDFace;
}
//! Returns surface.
inline const Handle(BRepAdaptor_HSurface)& GetSurface() const
{
return myDFace->GetSurface();
}
//! Returns U range.
inline const std::pair<Standard_Real, Standard_Real>& GetRangeU() const
{
return myRangeU;
}
//! Returns V range.
inline const std::pair<Standard_Real, Standard_Real>& GetRangeV() const
{
return myRangeV;
}
//! Returns delta.
inline const std::pair<Standard_Real, Standard_Real>& GetDelta () const
{
return myDelta;
}
inline const std::pair<Standard_Real, Standard_Real>& GetToleranceUV() const
{
return myTolerance;
}
private:
//! Computes length along U direction.
Standard_Real computeLengthU();
//! Computes length along V direction.
Standard_Real computeLengthV();
//! Updates discrete range of surface according to its geometric range.
void updateRange(const Standard_Real theGeomFirst,
const Standard_Real theGeomLast,
const Standard_Boolean isPeriodic,
Standard_Real& theDiscreteFirst,
Standard_Real& theDiscreteLast);
protected:
IMeshData::IFaceHandle myDFace;
std::pair<Standard_Real, Standard_Real> myRangeU;
std::pair<Standard_Real, Standard_Real> myRangeV;
std::pair<Standard_Real, Standard_Real> myDelta;
std::pair<Standard_Real, Standard_Real> myTolerance;
Standard_Boolean myIsValid;
};
#endif

View File

@@ -0,0 +1,162 @@
// Created on: 2016-04-19
// 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_Deflection.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshTools_Parameters.hxx>
#include <TopExp.hxx>
#include <TopoDS_Vertex.hxx>
//=======================================================================
//function : RelativeEdgeDeflection
//purpose :
//=======================================================================
Standard_Real BRepMesh_Deflection::ComputeAbsoluteDeflection(
const TopoDS_Shape& theShape,
const Standard_Real theRelativeDeflection,
const Standard_Real theMaxShapeSize)
{
if (theShape.IsNull())
{
return theRelativeDeflection;
}
Bnd_Box aBox;
BRepBndLib::Add (theShape, aBox, Standard_False);
Standard_Real aShapeSize = theRelativeDeflection;
BRepMesh_ShapeTool::BoxMaxDimension (aBox, aShapeSize);
// Adjust resulting value in relation to the total size
Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2;
aBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2);
const Standard_Real aMaxShapeSize = (theMaxShapeSize > 0.0) ? theMaxShapeSize :
Max(aX2 - aX1, Max(aY2 - aY1, aZ2 - aZ1));
Standard_Real anAdjustmentCoefficient = aMaxShapeSize / (2 * aShapeSize);
if (anAdjustmentCoefficient < 0.5)
{
anAdjustmentCoefficient = 0.5;
}
else if (anAdjustmentCoefficient > 2.)
{
anAdjustmentCoefficient = 2.;
}
return (anAdjustmentCoefficient * aShapeSize * theRelativeDeflection);
}
//=======================================================================
// Function: ComputeDeflection (edge)
// Purpose :
//=======================================================================
void BRepMesh_Deflection::ComputeDeflection (
const IMeshData::IEdgeHandle& theDEdge,
const Standard_Real theMaxShapeSize,
const IMeshTools_Parameters& theParameters)
{
const Standard_Real aAngDeflection = theParameters.Angle;
Standard_Real aLinDeflection =
!theParameters.Relative ? theParameters.Deflection :
ComputeAbsoluteDeflection(theDEdge->GetEdge(),
theParameters.Deflection,
theMaxShapeSize);
const TopoDS_Edge& anEdge = theDEdge->GetEdge();
TopoDS_Vertex aFirstVertex, aLastVertex;
TopExp::Vertices(anEdge, aFirstVertex, aLastVertex);
Handle(Geom_Curve) aCurve;
Standard_Real aFirstParam, aLastParam;
if (BRepMesh_ShapeTool::Range(anEdge, aCurve, aFirstParam, aLastParam))
{
const Standard_Real aDistF = aFirstVertex.IsNull() ? -1.0 :
BRep_Tool::Pnt(aFirstVertex).Distance(aCurve->Value(aFirstParam));
const Standard_Real aDistL = aLastVertex.IsNull() ? -1.0 :
BRep_Tool::Pnt(aLastVertex).Distance(aCurve->Value(aLastParam));
const Standard_Real aVertexAdjustDistance = Max(aDistF, aDistL);
aLinDeflection = Max(aVertexAdjustDistance, aLinDeflection);
}
theDEdge->SetDeflection (aLinDeflection);
theDEdge->SetAngularDeflection (aAngDeflection);
}
//=======================================================================
// Function: ComputeDeflection (wire)
// Purpose :
//=======================================================================
void BRepMesh_Deflection::ComputeDeflection (
const IMeshData::IWireHandle& theDWire,
const IMeshTools_Parameters& theParameters)
{
Standard_Real aWireDeflection = 0.;
if (theDWire->EdgesNb () > 0)
{
for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
{
aWireDeflection += theDWire->GetEdge(aEdgeIt)->GetDeflection();
}
aWireDeflection /= theDWire->EdgesNb ();
}
else
{
aWireDeflection = theParameters.Deflection;
}
theDWire->SetDeflection (aWireDeflection);
}
//=======================================================================
// Function: ComputeDeflection (face)
// Purpose :
//=======================================================================
void BRepMesh_Deflection::ComputeDeflection (
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters)
{
Standard_Real aDeflection = theParameters.DeflectionInterior;
if (theParameters.Relative)
{
aDeflection = ComputeAbsoluteDeflection(theDFace->GetFace(),
aDeflection, -1.0);
}
Standard_Real aFaceDeflection = 0.0;
if (theDFace->WiresNb () > 0)
{
for (Standard_Integer aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt)
{
aFaceDeflection += theDFace->GetWire(aWireIt)->GetDeflection();
}
aFaceDeflection /= theDFace->WiresNb ();
}
aFaceDeflection = Max(aDeflection, aFaceDeflection);
theDFace->SetDeflection (Max(2.* BRepMesh_ShapeTool::MaxFaceTolerance(
theDFace->GetFace()), aFaceDeflection));
}

View File

@@ -0,0 +1,64 @@
// Created on: 2016-04-19
// 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.
#ifndef _BRepMesh_Deflection_HeaderFile
#define _BRepMesh_Deflection_HeaderFile
#include <Standard_Type.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Transient.hxx>
#include <IMeshData_Types.hxx>
class Bnd_Box;
class TopoDS_Face;
class TopoDS_Edge;
struct IMeshTools_Parameters;
//! Auxiliary tool encompassing methods to compute deflection of shapes.
class BRepMesh_Deflection : public Standard_Transient
{
public:
//! Returns absolute deflection for theShape with respect to the
//! relative deflection and theMaxShapeSize.
//! @param theShape shape for that the deflection should be computed.
//! @param theRelativeDeflection relative deflection.
//! @param theMaxShapeSize maximum size of the whole shape.
//! @return absolute deflection for the shape.
Standard_EXPORT static Standard_Real ComputeAbsoluteDeflection (
const TopoDS_Shape& theShape,
const Standard_Real theRelativeDeflection,
const Standard_Real theMaxShapeSize);
//! Computes and updates deflection of the given discrete edge.
Standard_EXPORT static void ComputeDeflection (
const IMeshData::IEdgeHandle& theDEdge,
const Standard_Real theMaxShapeSize,
const IMeshTools_Parameters& theParameters);
//! Computes and updates deflection of the given discrete wire.
Standard_EXPORT static void ComputeDeflection (
const IMeshData::IWireHandle& theDWire,
const IMeshTools_Parameters& theParameters);
//! Computes and updates deflection of the given discrete face.
Standard_EXPORT static void ComputeDeflection (
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters);
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Deflection, Standard_Transient)
};
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@
#include <BRepMesh_CircleTool.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_Edge.hxx>
#include <BRepMesh.hxx>
#include <IMeshData_Types.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <TColStd_Array1OfInteger.hxx>
@@ -33,7 +33,6 @@
class Bnd_B2d;
class Bnd_Box2d;
class BRepMesh_Vertex;
class Message_ProgressSentry;
//! Compute the Delaunay's triangulation with the algorithm of Watson.
class BRepMesh_Delaun
@@ -42,29 +41,41 @@ public:
DEFINE_STANDARD_ALLOC
//! Creates instance of triangulator, but do not run the algorithm automatically.
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV,
const Standard_Boolean isFillCircles);
//! Creates the triangulation with an empty Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (BRepMesh::Array1OfVertexOfDelaun& theVertices);
Standard_EXPORT BRepMesh_Delaun (IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Creates the triangulation with an existent Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
BRepMesh::Array1OfVertexOfDelaun& theVertices);
IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Creates the triangulation with an existant Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
BRepMesh::Array1OfInteger& theVertexIndices);
IMeshData::VectorOfInteger& theVertexIndices);
//! Creates the triangulation with an existant Mesh data structure.
Standard_EXPORT BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV);
//! Initializes the triangulation with an array of vertices.
Standard_EXPORT void Init (BRepMesh::Array1OfVertexOfDelaun& theVertices);
Standard_EXPORT void Init (IMeshData::Array1OfVertexOfDelaun& theVertices);
//! Forces initialization of circles cell filter using working structure.
Standard_EXPORT void InitCirclesTool (const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV);
//! Removes a vertex from the triangulation.
Standard_EXPORT void RemoveVertex (const BRepMesh_Vertex& theVertex);
//! Adds some vertices into the triangulation.
Standard_EXPORT void AddVertices (BRepMesh::Array1OfVertexOfDelaun& theVertices);
//! Adds some vertices into the triangulation.
Standard_EXPORT void AddVertices (BRepMesh::Array1OfVertexOfDelaun& theVertices,
Message_ProgressSentry* theProgressEntry);
Standard_EXPORT void AddVertices (IMeshData::VectorOfInteger& theVerticesIndices);
//! Modify mesh to use the edge.
//! @return True if done
@@ -76,20 +87,29 @@ public:
return myMeshData;
}
//! Forces insertion of constraint edges into the base triangulation.
inline void ProcessConstraints()
{
insertInternalEdges();
// Adjustment of meshes to boundary edges
frontierAdjust();
}
//! Gives the list of frontier edges.
inline BRepMesh::HMapOfInteger Frontier() const
inline Handle(IMeshData::MapOfInteger) Frontier() const
{
return getEdgesByType (BRepMesh_Frontier);
}
//! Gives the list of internal edges.
inline BRepMesh::HMapOfInteger InternalEdges() const
inline Handle(IMeshData::MapOfInteger) InternalEdges() const
{
return getEdgesByType (BRepMesh_Fixed);
}
//! Gives the list of free edges used only one time
inline BRepMesh::HMapOfInteger FreeEdges() const
inline Handle(IMeshData::MapOfInteger) FreeEdges() const
{
return getEdgesByType (BRepMesh_Free);
}
@@ -136,29 +156,35 @@ private:
InsertBefore
};
typedef NCollection_DataMap<Standard_Integer, BRepMesh::MapOfInteger> DataMapOfMap;
typedef NCollection_DataMap<Standard_Integer, IMeshData::MapOfInteger> DataMapOfMap;
//! Performs initialization of circles cell filter tool.
void initCirclesTool (const Bnd_Box2d& theBox,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV);
//! Add boundig box for edge defined by start & end point to
//! the given vector of bounding boxes for triangulation edges.
void fillBndBox (BRepMesh::SequenceOfBndB2d& theBoxes,
void fillBndBox (IMeshData::SequenceOfBndB2d& theBoxes,
const BRepMesh_Vertex& theV1,
const BRepMesh_Vertex& theV2);
//! Gives the list of edges with type defined by the input parameter.
//! If the given type is BRepMesh_Free returns list of edges
//! that have number of connected elements less or equal 1.
BRepMesh::HMapOfInteger getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const;
Handle(IMeshData::MapOfInteger) getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const;
//! Create super mesh and run triangulation procedure.
void perform (Bnd_Box2d& theBndBox,
BRepMesh::Array1OfInteger& theVertexIndices);
//! Run triangulation procedure.
void perform (IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU = -1,
const Standard_Integer theCellsCountV = -1);
//! Build the super mesh.
void superMesh (const Bnd_Box2d& theBox);
//! Computes the triangulation and adds the vertices,
//! edges and triangles to the Mesh data structure.
void compute (BRepMesh::Array1OfInteger& theVertexIndices);
void compute (IMeshData::VectorOfInteger& theVertexIndices);
//! Adjust the mesh on the frontier.
void frontierAdjust();
@@ -167,7 +193,7 @@ private:
Standard_Boolean meshLeftPolygonOf(
const Standard_Integer theEdgeIndex,
const Standard_Boolean isForward,
BRepMesh::HMapOfInteger theSkipped = NULL);
Handle(IMeshData::MapOfInteger) theSkipped = NULL);
//! Find next link starting from the given node and has maximum
//! angle respect the given reference link.
@@ -178,12 +204,12 @@ private:
const Standard_Integer& thePivotNode,
const BRepMesh_Vertex& thePivotVertex,
const gp_Vec2d& theRefLinkDir,
const BRepMesh::SequenceOfBndB2d& theBoxes,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::HMapOfInteger theSkipped,
const IMeshData::SequenceOfBndB2d& theBoxes,
const IMeshData::SequenceOfInteger& thePolygon,
const Handle(IMeshData::MapOfInteger) theSkipped,
const Standard_Boolean& isSkipLeprous,
BRepMesh::MapOfInteger& theLeprousLinks,
BRepMesh::MapOfInteger& theDeadLinks,
IMeshData::MapOfInteger& theLeprousLinks,
IMeshData::MapOfInteger& theDeadLinks,
Standard_Integer& theNextPivotNode,
gp_Vec2d& theNextLinkDir,
Bnd_B2d& theNextLinkBndBox);
@@ -191,8 +217,8 @@ private:
//! Check is the given link intersects the polygon boundaries.
//! Returns bounding box for the given link trough the theLinkBndBox parameter.
Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
const Standard_Boolean isSkipLastEdge,
@@ -201,9 +227,9 @@ private:
//! Triangulatiion of a closed polygon described by the list
//! of indexes of its edges in the structure.
//! (negative index means reversed edge)
void meshPolygon (BRepMesh::SequenceOfInteger& thePolygon,
BRepMesh::SequenceOfBndB2d& thePolyBoxes,
BRepMesh::HMapOfInteger theSkipped = NULL);
void meshPolygon (IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes,
Handle(IMeshData::MapOfInteger) theSkipped = NULL);
//! Decomposes the given closed simple polygon (polygon without glued edges
//! and loops) on two simpler ones by adding new link at the most thin part
@@ -215,31 +241,27 @@ private:
//! @param thePolygonCut product of decomposition of source polygon (second part of decomposition).
//! @param thePolyBoxesCut bounding boxes corresponded to resulting polygon's links.
void decomposeSimplePolygon (
BRepMesh::SequenceOfInteger& thePolygon,
BRepMesh::SequenceOfBndB2d& thePolyBoxes,
BRepMesh::SequenceOfInteger& thePolygonCut,
BRepMesh::SequenceOfBndB2d& thePolyBoxesCut);
IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes,
IMeshData::SequenceOfInteger& thePolygonCut,
IMeshData::SequenceOfBndB2d& thePolyBoxesCut);
//! Triangulation of closed polygon containing only three edges.
inline Standard_Boolean meshElementaryPolygon (const BRepMesh::SequenceOfInteger& thePolygon);
inline Standard_Boolean meshElementaryPolygon (const IMeshData::SequenceOfInteger& thePolygon);
//! Creates the triangles beetween the given node and the given polyline.
void createTriangles (const Standard_Integer theVertexIndex,
BRepMesh::MapOfIntegerInteger& thePoly);
void createTriangles (const Standard_Integer theVertexIndex,
BRepMesh::MapOfIntegerInteger& thePoly,
Message_ProgressSentry* theProgressEntry);
IMeshData::MapOfIntegerInteger& thePoly);
//! Add a triangle based on the given oriented edges into mesh
void addTriangle (const Standard_Integer (&theEdgesId)[3],
inline void addTriangle (const Standard_Integer (&theEdgesId)[3],
const Standard_Boolean (&theEdgesOri)[3],
const Standard_Integer (&theNodesId)[3]);
//! Deletes the triangle with the given index and adds the free edges into the map.
//! When an edge is suppressed more than one time it is destroyed.
void deleteTriangle (const Standard_Integer theIndex,
BRepMesh::MapOfIntegerInteger& theLoopEdges);
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Returns start and end nodes of the given edge in respect to its orientation.
void getOrientedNodes (const BRepMesh_Edge& theEdge,
@@ -250,23 +272,19 @@ private:
//! links specified by start and end link indices.
void processLoop (const Standard_Integer theLinkFrom,
const Standard_Integer theLinkTo,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes);
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Creates new link based on the given nodes and updates the given polygon.
Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[],
const gp_Pnt2d thePnts [],
const Standard_Integer theRootIndex,
const ReplaceFlag theReplaceFlag,
BRepMesh::SequenceOfInteger& thePolygon,
BRepMesh::SequenceOfBndB2d& thePolyBoxes);
IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Creates the triangles on new nodes.
void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices,
Message_ProgressSentry* theProgressEntry);
//! Creates the triangles on new nodes.
void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices);
void createTrianglesOnNewVertices (IMeshData::VectorOfInteger& theVertexIndices);
//! Cleanup mesh from the free triangles.
void cleanupMesh();
@@ -282,35 +300,35 @@ private:
const Standard_Integer thePrevElementId);
//! Remove internal triangles from the given polygon.
void cleanupPolygon (const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes);
void cleanupPolygon (const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Checks is the given vertex lies inside the polygon.
Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId,
const BRepMesh::VectorOfInteger& thePolygonVertices) const;
const IMeshData::VectorOfInteger& thePolygonVertices) const;
//! Remove all triangles and edges that are placed inside the polygon or crossed it.
void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId,
const BRepMesh::VectorOfInteger& thePolyVertices,
const BRepMesh::MapOfInteger& thePolyVerticesFindMap,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
BRepMesh::MapOfInteger& theSurvivedLinks,
BRepMesh::MapOfIntegerInteger& theLoopEdges);
const IMeshData::VectorOfInteger& thePolyVertices,
const IMeshData::MapOfInteger& thePolyVerticesFindMap,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
IMeshData::MapOfInteger& theSurvivedLinks,
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Checks is the given link crosses the polygon boundary.
//! If yes, kills its triangles and checks neighbor links on boundary intersection. Does nothing elsewhere.
void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId,
const BRepMesh_Edge& theLinkToCheck,
const Standard_Integer& theEndPoint,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
BRepMesh::MapOfInteger& theSurvivedLinks,
BRepMesh::MapOfIntegerInteger& theLoopEdges);
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
IMeshData::MapOfInteger& theSurvivedLinks,
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Kill triangles bound to the given link.
void killLinkTriangles (const Standard_Integer& theLinkId,
BRepMesh::MapOfIntegerInteger& theLoopEdges);
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Calculates distances between the given point and edges of triangle.
Standard_Real calculateDist (const gp_XY theVEdges[3],
@@ -329,16 +347,13 @@ private:
gp_Pnt2d& theIntPnt) const;
//! Returns area of the loop of the given polygon defined by indices of its start and end links.
Standard_Real polyArea (const BRepMesh::SequenceOfInteger& thePolygon,
Standard_Real polyArea (const IMeshData::SequenceOfInteger& thePolygon,
const Standard_Integer theStartIndex,
const Standard_Integer theEndIndex) const;
//! Performs insertion of internal edges into mesh.
void insertInternalEdges();
//! Performs insertion of internal edges into mesh.
void insertInternalEdges (Message_ProgressSentry* theProgressEntry);
private:
Handle(BRepMesh_DataStructureOfDelaun) myMeshData;

View File

@@ -0,0 +1,57 @@
// Created on: 2016-04-19
// 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_DelaunayBaseMeshAlgo.hxx>
#include <BRepMesh_MeshTool.hxx>
#include <BRepMesh_Delaun.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_DelaunayBaseMeshAlgo::BRepMesh_DelaunayBaseMeshAlgo()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_DelaunayBaseMeshAlgo::~BRepMesh_DelaunayBaseMeshAlgo()
{
}
//=======================================================================
//function : generateMesh
//purpose :
//=======================================================================
void BRepMesh_DelaunayBaseMeshAlgo::generateMesh()
{
const Handle(BRepMesh_DataStructureOfDelaun)& aStructure = getStructure();
const Handle(VectorOfPnt)& aNodesMap = getNodesMap();
IMeshData::VectorOfInteger aVerticesOrder(aNodesMap->Size(), getAllocator());
for (Standard_Integer i = 1; i <= aNodesMap->Size(); ++i)
{
aVerticesOrder.Append(i);
}
std::pair<Standard_Integer, Standard_Integer> aCellsCount = getCellsCount (aVerticesOrder.Size ());
BRepMesh_Delaun aMesher(aStructure, aVerticesOrder, aCellsCount.first, aCellsCount.second);
BRepMesh_MeshTool aCleaner(aStructure);
aCleaner.EraseFreeLinks();
postProcessMesh(aMesher);
}

View File

@@ -0,0 +1,46 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile
#define _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile
#include <BRepMesh_ConstrainedBaseMeshAlgo.hxx>
#include <NCollection_Shared.hxx>
#include <IMeshTools_Parameters.hxx>
class BRepMesh_DataStructureOfDelaun;
class BRepMesh_Delaun;
//! Class provides base fuctionality to build face triangulation using Dealunay approach.
//! Performs generation of mesh using raw data from model.
class BRepMesh_DelaunayBaseMeshAlgo : public BRepMesh_ConstrainedBaseMeshAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_DelaunayBaseMeshAlgo();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_DelaunayBaseMeshAlgo();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DelaunayBaseMeshAlgo, BRepMesh_ConstrainedBaseMeshAlgo)
protected:
//! Generates mesh for the contour stored in data structure.
Standard_EXPORT virtual void generateMesh() Standard_OVERRIDE;
};
#endif

View File

@@ -0,0 +1,452 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile
#define _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile
#include <BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <GeomLib.hxx>
//! Extends node insertion Delaunay meshing algo in order to control
//! deflection of generated trianges. Splits triangles failing the check.
template<class RangeSplitter, class BaseAlgo>
class BRepMesh_DelaunayDeflectionControlMeshAlgo : public BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter, BaseAlgo>
{
private:
// Typedef for OCCT RTTI
typedef BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter, BaseAlgo> DelaunayInsertionBaseClass;
public:
//! Constructor.
BRepMesh_DelaunayDeflectionControlMeshAlgo()
: myMaxSqDeflection(-1.),
myIsAllDegenerated(Standard_False)
{
}
//! Destructor.
virtual ~BRepMesh_DelaunayDeflectionControlMeshAlgo()
{
}
protected:
//! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure.
virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE
{
// Insert surface nodes.
DelaunayInsertionBaseClass::postProcessMesh(theMesher);
if (this->getParameters().ControlSurfaceDeflection &&
this->getStructure()->ElementsOfDomain().Extent() > 0)
{
optimizeMesh(theMesher);
}
}
//! Checks deviation of a mesh from geometrical surface.
//! Inserts additional nodes in case of huge deviation.
virtual void optimizeMesh(BRepMesh_Delaun& theMesher)
{
Handle(NCollection_IncAllocator) aTmpAlloc =
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
myCouplesMap = new IMeshData::MapOfOrientedEdges(3 * this->getStructure()->ElementsOfDomain().Extent(), aTmpAlloc);
myControlNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
myCircles = &theMesher.Circles();
const Standard_Integer aIterationsNb = 11;
Standard_Boolean isInserted = Standard_True;
for (Standard_Integer aPass = 1; aPass <= aIterationsNb && isInserted && !myIsAllDegenerated; ++aPass)
{
// Reset stop condition
myMaxSqDeflection = -1.;
myIsAllDegenerated = Standard_True;
myControlNodes->Clear();
if (this->getStructure()->ElementsOfDomain().Extent() < 1)
{
break;
}
// Iterate on current triangles
IMeshData::IteratorOfMapOfInteger aTriangleIt(this->getStructure()->ElementsOfDomain());
for (; aTriangleIt.More(); aTriangleIt.Next())
{
const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aTriangleIt.Key());
splitTriangleGeometry(aTriangle);
}
isInserted = this->insertNodes(myControlNodes, theMesher);
}
myCouplesMap.Nullify();
myControlNodes.Nullify();
if (!(myMaxSqDeflection < 0.))
{
this->getDFace()->SetDeflection(Sqrt(myMaxSqDeflection));
}
}
private:
//! Contains geometrical data related to node of triangle.
struct TriangleNodeInfo
{
gp_XY Point2d;
gp_XYZ Point;
Standard_Boolean isFrontierLink;
};
//! Functor computing deflection of a point from surface.
class NormalDeviation
{
public:
NormalDeviation(
const gp_Pnt& theRefPnt,
const gp_Vec& theNormal)
: myRefPnt(theRefPnt),
myNormal(theNormal)
{
}
Standard_Real SquareDeviation(const gp_Pnt& thePoint) const
{
const Standard_Real aDeflection = Abs(myNormal.Dot(gp_Vec(myRefPnt, thePoint)));
return aDeflection * aDeflection;
}
private:
NormalDeviation (const NormalDeviation& theOther);
void operator= (const NormalDeviation& theOther);
private:
const gp_Pnt& myRefPnt;
const gp_Vec& myNormal;
};
//! Functor computing deflection of a point on triangle link from surface.
class LineDeviation
{
public:
LineDeviation(
const gp_Pnt& thePnt1,
const gp_Pnt& thePnt2)
: myPnt1(thePnt1),
myPnt2(thePnt2)
{
}
Standard_Real SquareDeviation(const gp_Pnt& thePoint) const
{
return BRepMesh_GeomTool::SquareDeflectionOfSegment(myPnt1, myPnt2, thePoint);
}
private:
LineDeviation (const LineDeviation& theOther);
void operator= (const LineDeviation& theOther);
private:
const gp_Pnt& myPnt1;
const gp_Pnt& myPnt2;
};
//! Returns nodes info of the given triangle.
inline void getTriangleInfo(
const BRepMesh_Triangle& theTriangle,
const Standard_Integer (&theNodesIndices)[3],
TriangleNodeInfo (&theInfo)[3]) const
{
const Standard_Integer(&e)[3] = theTriangle.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
{
const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(theNodesIndices[i]);
theInfo[i].Point2d = this->getRangeSplitter().Scale(aVertex.Coord(), Standard_False).XY();
theInfo[i].Point = this->getNodesMap()->Value(aVertex.Location3d()).XYZ();
theInfo[i].isFrontierLink = (this->getStructure()->GetLink(e[i]).Movability() == BRepMesh_Frontier);
}
}
// Check geometry of the given triangle. If triangle does not suit specified deflection, inserts new point.
void splitTriangleGeometry(const BRepMesh_Triangle& theTriangle)
{
if (theTriangle.Movability() != BRepMesh_Deleted)
{
Standard_Integer aNodexIndices[3];
this->getStructure()->ElementNodes(theTriangle, aNodexIndices);
TriangleNodeInfo aNodesInfo[3];
getTriangleInfo(theTriangle, aNodexIndices, aNodesInfo);
gp_Vec aNormal;
gp_Vec aLinkVec[3];
if (computeTriangleGeometry(aNodesInfo, aLinkVec, aNormal))
{
myIsAllDegenerated = Standard_False;
const gp_XY aCenter2d = (aNodesInfo[0].Point2d +
aNodesInfo[1].Point2d +
aNodesInfo[2].Point2d) / 3.;
usePoint(aCenter2d, NormalDeviation(aNodesInfo[0].Point, aNormal));
splitLinks(aNodesInfo, aNodexIndices);
}
}
}
//! Updates array of links vectors.
//! @return False on degenerative triangle.
inline Standard_Boolean computeTriangleGeometry(
const TriangleNodeInfo(&theNodesInfo)[3],
gp_Vec (&theLinks)[3],
gp_Vec &theNormal)
{
if (checkTriangleForDegenerativityAndGetLinks(theNodesInfo, theLinks))
{
if (checkTriangleArea2d(theNodesInfo))
{
if (computeNormal(theLinks[0], theLinks[1], theNormal))
{
return Standard_True;
}
}
}
return Standard_False;
}
//! Updates array of links vectors.
//! @return False on degenerative triangle.
inline Standard_Boolean checkTriangleForDegenerativityAndGetLinks(
const TriangleNodeInfo (&theNodesInfo)[3],
gp_Vec (&theLinks)[3])
{
const Standard_Real MinimalSqLength3d = 1.e-12;
for (Standard_Integer i = 0; i < 3; ++i)
{
theLinks[i] = theNodesInfo[(i + 1) % 3].Point - theNodesInfo[i].Point;
if (theLinks[i].SquareMagnitude() < MinimalSqLength3d)
{
return Standard_False;
}
}
return Standard_True;
}
//! Checks area of triangle in parametric space for degenerativity.
//! @return False on degenerative triangle.
inline Standard_Boolean checkTriangleArea2d(
const TriangleNodeInfo (&theNodesInfo)[3])
{
const gp_Vec2d aLink2d1(theNodesInfo[0].Point2d, theNodesInfo[1].Point2d);
const gp_Vec2d aLink2d2(theNodesInfo[1].Point2d, theNodesInfo[2].Point2d);
const Standard_Real MinimalArea2d = 1.e-9;
return (Abs(aLink2d1 ^ aLink2d2) > MinimalArea2d);
}
//! Computes normal using two link vectors.
//! @return True on success, False in case of normal of null magnitude.
inline Standard_Boolean computeNormal(const gp_Vec& theLink1,
const gp_Vec& theLink2,
gp_Vec& theNormal)
{
const gp_Vec aNormal(theLink1 ^ theLink2);
if (aNormal.SquareMagnitude() > gp::Resolution())
{
theNormal = aNormal.Normalized();
return Standard_True;
}
return Standard_False;
}
//! Computes deflection of midpoints of triangles links.
//! @return True if point fits specified deflection.
inline void splitLinks(
const TriangleNodeInfo (&theNodesInfo)[3],
const Standard_Integer (&theNodesIndices)[3])
{
// Check deflection at triangle links
for (Standard_Integer i = 0; i < 3; ++i)
{
if (theNodesInfo[i].isFrontierLink)
{
continue;
}
const Standard_Integer j = (i + 1) % 3;
// Check if this link was already processed
Standard_Integer aFirstVertex, aLastVertex;
if (theNodesIndices[i] < theNodesIndices[j])
{
aFirstVertex = theNodesIndices[i];
aLastVertex = theNodesIndices[j];
}
else
{
aFirstVertex = theNodesIndices[j];
aLastVertex = theNodesIndices[i];
}
if (myCouplesMap->Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex)))
{
const gp_XY aMidPnt2d = (theNodesInfo[i].Point2d +
theNodesInfo[j].Point2d) / 2.;
if (!usePoint (aMidPnt2d, LineDeviation (theNodesInfo[i].Point,
theNodesInfo[j].Point)))
{
if (!checkLinkEndsForAngularDeviation(theNodesInfo[i],
theNodesInfo[j],
aMidPnt2d))
{
myControlNodes->Append(aMidPnt2d);
}
}
}
}
}
//! Checks the given point (located between the given nodes)
//! for specified angular deviation.
Standard_Boolean checkLinkEndsForAngularDeviation(const TriangleNodeInfo& theNodeInfo1,
const TriangleNodeInfo& theNodeInfo2,
const gp_XY& /*theMidPoint*/)
{
gp_Dir aNorm1, aNorm2;
const Handle(Geom_Surface)& aSurf =
this->getDFace()->GetSurface()->ChangeSurface().Surface().Surface();
if ((GeomLib::NormEstim(aSurf, theNodeInfo1.Point2d, Precision::Confusion(), aNorm1) == 0) &&
(GeomLib::NormEstim(aSurf, theNodeInfo2.Point2d, Precision::Confusion(), aNorm2) == 0))
{
Standard_Real anAngle = aNorm1.Angle(aNorm2);
if (anAngle > this->getParameters().AngleInterior)
return Standard_False;
}
#if 0
else if (GeomLib::NormEstim(aSurf, theMidPoint, Precision::Confusion(), aNorm1) != 0)
{
// It is better to consider the singular point as a node of triangulation.
// However, it leads to hangs up meshing some faces (including faces with
// degenerated edges). E.g. tests "mesh standard_incmesh Q6".
// So, this code fragment is better to implement in the future.
return Standard_False;
}
#endif
return Standard_True;
}
//! Computes deflection of the given point and caches it for
//! insertion in case if it overflows deflection.
//! @return True if point has been cached for insertion.
template<class DeflectionFunctor>
inline Standard_Boolean usePoint(
const gp_XY& thePnt2d,
const DeflectionFunctor& theDeflectionFunctor)
{
gp_Pnt aPnt;
this->getDFace()->GetSurface()->D0(thePnt2d.X(), thePnt2d.Y(), aPnt);
if (!checkDeflectionOfPointAndUpdateCache(thePnt2d, aPnt, theDeflectionFunctor.SquareDeviation(aPnt)))
{
myControlNodes->Append(thePnt2d);
return Standard_True;
}
return Standard_False;
}
//! Checks the given point for specified linear deflection.
//! Updates value of total mesh defleciton.
Standard_Boolean checkDeflectionOfPointAndUpdateCache(
const gp_XY& thePnt2d,
const gp_Pnt& thePnt3d,
const Standard_Real theSqDeflection)
{
if (theSqDeflection > myMaxSqDeflection)
{
myMaxSqDeflection = theSqDeflection;
}
const Standard_Real aSqDeflection =
this->getDFace()->GetDeflection() * this->getDFace()->GetDeflection();
if (theSqDeflection < aSqDeflection)
{
return Standard_True;
}
return rejectByMinSize(thePnt2d, thePnt3d);
}
//! Checks the given node for
Standard_Boolean rejectByMinSize(
const gp_XY& thePnt2d,
const gp_Pnt& thePnt3d)
{
const Standard_Real aSqMinSize =
this->getParameters().MinSize * this->getParameters().MinSize;
IMeshData::MapOfInteger aUsedNodes;
IMeshData::ListOfInteger& aCirclesList =
const_cast<BRepMesh_CircleTool&>(*myCircles).Select(
this->getRangeSplitter().Scale(thePnt2d, Standard_True).XY());
IMeshData::ListOfInteger::Iterator aCircleIt(aCirclesList);
for (; aCircleIt.More(); aCircleIt.Next())
{
const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aCircleIt.Value());
Standard_Integer aNodes[3];
this->getStructure()->ElementNodes(aTriangle, aNodes);
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!aUsedNodes.Contains(aNodes[i]))
{
aUsedNodes.Add(aNodes[i]);
const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(aNodes[i]);
const gp_Pnt& aPoint = this->getNodesMap()->Value(aVertex.Location3d());
if (thePnt3d.SquareDistance(aPoint) < aSqMinSize)
{
return Standard_True;
}
}
}
}
return Standard_False;
}
private:
Standard_Real myMaxSqDeflection;
Standard_Boolean myIsAllDegenerated;
Handle(IMeshData::MapOfOrientedEdges) myCouplesMap;
Handle(IMeshData::ListOfPnt2d) myControlNodes;
const BRepMesh_CircleTool* myCircles;
};
#endif

View File

@@ -0,0 +1,159 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile
#define _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile
#include <BRepMesh_NodeInsertionMeshAlgo.hxx>
#include <BRepMesh_GeomTool.hxx>
//! Extends base Delaunay meshing algo in order to enable possibility
//! of addition of free vertices and internal nodes into the mesh.
template<class RangeSplitter, class BaseAlgo>
class BRepMesh_DelaunayNodeInsertionMeshAlgo : public BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BaseAlgo>
{
private:
// Typedef for OCCT RTTI
typedef BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BaseAlgo> InsertionBaseClass;
public:
//! Constructor.
BRepMesh_DelaunayNodeInsertionMeshAlgo()
: myIsPreProcessSurfaceNodes (Standard_False)
{
}
//! Destructor.
virtual ~BRepMesh_DelaunayNodeInsertionMeshAlgo()
{
}
//! Returns PreProcessSurfaceNodes flag.
inline Standard_Boolean IsPreProcessSurfaceNodes () const
{
return myIsPreProcessSurfaceNodes;
}
//! Sets PreProcessSurfaceNodes flag.
//! If TRUE, registers surface nodes before generation of base mesh.
//! If FALSE, inserts surface nodes after generation of base mesh.
inline void SetPreProcessSurfaceNodes (const Standard_Boolean isPreProcessSurfaceNodes)
{
myIsPreProcessSurfaceNodes = isPreProcessSurfaceNodes;
}
protected:
//! Performs initialization of data structure using existing model data.
virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
{
if (!InsertionBaseClass::initDataStructure())
{
return Standard_False;
}
if (myIsPreProcessSurfaceNodes)
{
const Handle(IMeshData::ListOfPnt2d) aSurfaceNodes =
this->getRangeSplitter().GenerateSurfaceNodes(this->getParameters());
registerSurfaceNodes (aSurfaceNodes);
}
return Standard_True;
}
//! Returns size of cell to be used by acceleration circles grid structure.
virtual std::pair<Standard_Integer, Standard_Integer> getCellsCount (const Standard_Integer theVerticesNb) Standard_OVERRIDE
{
return BRepMesh_GeomTool::CellsCount (this->getDFace()->GetSurface(), theVerticesNb,
this->getDFace()->GetDeflection(),
&this->getRangeSplitter());
}
//! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure.
virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE
{
InsertionBaseClass::postProcessMesh(theMesher);
if (!myIsPreProcessSurfaceNodes)
{
const Handle(IMeshData::ListOfPnt2d) aSurfaceNodes =
this->getRangeSplitter().GenerateSurfaceNodes(this->getParameters());
insertNodes(aSurfaceNodes, theMesher);
}
}
//! Inserts nodes into mesh.
Standard_Boolean insertNodes(
const Handle(IMeshData::ListOfPnt2d)& theNodes,
BRepMesh_Delaun& theMesher)
{
if (theNodes.IsNull() || theNodes->IsEmpty())
{
return Standard_False;
}
IMeshData::VectorOfInteger aVertexIndexes(theNodes->Size(), this->getAllocator());
IMeshData::ListOfPnt2d::Iterator aNodesIt(*theNodes);
for (Standard_Integer aNodeIt = 1; aNodesIt.More(); aNodesIt.Next(), ++aNodeIt)
{
const gp_Pnt2d& aPnt2d = aNodesIt.Value();
if (this->getClassifier()->Perform(aPnt2d) == TopAbs_IN)
{
aVertexIndexes.Append(this->registerNode(this->getRangeSplitter().Point(aPnt2d),
aPnt2d, BRepMesh_Free, Standard_False));
}
}
theMesher.AddVertices(aVertexIndexes);
return !aVertexIndexes.IsEmpty();
}
private:
//! Registers surface nodes in data structure.
Standard_Boolean registerSurfaceNodes(
const Handle(IMeshData::ListOfPnt2d)& theNodes)
{
if (theNodes.IsNull() || theNodes->IsEmpty())
{
return Standard_False;
}
Standard_Boolean isAdded = Standard_False;
IMeshData::ListOfPnt2d::Iterator aNodesIt(*theNodes);
for (Standard_Integer aNodeIt = 1; aNodesIt.More(); aNodesIt.Next(), ++aNodeIt)
{
const gp_Pnt2d& aPnt2d = aNodesIt.Value();
if (this->getClassifier()->Perform(aPnt2d) == TopAbs_IN)
{
isAdded = Standard_True;
this->registerNode(this->getRangeSplitter().Point(aPnt2d),
aPnt2d, BRepMesh_Free, Standard_False);
}
}
return isAdded;
}
private:
Standard_Boolean myIsPreProcessSurfaceNodes;
};
#endif

View File

@@ -47,7 +47,7 @@ public:
//! Setup meshing algorithm by name. <br>
//! Returns TRUE if requested tool is available. <br>
//! On fail Factory will continue to use previous algo.
Standard_EXPORT Standard_Boolean SetDefaultName(const TCollection_AsciiString& theName)
Standard_Boolean SetDefaultName(const TCollection_AsciiString& theName)
{
return SetDefault(theName, myFunctionName);
}
@@ -61,7 +61,7 @@ public:
//! Advanced function. Changes function name to retrieve from plugin. <br>
//! Returns TRUE if requested tool is available. <br>
//! On fail Factory will continue to use previous algo.
Standard_EXPORT Standard_Boolean SetFunctionName(const TCollection_AsciiString& theFuncName)
Standard_Boolean SetFunctionName(const TCollection_AsciiString& theFuncName)
{
return SetDefault(myDefaultName, theFuncName);
}

View File

@@ -46,7 +46,7 @@ public:
}
//! Compute triangulation for set shape.
Standard_EXPORT virtual void Perform() = 0;
virtual void Perform() = 0;
DEFINE_STANDARD_RTTIEXT(BRepMesh_DiscretRoot,Standard_Transient)

View File

@@ -76,7 +76,7 @@ public:
}
//! Alias for IsEqual.
Standard_Boolean operator ==(const BRepMesh_Edge& Other) const
inline Standard_Boolean operator ==(const BRepMesh_Edge& Other) const
{
return IsEqual(Other);
}
@@ -86,10 +86,13 @@ private:
BRepMesh_DegreeOfFreedom myMovability;
};
inline Standard_Integer HashCode(const BRepMesh_Edge& theEdge,
const Standard_Integer theUpper)
//! Computes a hash code for the given edge, in the range [1, theUpperBound]
//! @param theEdge the edge which hash code is to be computed
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const BRepMesh_Edge& theEdge, const Standard_Integer theUpperBound)
{
return theEdge.HashCode(theUpper);
return theEdge.HashCode (theUpperBound);
}
#endif

View File

@@ -0,0 +1,333 @@
// Created on: 2016-04-19
// 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_EdgeDiscret.hxx>
#include <BRepMesh_Deflection.hxx>
#include <IMeshData_Model.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_PCurve.hxx>
#include <TopExp.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <BRepMesh_EdgeTessellationExtractor.hxx>
#include <IMeshData_ParametersListArrayAdaptor.hxx>
#include <BRepMesh_CurveTessellator.hxx>
#include <OSD_Parallel.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_EdgeDiscret::BRepMesh_EdgeDiscret ()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_EdgeDiscret::~BRepMesh_EdgeDiscret ()
{
}
//=======================================================================
// Function: CreateFreeEdgeTessellator
// Purpose :
//=======================================================================
Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshTools_Parameters& theParameters)
{
return new BRepMesh_CurveTessellator(theDEdge, theParameters);
}
//=======================================================================
// Function: CreateEdgeTessellator
// Purpose :
//=======================================================================
Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator(
const IMeshData::IEdgeHandle& theDEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters)
{
return theDEdge->GetSameParam() ?
new BRepMesh_CurveTessellator(theDEdge, theParameters) :
new BRepMesh_CurveTessellator(theDEdge, theOrientation, theDFace, theParameters);
}
//=======================================================================
// Function: CreateEdgeTessellationExtractor
// Purpose :
//=======================================================================
Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellationExtractor(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IFaceHandle& theDFace)
{
return new BRepMesh_EdgeTessellationExtractor(theDEdge, theDFace);
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_EdgeDiscret::performInternal (
const Handle (IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters)
{
myModel = theModel;
myParameters = theParameters;
if (myModel.IsNull())
{
return Standard_False;
}
OSD_Parallel::For (0, myModel->EdgesNb (), *this, !myParameters.InParallel);
myModel.Nullify(); // Do not hold link to model.
return Standard_True;
}
//=======================================================================
// Function: process
// Purpose :
//=======================================================================
void BRepMesh_EdgeDiscret::process (const Standard_Integer theEdgeIndex) const
{
const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (theEdgeIndex);
try
{
OCC_CATCH_SIGNALS
BRepMesh_Deflection::ComputeDeflection (aDEdge, myModel->GetMaxSize (), myParameters);
Handle (IMeshTools_CurveTessellator) aEdgeTessellator;
if (!aDEdge->IsFree ())
{
// Iterate over pcurves and check deflection on corresponding face.
Standard_Real aMinDeflection = RealLast ();
Standard_Integer aMinPCurveIndex = -1;
for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt)
{
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve (aPCurveIt);
const Standard_Real aTmpDeflection = checkExistingPolygonAndUpdateStatus(aDEdge, aPCurve);
if (aTmpDeflection < aMinDeflection)
{
// Identify pcurve with the smallest deflection in order to
// retrieve polygon that represents the most smooth discretization.
aMinDeflection = aTmpDeflection;
aMinPCurveIndex = aPCurveIt;
}
BRepMesh_ShapeTool::CheckAndUpdateFlags (aDEdge, aPCurve);
}
if (aMinPCurveIndex != -1)
{
aDEdge->SetDeflection (aMinDeflection);
const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aMinPCurveIndex)->GetFace();
aEdgeTessellator = CreateEdgeTessellationExtractor(aDEdge, aDFace);
}
else
{
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0);
const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
aEdgeTessellator = BRepMesh_EdgeDiscret::CreateEdgeTessellator(
aDEdge, aPCurve->GetOrientation(), aDFace, myParameters);
}
}
else
{
TopLoc_Location aLoc;
const Handle (Poly_Polygon3D)& aPoly3D = BRep_Tool::Polygon3D (aDEdge->GetEdge (), aLoc);
if (!aPoly3D.IsNull ())
{
if (aPoly3D->HasParameters () &&
aPoly3D->Deflection () < 1.1 * aDEdge->GetDeflection ())
{
// Edge already has suitable 3d polygon.
aDEdge->SetStatus(IMeshData_Reused);
return;
}
else
{
aDEdge->SetStatus(IMeshData_Outdated);
}
}
aEdgeTessellator = CreateEdgeTessellator(aDEdge, myParameters);
}
Tessellate3d (aDEdge, aEdgeTessellator, Standard_True);
if (!aDEdge->IsFree())
{
Tessellate2d(aDEdge, Standard_True);
}
}
catch (Standard_Failure const&)
{
aDEdge->SetStatus (IMeshData_Failure);
}
}
//=======================================================================
// Function: checkExistingPolygonAndUpdateStatus
// Purpose :
//=======================================================================
Standard_Real BRepMesh_EdgeDiscret::checkExistingPolygonAndUpdateStatus(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IPCurveHandle& thePCurve) const
{
const TopoDS_Edge& aEdge = theDEdge->GetEdge ();
const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
TopLoc_Location aLoc;
const Handle (Poly_Triangulation)& aFaceTriangulation =
BRep_Tool::Triangulation (aFace, aLoc);
Standard_Real aDeflection = RealLast ();
if (aFaceTriangulation.IsNull())
{
return aDeflection;
}
const Handle (Poly_PolygonOnTriangulation)& aPolygon =
BRep_Tool::PolygonOnTriangulation (aEdge, aFaceTriangulation, aLoc);
if (!aPolygon.IsNull ())
{
Standard_Boolean isConsistent = aPolygon->HasParameters () &&
aPolygon->Deflection () < 1.1 * theDEdge->GetDeflection ();
if (!isConsistent)
{
// Nullify edge data and mark discrete pcurve to
// notify necessity to mesh the entire face.
theDEdge->SetStatus(IMeshData_Outdated);
}
else
{
aDeflection = aPolygon->Deflection();
}
}
return aDeflection;
}
//=======================================================================
// Function: Tessellate3d
// Purpose :
//=======================================================================
void BRepMesh_EdgeDiscret::Tessellate3d(
const IMeshData::IEdgeHandle& theDEdge,
const Handle (IMeshTools_CurveTessellator)& theTessellator,
const Standard_Boolean theUpdateEnds)
{
// Create 3d polygon.
const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
const TopoDS_Edge& aEdge = theDEdge->GetEdge();
TopoDS_Vertex aFirstVertex, aLastVertex;
TopExp::Vertices(aEdge, aFirstVertex, aLastVertex);
if(aFirstVertex.IsNull() || aLastVertex.IsNull())
return;
if (theUpdateEnds)
{
gp_Pnt aPoint;
Standard_Real aParam;
theTessellator->Value(1, aPoint, aParam);
aCurve->AddPoint(BRep_Tool::Pnt(aFirstVertex), aParam);
}
if (!theDEdge->GetDegenerated())
{
for (Standard_Integer i = 2; i < theTessellator->PointsNb(); ++i)
{
gp_Pnt aPoint;
Standard_Real aParam;
if (!theTessellator->Value(i, aPoint, aParam))
continue;
if (theUpdateEnds)
{
aCurve->AddPoint(aPoint, aParam);
}
else
{
aCurve->InsertPoint(aCurve->ParametersNb() - 1, aPoint, aParam);
}
}
}
if (theUpdateEnds)
{
gp_Pnt aPoint;
Standard_Real aParam;
theTessellator->Value(theTessellator->PointsNb(), aPoint, aParam);
aCurve->AddPoint(BRep_Tool::Pnt(aLastVertex), aParam);
}
}
//=======================================================================
// Function: Tessellate2d
// Purpose :
//=======================================================================
void BRepMesh_EdgeDiscret::Tessellate2d(
const IMeshData::IEdgeHandle& theDEdge,
const Standard_Boolean theUpdateEnds)
{
const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
{
const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
IMeshData::ICurveArrayAdaptorHandle aCurveArray(new IMeshData::ICurveArrayAdaptor(aCurve));
BRepMesh_EdgeParameterProvider<IMeshData::ICurveArrayAdaptorHandle> aProvider(
theDEdge, aPCurve->GetOrientation(), aDFace, aCurveArray);
const Handle(Adaptor2d_HCurve2d)& aGeomPCurve = aProvider.GetPCurve();
Standard_Integer aParamIdx, aParamNb;
if (theUpdateEnds)
{
aParamIdx = 0;
aParamNb = aCurve->ParametersNb();
}
else
{
aParamIdx = 1;
aParamNb = aCurve->ParametersNb() - 1;
}
for (; aParamIdx < aParamNb; ++aParamIdx)
{
const Standard_Real aParam = aProvider.Parameter(aParamIdx, aCurve->GetPoint(aParamIdx));
gp_Pnt2d aPoint2d;
aGeomPCurve->D0(aParam, aPoint2d);
if (theUpdateEnds)
{
aPCurve->AddPoint(aPoint2d, aParam);
}
else
{
aPCurve->InsertPoint(aPCurve->ParametersNb() - 1, aPoint2d, aParam);
}
}
}
}

View File

@@ -0,0 +1,98 @@
// Created on: 2016-04-19
// 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.
#ifndef _BRepMesh_EdgeDiscret_HeaderFile
#define _BRepMesh_EdgeDiscret_HeaderFile
#include <IMeshTools_ModelAlgo.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
class IMeshTools_CurveTessellator;
//! Class implements functionality of edge discret tool.
//! Performs check of the edges for existing Poly_PolygonOnTriangulation.
//! In case if it fits specified deflection, restores data structure using
//! it, else clears edges from outdated data.
class BRepMesh_EdgeDiscret : public IMeshTools_ModelAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_EdgeDiscret ();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_EdgeDiscret ();
//! Creates instance of free edge tessellator.
Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshTools_Parameters& theParameters);
//! Creates instance of edge tessellator.
Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator(
const IMeshData::IEdgeHandle& theDEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters);
//! Creates instance of tessellation extractor.
Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellationExtractor(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IFaceHandle& theDFace);
//! Functor API to discretize the given edge.
inline void operator() (const Standard_Integer theEdgeIndex) const {
process (theEdgeIndex);
}
//! Updates 3d discrete edge model using the given tessellation tool.
Standard_EXPORT static void Tessellate3d(
const IMeshData::IEdgeHandle& theDEdge,
const Handle(IMeshTools_CurveTessellator)& theTessellator,
const Standard_Boolean theUpdateEnds);
//! Updates 2d discrete edge model using tessellation of 3D curve.
Standard_EXPORT static void Tessellate2d(
const IMeshData::IEdgeHandle& theDEdge,
const Standard_Boolean theUpdateEnds);
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeDiscret, IMeshTools_ModelAlgo)
protected:
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean performInternal (
const Handle (IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
private:
//! Checks existing discretization of the edge and updates data model.
void process (const Standard_Integer theEdgeIndex) const;
//! Checks existing polygon on triangulation does it fit edge deflection or not.
//! @return deflection of polygon or RealLast () in case if edge has no polygon
//! or it was dropped.
Standard_Real checkExistingPolygonAndUpdateStatus(
const IMeshData::IEdgeHandle& theDEdge,
const IMeshData::IPCurveHandle& thePCurve) const;
private:
Handle (IMeshData_Model) myModel;
IMeshTools_Parameters myParameters;
};
#endif

View File

@@ -1,89 +0,0 @@
// Created on: 2014-08-13
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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 <BRepMesh_EdgeParameterProvider.hxx>
#include <gp_Pnt.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_EdgeParameterProvider::BRepMesh_EdgeParameterProvider(
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
const Handle(TColStd_HArray1OfReal)& theParameters)
: myParameters(theParameters),
myIsSameParam(BRep_Tool::SameParameter(theEdge)),
myScale(1.),
myCurveAdaptor(theEdge, theFace)
{
if (myIsSameParam)
return;
// Extract actual parametric values
Standard_Real aLastParam;
BRep_Tool::Range(theEdge, theFace, myFirstParam, aLastParam);
myFoundParam = myCurParam = myFirstParam;
// Extract parameters stored in polygon
myOldFirstParam =
myParameters->Value(myParameters->Lower());
const Standard_Real aOldLastParam =
myParameters->Value(myParameters->Upper());
// Calculate scale factor between actual and stored parameters
if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) &&
myOldFirstParam != aOldLastParam)
{
myScale = (aLastParam - myFirstParam) /
(aOldLastParam - myOldFirstParam);
}
myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(),
myCurveAdaptor.LastParameter(), Precision::PConfusion());
}
//=======================================================================
//function : Parameter
//purpose :
//=======================================================================
Standard_Real BRepMesh_EdgeParameterProvider::Parameter(
const Standard_Integer theIndex,
const gp_Pnt& thePoint3d)
{
if (myIsSameParam)
return myParameters->Value(theIndex);
// Use scaled
Standard_Real aPrevParam = myCurParam;
myCurParam = myFirstParam + myScale *
(myParameters->Value(theIndex) - myOldFirstParam);
myFoundParam += (myCurParam - aPrevParam);
myProjector.Perform(thePoint3d, myFoundParam);
if (myProjector.IsDone())
myFoundParam = myProjector.Point().Parameter();
return myFoundParam;
}

View File

@@ -16,44 +16,138 @@
#ifndef _BRepMesh_EdgeParameterProvider_HeaderFile
#define _BRepMesh_EdgeParameterProvider_HeaderFile
#include <IMeshData_Types.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Face.hxx>
#include <TopoDS.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <GeomAdaptor_HSurface.hxx>
class gp_Pnt;
class TopoDS_Edge;
class TopoDS_Face;
#include <TColStd_HArray1OfReal.hxx>
//! Auxiliary class provides correct parameters
//! on curve regarding SameParameter flag.
class BRepMesh_EdgeParameterProvider
template<class ParametersCollection>
class BRepMesh_EdgeParameterProvider : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor. Initializes empty provider.
BRepMesh_EdgeParameterProvider()
{
}
//! Constructor.
//! @param theEdge edge which parameters should be processed.
//! @param theFace face the parametric values are defined for.
//! @param theParameters parameters corresponded to discretization points.
BRepMesh_EdgeParameterProvider(
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
const Handle(TColStd_HArray1OfReal)& theParameters);
const IMeshData::IEdgeHandle& theEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theFace,
const ParametersCollection& theParameters)
{
Init(theEdge, theOrientation, theFace, theParameters);
}
//! Initialized provider by the given data.
void Init (
const IMeshData::IEdgeHandle& theEdge,
const TopAbs_Orientation theOrientation,
const IMeshData::IFaceHandle& theFace,
const ParametersCollection& theParameters)
{
myParameters = theParameters;
myIsSameParam = theEdge->GetSameParam();
myScale = 1.;
// Extract actual parametric values
const TopoDS_Edge aEdge = TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation));
myCurveAdaptor.Initialize(aEdge, theFace->GetFace());
if (myIsSameParam)
{
return;
}
myFirstParam = myCurveAdaptor.FirstParameter();
const Standard_Real aLastParam = myCurveAdaptor.LastParameter();
myFoundParam = myCurParam = myFirstParam;
// Extract parameters stored in polygon
myOldFirstParam = myParameters->Value(myParameters->Lower());
const Standard_Real aOldLastParam = myParameters->Value(myParameters->Upper());
// Calculate scale factor between actual and stored parameters
if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) &&
myOldFirstParam != aOldLastParam)
{
myScale = (aLastParam - myFirstParam) / (aOldLastParam - myOldFirstParam);
}
myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(),
myCurveAdaptor.LastParameter(),Precision::PConfusion());
}
//! Returns parameter according to SameParameter flag of the edge.
//! If SameParameter is TRUE returns value from parameters w/o changes,
//! elsewhere scales initial parameter and tries to determine resulting
//! value using projection of the corresponded 3D point on PCurve.
Standard_Real Parameter(const Standard_Integer theIndex,
const gp_Pnt& thePoint3d);
const gp_Pnt& thePoint3d) const
{
if (myIsSameParam)
{
return myParameters->Value(theIndex);
}
// Use scaled
const Standard_Real aParam = myParameters->Value(theIndex);
const Standard_Real aPrevParam = myCurParam;
myCurParam = myFirstParam + myScale * (aParam - myOldFirstParam);
const Standard_Real aPrevFoundParam = myFoundParam;
myFoundParam += (myCurParam - aPrevParam);
myProjector.Perform(thePoint3d, myFoundParam);
if (myProjector.IsDone())
{
const Standard_Real aFoundParam = myProjector.Point().Parameter();
if ((aPrevFoundParam < myFoundParam && aPrevFoundParam < aFoundParam) ||
(aPrevFoundParam > myFoundParam && aPrevFoundParam > aFoundParam))
{
// Rude protection against case when amplified parameter goes before
// previous one due to period or other reason occurred in projector.
// Using parameter returned by projector as is can produce self-intersections.
myFoundParam = aFoundParam;
}
}
return myFoundParam;
}
//! Returns pcurve used to compute parameters.
const Handle(Adaptor2d_HCurve2d)& GetPCurve() const
{
return myCurveAdaptor.CurveOnSurface().GetCurve();
}
private:
Handle(TColStd_HArray1OfReal) myParameters;
ParametersCollection myParameters;
Standard_Boolean myIsSameParam;
Standard_Real myFirstParam;
@@ -61,11 +155,12 @@ private:
Standard_Real myOldFirstParam;
Standard_Real myScale;
Standard_Real myCurParam;
Standard_Real myFoundParam;
mutable Standard_Real myCurParam;
mutable Standard_Real myFoundParam;
BRepAdaptor_Curve myCurveAdaptor;
Extrema_LocateExtPC myProjector;
mutable Extrema_LocateExtPC myProjector;
};
#endif

View File

@@ -1,6 +1,6 @@
// Created on: 2014-08-13
// Created on: 2016-04-19
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -14,31 +14,46 @@
// commercial license or contractual agreement.
#include <BRepMesh_EdgeTessellationExtractor.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <BRepMesh_ShapeTool.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool)
#include <gp_Pnt.hxx>
#include <BRep_Tool.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Edge.hxx>
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor (
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& thePCurve,
const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTriangulation,
const Handle(Poly_PolygonOnTriangulation)& thePolygon,
const TopLoc_Location& theLocation)
: myProvider(theEdge, theFace, thePolygon->Parameters()),
myPCurve(thePCurve),
myNodes(theTriangulation->Nodes()),
myIndices(thePolygon->Nodes()),
myLoc(theLocation)
const IMeshData::IEdgeHandle& theEdge,
const IMeshData::IFaceHandle& theFace)
{
Handle (Poly_Triangulation) aTriangulation =
BRep_Tool::Triangulation (theFace->GetFace(), myLoc);
Handle (Poly_PolygonOnTriangulation) aPolygon =
BRep_Tool::PolygonOnTriangulation (theEdge->GetEdge(), aTriangulation, myLoc);
myNodes = &aTriangulation->Nodes ();
myIndices = &aPolygon->Nodes ();
myProvider.Init (theEdge, TopAbs_FORWARD, theFace, aPolygon->Parameters ());
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_EdgeTessellationExtractor::~BRepMesh_EdgeTessellationExtractor ()
{
}
//=======================================================================
//function : NbPoints
//purpose :
//=======================================================================
Standard_Integer BRepMesh_EdgeTessellationExtractor::PointsNb () const
{
return myIndices->Size ();
}
//=======================================================================
@@ -47,15 +62,12 @@ BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor(
//=======================================================================
Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value (
const Standard_Integer theIndex,
Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Pnt2d& theUV)
Standard_Real& theParameter) const
{
const gp_Pnt& theRefPnt = myNodes(myIndices(theIndex));
const gp_Pnt& theRefPnt = (*myNodes) ((*myIndices) (theIndex));
thePoint = BRepMesh_ShapeTool::UseLocation (theRefPnt, myLoc);
theParameter = myProvider.Parameter (theIndex, thePoint);
theUV = myPCurve->Value(theParameter);
return Standard_True;
}

View File

@@ -1,6 +1,6 @@
// Created on: 2014-08-13
// Created on: 2016-04-19
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
// Copyright (c) 2011-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
@@ -16,72 +16,48 @@
#ifndef _BRepMesh_EdgeTessellationExtractor_HeaderFile
#define _BRepMesh_EdgeTessellationExtractor_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <BRepMesh_IEdgeTool.hxx>
#include <IMeshTools_CurveTessellator.hxx>
#include <IMeshData_Types.hxx>
#include <BRepMesh_EdgeParameterProvider.hxx>
#include <TopLoc_Location.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfInteger.hxx>
class Poly_Triangulation;
class Poly_PolygonOnTriangulation;
class TopoDS_Edge;
class TopoDS_Face;
class Geom2dAdaptor_HCurve;
#include <TopLoc_Location.hxx>
//! Auxiliary class implements functionality retrieving tessellated
//! representation of an edge stored in polygon.
class BRepMesh_EdgeTessellationExtractor : public BRepMesh_IEdgeTool
class BRepMesh_EdgeTessellationExtractor : public IMeshTools_CurveTessellator
{
public:
//! Constructor.
//! Initializes extractor.
BRepMesh_EdgeTessellationExtractor(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& thePCurve,
const TopoDS_Face& theFace,
const Handle(Poly_Triangulation)& theTriangulation,
const Handle(Poly_PolygonOnTriangulation)& thePolygon,
const TopLoc_Location& theLocation);
Standard_EXPORT BRepMesh_EdgeTessellationExtractor (
const IMeshData::IEdgeHandle& theEdge,
const IMeshData::IFaceHandle& theFace);
//! Returns number of dicretization points.
virtual Standard_Integer NbPoints() const Standard_OVERRIDE
{
return myIndices.Length();
}
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_EdgeTessellationExtractor ();
//! Returns number of tessellation points.
Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE;
//! Returns parameters of solution with the given index.
//! @param theIndex index of tessellation point.
//! @param theParameter parameters on PCurve corresponded to the solution.
//! @param thePoint tessellation point.
//! @param theUV coordinates of tessellation point in parametric space of face.
//! @return True in case of valid result, false elewhere.
virtual Standard_Boolean Value(
Standard_EXPORT virtual Standard_Boolean Value (
const Standard_Integer theIndex,
Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Pnt2d& theUV) Standard_OVERRIDE;
Standard_Real& theParameter) const Standard_OVERRIDE;
DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool)
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeTessellationExtractor, IMeshTools_CurveTessellator)
private:
//! Assignment operator.
void operator =(const BRepMesh_EdgeTessellationExtractor& /*theOther*/)
{
}
private:
BRepMesh_EdgeParameterProvider myProvider;
Handle(Geom2dAdaptor_HCurve) myPCurve;
const TColgp_Array1OfPnt& myNodes;
const TColStd_Array1OfInteger& myIndices;
const TopLoc_Location myLoc;
BRepMesh_EdgeParameterProvider<Handle(TColStd_HArray1OfReal)> myProvider;
const TColgp_Array1OfPnt* myNodes;
const TColStd_Array1OfInteger* myIndices;
TopLoc_Location myLoc;
};
DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool)
#endif

View File

@@ -1,264 +0,0 @@
// Created on: 2014-08-13
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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 <BRepMesh_EdgeTessellator.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopLoc_Location.hxx>
#include <BRep_Tool.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopoDS.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TColStd_Array1OfReal.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool)
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator(
const TopoDS_Edge& theEdge,
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Real theMinSize)
: mySurface(theFaceAttribute->Surface())
{
Standard_Real aPreciseAngDef = 0.5 * theAngDeflection;
Standard_Real aPreciseLinDef = 0.5 * theLinDeflection;
if (theEdge.Orientation() == TopAbs_INTERNAL)
aPreciseLinDef *= 0.5;
mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize);
myEdgeSqTol = BRep_Tool::Tolerance (theEdge);
myEdgeSqTol *= myEdgeSqTol;
Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge);
if (isSameParam)
myCOnS.Initialize(theEdge);
else
myCOnS.Initialize(theEdge, theFaceAttribute->Face());
const GeomAbs_CurveType aCurveType = myCOnS.GetType();
Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287
// Get 2d curve and init geom tool
Standard_Real aFirstParam, aLastParam;
Handle(Geom2d_Curve) aCurve2d =
BRep_Tool::CurveOnSurface(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam);
myCurve2d.Load(aCurve2d, aFirstParam, aLastParam);
myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam,
aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
if (aCurveType == GeomAbs_BSplineCurve)
{
// bug24220
const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1);
if ( aNbInt > 1 )
{
TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 );
myCOnS.Intervals(anIntervals, GeomAbs_C1);
for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt)
{
const Standard_Real& aStartInt = anIntervals.Value( aIntIt );
const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 );
BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt,
aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize);
Standard_Integer aNbAddNodes = aDetalizator.NbPoints();
for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt )
{
Standard_Real aParam;
gp_Pnt aPoint3d;
gp_Pnt2d aPoint2d;
aDetalizator.Value( aNodeIt, aParam, aPoint3d);
myCurve2d.D0(aParam, aPoint2d);
myTool->AddPoint( aPoint3d, aParam, Standard_False );
}
}
}
}
// PTv, chl/922/G9, Take into account internal vertices
// it is necessary for internal edges, which do not split other edges, by their vertex
TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX);
for (; aVertexIt.More(); aVertexIt.Next())
{
const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current());
if (aVertex.Orientation() != TopAbs_INTERNAL)
continue;
myTool->AddPoint(BRep_Tool::Pnt(aVertex),
BRep_Tool::Parameter(aVertex, theEdge), Standard_True);
}
Standard_Integer aNodesNb = myTool->NbPoints();
//Check deflection in 2d space for improvement of edge tesselation.
if( isSameParam && aNodesNb > 1)
{
const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge);
TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces);
for (; aFaceIt.More(); aFaceIt.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value());
BRepAdaptor_Surface aSurf(aFace, Standard_False);
if (aSurf.GetType() == GeomAbs_Plane)
continue;
Standard_Real aF, aL;
aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL);
if ( Abs(aF - aFirstParam) > Precision::PConfusion() ||
Abs(aL - aLastParam ) > Precision::PConfusion() )
{
continue;
}
Geom2dAdaptor_Curve aGACurve(aCurve2d, aF, aL);
aNodesNb = myTool->NbPoints();
TColStd_Array1OfReal aParamArray(1, aNodesNb);
for (Standard_Integer i = 1; i <= aNodesNb; ++i)
{
gp_Pnt aTmpPnt;
Standard_Real aParam;
myTool->Value(i, aParam, aTmpPnt);
aParamArray.SetValue(i, aParam);
}
for (Standard_Integer i = 1; i < aNodesNb; ++i)
splitSegment(aSurf, aGACurve, aParamArray(i), aParamArray(i + 1), 1);
}
}
const Standard_Real aTol = Precision::Confusion();
const Standard_Real aDu = mySurface->UResolution (aTol);
const Standard_Real aDv = mySurface->VResolution (aTol);
myFaceRangeU[0] = mySurface->FirstUParameter() - aDu;
myFaceRangeU[1] = mySurface->LastUParameter() + aDu;
myFaceRangeV[0] = mySurface->FirstVParameter() - aDv;
myFaceRangeV[1] = mySurface->LastVParameter() + aDv;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_EdgeTessellator::Value(
const Standard_Integer theIndex,
Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Pnt2d& theUV)
{
myTool->Value(theIndex, theParameter, thePoint);
myCurve2d.D0(theParameter, theUV);
// If point coordinates are out of surface range,
// it is necessary to re-project point.
if (mySurface->GetType() != GeomAbs_BSplineSurface &&
mySurface->GetType() != GeomAbs_BezierSurface &&
mySurface->GetType() != GeomAbs_OtherSurface)
{
return Standard_True;
}
// Let skip periodic case.
if (mySurface->IsUPeriodic() || mySurface->IsVPeriodic())
return Standard_True;
// Point lies within the surface range - nothing to do.
if (theUV.X() > myFaceRangeU[0] && theUV.X() < myFaceRangeU[1] &&
theUV.Y() > myFaceRangeV[0] && theUV.Y() < myFaceRangeV[1])
{
return Standard_True;
}
gp_Pnt aPntOnSurf;
mySurface->D0 (theUV.X (), theUV.Y (), aPntOnSurf);
return (thePoint.SquareDistance (aPntOnSurf) < myEdgeSqTol);
}
//=======================================================================
//function : splitSegment
//purpose :
//=======================================================================
void BRepMesh_EdgeTessellator::splitSegment(
const Adaptor3d_Surface& theSurf,
const Geom2dAdaptor_Curve& theCurve2d,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Integer theNbIter)
{
// limit iteration depth
if(theNbIter > 10)
return;
gp_Pnt2d uvf, uvl, uvm;
gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf;
Standard_Real midpar;
if(Abs(theLast - theFirst) < 2 * Precision::PConfusion())
return;
theCurve2d.D0(theFirst, uvf);
theCurve2d.D0(theLast, uvl);
P3dF = theSurf.Value(uvf.X(), uvf.Y());
P3dL = theSurf.Value(uvl.X(), uvl.Y());
if(P3dF.SquareDistance(P3dL) < mySquareMinSize)
return;
uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5);
midP3dFromSurf = theSurf.Value(uvm.X(), uvm.Y());
gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ();
if(Vec1.SquareModulus() < mySquareMinSize)
return;
gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ();
aVec.Normalize();
Standard_Real aModulus = Vec1.Dot(aVec);
gp_XYZ aProj = aVec * aModulus;
gp_XYZ aDist = Vec1 - aProj;
if(aDist.SquareModulus() < mySquareEdgeDef)
return;
midpar = (theFirst + theLast) * 0.5;
myCOnS.D0(midpar, midP3d);
myTool->AddPoint(midP3d, midpar, Standard_False);
splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1);
splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1);
}

View File

@@ -1,93 +0,0 @@
// Created on: 2014-08-13
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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.
#ifndef _BRepMesh_EdgeTessellator_HeaderFile
#define _BRepMesh_EdgeTessellator_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <BRepMesh.hxx>
#include <BRepMesh_IEdgeTool.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <BRepMesh_FaceAttribute.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
class Adaptor3d_Surface;
class TopoDS_Edge;
class BRepAdaptor_HSurface;
//! Auxiliary class implements functionality producing tessellated
//! representation of an edge based on edge geometry.
class BRepMesh_EdgeTessellator : public BRepMesh_IEdgeTool
{
public:
//! Constructor.
//! Automatically performs tessellation of the edge according to the
//! given parameters.
BRepMesh_EdgeTessellator(
const TopoDS_Edge& theEdge,
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute,
const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Real theMinSize);
//! Returns number of dicretization points.
virtual Standard_Integer NbPoints() const Standard_OVERRIDE
{
return myTool->NbPoints();
}
//! Returns parameters of solution with the given index.
//! @param theIndex index of tessellation point.
//! @param theParameter parameters on PCurve corresponded to the solution.
//! @param thePoint tessellation point.
//! @param theUV coordinates of tessellation point in parametric space of face.
//! @return True in case of valid result, false elewhere.
virtual Standard_Boolean Value(
const Standard_Integer theIndex,
Standard_Real& theParameter,
gp_Pnt& thePoint,
gp_Pnt2d& theUV) Standard_OVERRIDE;
DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool)
private:
//!
void splitSegment(const Adaptor3d_Surface& theSurf,
const Geom2dAdaptor_Curve& theCurve2d,
const Standard_Real theFirst,
const Standard_Real theLast,
const Standard_Integer theNbIter);
private:
NCollection_Handle<BRepMesh_GeomTool> myTool;
Handle(BRepAdaptor_HSurface) mySurface;
BRepAdaptor_Curve myCOnS;
Geom2dAdaptor_Curve myCurve2d;
Standard_Real mySquareEdgeDef;
Standard_Real mySquareMinSize;
Standard_Real myEdgeSqTol;
Standard_Real myFaceRangeU[2];
Standard_Real myFaceRangeV[2];
};
DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool)
#endif

View File

@@ -1,257 +0,0 @@
// Created by: Ekaterina SMIRNOVA
// Copyright (c) 2008-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 <BRepMesh_FaceAttribute.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepTools.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Iterator.hxx>
#include <BRep_Tool.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient)
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_FaceAttribute::BRepMesh_FaceAttribute()
: myDefFace (0.),
myUMin (0.),
myUMax (0.),
myVMin (0.),
myVMax (0.),
myDeltaX (1.),
myDeltaY (1.),
myMinStep (-1.),
myStatus (BRepMesh_NoError),
myAdaptiveMin (Standard_False)
{
init();
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints)
: myDefFace (0.),
myUMin (0.),
myUMax (0.),
myVMin (0.),
myVMax (0.),
myDeltaX (1.),
myDeltaY (1.),
myMinStep (-1.),
myStatus (BRepMesh_NoError),
myAdaptiveMin (Standard_False),
myBoundaryVertices(theBoundaryVertices),
myBoundaryPoints (theBoundaryPoints)
{
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_FaceAttribute::BRepMesh_FaceAttribute(
const TopoDS_Face& theFace,
const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints,
const Standard_Boolean theAdaptiveMin)
: myDefFace (0.),
myUMin (0.),
myUMax (0.),
myVMin (0.),
myVMax (0.),
myDeltaX (1.),
myDeltaY (1.),
myMinStep (-1.),
myStatus (BRepMesh_NoError),
myAdaptiveMin (theAdaptiveMin),
myBoundaryVertices(theBoundaryVertices),
myBoundaryPoints (theBoundaryPoints),
myFace (theFace)
{
init();
}
//=======================================================================
//function : Destructor
//purpose :
//=======================================================================
BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute()
{
}
//=======================================================================
//function : SetFace
//purpose :
//=======================================================================
void BRepMesh_FaceAttribute::SetFace (
const TopoDS_Face& theFace,
const Standard_Boolean theAdaptiveMin)
{
myFace = theFace;
myAdaptiveMin = theAdaptiveMin;
init ();
}
//=======================================================================
//function : init
//purpose :
//=======================================================================
void BRepMesh_FaceAttribute::init()
{
myVertexEdgeMap = new BRepMesh::IMapOfInteger;
myInternalEdges = new BRepMesh::DMapOfShapePairOfPolygon;
myLocation2D = new BRepMesh::DMapOfIntegerListOfXY;
myClassifier = new BRepMesh_Classifier;
if (myFace.IsNull())
return;
BRepTools::Update(myFace);
myFace.Orientation(TopAbs_FORWARD);
BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax);
if (myAdaptiveMin)
{
// compute minimal UV distance
// between vertices
myMinStep = RealLast();
for (TopoDS_Iterator aFaceIt(myFace); aFaceIt.More(); aFaceIt.Next())
{
for (TopoDS_Iterator aWireIt(aFaceIt.Value()); aWireIt.More(); aWireIt.Next())
{
const TopoDS_Edge& anEdge = TopoDS::Edge(aWireIt.Value());
if (anEdge.IsNull() || BRep_Tool::IsClosed(anEdge))
continue;
// Get end points on 2d curve
gp_Pnt2d aFirst2d, aLast2d;
BRep_Tool::UVPoints(anEdge, myFace, aFirst2d, aLast2d);
Standard_Real aDist =aFirst2d.Distance(aLast2d);
if (aDist < myMinStep)
myMinStep = aDist;
}
}
}
BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False);
mySurface = new BRepAdaptor_HSurface(aSurfAdaptor);
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepMesh_FaceAttribute::Clear()
{
myStructure.Nullify();
myLocation2D->Clear();
myInternalEdges->Clear();
myVertexEdgeMap->Clear();
}
//=======================================================================
//function : computeParametricTolerance
//purpose :
//=======================================================================
Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance(
const Standard_Real theFirstParam,
const Standard_Real theLastParam) const
{
const Standard_Real aDeflectionUV = 1.e-05;
Standard_Real aPreci = (theLastParam - theFirstParam) * aDeflectionUV;
if(myAdaptiveMin && myMinStep < aPreci)
aPreci = myMinStep;
return Max(Precision::PConfusion(), aPreci);
}
//=======================================================================
//function : getVertexIndex
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex(
const TopoDS_Vertex& theVertex,
Standard_Integer& theVertexIndex) const
{
if (!myBoundaryVertices.IsNull() && myBoundaryVertices->IsBound(theVertex))
theVertexIndex = myBoundaryVertices->Find(theVertex);
else if (!mySurfaceVertices.IsNull() && mySurfaceVertices->IsBound(theVertex))
theVertexIndex = mySurfaceVertices->Find(theVertex);
else
return Standard_False;
return Standard_True;
}
//=======================================================================
//function : AddNode
//purpose :
//=======================================================================
void BRepMesh_FaceAttribute::AddNode(
const Standard_Integer theIndex,
const gp_XY& theUV,
const BRepMesh_DegreeOfFreedom theMovability,
Standard_Integer& theNodeIndex,
Standard_Integer& theNodeOnEdgeIndex)
{
BRepMesh_Vertex aNode(theUV, theIndex, theMovability);
theNodeIndex = myStructure->AddNode(aNode);
theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex);
if (theNodeOnEdgeIndex == 0)
theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex);
}
//=======================================================================
//function : Scale
//purpose :
//=======================================================================
gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY& thePoint2d,
const Standard_Boolean isToFaceBasis)
{
return isToFaceBasis ?
gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) :
gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin);
}
//=======================================================================
//function : ToleranceU
//purpose :
//=======================================================================
Standard_Real BRepMesh_FaceAttribute::ToleranceU() const
{
return computeParametricTolerance(myUMin, myUMax);
}
//=======================================================================
//function : ToleranceV
//purpose :
//=======================================================================
Standard_Real BRepMesh_FaceAttribute::ToleranceV() const
{
return computeParametricTolerance(myVMin, myVMax);
}

View File

@@ -1,405 +0,0 @@
// Copyright (c) 2013 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.
#ifndef _BRepMesh_FaceAttribute_HeaderFile
#define _BRepMesh_FaceAttribute_HeaderFile
#include <Standard.hxx>
#include <Standard_Transient.hxx>
#include <Standard_Type.hxx>
#include <BRepMesh_Status.hxx>
#include <BRepMesh.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
class BRepAdaptor_HSurface;
//! Auxiliary class for FastDiscret and FastDiscretFace classes.
class BRepMesh_FaceAttribute : public Standard_Transient
{
public:
//! Constructor. Initializes empty attribute.
//! @param theBoundaryVertices shared map of shape vertices.
//! @param theBoundaryPoints shared discretization points of shape boundaries.
Standard_EXPORT BRepMesh_FaceAttribute(
const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints);
//! Constructor.
//! @param theFace face the attribute is created for.
//! Used for default initialization. Attribute keeps reference
//! to the source face with forward orientation.
//! @param theBoundaryVertices shared map of shape vertices.
//! @param theBoundaryPoints shared discretization points of shape boundaries.
//! @param theAdaptiveMin switches on adaptive computation of minimal parametric
//! tolerance (if true).
Standard_EXPORT BRepMesh_FaceAttribute(
const TopoDS_Face& theFace,
const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices,
const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints,
const Standard_Boolean theAdaptiveMin);
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_FaceAttribute();
public: //! @name main geometrical properties.
//! Returns face's surface.
inline const Handle(BRepAdaptor_HSurface)& Surface() const
{
return mySurface;
}
//! Returns True in case if this attribute has already been intialized.
inline Standard_Boolean IsInitialized () const
{
return !myFace.IsNull ();
}
//! Initializes this attribute by the given face.
Standard_EXPORT void SetFace (
const TopoDS_Face& theFace,
const Standard_Boolean theAdaptiveMin);
//! Returns forward oriented face to be used for calculations.
inline const TopoDS_Face& Face() const
{
return myFace;
}
//! Sets boundary vertices map.
inline void SetBoundaryVertices(const BRepMesh::HDMapOfVertexInteger& theVertices)
{
myBoundaryVertices = theVertices;
}
//! Sets boundary points map.
inline void SetBoundaryPoints(const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints)
{
myBoundaryPoints = theBoundaryPoints;
}
//! Returns U tolerance of face calculated regarding its parameters.
Standard_EXPORT Standard_Real ToleranceU() const;
//! Returns V tolerance of face calculated regarding its parameters.
Standard_EXPORT Standard_Real ToleranceV() const;
//! Gives face deflection parameter.
inline Standard_Real GetDefFace() const
{
return myDefFace;
}
//! Sets face deflection.
inline void SetDefFace(const Standard_Real theDefFace)
{
myDefFace = theDefFace;
}
//! Gives minimal value in U domain.
inline Standard_Real GetUMin() const
{
return myUMin;
}
//! Sets minimal value in U domain.
inline void SetUMin(const Standard_Real theUMin)
{
myUMin = theUMin;
}
//! Gives minimal value in V domain.
inline Standard_Real GetVMin() const
{
return myVMin;
}
//! Sets minimal value in V domain.
inline void SetVMin(const Standard_Real theVMin)
{
myVMin = theVMin;
}
//! Gives maximal value in U domain.
inline Standard_Real GetUMax() const
{
return myUMax;
}
//! Sets maximal value in U domain.
inline void SetUMax(const Standard_Real theUMax)
{
myUMax = theUMax;
}
//! Gives maximal value in V domain.
inline Standard_Real GetVMax() const
{
return myVMax;
}
//! Sets maximal value in V domain.
inline void SetVMax(const Standard_Real theVMax)
{
myVMax = theVMax;
}
//! Gives value of step in U domain.
inline Standard_Real GetDeltaX() const
{
return myDeltaX;
}
//! Sets value of step in U domain.
inline void SetDeltaX(const Standard_Real theDeltaX)
{
myDeltaX = theDeltaX;
}
//! Gives value of step in V domain.
inline Standard_Real GetDeltaY() const
{
return myDeltaY;
}
//! Sets value of step in V domain.
inline void SetDeltaY(const Standard_Real theDeltaY)
{
myDeltaY = theDeltaY;
}
//! Sets set of status flags for this face.
inline Standard_Integer GetStatus() const
{
return myStatus;
}
//! Sets status flag for this face.
inline void SetStatus(const BRepMesh_Status theStatus)
{
myStatus |= theStatus;
}
//! Returns TRUE in case if computed data is valid.
inline Standard_Boolean IsValid() const
{
return (myStatus == BRepMesh_NoError || myStatus == BRepMesh_ReMesh);
}
public: //! @name auxiliary structures
//! Clear face attribute.
Standard_EXPORT void Clear();
//! Gives reference to map of internal edges of face.
inline BRepMesh::HDMapOfShapePairOfPolygon& ChangeInternalEdges()
{
return myInternalEdges;
}
//! Gives reference to map of 2D points of discretization.
inline BRepMesh::HDMapOfIntegerListOfXY& ChangeLocation2D()
{
return myLocation2D;
}
//! Gives reference to map of 3D points of discretization.
inline BRepMesh::HDMapOfIntegerPnt& ChangeSurfacePoints()
{
return mySurfacePoints;
}
//! Gives reference to map of vertices of discretization.
inline BRepMesh::HDMapOfVertexInteger& ChangeSurfaceVertices()
{
return mySurfaceVertices;
}
//! Gives reference on map of (vertex, edge) pairs of face.
inline BRepMesh::HIMapOfInteger& ChangeVertexEdgeMap()
{
return myVertexEdgeMap;
}
//! Gives Delaunay data structure.
inline Handle(BRepMesh_DataStructureOfDelaun)& ChangeStructure()
{
return myStructure;
}
//! Returns classifier.
inline BRepMesh::HClassifier& ChangeClassifier()
{
return myClassifier;
}
//! Returns mesh nodes calculated for boundaries.
inline BRepMesh::HVectorOfVertex& ChangeMeshNodes()
{
return myMeshNodes;
}
public: //! @name Point/Vertex/Node manipulators
//! Gives the number of different locations in 3D space.
inline Standard_Integer LastPointId() const
{
return (myBoundaryPoints.IsNull() ? 0 : myBoundaryPoints->Extent()) +
(mySurfacePoints.IsNull() ? 0 : mySurfacePoints->Extent());
}
//! Gives the 3D location of the vertex.
inline const gp_Pnt& GetPoint(const BRepMesh_Vertex& theVertex) const
{
return GetPoint(theVertex.Location3d());
}
//! Gives the 3D location of the vertex.
inline const gp_Pnt& GetPoint(const Standard_Integer theIndex) const
{
if (!mySurfacePoints.IsNull() && theIndex > myBoundaryPoints->Extent())
return mySurfacePoints->Find(theIndex);
return myBoundaryPoints->Find(theIndex);
}
//! Returns index of the given vertex if it exists in cache,
//! elsewhere adds it to cache and returns cached index.
//! @param theVertexExplorer template parameter intended to transfer
//! parameters of vertex to method. Explorer class can implement different
//! approaches of extraction of target parameters.
//! @param isFillEdgeVertices if TRUE adds vertex to shared map of
//! edges vertices, elsewhere adds it map of face vertices.
template<class HVertexExplorer>
Standard_Integer GetVertexIndex(
const HVertexExplorer& theVertexExplorer,
const Standard_Boolean isFillEdgeVertices = Standard_False)
{
const TopoDS_Vertex& aVertex = theVertexExplorer->Vertex();
Standard_Integer aNewVertexIndex = 0;
if (getVertexIndex(aVertex, aNewVertexIndex))
return aNewVertexIndex;
if (!theVertexExplorer->IsSameUV() ||
!getVertexIndex(theVertexExplorer->SameVertex(), aNewVertexIndex))
{
aNewVertexIndex = LastPointId() + 1;
BRepMesh::DMapOfIntegerPnt& aPointsMap = isFillEdgeVertices ?
*myBoundaryPoints : *mySurfacePoints;
aPointsMap.Bind(aNewVertexIndex, theVertexExplorer->Point());
}
BRepMesh::DMapOfVertexInteger& aVertexMap = isFillEdgeVertices ?
*myBoundaryVertices : *mySurfaceVertices;
aVertexMap.Bind(aVertex, aNewVertexIndex);
return aNewVertexIndex;
}
//! Adds node with the given parameters to mesh.
//! @param theIndex index of 3D point corresponded to the node.
//! @param theUV node position.
//! @param theMovability movability of a node.
//! @param theNodeIndex index of vertex in mesh structure.
//! @param theNodeOnEdgeIndex ordered index of node on the boundary.
Standard_EXPORT void AddNode(const Standard_Integer theIndex,
const gp_XY& theUV,
const BRepMesh_DegreeOfFreedom theMovability,
Standard_Integer& theNodeIndex,
Standard_Integer& theNodeOnEdgeIndex);
public: //! @name Auxiliary methods
//! Scales the given point from real parametric space
//! to face basis and otherwise.
//! @param thePoint2d point to be scaled.
//! @param isToFaceBasis if TRUE converts point to face basis,
//! otherwise performs reverse conversion.
//! @return scaled point.
Standard_EXPORT gp_XY Scale(const gp_XY& thePoint2d,
const Standard_Boolean isToFaceBasis);
DEFINE_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient)
private:
//! Default constructor.
BRepMesh_FaceAttribute();
//! Assignment operator.
void operator =(const BRepMesh_FaceAttribute& /*theOther*/)
{
}
//! Initializes internal data structures.
void init();
//! Computes parametric tolerance of a face regarding the given limits.
Standard_Real computeParametricTolerance(
const Standard_Real theFirstParam,
const Standard_Real theLastParam) const;
//! Clears internal data structures local to face.
void clearLocal(
const Standard_Boolean isClearSurfaceDataOnly = Standard_False);
//! Returns index of the given vertex if it exists in cache.
//! @param theVertex vertex which index should be retrieved.
//! @param theVertexIndex index of the given vertex.
//! @return TRUE if cached value is found, FALSE elsewhere.
Standard_EXPORT Standard_Boolean getVertexIndex(
const TopoDS_Vertex& theVertex,
Standard_Integer& theVertexIndex) const;
private:
Standard_Real myDefFace; //!< Restore face deflection
Standard_Real myUMin; //!< Describes minimal value in U domain
Standard_Real myUMax; //!< Describes maximal value in U domain
Standard_Real myVMin; //!< Describes minimal value in V domain
Standard_Real myVMax; //!< Describes maximal value in V domain
Standard_Real myDeltaX;
Standard_Real myDeltaY;
Standard_Real myMinStep;
Standard_Integer myStatus;
Standard_Boolean myAdaptiveMin;
BRepMesh::HDMapOfVertexInteger myBoundaryVertices;
BRepMesh::HDMapOfIntegerPnt myBoundaryPoints;
TopoDS_Face myFace;
Handle(BRepAdaptor_HSurface) mySurface;
BRepMesh::HClassifier myClassifier;
BRepMesh::HDMapOfShapePairOfPolygon myInternalEdges;
BRepMesh::HDMapOfIntegerListOfXY myLocation2D;
BRepMesh::HIMapOfInteger myVertexEdgeMap;
// This field is intended to keep calculated mesh nodes to prevent
// extremely high memory consumption in case if the whole structure is kept.
BRepMesh::HVectorOfVertex myMeshNodes;
BRepMesh::HDMapOfVertexInteger mySurfaceVertices;
BRepMesh::HDMapOfIntegerPnt mySurfacePoints;
Handle(BRepMesh_DataStructureOfDelaun) myStructure;
};
DEFINE_STANDARD_HANDLE(BRepMesh_FaceAttribute, Standard_Transient)
#endif

View File

@@ -0,0 +1,312 @@
// 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_FaceChecker.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <OSD_Parallel.hxx>
#include <BRepMesh_GeomTool.hxx>
namespace
{
const Standard_Real MaxTangentAngle = 5. * M_PI / 180.;
//! Functor to be used to fill segments and bounding box tree in parallel.
class SegmentsFiller
{
public:
//! Constructor.
SegmentsFiller(const IMeshData::IFaceHandle& theDFace,
Handle(BRepMesh_FaceChecker::ArrayOfSegments)& theWiresSegments,
Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& theWiresBndBoxTree)
: myDFace(theDFace),
myWiresSegments(theWiresSegments),
myWiresBndBoxTree(theWiresBndBoxTree)
{
myWiresSegments = new BRepMesh_FaceChecker::ArrayOfSegments (0, myDFace->WiresNb() - 1);
myWiresBndBoxTree = new BRepMesh_FaceChecker::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1);
}
//! Performs initialization of wire with the given index.
void operator()(const Standard_Integer theWireIndex) const
{
const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex);
Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator();
Handle(BRepMesh_FaceChecker::Segments) aSegments =
new BRepMesh_FaceChecker::Segments(aDWire->EdgesNb(), aTmpAlloc1);
Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1);
myWiresSegments ->ChangeValue(theWireIndex) = aSegments;
myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree;
Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator();
IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2);
for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
{
// TODO: check 2d wire for consistency.
const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge(aEdgeIt);
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt)
{
gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1);
gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt);
Bnd_Box2d aBox;
aBox.Add(aPnt1);
aBox.Add(aPnt2);
aBox.Enlarge(Precision::Confusion());
aBndBoxTreeFiller.Add(aSegments->Size(), aBox);
aSegments->Append(BRepMesh_FaceChecker::Segment(aDEdge, &aPnt1, &aPnt2));
}
}
aBndBoxTreeFiller.Fill();
}
private:
SegmentsFiller (const SegmentsFiller& theOther);
void operator=(const SegmentsFiller& theOther);
private:
const IMeshData::IFaceHandle& myDFace;
Handle(BRepMesh_FaceChecker::ArrayOfSegments)& myWiresSegments;
Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& myWiresBndBoxTree;
};
//! Selector.
//! Used to identify segments with overlapped bounding boxes.
class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector
{
public:
//! Constructor.
BndBox2dTreeSelector(const Standard_Real theTolerance)
: myMaxLoopSize(M_PI * theTolerance * theTolerance),
mySelfSegmentIndex(-1),
myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
{
}
//! Sets working set of segments.
void SetSegments(const Handle(BRepMesh_FaceChecker::Segments)& theSegments)
{
mySegments = theSegments;
}
//! Resets current selector.
void Reset(const BRepMesh_FaceChecker::Segment* theSegment,
const Standard_Integer theSelfSegmentIndex)
{
myIndices.Clear();
mySelfSegmentIndex = theSelfSegmentIndex;
mySegment = theSegment;
myBox.SetVoid();
myBox.Add(*mySegment->Point1);
myBox.Add(*mySegment->Point2);
myBox.Enlarge(Precision::Confusion());
}
//! Indicates should the given box be rejected or not.
virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const
{
return myBox.IsOut(theBox);
}
//! Accepts segment with the given index in case if it fits conditions.
virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex)
{
const BRepMesh_FaceChecker::Segment& aSegment = mySegments->Value(theSegmentIndex);
gp_Pnt2d aIntPnt;
const BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
mySegment->Point1->XY(), mySegment->Point2->XY(),
aSegment.Point1->XY(), aSegment.Point2->XY(),
Standard_False, Standard_False, aIntPnt);
if (aIntStatus == BRepMesh_GeomTool::Cross)
{
const Standard_Real aAngle = gp_Vec2d(mySegment->Point1->XY(), mySegment->Point2->XY()).Angle(
gp_Vec2d(aSegment.Point1->XY(), aSegment.Point2->XY()));
if (Abs(aAngle) < MaxTangentAngle)
{
return Standard_False;
}
if (mySelfSegmentIndex != -1)
{
gp_XY aPrevVec;
Standard_Real aSumS = 0.;
const gp_XY& aRefPnt = aIntPnt.Coord();
for (Standard_Integer i = mySelfSegmentIndex; i < theSegmentIndex; ++i)
{
const BRepMesh_FaceChecker::Segment& aCurrSegment = mySegments->Value(i);
gp_XY aCurVec = aCurrSegment.Point2->XY() - aRefPnt;
if (aCurVec.SquareModulus() < gp::Resolution())
continue;
if (aPrevVec.SquareModulus() > gp::Resolution())
aSumS += aPrevVec ^ aCurVec;
aPrevVec = aCurVec;
}
if (Abs(aSumS / 2.) < myMaxLoopSize)
{
return Standard_False;
}
}
myIndices.Append(theSegmentIndex);
return Standard_True;
}
return Standard_False;
}
//! Returns indices of intersecting segments.
const IMeshData::VectorOfInteger& Indices() const
{
return myIndices;
}
private:
Standard_Real myMaxLoopSize;
Standard_Integer mySelfSegmentIndex;
Handle(BRepMesh_FaceChecker::Segments) mySegments;
const BRepMesh_FaceChecker::Segment* mySegment;
Bnd_Box2d myBox;
IMeshData::VectorOfInteger myIndices;
};
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_FaceChecker::BRepMesh_FaceChecker(
const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters)
: myDFace(theFace),
myParameters(theParameters)
{
}
//=======================================================================
//function : Destructor
//purpose :
//=======================================================================
BRepMesh_FaceChecker::~BRepMesh_FaceChecker()
{
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_FaceChecker::Perform()
{
myIntersectingEdges = new IMeshData::MapOfIEdgePtr;
collectSegments();
OSD_Parallel::For(0, myDFace->WiresNb(), *this, !isParallel());
collectResult();
myWiresBndBoxTree.Nullify();
myWiresSegments.Nullify();
myWiresIntersectingEdges.Nullify();
return myIntersectingEdges->IsEmpty();
}
//=======================================================================
//function : collectSegments
//purpose :
//=======================================================================
void BRepMesh_FaceChecker::collectSegments()
{
SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree);
OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel());
myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1);
}
//=======================================================================
//function : perform
//purpose :
//=======================================================================
void BRepMesh_FaceChecker::perform(const Standard_Integer theWireIndex) const
{
const Handle(Segments)& aSegments1 = myWiresSegments->Value(theWireIndex);
Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myWiresIntersectingEdges->ChangeValue(theWireIndex);
// TODO: Tolerance is set to twice value of face deflection in order to fit regressions.
BndBox2dTreeSelector aSelector(2 * myDFace->GetDeflection());
for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt)
{
const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt);
const Handle(Segments)& aSegments2 = myWiresSegments->Value(aWireIt);
aSelector.SetSegments(aSegments2);
for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt)
{
const BRepMesh_FaceChecker::Segment& aSegment1 = aSegments1->Value(aSegmentIt);
aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1);
if (aBndBoxTree2->Select(aSelector) != 0)
{
if (aIntersections.IsNull())
{
aIntersections = new IMeshData::MapOfIEdgePtr;
}
aIntersections->Add(aSegment1.EdgePtr);
const IMeshData::VectorOfInteger& aSegments = aSelector.Indices();
for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt)
{
const BRepMesh_FaceChecker::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt));
aIntersections->Add(aSegment2.EdgePtr);
}
}
}
}
}
//=======================================================================
//function : collectResult
//purpose :
//=======================================================================
void BRepMesh_FaceChecker::collectResult()
{
for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt)
{
const Handle(IMeshData::MapOfIEdgePtr)& aEdges = myWiresIntersectingEdges->Value(aWireIt);
if (!aEdges.IsNull())
{
myIntersectingEdges->Unite(*aEdges);
}
}
}

View File

@@ -0,0 +1,122 @@
// 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.
#ifndef _BRepMesh_FaceChecker_HeaderFile
#define _BRepMesh_FaceChecker_HeaderFile
#include <IMeshTools_Parameters.hxx>
#include <Standard_Transient.hxx>
#include <IMeshData_Face.hxx>
#include <Standard_Type.hxx>
#include <NCollection_Shared.hxx>
//! Auxiliary class checking wires of target face for self-intersections.
//! Explodes wires of discrete face on sets of segments using tessellation
//! data stored in model. Each segment is then checked for intersection with
//! other ones. All collisions are registerd and returned as result of check.
class BRepMesh_FaceChecker : public Standard_Transient
{
public: //! @name mesher API
//! Identifies segment inside face.
struct Segment
{
IMeshData::IEdgePtr EdgePtr;
gp_Pnt2d* Point1; // \ Use explicit pointers to points instead of accessing
gp_Pnt2d* Point2; // / using indices.
Segment()
: Point1(NULL)
, Point2(NULL)
{
}
Segment(const IMeshData::IEdgePtr& theEdgePtr,
gp_Pnt2d* thePoint1,
gp_Pnt2d* thePoint2)
: EdgePtr(theEdgePtr)
, Point1(thePoint1)
, Point2(thePoint2)
{
}
};
typedef NCollection_Shared<NCollection_Vector<Segment> > Segments;
typedef NCollection_Shared<NCollection_Array1<Handle(Segments)> > ArrayOfSegments;
typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::BndBox2dTree)> > ArrayOfBndBoxTree;
typedef NCollection_Shared<NCollection_Array1<Handle(IMeshData::MapOfIEdgePtr)> > ArrayOfMapOfIEdgePtr;
//! Default constructor
Standard_EXPORT BRepMesh_FaceChecker(const IMeshData::IFaceHandle& theFace,
const IMeshTools_Parameters& theParameters);
//! Destructor
Standard_EXPORT virtual ~BRepMesh_FaceChecker();
//! Performs check wires of the face for intersections.
//! @return True if there is no intersection, False elsewhere.
Standard_EXPORT Standard_Boolean Perform();
//! Returns intersecting edges.
const Handle(IMeshData::MapOfIEdgePtr)& GetIntersectingEdges() const
{
return myIntersectingEdges;
}
//! Checks wire with the given index for intersection with others.
inline void operator()(const Standard_Integer theWireIndex) const
{
perform(theWireIndex);
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceChecker, Standard_Transient)
private:
//! Returns True in case if check can be performed in parallel mode.
inline Standard_Boolean isParallel() const
{
return (myParameters.InParallel && myDFace->WiresNb() > 1);
}
//! Collects face segments.
void collectSegments();
//! Collects intersecting edges.
void collectResult();
//! Checks wire with the given index for intersection with others.
void perform(const Standard_Integer theWireIndex) const;
private:
BRepMesh_FaceChecker (const BRepMesh_FaceChecker& theOther);
void operator=(const BRepMesh_FaceChecker& theOther);
private:
IMeshData::IFaceHandle myDFace;
const IMeshTools_Parameters& myParameters;
Handle(ArrayOfSegments) myWiresSegments;
Handle(ArrayOfBndBoxTree) myWiresBndBoxTree;
Handle(ArrayOfMapOfIEdgePtr) myWiresIntersectingEdges;
Handle(IMeshData::MapOfIEdgePtr) myIntersectingEdges;
};
#endif

View File

@@ -0,0 +1,95 @@
// Created on: 2016-04-19
// 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_FaceDiscret.hxx>
#include <IMeshData_Model.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshTools_MeshAlgo.hxx>
#include <OSD_Parallel.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_FaceDiscret::BRepMesh_FaceDiscret(
const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory)
: myAlgoFactory(theAlgoFactory)
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_FaceDiscret::~BRepMesh_FaceDiscret()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_FaceDiscret::performInternal(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters)
{
myModel = theModel;
myParameters = theParameters;
if (myModel.IsNull())
{
return Standard_False;
}
OSD_Parallel::For(0, myModel->FacesNb(), *this, !(myParameters.InParallel && myModel->FacesNb() > 1));
myModel.Nullify(); // Do not hold link to model.
return Standard_True;
}
//=======================================================================
// Function: process
// Purpose :
//=======================================================================
void BRepMesh_FaceDiscret::process(const Standard_Integer theFaceIndex) const
{
const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
if (aDFace->IsSet(IMeshData_Failure) ||
aDFace->IsSet(IMeshData_Reused))
{
return;
}
try
{
OCC_CATCH_SIGNALS
Handle(IMeshTools_MeshAlgo) aMeshingAlgo =
myAlgoFactory->GetAlgo(aDFace->GetSurface()->GetType(), myParameters);
if (aMeshingAlgo.IsNull())
{
aDFace->SetStatus(IMeshData_Failure);
return;
}
aMeshingAlgo->Perform(aDFace, myParameters);
}
catch (Standard_Failure const&)
{
aDFace->SetStatus (IMeshData_Failure);
}
}

View File

@@ -0,0 +1,65 @@
// Created on: 2016-04-19
// 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.
#ifndef _BRepMesh_FaceDiscret_HeaderFile
#define _BRepMesh_FaceDiscret_HeaderFile
#include <IMeshTools_ModelAlgo.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
#include <IMeshTools_MeshAlgoFactory.hxx>
//! Class implements functionality starting triangulation of model's faces.
//! Each face is processed separately and can be executed in parallel mode.
//! Uses mesh algo factory passed as initializer to create instance of triangulation
//! algorithm according to type of surface of target face.
class BRepMesh_FaceDiscret : public IMeshTools_ModelAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_FaceDiscret(
const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory);
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_FaceDiscret();
//! Functor API to discretize the given edge.
inline void operator() (const Standard_Integer theFaceIndex) const {
process(theFaceIndex);
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceDiscret, IMeshTools_ModelAlgo)
protected:
//! Performs processing of faces of the given model.
Standard_EXPORT virtual Standard_Boolean performInternal (
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
private:
//! Checks existing discretization of the face and updates data model.
void process(const Standard_Integer theFaceIndex) const;
private:
Handle(IMeshTools_MeshAlgoFactory) myAlgoFactory;
Handle(IMeshData_Model) myModel;
IMeshTools_Parameters myParameters;
};
#endif

View File

@@ -1,989 +0,0 @@
// Created on: 1996-02-27
// Created by: Ekaterina SMIRNOVA
// Copyright (c) 1996-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 <BRepMesh_FastDiscret.hxx>
#include <BRepMesh_WireChecker.hxx>
#include <BRepMesh_FastDiscretFace.hxx>
#include <BRepMesh_FaceAttribute.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepMesh_EdgeParameterProvider.hxx>
#include <BRepMesh_IEdgeTool.hxx>
#include <BRepMesh_EdgeTessellator.hxx>
#include <BRepMesh_EdgeTessellationExtractor.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <Bnd_Box.hxx>
#include <BRepTools.hxx>
#include <BRepBndLib.hxx>
#include <BndLib_Add3dCurve.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Precision.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2dAdaptor_HCurve.hxx>
#include <Geom_Surface.hxx>
#include <Geom_Plane.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <Extrema_LocateExtPC.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <TColStd_Array1OfCharacter.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColGeom2d_SequenceOfCurve.hxx>
#include <TopTools_SequenceOfShape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopAbs.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <OSD_Parallel.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Failure.hxx>
#include <NCollection_IncAllocator.hxx>
#include <Message_ProgressSentry.hxx>
#include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
#include <BRep_PointRepresentation.hxx>
#include <vector>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient)
#define UVDEFLECTION 1.e-05
//=======================================================================
//function : BRepMesh_FastDiscret
//purpose :
//=======================================================================
BRepMesh_FastDiscret::BRepMesh_FastDiscret( const Bnd_Box& theBox,
const BRepMesh_FastDiscret::Parameters& theParams)
:
myMapdefle(1000, new NCollection_IncAllocator()),
myBoundaryVertices(new BRepMesh::DMapOfVertexInteger),
myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt),
myParameters(theParams),
myDtotale(0.)
{
if ( myParameters.Relative )
BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale);
}
//=======================================================================
//function : InitSharedFaces
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape)
{
TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces);
}
//=======================================================================
//function : Perform(shape)
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape)
{
InitSharedFaces(theShape);
std::vector<TopoDS_Face> aFaces;
TopExp_Explorer anExplorer(theShape, TopAbs_FACE);
for (; anExplorer.More(); anExplorer.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current());
Add(aFace);
aFaces.push_back(aFace);
}
OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myParameters.InParallel);
}
//=======================================================================
//function : Process
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
{
Process (theFace, NULL);
}
//=======================================================================
//function : Process
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::Process (const TopoDS_Face& theFace,
Message_ProgressSentry* theProgrEntry) const
{
Handle(BRepMesh_FaceAttribute) anAttribute;
if (GetFaceAttribute(theFace, anAttribute)
&& (theProgrEntry == NULL || theProgrEntry->More()))
{
try
{
OCC_CATCH_SIGNALS
BRepMesh_FastDiscretFace aTool(myParameters.Angle, myParameters.MinSize,
myParameters.InternalVerticesMode, myParameters.ControlSurfaceDeflection);
aTool.Perform (anAttribute, theProgrEntry);
}
catch (Standard_Failure)
{
anAttribute->SetStatus(BRepMesh_Failure);
}
}
}
//=======================================================================
//function : resetDataStructure
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::resetDataStructure()
{
Handle(NCollection_IncAllocator) aAllocator;
if (myAttribute->ChangeStructure().IsNull())
aAllocator = new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
else
aAllocator = myAttribute->ChangeStructure()->Allocator();
myAttribute->Clear();
aAllocator->Reset(Standard_False);
Handle(BRepMesh_DataStructureOfDelaun) aStructure =
new BRepMesh_DataStructureOfDelaun(aAllocator);
const Standard_Real aTolU = myAttribute->ToleranceU();
const Standard_Real aTolV = myAttribute->ToleranceV();
const Standard_Real uCellSize = 14.0 * aTolU;
const Standard_Real vCellSize = 14.0 * aTolV;
aStructure->Data()->SetCellSize ( uCellSize, vCellSize);
aStructure->Data()->SetTolerance( aTolU , aTolV );
myAttribute->ChangeStructure() = aStructure;
}
//=======================================================================
//function : Add(face)
//purpose :
//=======================================================================
Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace)
{
myAttribute.Nullify();
GetFaceAttribute(theFace, myAttribute, Standard_True);
try
{
OCC_CATCH_SIGNALS
// Initialize face attributes
if (!myAttribute->IsInitialized ())
myAttribute->SetFace (theFace, myParameters.AdaptiveMin);
BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap();
BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
resetDataStructure();
Standard_Real defedge = myParameters.Deflection;
Standard_Integer nbEdge = 0;
Standard_Real savangle = myParameters.Angle;
Standard_Real cdef;
Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace);
Standard_Real defface = 0.;
if (!myParameters.Relative)
{
defedge = Max(UVDEFLECTION, defedge);
defface = Max(myParameters.Deflection, maxdef);
}
const TopoDS_Face& aFace = myAttribute->Face();
for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next())
{
for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Value());
if (aEdge.IsNull())
continue;
if (myParameters.Relative)
{
if (!myMapdefle.IsBound(aEdge))
{
if (myEdges.IsBound(aEdge))
{
const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge);
const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
defedge = aPolygon->Deflection();
}
else
{
defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection(
aEdge, myParameters.Deflection, myDtotale, cdef);
myParameters.Angle = savangle * cdef;
}
}
else
{
defedge = myMapdefle(aEdge);
}
defface += defedge;
defface = Max(maxdef, defface);
if (!myMapdefle.IsBound(aEdge))
{
defedge = Max(UVDEFLECTION, defedge);
myMapdefle.Bind(aEdge, defedge);
}
}
else
{
if (!myMapdefle.IsBound(aEdge))
{
myMapdefle.Bind(aEdge, defedge);
}
}
Standard_Real aFirstParam, aLastParam;
Handle(Geom2d_Curve) aCurve2d =
BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam);
if (aCurve2d.IsNull())
continue;
Handle(Geom2dAdaptor_HCurve) aPCurve =
new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam);
add(aEdge, aPCurve, defedge);
myParameters.Angle = savangle;
}
}
if ( nbEdge == 0 || aVertexEdgeMap->Extent() < 3 )
{
myAttribute->ChangeStructure().Nullify();
myAttribute->SetStatus(BRepMesh_Failure);
return myAttribute->GetStatus();
}
if ( myParameters.Relative )
{
defface = defface / nbEdge;
}
else
{
defface = myParameters.Deflection;
}
defface = Max(maxdef, defface);
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
if ( aTriangulation.IsNull() )
{
Standard_Real xCur, yCur;
Standard_Real maxX, minX, maxY, minY;
minX = minY = 1.e100;
maxX = maxY =-1.e100;
Standard_Integer ipn = 0;
Standard_Integer i1 = 1;
for ( i1 = 1; i1 <= aVertexEdgeMap->Extent(); ++i1 )
{
const BRepMesh_Vertex& aVertex =
myAttribute->ChangeStructure()->GetNode(aVertexEdgeMap->FindKey(i1));
++ipn;
xCur = aVertex.Coord().X();
yCur = aVertex.Coord().Y();
minX = Min(xCur, minX);
maxX = Max(xCur, maxX);
minY = Min(yCur, minY);
maxY = Max(yCur, maxY);
}
Standard_Real myumin = minX;
Standard_Real myumax = maxX;
Standard_Real myvmin = minY;
Standard_Real myvmax = maxY;
const Standard_Real umin = gFace->FirstUParameter();
const Standard_Real umax = gFace->LastUParameter();
const Standard_Real vmin = gFace->FirstVParameter();
const Standard_Real vmax = gFace->LastVParameter();
if (myumin < umin || myumax > umax)
{
if (gFace->IsUPeriodic())
{
if ((myumax - myumin) > (umax - umin))
myumax = myumin + (umax - umin);
}
else
{
if (umin > myumin)
myumin = umin;
if (umax < myumax)
myumax = umax;
}
}
if (myvmin < vmin || myvmax > vmax)
{
if (gFace->IsVPeriodic())
{
if ((myvmax - myvmin) > (vmax - vmin))
myvmax = myvmin + (vmax - vmin);
}
else
{
if ( vmin > myvmin )
myvmin = vmin;
if (vmax < myvmax)
myvmax = vmax;
}
}
GeomAbs_SurfaceType aSurfType = gFace->GetType();
// Fast verification of the validity of calculated limits.
// If wrong, sure a problem of pcurve.
if (aSurfType == GeomAbs_BezierSurface &&
(myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) )
{
myAttribute->ChangeStructure().Nullify();
myAttribute->SetStatus(BRepMesh_Failure);
return myAttribute->GetStatus();
}
//define parameters for correct parametrics
Standard_Real deltaX = 1.0;
Standard_Real deltaY = 1.0;
{
Standard_Real aTolU, aTolV;
myAttribute->ChangeStructure()->Data()->GetTolerance(aTolU, aTolV);
const Standard_Real aTol = Sqrt(aTolU * aTolU + aTolV * aTolV);
BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
BRepMesh_WireChecker aDFaceChecker(aFace, aTol, aInternalEdges,
aVertexEdgeMap, myAttribute->ChangeStructure(),
myumin, myumax, myvmin, myvmax, myParameters.InParallel );
aDFaceChecker.ReCompute(aClassifier);
BRepMesh_Status aCheckStatus = aDFaceChecker.Status();
if (aCheckStatus == BRepMesh_SelfIntersectingWire)
{
Standard_Integer nbmaill = 0;
Standard_Real eps = Precision::Confusion();
while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh)
{
++nbmaill;
resetDataStructure();
for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next())
{
for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge)
{
const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Value());
if (anEdge.IsNull())
continue;
if (myEdges.IsBound(anEdge))
myEdges.UnBind(anEdge);
defedge = Max(myMapdefle(anEdge) / 3.0, eps);
myMapdefle.Bind(anEdge, defedge);
Standard_Real aFirstParam, aLastParam;
Handle(Geom2d_Curve) aCurve2d =
BRep_Tool::CurveOnSurface(anEdge, aFace, aFirstParam, aLastParam);
if (aCurve2d.IsNull())
continue;
Handle(Geom2dAdaptor_HCurve) aPCurve =
new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam);
add(anEdge, aPCurve, defedge);
}
}
aDFaceChecker.ReCompute(aClassifier);
if (aDFaceChecker.Status() == BRepMesh_NoError)
aCheckStatus = BRepMesh_ReMesh;
}
}
myAttribute->SetStatus(aCheckStatus);
if (!myAttribute->IsValid())
{
myAttribute->ChangeStructure().Nullify();
return myAttribute->GetStatus();
}
}
// try to find the real length:
// akm (bug OCC16) : We must calculate these measures in non-singular
// parts of face. Let's try to compute average value of three
// (umin, (umin+umax)/2, umax), and respectively for v.
// vvvvv
Standard_Real longu = 0.0, longv = 0.0; //, last , first;
gp_Pnt P11, P12, P21, P22, P31, P32;
Standard_Real du = 0.05 * ( myumax - myumin );
Standard_Real dv = 0.05 * ( myvmax - myvmin );
Standard_Real dfuave = 0.5 * ( myumin + myumax );
Standard_Real dfvave = 0.5 * ( myvmin + myvmax );
Standard_Real dfucur, dfvcur;
// U loop
gFace->D0(myumin, myvmin, P11);
gFace->D0(myumin, dfvave, P21);
gFace->D0(myumin, myvmax, P31);
for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du)
{
gFace->D0(dfucur, myvmin, P12);
gFace->D0(dfucur, dfvave, P22);
gFace->D0(dfucur, myvmax, P32);
longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
P11 = P12;
P21 = P22;
P31 = P32;
}
// V loop
gFace->D0(myumin, myvmin, P11);
gFace->D0(dfuave, myvmin, P21);
gFace->D0(myumax, myvmin, P31);
for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv)
{
gFace->D0(myumin, dfvcur, P12);
gFace->D0(dfuave, dfvcur, P22);
gFace->D0(myumax, dfvcur, P32);
longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) );
P11 = P12;
P21 = P22;
P31 = P32;
}
longu /= 3.;
longv /= 3.;
// akm (bug OCC16) ^^^^^
if (longu <= 1.e-16 || longv <= 1.e-16)
{
//yes, it is seen!!
myAttribute->ChangeStructure().Nullify();
myAttribute->SetStatus(BRepMesh_Failure);
return myAttribute->GetStatus();
}
if (aSurfType == GeomAbs_Torus)
{
gp_Torus Tor = gFace->Torus();
Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius();
Standard_Real Du, Dv;//, pasu, pasv;
Dv = Max(1.0e0 - (defface/r),0.0e0) ;
Standard_Real oldDv = 2.0 * ACos (Dv);
oldDv = Min(oldDv, myParameters.Angle);
Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
Dv = oldDv;
Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2);
Dv = (myvmax-myvmin)/(nbV+1);
Standard_Real ru = R + r;
if ( ru > 1.e-16 )
{
Du = Max(1.0e0 - (defface/ru),0.0e0);
Du = (2.0 * ACos (Du));
Du = Min(Du, myParameters.Angle);
Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
if (aa < gp::Resolution())
{
myAttribute->ChangeStructure().Nullify();
return myAttribute->GetStatus();
}
Du = Du * Min(oldDv, Du) / aa;
}
else
{
Du = Dv;
}
Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2);
nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.));
Du = (myumax-myumin)/(nbU+1);
//-- DeltaX and DeltaY are chosen so that to avoid "jumping"
//-- of points on the grid
deltaX = Du;
deltaY = Dv;
}
else if (aSurfType == GeomAbs_Cylinder)
{
gp_Cylinder Cyl = gFace->Cylinder();
Standard_Real R = Cyl.Radius();
// Calculate parameters for iteration in U direction
Standard_Real Du = 1.0 - (defface/R);
if (Du < 0.0)
Du = 0.0;
Du = 2.0 * ACos (Du);
if (Du > myParameters.Angle)
Du = myParameters.Angle;
deltaX = Du / longv;
deltaY = 1.;
}
else
{
deltaX = (myumax-myumin)/longu;
deltaY = (myvmax-myvmin)/longv;
}
// Restore face attribute
myAttribute->SetDefFace(defface);
myAttribute->SetUMax(myumax);
myAttribute->SetVMax(myvmax);
myAttribute->SetUMin(myumin);
myAttribute->SetVMin(myvmin);
myAttribute->SetDeltaX(deltaX);
myAttribute->SetDeltaY(deltaY);
}
myAttribute->ChangeMeshNodes() =
myAttribute->ChangeStructure()->Data()->Vertices();
}
catch(Standard_Failure)
{
myAttribute->SetStatus(BRepMesh_Failure);
}
myAttribute->ChangeStructure().Nullify();
return myAttribute->GetStatus();
}
//=======================================================================
//function : getEdgeAttributes
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& thePCurve,
const Standard_Real theDefEdge,
BRepMesh_FastDiscret::EdgeAttributes& theAttributes) const
{
EdgeAttributes& aEAttr = theAttributes;
// Get vertices
TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex);
if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull())
return Standard_False;
// Get range on 2d curve
const TopoDS_Face& aFace = myAttribute->Face();
BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam);
// Get end points on 2d curve
BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV);
aEAttr.IsSameUV =
aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
if (aEAttr.IsSameUV)
{
// 1. is it really sameUV without being degenerated
gp_Pnt2d uvF, uvL;
thePCurve->D0(thePCurve->FirstParameter(), uvF);
thePCurve->D0(thePCurve->LastParameter(), uvL);
if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion()))
aEAttr.FirstUV = uvF;
if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion()))
aEAttr.LastUV = uvL;
aEAttr.IsSameUV =
aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion());
}
//Control tolerance of vertices
const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
gp_Pnt pLast = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y());
Standard_Real aSqDist = pFirst.SquareDistance(BRep_Tool::Pnt(aEAttr.FirstVertex));
aSqDist = Max(aSqDist, pLast.SquareDistance(BRep_Tool::Pnt(aEAttr.LastVertex)));
aEAttr.Deflection = Max(theDefEdge, BRep_Tool::Tolerance(theEdge));
aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist));
return Standard_True;
}
//=======================================================================
//function : registerEdgeVertices
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::registerEdgeVertices(
BRepMesh_FastDiscret::EdgeAttributes& theAttributes,
Standard_Integer& ipf,
Standard_Integer& ivf,
Standard_Integer& isvf,
Standard_Integer& ipl,
Standard_Integer& ivl,
Standard_Integer& isvl)
{
EdgeAttributes& aEAttr = theAttributes;
if (aEAttr.FirstVExtractor.IsNull())
{
// Use edge geometry to produce tesselation.
aEAttr.FirstVExtractor =
new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex);
}
if (aEAttr.LastVExtractor.IsNull())
{
// Use edge geometry to produce tesselation.
aEAttr.LastVExtractor =
new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex);
}
// Process first vertex
ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True);
Standard_Real aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.FirstVertex);
gp_XY aTmpUV1 = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aMinDist, myAttribute);
myAttribute->AddNode(ipf, aTmpUV1, BRepMesh_Frontier, ivf, isvf);
// Process last vertex
ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf :
myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True);
aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.LastVertex);
gp_XY aTmpUV2 = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aMinDist, myAttribute);
myAttribute->AddNode(ipl, aTmpUV2, BRepMesh_Frontier, ivl, isvl);
// Update edge deflection
const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface();
gp_Pnt aPntE1 = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y());
gp_Pnt aPntFound1 = gFace->Value(aTmpUV1.X(), aTmpUV1.Y());
Standard_Real aSqDist = aPntE1.SquareDistance(aPntFound1);
gp_Pnt aPntE2 = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y());
gp_Pnt aPntFound2 = gFace->Value(aTmpUV2.X(), aTmpUV2.Y());
aSqDist = Max(aSqDist, aPntE2.SquareDistance(aPntFound2));
aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist));
}
//=======================================================================
//function : add
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::add(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& thePCurve,
const Standard_Real theDefEdge)
{
const TopAbs_Orientation orEdge = theEdge.Orientation();
if (orEdge == TopAbs_EXTERNAL)
return;
EdgeAttributes aEAttr;
if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr))
return;
if (!myEdges.IsBound(theEdge))
{
update(theEdge, thePCurve, theDefEdge, aEAttr);
return;
}
Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
// If this Edge has been already checked and it is not degenerated,
// the points of the polygon calculated at the first check are retrieved :
// retrieve the polygone:
const BRepMesh_PairOfPolygon& aPair = myEdges.Find(theEdge);
const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First();
const TColStd_Array1OfInteger& aNodes = aPolygon->Nodes();
Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
// creation anew:
const Standard_Integer aNodesNb = aNodes.Length();
TColStd_Array1OfInteger aNewNodes (1, aNodesNb);
TColStd_Array1OfReal aNewParams(1, aNodesNb);
aNewNodes (1) = isvf;
aNewParams(1) = aEAttr.FirstParam;
aNewNodes (aNodesNb) = isvl;
aNewParams(aNodesNb) = aEAttr.LastParam;
const TopoDS_Face& aFace = myAttribute->Face();
if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
{
BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams);
for (Standard_Integer i = 2; i < aNodesNb; ++i)
{
const Standard_Integer aPointId = aNodes(i);
const gp_Pnt& aPnt = myBoundaryPoints->Find(aPointId);
const Standard_Real aParam = aProvider.Parameter(i, aPnt);
gp_Pnt2d aUV = thePCurve->Value(aParam);
Standard_Integer iv2, isv;
myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv);
aNewNodes (i) = isv;
aNewParams(i) = aParam;
}
}
Handle(Poly_PolygonOnTriangulation) P1 =
new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
storePolygon(theEdge, P1, aEAttr.Deflection);
}
//=======================================================================
//function : update(edge)
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::update(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& theC2d,
const Standard_Real theDefEdge,
BRepMesh_FastDiscret::EdgeAttributes& theAttributes)
{
EdgeAttributes& aEAttr = theAttributes;
const TopoDS_Face& aFace = myAttribute->Face();
Handle(BRepMesh_IEdgeTool) aEdgeTool;
// Try to find existing tessellation.
for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i)
{
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation;
Handle(Poly_PolygonOnTriangulation) aPolygon;
BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i);
if (aPolygon.IsNull())
break;
if (aTriangulation.IsNull() || !aPolygon->HasParameters())
continue;
if (aPolygon->Deflection() > 1.1 * theDefEdge)
continue;
const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes();
Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters();
aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex,
aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc);
aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex,
aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc);
aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d,
aFace, aTriangulation, aPolygon, aLoc);
}
if (aEdgeTool.IsNull())
{
aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute,
mySharedFaces, theDefEdge, myParameters.Angle, myParameters.MinSize);
}
Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl;
registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl);
Handle(Poly_PolygonOnTriangulation) P1, P2;
if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace))
{
// two nodes
Standard_Integer aNewNodesArr[] = {isvf, isvl};
Standard_Integer aNewNodInStructArr[] = {ipf, ipl};
Standard_Real aNewParamsArr[] = {aEAttr.FirstParam, aEAttr.LastParam};
TColStd_Array1OfInteger aNewNodes (aNewNodesArr[0], 1, 2);
TColStd_Array1OfInteger aNewNodInStruct(aNewNodInStructArr[0], 1, 2);
TColStd_Array1OfReal aNewParams (aNewParamsArr[0], 1, 2);
P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
}
else
{
const Standard_Integer aNodesNb = aEdgeTool->NbPoints();
// Allocate the memory for arrays aNewNodesVec, aNewNodesInStructVec, aNewParamsVec
// only once using the buffer aBuf.
TColStd_Array1OfCharacter aBuf(1, aNodesNb * (2*sizeof(Standard_Integer) + sizeof(Standard_Real)));
TColStd_Array1OfInteger aNewNodesVec(*reinterpret_cast<const Standard_Integer*>
(&aBuf(1)), 1, aNodesNb);
TColStd_Array1OfInteger aNewNodesInStructVec(*reinterpret_cast<const Standard_Integer*>
(&aBuf(1 + aNodesNb*sizeof(Standard_Integer))), 1, aNodesNb);
TColStd_Array1OfReal aNewParamsVec(*reinterpret_cast<const Standard_Real*>
(&aBuf(1 + aNodesNb*2*sizeof(Standard_Integer))), 1, aNodesNb);
Standard_Integer aNodesCount = 1;
aNewNodesInStructVec(aNodesCount) = ipf;
aNewNodesVec (aNodesCount) = isvf;
aNewParamsVec (aNodesCount) = aEAttr.FirstParam;
++aNodesCount;
Standard_Integer aPrevNodeId = ivf;
Standard_Integer aLastPointId = myAttribute->LastPointId();
for (Standard_Integer i = 2; i < aNodesNb; ++i)
{
gp_Pnt aPnt;
gp_Pnt2d aUV;
Standard_Real aParam;
if (!aEdgeTool->Value(i, aParam, aPnt, aUV))
continue;
// Imitate index of 3d point in order to not to add points to map without necessity.
Standard_Integer iv2, isv;
myAttribute->AddNode(aLastPointId + 1, aUV.Coord(), BRepMesh_Frontier, iv2, isv);
if (aPrevNodeId == iv2)
continue;
// Ok, now we can add point to the map.
myBoundaryPoints->Bind (++aLastPointId, aPnt);
aNewNodesInStructVec(aNodesCount) = aLastPointId;
aNewNodesVec (aNodesCount) = isv;
aNewParamsVec (aNodesCount) = aParam;
++aNodesCount;
aPrevNodeId = iv2;
}
aNewNodesInStructVec(aNodesCount) = ipl;
aNewNodesVec (aNodesCount) = isvl;
aNewParamsVec (aNodesCount) = aEAttr.LastParam;
TColStd_Array1OfInteger aNewNodes (aNewNodesVec.First (), 1, aNodesCount);
TColStd_Array1OfInteger aNewNodInStruct(aNewNodesInStructVec.First(), 1, aNodesCount);
TColStd_Array1OfReal aNewParams (aNewParamsVec.First(), 1, aNodesCount);
P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams);
P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams);
}
storePolygon(theEdge, P1, aEAttr.Deflection);
storePolygonSharedData(theEdge, P2, aEAttr.Deflection);
}
//=======================================================================
//function : storeInternalPolygon
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::storePolygon(
const TopoDS_Edge& theEdge,
Handle(Poly_PolygonOnTriangulation)& thePolygon,
const Standard_Real theDeflection)
{
thePolygon->Deflection(theDeflection);
BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges();
if (aInternalEdges->IsBound(theEdge))
{
BRepMesh_PairOfPolygon& aPair = aInternalEdges->ChangeFind(theEdge);
if (theEdge.Orientation() == TopAbs_REVERSED)
aPair.Append(thePolygon);
else
aPair.Prepend(thePolygon);
return;
}
BRepMesh_PairOfPolygon aPair;
aPair.Append(thePolygon);
aInternalEdges->Bind(theEdge, aPair);
}
//=======================================================================
//function : storePolygonSharedData
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::storePolygonSharedData(
const TopoDS_Edge& theEdge,
Handle(Poly_PolygonOnTriangulation)& thePolygon,
const Standard_Real theDeflection)
{
thePolygon->Deflection(theDeflection);
BRepMesh_PairOfPolygon aPair;
aPair.Append(thePolygon);
myEdges.Bind(theEdge, aPair);
}
//=======================================================================
//function : GetFaceAttribute
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute(
const TopoDS_Face& theFace,
Handle(BRepMesh_FaceAttribute)& theAttribute,
const Standard_Boolean isForceCreate) const
{
if (myAttributes.IsBound(theFace))
{
theAttribute = myAttributes(theFace);
return Standard_True;
}
else if (isForceCreate)
{
theAttribute = new BRepMesh_FaceAttribute(myBoundaryVertices, myBoundaryPoints);
myAttributes.Bind(theFace, theAttribute);
}
return Standard_False;
}
//=======================================================================
//function : RemoveFaceAttribute
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace)
{
if (myAttributes.IsBound(theFace))
myAttributes.UnBind(theFace);
}

View File

@@ -14,358 +14,13 @@
#ifndef _BRepMesh_FastDiscret_HeaderFile
#define _BRepMesh_FastDiscret_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <BRepMesh_FastDiscret.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <BRepMesh_Status.hxx>
#include <TopTools_DataMapOfShapeReal.hxx>
#include <TopTools_ListOfShape.hxx>
#include <TopTools_MutexForShapeProvider.hxx>
#include <Standard_Transient.hxx>
#include <BRepMesh_Delaun.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_FaceAttribute.hxx>
#include <BRepMesh.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <BRep_Tool.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <IMeshTools_Parameters.hxx>
class BRepMesh_DataStructureOfDelaun;
class Bnd_Box;
class TopoDS_Shape;
class TopoDS_Face;
class TopoDS_Edge;
class Geom2dAdaptor_HCurve;
class BRepAdaptor_HSurface;
class BRepMesh_Edge;
class BRepMesh_Vertex;
class gp_Pnt;
class BRepMesh_FaceAttribute;
class Message_ProgressSentry;
//! Algorithm to mesh a shape with respect of the <br>
//! frontier the deflection and by option the shared <br>
//! components. <br>
class BRepMesh_FastDiscret : public Standard_Transient
class Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package") BRepMesh_FastDiscret
{
public:
//! Structure storing meshing parameters
struct Parameters {
//! Default constructor
Parameters()
:
Angle(0.1),
Deflection(0.001),
MinSize(Precision::Confusion()),
InParallel(Standard_False),
Relative(Standard_False),
AdaptiveMin(Standard_False),
InternalVerticesMode(Standard_True),
ControlSurfaceDeflection(Standard_True)
{
}
//! Angular deflection
Standard_Real Angle;
//! Deflection
Standard_Real Deflection;
//! Minimal allowed size of mesh element
Standard_Real MinSize;
//! Switches on/off multy thread computation
Standard_Boolean InParallel;
//! Switches on/off relative computation of edge tolerance<br>
//! If trur, deflection used for the polygonalisation of each edge will be
//! <defle> * Size of Edge. The deflection used for the faces will be the
//! maximum deflection of their edges.
Standard_Boolean Relative;
//! Adaptive parametric tolerance flag. <br>
//! If this flag is set to true the minimal parametric tolerance
//! is computed taking minimal parametric distance between vertices
//! into account
Standard_Boolean AdaptiveMin;
//! Mode to take or ont to take internal face vertices into account
//! in triangulation process
Standard_Boolean InternalVerticesMode;
//! Prameter to check the deviation of triangulation and interior of
//! the face
Standard_Boolean ControlSurfaceDeflection;
Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package")
typedef IMeshTools_Parameters Parameters;
};
public:
//! Constructor.
//! Sets the meshing parameters and updates
//! relative defletion according to bounding box
//! @param B - bounding box encompasing shape
//! @param theParams - meshing algo parameters
Standard_EXPORT BRepMesh_FastDiscret (const Bnd_Box& B,
const Parameters& theParams);
//! Build triangulation on the whole shape.
Standard_EXPORT void Perform(const TopoDS_Shape& shape);
//! Record a face for further processing.
//! @return status flags collected during discretization
//! of boundaries of the given face.
Standard_EXPORT Standard_Integer Add(const TopoDS_Face& face);
//! Triangulate a face previously recorded for
//! processing by call to Add(). Can be executed in
//! parallel threads.
Standard_EXPORT void Process(const TopoDS_Face& face) const;
//! Triangulate a face previously recorded for
//! processing by call to Add(). Can be executed in
//! parallel threads.
Standard_EXPORT void Process (const TopoDS_Face& theFace,
Message_ProgressSentry* theProgrEntry) const;
void operator () (const TopoDS_Face& face) const
{
Process(face);
}
//! Returns parameters of meshing
inline const Parameters& MeshParameters() const
{
return myParameters;
}
//! Returns modificable mesh parameters
inline Parameters& ChangeMeshParameters()
{
return myParameters;
}
Standard_EXPORT void InitSharedFaces(const TopoDS_Shape& theShape);
inline const TopTools_IndexedDataMapOfShapeListOfShape& SharedFaces() const
{
return mySharedFaces;
}
//! Returns attribute descriptor for the given face.
//! @param theFace face the attribute should be returned for.
//! @param[out] theAttribute attribute found for the specified face.
//! @param isForceCreate if True creates new attribute in case if there
//! is no data for the given face.
Standard_EXPORT Standard_Boolean GetFaceAttribute (
const TopoDS_Face& theFace,
Handle(BRepMesh_FaceAttribute)& theAttribute,
const Standard_Boolean isForceCreate = Standard_False) const;
//! Remove face attribute as useless to free locate memory.
Standard_EXPORT void RemoveFaceAttribute( const TopoDS_Face& theFace );
//! Returns number of boundary 3d points.
inline Standard_Integer NbBoundaryPoints() const
{
return myBoundaryPoints->Extent();
}
DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient)
private:
//! Auxiliary class used to extract geometrical parameters of TopoDS_Vertex.
class TopoDSVExplorer
{
public:
TopoDSVExplorer(
const TopoDS_Vertex& theVertex,
const Standard_Boolean isSameUV,
const TopoDS_Vertex& theSameVertex)
: myVertex(theVertex),
myIsSameUV(isSameUV),
mySameVertex(theSameVertex)
{
}
virtual ~TopoDSVExplorer() {
}
const TopoDS_Vertex& Vertex() const
{
return myVertex;
}
Standard_Boolean IsSameUV() const
{
return myIsSameUV;
}
const TopoDS_Vertex& SameVertex() const
{
return mySameVertex;
}
virtual gp_Pnt Point() const
{
return BRep_Tool::Pnt(myVertex);
}
private:
void operator =(const TopoDSVExplorer& /*theOther*/)
{
}
private:
const TopoDS_Vertex& myVertex;
Standard_Boolean myIsSameUV;
const TopoDS_Vertex& mySameVertex;
};
//! Auxiliary class used to extract polygonal parameters of TopoDS_Vertex.
class PolyVExplorer : public TopoDSVExplorer
{
public:
PolyVExplorer(
const TopoDS_Vertex& theVertex,
const Standard_Boolean isSameUV,
const TopoDS_Vertex& theSameVertex,
const Standard_Integer theVertexIndex,
const TColgp_Array1OfPnt& thePolygon,
const TopLoc_Location& theLoc)
: TopoDSVExplorer(theVertex, isSameUV, theSameVertex),
myVertexIndex(theVertexIndex),
myPolygon(thePolygon),
myLoc(theLoc)
{
}
virtual gp_Pnt Point() const
{
return BRepMesh_ShapeTool::UseLocation(myPolygon(myVertexIndex), myLoc);
}
private:
void operator =(const PolyVExplorer& /*theOther*/)
{
}
private:
Standard_Integer myVertexIndex;
const TColgp_Array1OfPnt& myPolygon;
const TopLoc_Location myLoc;
};
//! Structure keeps common parameters of edge
//! used for tessellation.
struct EdgeAttributes
{
TopoDS_Vertex FirstVertex;
TopoDS_Vertex LastVertex;
Standard_Real FirstParam;
Standard_Real LastParam;
gp_Pnt2d FirstUV;
gp_Pnt2d LastUV;
Standard_Real Deflection;
Standard_Boolean IsSameUV;
NCollection_Handle<TopoDSVExplorer> FirstVExtractor;
NCollection_Handle<TopoDSVExplorer> LastVExtractor;
};
//! Fills structure of by attributes of the given edge.
//! @return TRUE on success, FALSE elsewhere.
Standard_Boolean getEdgeAttributes(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& thePCurve,
const Standard_Real theDefEdge,
EdgeAttributes& theAttributes) const;
//! Registers end vertices of the edge in mesh data
//! structure of currently processed face.
void registerEdgeVertices(
EdgeAttributes& theAttributes,
Standard_Integer& ipf,
Standard_Integer& ivf,
Standard_Integer& isvf,
Standard_Integer& ipl,
Standard_Integer& ivl,
Standard_Integer& isvl);
//! Adds tessellated representation of the given edge to
//! mesh data structure of currently processed face.
void add(const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& theCurve2D,
const Standard_Real theEdgeDeflection);
//! Updates tessellated representation of the given edge.
//! If edge already has a polygon which deflection satisfies
//! the given value, retrieves tessellation from polygon.
//! Computes tessellation using edge's geometry elsewhere.
void update(
const TopoDS_Edge& theEdge,
const Handle(Geom2dAdaptor_HCurve)& theCurve2D,
const Standard_Real theEdgeDeflection,
EdgeAttributes& theAttributes);
//! Stores polygonal model of the given edge.
//! @param theEdge edge which polygonal model is stored.
//! @param thePolygon polygonal model of the edge.
//! @param theDeflection deflection with which polygonalization is performed.
//! This value is stored inside the polygon.
void storePolygon(
const TopoDS_Edge& theEdge,
Handle(Poly_PolygonOnTriangulation)& thePolygon,
const Standard_Real theDeflection);
//! Caches polygonal model of the given edge to be used in further.
//! @param theEdge edge which polygonal data is stored.
//! @param thePolygon shared polygonal data of the edge.
//! @param theDeflection deflection with which polygonalization is performed.
//! This value is stored inside the polygon.
void storePolygonSharedData(
const TopoDS_Edge& theEdge,
Handle(Poly_PolygonOnTriangulation)& thePolygon,
const Standard_Real theDeflection);
//! Resets temporary data structure used to collect unique nodes.
void resetDataStructure();
private:
TopoDS_Face myFace;
BRepMesh::DMapOfShapePairOfPolygon myEdges;
mutable BRepMesh::DMapOfFaceAttribute myAttributes;
TopTools_DataMapOfShapeReal myMapdefle;
// Data shared for whole shape
BRepMesh::HDMapOfVertexInteger myBoundaryVertices;
BRepMesh::HDMapOfIntegerPnt myBoundaryPoints;
// Fast access to attributes of current face
Handle(BRepMesh_FaceAttribute) myAttribute;
TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces;
Parameters myParameters;
Standard_Real myDtotale;
};
DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,201 +0,0 @@
// Copyright (c) 2013 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.
#ifndef _BRepMesh_FastDiscretFace_HeaderFile
#define _BRepMesh_FastDiscretFace_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <BRepMesh_FastDiscretFace.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh.hxx>
#include <BRepMesh_FaceAttribute.hxx>
#include <Standard_Transient.hxx>
#include <TopTools_MutexForShapeProvider.hxx>
#include <TopTools_DataMapOfShapeReal.hxx>
#include <BRepMesh_Delaun.hxx>
#include <BRepMesh_Triangle.hxx>
#include <BRepMesh_Classifier.hxx>
#include <ElSLib.hxx>
class BRepMesh_DataStructureOfDelaun;
class BRepMesh_FaceAttribute;
class TopoDS_Face;
class TopoDS_Vertex;
class BRepAdaptor_HSurface;
class TopoDS_Edge;
class Poly_Triangulation;
class TopLoc_Location;
class gp_XY;
class gp_Pnt2d;
class BRepMesh_Edge;
class BRepMesh_Vertex;
class gp_Pnt;
class Message_ProgressSentry;
//! Algorithm to mesh a face with respect of the frontier
//! the deflection and by option the shared components.
class BRepMesh_FastDiscretFace : public Standard_Transient
{
public:
//! Constructor.
//! @param theAngle deviation angle to be used for surface tessellation.
//! @param isInternalVerticesMode flag enabling/disabling internal
//! vertices mode.
//! @param isControlSurfaceDeflection enables/disables adaptive
//! reconfiguration of mesh.
Standard_EXPORT BRepMesh_FastDiscretFace(
const Standard_Real theAngle,
const Standard_Real theMinSize,
const Standard_Boolean isInternalVerticesMode,
const Standard_Boolean isControlSurfaceDeflection);
Standard_EXPORT void Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute);
Standard_EXPORT void Perform (const Handle(BRepMesh_FaceAttribute)& theAttribute,
Message_ProgressSentry* theProgressEntry);
DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient)
private:
void add(const Handle(BRepMesh_FaceAttribute)& theAttribute, Message_ProgressSentry* theProgressEntry);
void add(const TopoDS_Vertex& theVertex);
Standard_Real control(BRepMesh_Delaun& theMeshBuilder,
const Standard_Boolean theIsFirst,
Message_ProgressSentry* theProgressEntry);
//! Registers the given nodes in mesh data structure and
//! performs refinement of existing mesh.
//! @param theVertices nodes to be inserted.
//! @param theMeshBuilder initialized tool refining mesh
//! in respect to inserting nodes.
//! @return TRUE if vertices were been inserted, FALSE elewhere.
Standard_Boolean addVerticesToMesh(
const BRepMesh::ListOfVertex& theVertices,
BRepMesh_Delaun& theMeshBuilder,
Message_ProgressSentry* theProgressEntry);
//! Calculates nodes lying on face's surface and inserts them to a mesh.
//! @param theMeshBuilder initialized tool refining mesh
//! in respect to inserting nodes.
void insertInternalVertices(BRepMesh_Delaun& theMeshBuilder,
Message_ProgressSentry* theProgressEntry);
//! Calculates nodes lying on spherical surface.
//! @param theNewVertices list of vertices to be extended and added to mesh.
void insertInternalVerticesSphere(BRepMesh::ListOfVertex& theNewVertices);
//! Calculates nodes lying on cylindrical surface.
//! @param theNewVertices list of vertices to be extended and added to mesh.
void insertInternalVerticesCylinder(BRepMesh::ListOfVertex& theNewVertices);
//! Calculates nodes lying on conical surface.
//! @param theNewVertices list of vertices to be extended and added to mesh.
void insertInternalVerticesCone(BRepMesh::ListOfVertex& theNewVertices);
//! Calculates nodes lying on toroidal surface.
//! @param theNewVertices list of vertices to be extended and added to mesh.
void insertInternalVerticesTorus(BRepMesh::ListOfVertex& theNewVertices);
//! Calculates nodes lying on custom-type surface.
//! @param theNewVertices list of vertices to be extended and added to mesh.
void insertInternalVerticesOther(BRepMesh::ListOfVertex& theNewVertices);
//! Template method trying to insert new internal vertex corresponded to
//! the given 2d point. Calculates 3d position analytically using the given
//! surface.
//! @param thePnt2d 2d point to be inserted to the list.
//! @param theAnalyticSurface analytic surface to calculate 3d point.
//! @param[out] theVertices list of vertices to be updated.
template<class AnalyticSurface>
void tryToInsertAnalyticVertex(const gp_Pnt2d& thePnt2d,
const AnalyticSurface& theAnalyticSurface,
BRepMesh::ListOfVertex& theVertices)
{
const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier();
if (aClassifier->Perform(thePnt2d) != TopAbs_IN)
return;
gp_Pnt aPnt;
ElSLib::D0(thePnt2d.X(), thePnt2d.Y(), theAnalyticSurface, aPnt);
insertVertex(aPnt, thePnt2d.Coord(), theVertices);
}
//! Creates new vertex with the given parameters.
//! @param thePnt3d 3d point corresponded to the vertex.
//! @param theUV UV point corresponded to the vertex.
//! @param[out] theVertices list of vertices to be updated.
void insertVertex(const gp_Pnt& thePnt3d,
const gp_XY& theUV,
BRepMesh::ListOfVertex& theVertices);
//! Stores mesh into the face (without internal edges).
void commitSurfaceTriangulation();
//! Performs initialization of data structure using existing data.
void initDataStructure();
//! Adds new link to the mesh data structure.
//! Movability of the link and order of nodes depend on orientation parameter.
void addLinkToMesh(const Standard_Integer theFirstNodeId,
const Standard_Integer theLastNodeId,
const TopAbs_Orientation theOrientation);
//! Inserts new node into a mesh in case if smoothed region build
//! using the given node has better deflection metrics than source state.
//! @param thePnt3d 3d point corresponded to the vertex.
//! @param theUV UV point corresponded to the vertex.
//! @param isDeflectionCheckOnly if TRUE new node will not be added to a mesh
//! even if deflection parameter is better.
//! @param theTriangleDeflection deflection of a triangle from real geometry.
//! @param theFaceDeflection deflection to be achieved.
//! @param theCircleTool tool used for fast extraction of triangles
//! touched by the given point.
//! @param[out] theVertices list of vertices to be updated.
//! @param[in out] theMaxTriangleDeflection maximal deflection of a mesh.
//! @return TRUE in case if the given deflection of triangle is fine and
//! there is no necessity to insert new node or new node was being inserted
//! successfully, FALSE in case if new configuration is better but
//! isDeflectionCheckOnly flag is set.
Standard_Boolean checkDeflectionAndInsert(
const gp_Pnt& thePnt3d,
const gp_XY& theUV,
const Standard_Boolean isDeflectionCheckOnly,
const Standard_Real theTriangleDeflection,
const Standard_Real theFaceDeflection,
const BRepMesh_CircleTool& theCircleTool,
BRepMesh::ListOfVertex& theVertices,
Standard_Real& theMaxTriangleDeflection,
const Handle(NCollection_IncAllocator)& theTempAlloc);
private:
Standard_Real myAngle;
Standard_Boolean myInternalVerticesMode;
BRepMesh::IMapOfReal myUParam;
BRepMesh::IMapOfReal myVParam;
// Fast access to attributes of current face
Handle(BRepMesh_FaceAttribute) myAttribute;
Handle(BRepMesh_DataStructureOfDelaun) myStructure;
Standard_Real myMinSize;
Standard_Boolean myIsControlSurfaceDeflection;
};
DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient)
#endif

View File

@@ -16,15 +16,134 @@
#include <BRepMesh_GeomTool.hxx>
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <TopAbs_Orientation.hxx>
#include <CSLib.hxx>
#include <Precision.hxx>
#include <Adaptor3d_IsoCurve.hxx>
#include <Adaptor3d_HCurve.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <Geom2d_Curve.hxx>
#include <BRep_Tool.hxx>
namespace
{
void ComputeErrFactors (const Standard_Real theDeflection,
const Handle(Adaptor3d_HSurface)& theFace,
Standard_Real& theErrFactorU,
Standard_Real& theErrFactorV)
{
theErrFactorU = theDeflection * 10.;
theErrFactorV = theDeflection * 10.;
switch (theFace->GetType ())
{
case GeomAbs_Cylinder:
case GeomAbs_Cone:
case GeomAbs_Sphere:
case GeomAbs_Torus:
break;
case GeomAbs_SurfaceOfExtrusion:
case GeomAbs_SurfaceOfRevolution:
{
Handle(Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2)
{
theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ());
}
break;
}
case GeomAbs_BezierSurface:
{
if (theFace->UDegree () > 2)
{
theErrFactorU /= (theFace->UDegree ());
}
if (theFace->VDegree () > 2)
{
theErrFactorV /= (theFace->VDegree ());
}
break;
}
case GeomAbs_BSplineSurface:
{
if (theFace->UDegree () > 2)
{
theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ());
}
if (theFace->VDegree () > 2)
{
theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ());
}
break;
}
case GeomAbs_Plane:
default:
theErrFactorU = theErrFactorV = 1.;
}
}
void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace,
const Standard_Integer theNbVertices,
Standard_Integer& theCellsCountU,
Standard_Integer& theCellsCountV)
{
const GeomAbs_SurfaceType aType = theFace->GetType ();
if (aType == GeomAbs_OtherSurface)
{
// fallback to the default behavior
theCellsCountU = theCellsCountV = -1;
return;
}
Standard_Real aSqNbVert = theNbVertices;
if (aType == GeomAbs_Plane)
{
theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone)
{
theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution)
{
Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve ();
if (aCurve->GetType () == GeomAbs_Line ||
(aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2))
{
// planar, cylindrical, conical cases
if (aType == GeomAbs_SurfaceOfExtrusion)
theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
else
theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
if (aType == GeomAbs_SurfaceOfExtrusion)
{
// V is always a line
theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
}
else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface)
{
if (theFace->UDegree () < 2)
{
theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
if (theFace->VDegree () < 2)
{
theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert)));
}
}
theCellsCountU = Max (theCellsCountU, 2);
theCellsCountV = Max (theCellsCountV, 2);
}
}
//=======================================================================
//function : Constructor
//purpose :
@@ -76,8 +195,10 @@ BRepMesh_GeomTool::BRepMesh_GeomTool(
//=======================================================================
Standard_Boolean BRepMesh_GeomTool::Value(
const Standard_Integer theIndex,
const Handle(BRepAdaptor_HSurface)& theSurface,
Standard_Real& theParam,
gp_Pnt& thePoint) const
gp_Pnt& thePoint,
gp_Pnt2d& theUV) const
{
if (theIndex < 1 || theIndex > NbPoints())
return Standard_False;
@@ -88,6 +209,14 @@ Standard_Boolean BRepMesh_GeomTool::Value(
thePoint = myDiscretTool.Value(theIndex);
theParam = myDiscretTool.Parameter(theIndex);
const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face();
Standard_Real aFirst, aLast;
Handle(Geom2d_Curve) aCurve =
BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast);
aCurve->D0(theParam, theUV);
return Standard_True;
}
@@ -95,7 +224,8 @@ Standard_Boolean BRepMesh_GeomTool::Value(
//function : Value
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex,
Standard_Boolean BRepMesh_GeomTool::Value(
const Standard_Integer theIndex,
const Standard_Real theIsoParam,
Standard_Real& theParam,
gp_Pnt& thePoint,
@@ -293,6 +423,56 @@ BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg(
return BRepMesh_GeomTool::Cross;
}
//=============================================================================
//function : CellsCount
//purpose :
//=============================================================================
std::pair<Standard_Integer, Standard_Integer> BRepMesh_GeomTool::CellsCount (
const Handle (Adaptor3d_HSurface)& theSurface,
const Standard_Integer theVerticesNb,
const Standard_Real theDeflection,
const BRepMesh_DefaultRangeSplitter* theRangeSplitter)
{
if (theRangeSplitter == NULL)
return std::pair<Standard_Integer, Standard_Integer>(-1, -1);
const GeomAbs_SurfaceType aType = theSurface->GetType ();
Standard_Real anErrFactorU, anErrFactorV;
ComputeErrFactors(theDeflection, theSurface, anErrFactorU, anErrFactorV);
const std::pair<Standard_Real, Standard_Real>& aRangeU = theRangeSplitter->GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = theRangeSplitter->GetRangeV();
const std::pair<Standard_Real, Standard_Real>& aDelta = theRangeSplitter->GetDelta ();
Standard_Integer aCellsCountU, aCellsCountV;
if (aType == GeomAbs_Torus)
{
aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeU.second - aRangeU.first) / aDelta.first)));
aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeV.second - aRangeV.first) / aDelta.second)));
}
else if (aType == GeomAbs_Cylinder)
{
aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeU.second - aRangeU.first) / aDelta.first /
(aRangeV.second - aRangeV.first))));
aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeV.second - aRangeV.first) / anErrFactorV)));
}
else
{
aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeU.second - aRangeU.first) / aDelta.first / anErrFactorU)));
aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10(
(aRangeV.second - aRangeV.first) / aDelta.second / anErrFactorV)));
}
AdjustCellsCounts(theSurface, theVerticesNb, aCellsCountU, aCellsCountV);
return std::pair<Standard_Integer, Standard_Integer>(aCellsCountU, aCellsCountV);
}
//=============================================================================
//function : classifyPoint
//purpose :

View File

@@ -27,6 +27,8 @@ class BRepAdaptor_HSurface;
class gp_Pnt;
class gp_Pnt2d;
class gp_Dir;
class BRepMesh_DefaultRangeSplitter;
class Adaptor3d_HSurface;
//! Tool class accumulating common geometrical functions as well as
//! functionality using shape geometry to produce data necessary for
@@ -60,7 +62,8 @@ public:
//! @param theLinDeflection linear deflection.
//! @param theAngDeflection angular deflection.
//! @param theMinPointsNb minimum nuber of points to be produced.
Standard_EXPORT BRepMesh_GeomTool(const BRepAdaptor_Curve& theCurve,
Standard_EXPORT BRepMesh_GeomTool(
const BRepAdaptor_Curve& theCurve,
const Standard_Real theFirstParam,
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
@@ -79,7 +82,8 @@ public:
//! @param theLinDeflection linear deflection.
//! @param theAngDeflection angular deflection.
//! @param theMinPointsNb minimum nuber of points to be produced.
Standard_EXPORT BRepMesh_GeomTool(const Handle(BRepAdaptor_HSurface)& theSurface,
Standard_EXPORT BRepMesh_GeomTool(
const Handle(BRepAdaptor_HSurface)& theSurface,
const GeomAbs_IsoType theIsoType,
const Standard_Real theParamIso,
const Standard_Real theFirstParam,
@@ -124,12 +128,16 @@ public:
//! Gets parameters of discretization point with the given index.
//! @param theIndex index of discretization point.
//! @param theSurface surface the curve is lying onto.
//! @param theParam[out] parameter of the point on the curve.
//! @param thePoint[out] discretization point.
//! @param theUV[out] discretization point in parametric space of the surface.
//! @return TRUE on success, FALSE elsewhere.
Standard_EXPORT Standard_Boolean Value(const Standard_Integer theIndex,
const Handle(BRepAdaptor_HSurface)& theSurface,
Standard_Real& theParam,
gp_Pnt& thePoint) const;
gp_Pnt& thePoint,
gp_Pnt2d& theUV) const;
public: //! @name static API
@@ -188,6 +196,38 @@ public: //! @name static API
const Standard_Boolean isConsiderPointOnSegment,
gp_Pnt2d& theIntPnt);
//! Compute deflection of the given segment.
static Standard_Real SquareDeflectionOfSegment(
const gp_Pnt& theFirstPoint,
const gp_Pnt& theLastPoint,
const gp_Pnt& theMidPoint)
{
// 23.03.2010 skl for OCC21645 - change precision for comparison
if (theFirstPoint.SquareDistance(theLastPoint) > Precision::SquareConfusion())
{
gp_Lin aLin(theFirstPoint, gp_Dir(gp_Vec(theFirstPoint, theLastPoint)));
return aLin.SquareDistance(theMidPoint);
}
return theFirstPoint.SquareDistance(theMidPoint);
}
// For better meshing performance we try to estimate the acceleration circles grid structure sizes:
// For each parametric direction (U, V) we estimate firstly an approximate distance between the future points -
// this estimation takes into account the required face deflection and the complexity of the face.
// Particularly, the complexity of the faces based on BSpline curves and surfaces requires much more points.
// At the same time, for planar faces and linear parts of the arbitrary surfaces usually no intermediate points
// are necessary.
// The general idea for each parametric direction:
// cells_count = 2 ^ log10 ( estimated_points_count )
// For linear parametric direction we fall back to the initial vertex count:
// cells_count = 2 ^ log10 ( initial_vertex_count )
Standard_EXPORT static std::pair<Standard_Integer, Standard_Integer> CellsCount (
const Handle (Adaptor3d_HSurface)& theSurface,
const Standard_Integer theVerticesNb,
const Standard_Real theDeflection,
const BRepMesh_DefaultRangeSplitter* theRangeSplitter);
private:
//! Classifies the point in case of coincidence of two vectors.

View File

@@ -1,20 +0,0 @@
// Created on: 2014-08-13
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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 <BRepMesh_IEdgeTool.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient)

View File

@@ -15,48 +15,12 @@
// commercial license or contractual agreement.
#include <BRepMesh_IncrementalMesh.hxx>
#include <OSD_Parallel.hxx>
#include <Precision.hxx>
#include <Standard_ErrorHandler.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <BRepMesh_Edge.hxx>
#include <BRepMesh_Context.hxx>
#include <BRepMesh_PluginMacro.hxx>
#include <Bnd_Box.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepTools.hxx>
#include <BRepLib.hxx>
#include <BRepBndLib.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopAbs.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_MapOfTransient.hxx>
#include <TopTools_HArray1OfShape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <Message_ProgressSentry.hxx>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
#include <IMeshData_Status.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshTools_MeshBuilder.hxx>
namespace
{
@@ -65,60 +29,13 @@ namespace
static Standard_Boolean IS_IN_PARALLEL = Standard_False;
}
class BRepMesh_IncrementalMesh::FaceListFunctor
{
public:
FaceListFunctor (BRepMesh_IncrementalMesh* theAlgo,
const Handle(Message_ProgressIndicator)& theProgress,
Standard_Boolean theParallel)
: myAlgo (theAlgo),
mySentry (theProgress, "Mesh faces", 0, theAlgo->myFaces.Size(), 1),
myThreadId (OSD_Thread::Current()),
myIsParallel (theParallel),
myHasProgress (!theProgress.IsNull())
{
}
void operator() (const Standard_Integer theFaceIndex) const
{
if (!mySentry.More())
{
return;
}
TopoDS_Face& aFace = myAlgo->myFaces.ChangeValue (theFaceIndex);
myAlgo->myMesh->Process (aFace, &mySentry);
if (myIsParallel)
{
// use a trick to avoid mutex locks - increment the progress only within main thread
if (myHasProgress && myThreadId == OSD_Thread::Current())
{
mySentry.Next (OSD_Parallel::NbLogicalProcessors());
}
}
else
{
mySentry.Next();
}
}
private:
mutable BRepMesh_IncrementalMesh* myAlgo;
mutable Message_ProgressSentry mySentry;
Standard_ThreadId myThreadId;
Standard_Boolean myIsParallel;
Standard_Boolean myHasProgress;
};
//=======================================================================
//function : Default constructor
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
: myMaxShapeSize(0.),
myModified(Standard_False),
myStatus(0)
: myModified(Standard_False),
myStatus(IMeshData_NoError)
{
}
@@ -130,17 +47,14 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh
const Standard_Real theLinDeflection,
const Standard_Boolean isRelative,
const Standard_Real theAngDeflection,
const Standard_Boolean isInParallel,
const Standard_Boolean adaptiveMin)
: myMaxShapeSize(0.),
myModified(Standard_False),
myStatus(0)
const Standard_Boolean isInParallel)
: myModified(Standard_False),
myStatus(IMeshData_NoError)
{
myParameters.Deflection = theLinDeflection;
myParameters.Relative = isRelative;
myParameters.Angle = theAngDeflection;
myParameters.Relative = isRelative;
myParameters.InParallel = isInParallel;
myParameters.AdaptiveMin = adaptiveMin;
myShape = theShape;
Perform();
@@ -150,12 +64,12 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
const BRepMesh_FastDiscret::Parameters& theParameters)
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(
const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters)
: myParameters(theParameters)
{
myShape = theShape;
Perform();
}
@@ -167,490 +81,46 @@ BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh()
{
}
//=======================================================================
//function : clear
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::clear()
{
// the allocator will be alive while the structures are alive
Handle(NCollection_BaseAllocator) anAlloc =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
myEdges.Clear(anAlloc);
myEdgeDeflection.Clear(anAlloc);
myFaces.Clear();
myMesh.Nullify();
}
//=======================================================================
//function : init
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::init()
{
myStatus = 0;
myModified = Standard_False;
setDone();
clear();
collectFaces();
Bnd_Box aBox;
if ( myParameters.Relative )
{
BRepBndLib::Add(myShape, aBox, Standard_False);
if (aBox.IsVoid())
{
// Nothing to mesh.
return;
}
BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize);
}
myMesh = new BRepMesh_FastDiscret (aBox, myParameters);
myMesh->InitSharedFaces(myShape);
}
//=======================================================================
//function : collectFaces
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::collectFaces()
{
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
TopTools_ListOfShape aFaceList(anAlloc);
BRepLib::ReverseSortFaces(myShape, aFaceList);
TColStd_MapOfTransient aTFaceMap(1, anAlloc);
// make array of faces suitable for processing (excluding faces without surface)
TopLoc_Location aDummyLoc;
TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList);
for (; aFaceIter.More(); aFaceIter.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(aFaceIter.Value());
const Handle(TopoDS_TShape)& aTFace = aFace.TShape();
if (!aTFaceMap.Add (aTFace))
continue; // already processed
const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc);
if (aSurf.IsNull())
continue;
myFaces.Append(aFace);
}
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::Perform()
{
Perform (Handle(Message_ProgressIndicator)());
Handle(BRepMesh_Context) aContext = new BRepMesh_Context;
Perform (aContext);
}
//=======================================================================
//function : Perform
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::Perform (const Handle(Message_ProgressIndicator)& theProgress)
void BRepMesh_IncrementalMesh::Perform(const Handle(IMeshTools_Context)& theContext)
{
init();
initParameters();
if (myMesh.IsNull())
return;
theContext->SetShape(Shape());
theContext->ChangeParameters() = myParameters;
theContext->ChangeParameters().CleanModel = Standard_False;
update (theProgress);
}
IMeshTools_MeshBuilder aIncMesh(theContext);
aIncMesh.Perform();
//=======================================================================
//function : update()
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::update (const Handle(Message_ProgressIndicator)& theProgress)
myStatus = IMeshData_NoError;
const Handle(IMeshData_Model)& aModel = theContext->GetModel();
for (Standard_Integer aFaceIt = 0; aFaceIt < aModel->FacesNb(); ++aFaceIt)
{
Message_ProgressSentry anOuterSentry (theProgress, "Updating", 0, 100, 1);
const IMeshData::IFaceHandle& aDFace = aModel->GetFace(aFaceIt);
myStatus |= aDFace->GetStatusMask();
// Update edges data
anOuterSentry.Next(9);
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
{
int aNbEdges = 0;
for (TopExp_Explorer aExplorer (myShape, TopAbs_EDGE); aExplorer.More(); aExplorer.Next())
{
++aNbEdges;
}
Message_ProgressSentry anEdgeSentry (theProgress, "Update edges data", 0, aNbEdges, 1);
for (TopExp_Explorer aExplorer (myShape, TopAbs_EDGE);
aExplorer.More() && anEdgeSentry.More(); aExplorer.Next(), anEdgeSentry.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
if(!BRep_Tool::IsGeometric(aEdge))
continue;
update(aEdge);
const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
myStatus |= aDWire->GetStatusMask();
}
}
if (!anOuterSentry.More())
{
myStatus = BRepMesh_UserBreak;
return;
}
anOuterSentry.Next(5);
// Update faces data
NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
for (Message_ProgressSentry aFacesSentry (theProgress, "Update faces data", 0, myFaces.Size(), 1);
aFaceIt.More() && aFacesSentry.More(); aFaceIt.Next(), aFacesSentry.Next())
{
update(aFaceIt.Value());
}
if (!anOuterSentry.More())
{
myStatus = BRepMesh_UserBreak;
return;
}
anOuterSentry.Next(80);
{
// Mesh faces
FaceListFunctor aFacesFunctor (this, theProgress, myParameters.InParallel);
OSD_Parallel::For (0, myFaces.Size(), aFacesFunctor, !myParameters.InParallel);
}
if (!anOuterSentry.More())
{
myStatus = BRepMesh_UserBreak;
return;
}
anOuterSentry.Next(5);
{
Message_ProgressSentry aSentry (theProgress, "Commit", 0, myFaces.Size(), 1);
commit (aSentry);
}
anOuterSentry.Next();
clear();
}
//=======================================================================
//function : discretizeFreeEdges
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::discretizeFreeEdges()
{
TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE);
for (; aExplorer.More(); aExplorer.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
if(!BRep_Tool::IsGeometric(aEdge))
continue;
TopLoc_Location aLoc;
Standard_Real aEdgeDeflection = edgeDeflection(aEdge);
Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc);
if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection)
continue;
BRepAdaptor_Curve aCurve(aEdge);
GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(),
aCurve.LastParameter(), myParameters.Angle, aEdgeDeflection, 2,
Precision::PConfusion(), myParameters.MinSize);
Standard_Integer aNodesNb = aDiscret.NbPoints();
TColgp_Array1OfPnt aNodes (1, aNodesNb);
TColStd_Array1OfReal aUVNodes(1, aNodesNb);
for (Standard_Integer i = 1; i <= aNodesNb; ++i)
{
aNodes (i) = aDiscret.Value(i);
aUVNodes(i) = aDiscret.Parameter(i);
}
aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
aPoly3D->Deflection(myParameters.Deflection);
BRep_Builder aBuilder;
aBuilder.UpdateEdge(aEdge, aPoly3D);
}
}
//=======================================================================
//function : edgeDeflection
//purpose :
//=======================================================================
Standard_Real BRepMesh_IncrementalMesh::edgeDeflection(
const TopoDS_Edge& theEdge)
{
const Standard_Real* pDef = myEdgeDeflection.Seek(theEdge);
if (pDef)
return *pDef;
Standard_Real aEdgeDeflection;
if ( myParameters.Relative )
{
Standard_Real aScale;
aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge,
myParameters.Deflection, myMaxShapeSize, aScale);
}
else
aEdgeDeflection = myParameters.Deflection;
myEdgeDeflection.Bind(theEdge, aEdgeDeflection);
return aEdgeDeflection;
}
//=======================================================================
//function : faceDeflection
//purpose :
//=======================================================================
Standard_Real BRepMesh_IncrementalMesh::faceDeflection(
const TopoDS_Face& theFace)
{
if ( !myParameters.Relative )
return myParameters.Deflection;
Standard_Integer aEdgesNb = 0;
Standard_Real aFaceDeflection = 0.;
TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb)
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
aFaceDeflection += edgeDeflection(aEdge);
}
return (aEdgesNb == 0) ? myParameters.Deflection : (aFaceDeflection / aEdgesNb);
}
//=======================================================================
//function : update(edge)
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge)
{
if (!myEdges.IsBound(theEdge))
myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool(3, myEdges.Allocator()));
Standard_Real aEdgeDeflection = edgeDeflection(theEdge);
// Check that triangulation relies to face of the given shape.
const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
myMesh->SharedFaces();
const TopTools_ListOfShape& aSharedFaces =
aMapOfSharedFaces.FindFromKey(theEdge);
TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
{
TopLoc_Location aLoc;
const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
const Handle(Poly_Triangulation)& aFaceTriangulation =
BRep_Tool::Triangulation(aFace, aLoc);
if (aFaceTriangulation.IsNull())
continue;
Standard_Boolean isConsistent = Standard_False;
const Handle(Poly_PolygonOnTriangulation)& aPolygon =
BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc);
if (!aPolygon.IsNull())
{
isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection &&
aPolygon->HasParameters();
if (!isConsistent)
{
myModified = Standard_True;
BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc);
}
}
myEdges(theEdge).Bind(aFaceTriangulation, isConsistent);
}
}
//=======================================================================
//function : isToBeMeshed
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed(
const TopoDS_Face& theFace,
const Standard_Boolean isWithCheck)
{
TopLoc_Location aLoc;
const Handle(Poly_Triangulation)& aTriangulation =
BRep_Tool::Triangulation(theFace, aLoc);
if (aTriangulation.IsNull())
return Standard_True;
if (isWithCheck)
{
Standard_Real aFaceDeflection = faceDeflection(theFace);
if (aTriangulation->Deflection() < 1.1 * aFaceDeflection)
{
Standard_Boolean isEdgesConsistent = Standard_True;
TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
if (!myEdges.IsBound(aEdge))
continue;
BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge);
isEdgesConsistent &= aTriMap.IsBound(aTriangulation) &&
aTriMap(aTriangulation);
}
if (isEdgesConsistent)
{
// #25080: check that indices of links forming triangles are in range.
Standard_Boolean isTriangulationConsistent = Standard_True;
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 n[3];
aTriangle.Get(n[0], n[1], n[2]);
for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j)
isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb);
}
if (isTriangulationConsistent)
return Standard_False;
}
}
}
// Nullify edges
TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc);
}
BRepMesh_ShapeTool::NullifyFace(theFace);
return Standard_True;
}
//=======================================================================
//function : update(face)
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace)
{
if (!toBeMeshed(theFace, Standard_True))
return;
myModified = Standard_True;
Standard_Integer aStatus = myMesh->Add(theFace);
myStatus |= aStatus;
if (aStatus != BRepMesh_ReMesh)
return;
BRepMesh::MapOfShape aUsedFaces;
aUsedFaces.Add(theFace);
const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces =
myMesh->SharedFaces();
TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current());
if (aMapOfSharedFaces.FindIndex(aEdge) == 0)
continue;
const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge);
TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces);
for (; aSharedFaceIt.More(); aSharedFaceIt.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value());
if (aUsedFaces.Contains(aFace))
continue;
aUsedFaces.Add(aFace);
toBeMeshed(aFace, Standard_False);
myStatus |= myMesh->Add(aFace);
}
}
}
//=======================================================================
//function : commit
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::commit (Message_ProgressSentry& theSentry)
{
NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
for (; aFaceIt.More() && theSentry.More(); aFaceIt.Next(), theSentry.Next())
commitEdges(aFaceIt.Value());
discretizeFreeEdges();
}
//=======================================================================
//function : commitEdges
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::commitEdges(const TopoDS_Face& theFace)
{
TopoDS_Face aFace = theFace;
aFace.Orientation(TopAbs_FORWARD);
Handle(BRepMesh_FaceAttribute) aFaceAttribute;
if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute))
return;
if (!aFaceAttribute->IsValid())
{
myStatus |= aFaceAttribute->GetStatus();
return;
}
TopLoc_Location aLoc;
Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc);
if (aTriangulation.IsNull())
return;
try
{
OCC_CATCH_SIGNALS
// Store discretization of edges
BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges();
BRepMesh::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key());
const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value();
const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First();
const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last();
if (aPolygon1 == aPolygon2)
BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aTriangulation, aLoc);
else
BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aTriangulation, aLoc);
}
}
catch (Standard_Failure)
{
myStatus |= BRepMesh_Failure;
}
setDone();
}
//=======================================================================

View File

@@ -14,22 +14,9 @@
#ifndef _BRepMesh_IncrementalMesh_HeaderFile
#define _BRepMesh_IncrementalMesh_HeaderFile
#include <Standard.hxx>
#include <Standard_Type.hxx>
#include <BRepMesh_FastDiscret.hxx>
#include <TopTools_MapOfShape.hxx>
#include <TopTools_DataMapOfShapeReal.hxx>
#include <BRepMesh_DiscretRoot.hxx>
#include <BRepMesh.hxx>
#include <vector>
class Message_ProgressIndicator;
class Poly_Triangulation;
class TopoDS_Shape;
class TopoDS_Edge;
class TopoDS_Face;
#include <IMeshTools_Parameters.hxx>
#include <IMeshTools_Context.hxx>
//! Builds the mesh of a shape with respect of their
//! correctly triangulated parts
@@ -52,37 +39,35 @@ public: //! @name mesher API
//! used for the faces will be the maximum deflection of their edges.
//! @param theAngDeflection angular deflection.
//! @param isInParallel if TRUE shape will be meshed in parallel.
Standard_EXPORT BRepMesh_IncrementalMesh(
const TopoDS_Shape& theShape,
Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
const Standard_Real theLinDeflection,
const Standard_Boolean isRelative = Standard_False,
const Standard_Real theAngDeflection = 0.5,
const Standard_Boolean isInParallel = Standard_False,
const Standard_Boolean adaptiveMin = Standard_False);
const Standard_Boolean isInParallel = Standard_False);
//! Constructor.
//! Automatically calls method Perform.
//! @param theShape shape to be meshed.
//! @param theParameters - parameters of meshing
Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
const BRepMesh_FastDiscret::Parameters& theParameters);
const IMeshTools_Parameters& theParameters);
//! Performs meshing ot the shape.
Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
//! Performs meshing ot the shape.
Standard_EXPORT void Perform(const Handle(Message_ProgressIndicator)& theProgress);
//! Performs meshing using custom context;
Standard_EXPORT void Perform(const Handle(IMeshTools_Context)& theContext);
public: //! @name accessing to parameters.
//! Returns meshing parameters
inline const BRepMesh_FastDiscret::Parameters& Parameters() const
inline const IMeshTools_Parameters& Parameters() const
{
return myParameters;
}
//! Returns modifiable meshing parameters
inline BRepMesh_FastDiscret::Parameters& ChangeParameters()
inline IMeshTools_Parameters& ChangeParameters()
{
return myParameters;
}
@@ -99,6 +84,29 @@ public: //! @name accessing to parameters.
return myStatus;
}
private:
//! Initializes specific parameters
inline void initParameters()
{
if (myParameters.DeflectionInterior < Precision::Confusion())
{
myParameters.DeflectionInterior = myParameters.Deflection;
}
if (myParameters.MinSize < Precision::Confusion())
{
myParameters.MinSize =
Max(IMeshTools_Parameters::RelMinSize() * Min(myParameters.Deflection,
myParameters.DeflectionInterior),
Precision::Confusion());
}
if (myParameters.AngleInterior < Precision::Angular())
{
myParameters.AngleInterior = 2.0 * myParameters.Angle;
}
}
public: //! @name plugin API
@@ -121,81 +129,13 @@ public: //! @name plugin API
//! Discret() static method (thus applied only to Mesh Factories).
Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel);
DEFINE_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot)
protected:
Standard_EXPORT virtual void init() Standard_OVERRIDE;
private:
//! Builds the incremental mesh for the shape.
void update(const Handle(Message_ProgressIndicator)& theProgress);
//! Checks triangulation of the given face for consistency
//! with the chosen tolerance. If some edge of face has no
//! discrete representation triangulation will be calculated.
//! @param theFace face to be checked.
void update(const TopoDS_Face& theFace);
//! Checks discretization of the given edge for consistency
//! with the chosen tolerance.
//! @param theEdge edge to be checked.
void update(const TopoDS_Edge& theEdge);
//! Collects faces suitable for meshing.
void collectFaces();
//! Discretizes edges that have no associations with faces.
void discretizeFreeEdges();
//! Returns deflection of the given edge.
//! @param theEdge edge which tolerance should be taken.
Standard_Real edgeDeflection(const TopoDS_Edge& theEdge);
//! Returns deflection of the given face.
//! If relative flag is set, calculates relative deflection of the face
//! as an average value of relative deflection regarding face's edges.
//! Returns value of deflection set by user elsewhere.
Standard_Real faceDeflection(const TopoDS_Face& theFace);
//! Prepares the given face for meshing.
//! Nullifies triangulation of face and polygons of face's edges.
//! @param theFace face to be checked.
//! @param isWithCheck if TRUE, checks parameters of triangulation
//! existing in face. If its deflection satisfies the given value and
//! each edge of face has polygon corresponded to this triangulation,
//! method return FALSE.
//! @return TRUE in case if the given face should be meshed.
Standard_Boolean toBeMeshed(const TopoDS_Face& theFace,
const Standard_Boolean isWithCheck);
//! Stores mesh to the shape.
void commit(Message_ProgressSentry& theSentry);
//! Stores mesh of internal edges to the face.
void commitEdges(const TopoDS_Face& theFace);
//! Clears internal data structures.
void clear();
private:
class FaceListFunctor;
protected:
BRepMesh::DMapOfEdgeListOfTriangulationBool myEdges;
Handle(BRepMesh_FastDiscret) myMesh;
TopTools_DataMapOfShapeReal myEdgeDeflection;
NCollection_Vector<TopoDS_Face> myFaces;
BRepMesh_FastDiscret::Parameters myParameters;
Standard_Real myMaxShapeSize;
IMeshTools_Parameters myParameters;
Standard_Boolean myModified;
Standard_Integer myStatus;
};
DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
#endif

View File

@@ -0,0 +1,105 @@
// Created on: 2016-04-19
// 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_MeshAlgoFactory.hxx>
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <BRepMesh_NURBSRangeSplitter.hxx>
#include <BRepMesh_SphereRangeSplitter.hxx>
#include <BRepMesh_CylinderRangeSplitter.hxx>
#include <BRepMesh_ConeRangeSplitter.hxx>
#include <BRepMesh_TorusRangeSplitter.hxx>
#include <BRepMesh_DelaunayBaseMeshAlgo.hxx>
#include <BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx>
#include <BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx>
#include <BRepMesh_BoundaryParamsRangeSplitter.hxx>
namespace
{
struct BaseMeshAlgo
{
typedef BRepMesh_DelaunayBaseMeshAlgo Type;
};
template<class RangeSplitter>
struct NodeInsertionMeshAlgo
{
typedef BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo> Type;
};
template<class RangeSplitter>
struct DeflectionControlMeshAlgo
{
typedef BRepMesh_DelaunayDeflectionControlMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo> Type;
};
}
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_MeshAlgoFactory::BRepMesh_MeshAlgoFactory()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_MeshAlgoFactory::~BRepMesh_MeshAlgoFactory()
{
}
//=======================================================================
// Function: GetAlgo
// Purpose :
//=======================================================================
Handle(IMeshTools_MeshAlgo) BRepMesh_MeshAlgoFactory::GetAlgo(
const GeomAbs_SurfaceType theSurfaceType,
const IMeshTools_Parameters& theParameters) const
{
switch (theSurfaceType)
{
case GeomAbs_Plane:
return theParameters.InternalVerticesMode ?
new NodeInsertionMeshAlgo<BRepMesh_DefaultRangeSplitter>::Type :
new BaseMeshAlgo::Type;
break;
case GeomAbs_Sphere:
return new NodeInsertionMeshAlgo<BRepMesh_SphereRangeSplitter>::Type;
break;
case GeomAbs_Cylinder:
return theParameters.InternalVerticesMode ?
new NodeInsertionMeshAlgo<BRepMesh_CylinderRangeSplitter>::Type :
new BaseMeshAlgo::Type;
break;
case GeomAbs_Cone:
return new NodeInsertionMeshAlgo<BRepMesh_ConeRangeSplitter>::Type;
break;
case GeomAbs_Torus:
return new NodeInsertionMeshAlgo<BRepMesh_TorusRangeSplitter>::Type;
break;
case GeomAbs_SurfaceOfRevolution:
return new DeflectionControlMeshAlgo<BRepMesh_BoundaryParamsRangeSplitter>::Type;
break;
default:
return new DeflectionControlMeshAlgo<BRepMesh_NURBSRangeSplitter>::Type;
}
}

View File

@@ -0,0 +1,44 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_MeshAlgoFactory_HeaderFile
#define _BRepMesh_MeshAlgoFactory_HeaderFile
#include <Standard_Transient.hxx>
#include <Standard_Type.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <IMeshTools_MeshAlgoFactory.hxx>
//! Default implementation of IMeshTools_MeshAlgoFactory providing algorithms
//! of different compexity depending on type of target surface.
class BRepMesh_MeshAlgoFactory : public IMeshTools_MeshAlgoFactory
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_MeshAlgoFactory();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_MeshAlgoFactory();
//! Creates instance of meshing algorithm for the given type of surface.
Standard_EXPORT virtual Handle(IMeshTools_MeshAlgo) GetAlgo(
const GeomAbs_SurfaceType theSurfaceType,
const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshAlgoFactory, IMeshTools_MeshAlgoFactory)
};
#endif

View File

@@ -0,0 +1,368 @@
// Created on: 2016-08-22
// 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_MeshTool.hxx>
#include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
#include <stack>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#include <BRepTools.hxx>
#include <gp_Pln.hxx>
namespace
{
//! Returns index of triangle node opposite to the given link.
inline Standard_Integer findApexIndex(
const Standard_Integer(&aNodes)[3],
const BRepMesh_Edge& theLink)
{
Standard_Integer i = 0;
for (; i < 3; ++i)
{
if (aNodes[i] != theLink.FirstNode() &&
aNodes[i] != theLink.LastNode())
{
break;
}
}
return i;
}
}
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_MeshTool::BRepMesh_MeshTool(
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
: myStructure(theStructure)
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_MeshTool::~BRepMesh_MeshTool()
{
}
//=======================================================================
//function : Legalize
//purpose :
//=======================================================================
void BRepMesh_MeshTool::Legalize(const Standard_Integer theLinkIndex)
{
std::stack<Standard_Integer> aStack;
aStack.push(theLinkIndex);
IMeshData::MapOfInteger aUsedLinks;
while (!aStack.empty())
{
const Standard_Integer aLinkIndex = aStack.top();
aStack.pop();
aUsedLinks.Add(aLinkIndex);
const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
if (aLink.Movability() != BRepMesh_Frontier)
{
const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
if (aPair.Extent() == 2)
{
const BRepMesh_Triangle& aTriangle1 = myStructure->GetElement(aPair.FirstIndex());
const BRepMesh_Triangle& aTriangle2 = myStructure->GetElement(aPair.LastIndex());
Standard_Integer aNodes[2][3];
myStructure->ElementNodes(aTriangle1, aNodes[0]);
myStructure->ElementNodes(aTriangle2, aNodes[1]);
const Standard_Integer aApexIndex[2] = {
findApexIndex(aNodes[0], aLink),
findApexIndex(aNodes[1], aLink)
};
if (checkCircle(aNodes[0], aNodes[1][aApexIndex[1]]) ||
checkCircle(aNodes[1], aNodes[0][aApexIndex[0]]))
{
myStructure->RemoveElement(aPair.FirstIndex());
myStructure->RemoveElement(aPair.LastIndex());
myStructure->RemoveLink(aLinkIndex);
addTriangleAndUpdateStack(
aNodes[0][(aApexIndex[0])],
aNodes[0][(aApexIndex[0] + 1) % 3],
aNodes[1][(aApexIndex[1])],
aUsedLinks, aStack);
addTriangleAndUpdateStack(
aNodes[1][(aApexIndex[1])],
aNodes[1][(aApexIndex[1] + 1) % 3],
aNodes[0][(aApexIndex[0])],
aUsedLinks, aStack);
}
}
}
}
}
//=======================================================================
//function : EraseItemsConnectedTo
//purpose :
//=======================================================================
void BRepMesh_MeshTool::EraseItemsConnectedTo(
const Standard_Integer theNodeIndex)
{
BRepMesh_SelectorOfDataStructureOfDelaun aSelector(myStructure);
aSelector.NeighboursOfNode(theNodeIndex);
IMeshData::MapOfIntegerInteger aLoopEdges(1, new NCollection_IncAllocator);
EraseTriangles(aSelector.Elements(), aLoopEdges);
EraseFreeLinks(aLoopEdges);
myStructure->RemoveNode(theNodeIndex);
}
//=======================================================================
//function : CleanFrontierLinks
//purpose :
//=======================================================================
void BRepMesh_MeshTool::CleanFrontierLinks()
{
Handle(NCollection_IncAllocator) aAlloc = new NCollection_IncAllocator;
IMeshData::MapOfInteger aTrianglesToErase;
IMeshData::MapOfIntegerInteger aLoopEdges(1, aAlloc);
Handle(IMeshData::MapOfInteger) aFrontier = GetEdgesByType(BRepMesh_Frontier);
IMeshData::IteratorOfMapOfInteger aFrontierIt(*aFrontier);
for (; aFrontierIt.More(); aFrontierIt.Next())
{
Standard_Integer aFrontierId = aFrontierIt.Key();
const BRepMesh_Edge& aLink = myStructure->GetLink(aFrontierId);
Standard_Boolean isTriangleFound = Standard_False;
const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aFrontierId);
for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent() && !isTriangleFound; ++aElemIt)
{
const Standard_Integer aPriorElemId = aPair.Index(aElemIt);
const BRepMesh_Triangle& aElement = myStructure->GetElement(aPriorElemId);
const Standard_Integer(&e)[3] = aElement.myEdges;
const Standard_Boolean(&o)[3] = aElement.myOrientations;
for (Standard_Integer n = 0; n < 3 && !isTriangleFound; ++n)
{
if (aFrontierId == e[n] && !o[n])
{
// Destruction of external triangles on boundary edges
isTriangleFound = Standard_True;
aTrianglesToErase.Add(aPriorElemId);
collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 1) % 3], aTrianglesToErase);
collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 2) % 3], aTrianglesToErase);
}
}
}
}
EraseTriangles(aTrianglesToErase, aLoopEdges);
EraseFreeLinks(aLoopEdges);
}
//=======================================================================
//function : EraseTriangles
//purpose :
//=======================================================================
void BRepMesh_MeshTool::EraseTriangles(
const IMeshData::MapOfInteger& theTriangles,
IMeshData::MapOfIntegerInteger& theLoopEdges)
{
IMeshData::IteratorOfMapOfInteger aFreeTriangles(theTriangles);
for (; aFreeTriangles.More(); aFreeTriangles.Next())
{
EraseTriangle(aFreeTriangles.Key(), theLoopEdges);
}
}
//=======================================================================
//function : EraseTriangle
//purpose :
//=======================================================================
void BRepMesh_MeshTool::EraseTriangle(
const Standard_Integer theTriangleIndex,
IMeshData::MapOfIntegerInteger& theLoopEdges)
{
const BRepMesh_Triangle& aElement = myStructure->GetElement(theTriangleIndex);
const Standard_Integer(&e)[3] = aElement.myEdges;
const Standard_Boolean(&o)[3] = aElement.myOrientations;
myStructure->RemoveElement(theTriangleIndex);
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!theLoopEdges.Bind(e[i], o[i]))
{
theLoopEdges.UnBind(e[i]);
myStructure->RemoveLink(e[i]);
}
}
}
//=======================================================================
//function : EraseFreeLinks
//purpose :
//=======================================================================
void BRepMesh_MeshTool::EraseFreeLinks()
{
for (Standard_Integer i = 1; i <= myStructure->NbLinks(); i++)
{
if (myStructure->ElementsConnectedTo(i).IsEmpty())
{
BRepMesh_Edge& anEdge = (BRepMesh_Edge&) myStructure->GetLink(i);
if (anEdge.Movability() == BRepMesh_Deleted)
{
continue;
}
anEdge.SetMovability(BRepMesh_Free);
myStructure->RemoveLink(i);
}
}
}
//=======================================================================
//function : collectTrianglesOnFreeLinksAroundNodesOf
//purpose :
//=======================================================================
void BRepMesh_MeshTool::collectTrianglesOnFreeLinksAroundNodesOf(
const BRepMesh_Edge& theConstraint,
const Standard_Integer theStartLink,
IMeshData::MapOfInteger& theTriangles)
{
IMeshData::MapOfInteger aUsedLinks;
std::stack<Standard_Integer> aStack;
aStack.push(theStartLink);
aUsedLinks.Add(theStartLink);
while (!aStack.empty())
{
const Standard_Integer aLinkIndex = aStack.top();
aStack.pop();
const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex);
if (aLink.Movability() == BRepMesh_Free &&
(aLink.FirstNode() == theConstraint.FirstNode() ||
aLink.LastNode () == theConstraint.FirstNode() ||
aLink.FirstNode() == theConstraint.LastNode () ||
aLink.LastNode () == theConstraint.LastNode ()))
{
const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex);
for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent(); ++aElemIt)
{
const Standard_Integer aIndex = aPair.Index(aElemIt);
theTriangles.Add(aIndex);
const BRepMesh_Triangle& aElement = myStructure->GetElement(aIndex);
const Standard_Integer(&aEdges)[3] = aElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
{
if (aEdges[i] != aLinkIndex && !aUsedLinks.Contains(aEdges[i]))
{
aUsedLinks.Add(aEdges[i]);
aStack .push(aEdges[i]);
}
}
}
}
}
}
//=======================================================================
//function : EraseFreeLinks
//purpose :
//=======================================================================
void BRepMesh_MeshTool::EraseFreeLinks(
const IMeshData::MapOfIntegerInteger& theLinks)
{
IMeshData::MapOfIntegerInteger::Iterator aFreeEdges(theLinks);
for (; aFreeEdges.More(); aFreeEdges.Next())
{
if (myStructure->ElementsConnectedTo(aFreeEdges.Key()).IsEmpty())
{
myStructure->RemoveLink(aFreeEdges.Key());
}
}
}
//=======================================================================
//function : GetEdgesByType
//purpose :
//=======================================================================
Handle(IMeshData::MapOfInteger) BRepMesh_MeshTool::GetEdgesByType(
const BRepMesh_DegreeOfFreedom theEdgeType) const
{
Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
IMeshData::IteratorOfMapOfInteger aEdgeIt(myStructure->LinksOfDomain());
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const BRepMesh_Edge& aEdge = myStructure->GetLink(aEdgeIt.Key());
if (aEdge.Movability() == theEdgeType)
{
aResult->Add(aEdgeIt.Key());
}
}
return aResult;
}
//=======================================================================
//function : DumpStruct
//purpose :
//=======================================================================
void BRepMesh_MeshTool::DumpTriangles(const Standard_CString theFileName,
IMeshData::MapOfInteger* theTriangles)
{
BRep_Builder aBuilder;
TopoDS_Compound aResult;
aBuilder.MakeCompound(aResult);
const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain();
for (IMeshData::IteratorOfMapOfInteger aIt(aTriangles); aIt.More(); aIt.Next())
{
if (theTriangles != NULL && !theTriangles->Contains(aIt.Key()))
continue;
Standard_Integer aNodes[3];
const BRepMesh_Triangle& aTri = myStructure->GetElement(aIt.Key());
myStructure->ElementNodes(aTri, aNodes);
const gp_XY& aV1 = myStructure->GetNode(aNodes[0]).Coord();
const gp_XY& aV2 = myStructure->GetNode(aNodes[1]).Coord();
const gp_XY& aV3 = myStructure->GetNode(aNodes[2]).Coord();
BRepBuilderAPI_MakePolygon aPoly(gp_Pnt(aV1.X(), aV1.Y(), 0.),
gp_Pnt(aV2.X(), aV2.Y(), 0.),
gp_Pnt(aV3.X(), aV3.Y(), 0.),
Standard_True);
BRepBuilderAPI_MakeFace aFaceBuilder(gp_Pln(gp::XOY()), aPoly.Wire());
aBuilder.Add(aResult, aFaceBuilder.Shape());
}
BRepTools::Write(aResult, theFileName);
}

View File

@@ -0,0 +1,235 @@
// Created on: 2016-08-22
// 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.
#ifndef _BRepMesh_MeshTool_HeaderFile
#define _BRepMesh_MeshTool_HeaderFile
#include <Standard_Transient.hxx>
#include <Standard_DefineHandle.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_CircleTool.hxx>
#include <gp_Lin2d.hxx>
#include <IMeshData_Types.hxx>
#include <BRepMesh_Edge.hxx>
#include <stack>
//! Auxiliary tool providing API for manipulation with BRepMesh_DataStructureOfDelaun.
class BRepMesh_MeshTool : public Standard_Transient
{
public:
//! Helper functor intended to separate points to left and right from the constraint.
class NodeClassifier
{
public:
NodeClassifier(
const BRepMesh_Edge& theConstraint,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure)
: myStructure(theStructure)
{
const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(theConstraint.FirstNode());
const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(theConstraint.LastNode());
myConstraint.SetLocation(aVertex1.Coord());
myConstraint.SetDirection(gp_Vec2d(aVertex1.Coord(), aVertex2.Coord()));
mySign = myConstraint.Direction().X() > 0;
}
inline Standard_Boolean IsAbove(const Standard_Integer theNodeIndex) const
{
const BRepMesh_Vertex& aVertex = myStructure->GetNode(theNodeIndex);
const gp_Vec2d aNodeVec(myConstraint.Location(), aVertex.Coord());
if (aNodeVec.SquareMagnitude() > gp::Resolution())
{
const Standard_Real aCross = aNodeVec.Crossed(myConstraint.Direction());
if (Abs(aCross) > gp::Resolution())
{
return mySign ?
aCross < 0. :
aCross > 0.;
}
}
return Standard_False;
}
private:
NodeClassifier (const NodeClassifier& theOther);
void operator=(const NodeClassifier& theOther);
private:
const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
gp_Lin2d myConstraint;
Standard_Boolean mySign;
};
//! Constructor.
//! Initializes tool by the given data structure.
Standard_EXPORT BRepMesh_MeshTool(const Handle(BRepMesh_DataStructureOfDelaun)& theStructure);
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_MeshTool();
//! Returns data structure manipulated by this tool.
inline const Handle(BRepMesh_DataStructureOfDelaun)& GetStructure() const
{
return myStructure;
}
//! Dumps triangles to specified file.
void DumpTriangles(const Standard_CString theFileName, IMeshData::MapOfInteger* theTriangles);
//! Adds new triangle with specified nodes to mesh.
//! Legalizes triangle in case if it violates circle criteria.
inline void AddAndLegalizeTriangle(
const Standard_Integer thePoint1,
const Standard_Integer thePoint2,
const Standard_Integer thePoint3)
{
Standard_Integer aEdges[3];
AddTriangle(thePoint1, thePoint2, thePoint3, aEdges);
Legalize(aEdges[0]);
Legalize(aEdges[1]);
Legalize(aEdges[2]);
}
//! Adds new triangle with specified nodes to mesh.
inline void AddTriangle(
const Standard_Integer thePoint1,
const Standard_Integer thePoint2,
const Standard_Integer thePoint3,
Standard_Integer (&theEdges)[3])
{
Standard_Boolean aOri[3];
AddLink(thePoint1, thePoint2, theEdges[0], aOri[0]);
AddLink(thePoint2, thePoint3, theEdges[1], aOri[1]);
AddLink(thePoint3, thePoint1, theEdges[2], aOri[2]);
myStructure->AddElement(BRepMesh_Triangle(theEdges, aOri, BRepMesh_Free));
}
//! Adds new link to mesh.
//! Updates link index and link orientaion parameters.
inline void AddLink(const Standard_Integer theFirstNode,
const Standard_Integer theLastNode,
Standard_Integer& theLinkIndex,
Standard_Boolean& theLinkOri)
{
const Standard_Integer aLinkIt = myStructure->AddLink(
BRepMesh_Edge(theFirstNode, theLastNode, BRepMesh_Free));
theLinkIndex = Abs(aLinkIt);
theLinkOri = (aLinkIt > 0);
}
//! Performs legalization of triangles connected to the specified link.
Standard_EXPORT void Legalize(const Standard_Integer theLinkIndex);
//! Erases all elements connected to the specified artificial node.
//! In addition, erases the artificial node itself.
Standard_EXPORT void EraseItemsConnectedTo(const Standard_Integer theNodeIndex);
//! Cleans frontier links from triangles to the right.
Standard_EXPORT void CleanFrontierLinks();
//! Erases the given set of triangles.
//! Fills map of loop edges forming the countour surrounding the erased triangles.
void EraseTriangles(const IMeshData::MapOfInteger& theTriangles,
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Erases triangle with the given index and adds the free edges into the map.
//! When an edge is suppressed more than one time it is destroyed.
Standard_EXPORT void EraseTriangle(const Standard_Integer theTriangleIndex,
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Erases all links that have no elements connected to them.
Standard_EXPORT void EraseFreeLinks();
//! Erases links from the specified map that have no elements connected to them.
Standard_EXPORT void EraseFreeLinks(const IMeshData::MapOfIntegerInteger& theLinks);
//! Gives the list of edges with type defined by input parameter.
Standard_EXPORT Handle(IMeshData::MapOfInteger) GetEdgesByType(const BRepMesh_DegreeOfFreedom theEdgeType) const;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshTool, Standard_Transient)
private:
//! Returns True if the given point lies within circumcircle of the given triangle.
inline Standard_Boolean checkCircle(
const Standard_Integer(&aNodes)[3],
const Standard_Integer thePoint)
{
const BRepMesh_Vertex& aVertex0 = myStructure->GetNode(aNodes[0]);
const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(aNodes[1]);
const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(aNodes[2]);
gp_XY aLocation;
Standard_Real aRadius;
const Standard_Boolean isOk = BRepMesh_CircleTool::MakeCircle(
aVertex0.Coord(), aVertex1.Coord(), aVertex2.Coord(),
aLocation, aRadius);
if (isOk)
{
const BRepMesh_Vertex& aVertex = myStructure->GetNode(thePoint);
const Standard_Real aDist = (aVertex.Coord() - aLocation).SquareModulus() - (aRadius * aRadius);
return (aDist < Precision::SquareConfusion());
}
return Standard_False;
}
//! Adds new triangle with the given nodes and updates
//! links stack by ones are not in used map.
inline void addTriangleAndUpdateStack(
const Standard_Integer theNode0,
const Standard_Integer theNode1,
const Standard_Integer theNode2,
const IMeshData::MapOfInteger& theUsedLinks,
std::stack<Standard_Integer>& theStack)
{
Standard_Integer aEdges[3];
AddTriangle(theNode0, theNode1, theNode2, aEdges);
for (Standard_Integer i = 0; i < 3; ++i)
{
if (!theUsedLinks.Contains(aEdges[i]))
{
theStack.push(aEdges[i]);
}
}
}
//! Iteratively erases triangles and their neighbours consisting
//! of free links using the given link as starting front.
//! Only triangles around the constraint's saddle nodes will be removed.
void collectTrianglesOnFreeLinksAroundNodesOf(
const BRepMesh_Edge& theConstraint,
const Standard_Integer theStartLink,
IMeshData::MapOfInteger& theTriangles);
private:
Handle(BRepMesh_DataStructureOfDelaun) myStructure;
};
#endif

View File

@@ -0,0 +1,84 @@
// Created on: 2016-04-07
// 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_ModelBuilder.hxx>
#include <BRepMeshData_Model.hxx>
#include <BRepMesh_ShapeVisitor.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <IMeshTools_ShapeExplorer.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_ModelBuilder::BRepMesh_ModelBuilder ()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_ModelBuilder::~BRepMesh_ModelBuilder ()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Handle (IMeshData_Model) BRepMesh_ModelBuilder::performInternal (
const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters)
{
Handle (BRepMeshData_Model) aModel;
Bnd_Box aBox;
BRepBndLib::Add (theShape, aBox, Standard_False);
if (!aBox.IsVoid ())
{
// Build data model for further processing.
aModel = new BRepMeshData_Model (theShape);
if (theParameters.Relative)
{
Standard_Real aMaxSize;
BRepMesh_ShapeTool::BoxMaxDimension (aBox, aMaxSize);
aModel->SetMaxSize(aMaxSize);
}
else
{
aModel->SetMaxSize(Max(theParameters.Deflection,
theParameters.DeflectionInterior));
}
Handle (IMeshTools_ShapeVisitor) aVisitor =
new BRepMesh_ShapeVisitor (aModel);
IMeshTools_ShapeExplorer aExplorer (theShape);
aExplorer.Accept (aVisitor);
SetStatus (Message_Done1);
}
else
{
SetStatus (Message_Fail1);
}
return aModel;
}

View File

@@ -0,0 +1,50 @@
// Created on: 2016-04-07
// 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.
#ifndef _BRepMesh_ModelBuilder_HeaderFile
#define _BRepMesh_ModelBuilder_HeaderFile
#include <IMeshTools_ModelBuilder.hxx>
#include <Standard_Type.hxx>
#include <TopoDS_Shape.hxx>
//! Class implements interface representing tool for discrete model building.
//!
//! The following statuses should be used by default:
//! Message_Done1 - model has been sucessfully built.
//! Message_Fail1 - empty shape.
//! Message_Fail2 - model has not been build due to unexpected reason.
class BRepMesh_ModelBuilder : public IMeshTools_ModelBuilder
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_ModelBuilder ();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_ModelBuilder ();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelBuilder, IMeshTools_ModelBuilder)
protected:
//! Creates discrete model for the given shape.
//! Returns nullptr in case of failure.
Standard_EXPORT virtual Handle (IMeshData_Model) performInternal (
const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
};
#endif

View File

@@ -0,0 +1,499 @@
// Created on: 2016-06-23
// 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_ModelHealer.hxx>
#include <BRepMesh_Deflection.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <BRepMesh_FaceChecker.hxx>
#include <BRepMesh_EdgeDiscret.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <OSD_Parallel.hxx>
#include <TopExp.hxx>
#include <TopoDS_Vertex.hxx>
#ifdef DEBUG_HEALER
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepTools.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#endif
namespace
{
//! Decreases deflection of the given edge and tries to update discretization.
class EdgeAmplifier
{
public:
//! Constructor.
EdgeAmplifier(const IMeshTools_Parameters& theParameters)
: myParameters(theParameters)
{
}
//! Main operator.
void operator()(const IMeshData::IEdgePtr& theDEdge) const
{
const IMeshData::IEdgeHandle aDEdge = theDEdge;
aDEdge->Clear(Standard_True);
aDEdge->SetDeflection(Max(aDEdge->GetDeflection() / 3., Precision::Confusion()));
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0);
const IMeshData::IFaceHandle aDFace = aPCurve->GetFace();
Handle(IMeshTools_CurveTessellator) aTessellator =
BRepMesh_EdgeDiscret::CreateEdgeTessellator(
aDEdge, aPCurve->GetOrientation(), aDFace, myParameters);
BRepMesh_EdgeDiscret::Tessellate3d(aDEdge, aTessellator, Standard_False);
BRepMesh_EdgeDiscret::Tessellate2d(aDEdge, Standard_False);
}
private:
EdgeAmplifier (const EdgeAmplifier& theOther);
void operator=(const EdgeAmplifier& theOther);
private:
const IMeshTools_Parameters& myParameters;
};
//! Returns True if some of two vertcies is same with reference one.
inline Standard_Boolean isSameWithSomeOf(
const TopoDS_Vertex& theRefVertex,
const TopoDS_Vertex& theVertex1,
const TopoDS_Vertex& theVertex2)
{
return (theRefVertex.IsSame(theVertex1) ||
theRefVertex.IsSame(theVertex2));
}
//! Returns True if some of two vertcies is within tolerance of reference one.
inline Standard_Boolean isInToleranceWithSomeOf(
const gp_Pnt& theRefPoint,
const gp_Pnt& thePoint1,
const gp_Pnt& thePoint2,
const Standard_Real theTol)
{
const Standard_Real aSqTol = theTol * theTol;
return (theRefPoint.SquareDistance(thePoint1) < aSqTol ||
theRefPoint.SquareDistance(thePoint2) < aSqTol);
}
}
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_ModelHealer::BRepMesh_ModelHealer()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_ModelHealer::~BRepMesh_ModelHealer()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ModelHealer::performInternal(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters)
{
myModel = theModel;
myParameters = theParameters;
if (myModel.IsNull())
{
return Standard_False;
}
// MinSize is made as a constant. It is connected with
// the fact that too rude discretisation can lead to
// self-intersecting polygon, which cannot be fixed.
// As result the face will not be triangulated at all.
// E.g. see "Test mesh standard_mesh C7", the face #17.
myParameters.MinSize = Precision::Confusion();
myFaceIntersectingEdges = new IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs;
for (Standard_Integer aFaceIt = 0; aFaceIt < myModel->FacesNb(); ++aFaceIt)
{
myFaceIntersectingEdges->Bind(myModel->GetFace(aFaceIt).get(), Handle(IMeshData::MapOfIEdgePtr)());
}
// TODO: Here we can process edges in order to remove close discrete points.
OSD_Parallel::For(0, myModel->FacesNb(), *this, !isParallel());
amplifyEdges();
IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges);
for (; aFaceIt.More(); aFaceIt.Next())
{
if (!aFaceIt.Value().IsNull())
{
const IMeshData::IFaceHandle aDFace = aFaceIt.Key();
aDFace->SetStatus(IMeshData_SelfIntersectingWire);
aDFace->SetStatus(IMeshData_Failure);
}
}
myFaceIntersectingEdges.Nullify();
myModel.Nullify(); // Do not hold link to model.
return Standard_True;
}
//=======================================================================
// Function: amplifyEdges
// Purpose :
//=======================================================================
void BRepMesh_ModelHealer::amplifyEdges()
{
Handle(NCollection_IncAllocator) aTmpAlloc =
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
Standard_Integer aAmpIt = 0;
const Standard_Real aIterNb = 5;
IMeshData::MapOfIEdgePtr aEdgesToUpdate(1, aTmpAlloc);
while (aAmpIt++ < aIterNb && popEdgesToUpdate(aEdgesToUpdate))
{
// Try to update discretization by decreasing deflection of problematic edges.
OSD_Parallel::ForEach(aEdgesToUpdate.cbegin(), aEdgesToUpdate.cend(),
EdgeAmplifier(myParameters),
!(myParameters.InParallel && aEdgesToUpdate.Size() > 1),
aEdgesToUpdate.Size());
IMeshData::MapOfIFacePtr aFacesToCheck(1, aTmpAlloc);
IMeshData::MapOfIEdgePtr::Iterator aEdgeIt(aEdgesToUpdate);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const IMeshData::IEdgeHandle aDEdge = aEdgeIt.Value();
for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt)
{
aFacesToCheck.Add(aDEdge->GetPCurve(aPCurveIt)->GetFace());
}
}
OSD_Parallel::ForEach(aFacesToCheck.cbegin(), aFacesToCheck.cend(),
*this, !(myParameters.InParallel && aFacesToCheck.Size() > 1),
aFacesToCheck.Size());
aEdgesToUpdate.Clear();
aTmpAlloc->Reset(Standard_False);
}
}
//=======================================================================
// Function: popEdgesToUpdate
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ModelHealer::popEdgesToUpdate(
IMeshData::MapOfIEdgePtr& theEdgesToUpdate)
{
IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges);
for (; aFaceIt.More(); aFaceIt.Next())
{
Handle(IMeshData::MapOfIEdgePtr)& aIntersections = aFaceIt.ChangeValue();
if (!aIntersections.IsNull())
{
theEdgesToUpdate.Unite(*aIntersections);
aIntersections.Nullify();
}
}
return !theEdgesToUpdate.IsEmpty();
}
//=======================================================================
// Function: process
// Purpose :
//=======================================================================
void BRepMesh_ModelHealer::process(const IMeshData::IFaceHandle& theDFace) const
{
try
{
OCC_CATCH_SIGNALS
Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myFaceIntersectingEdges->ChangeFind(theDFace.get());
aIntersections.Nullify();
fixFaceBoundaries(theDFace);
if (!theDFace->IsSet(IMeshData_Failure))
{
BRepMesh_FaceChecker aChecker(theDFace, myParameters);
if (!aChecker.Perform())
{
#ifdef DEBUG_HEALER
std::cout << "Failed : #" << aChecker.GetIntersectingEdges()->Size() << std::endl;
#endif
aIntersections = aChecker.GetIntersectingEdges();
}
else
{
if (theDFace->WiresNb () == 1)
{
const IMeshData::IWireHandle& aDWire = theDFace->GetWire (0);
if (aDWire->EdgesNb () == 2)
{
const IMeshData::IEdgePtr& aDEdge0 = aDWire->GetEdge (0);
const IMeshData::IEdgePtr& aDEdge1 = aDWire->GetEdge (1);
const IMeshData::IPCurveHandle& aPCurve0 = aDEdge0->GetPCurve (theDFace.get (), aDWire->GetEdgeOrientation (0));
const IMeshData::IPCurveHandle& aPCurve1 = aDEdge1->GetPCurve (theDFace.get (), aDWire->GetEdgeOrientation (1));
if (aPCurve0->ParametersNb () == 2 && aPCurve1->ParametersNb () == 2)
{
aIntersections = new IMeshData::MapOfIEdgePtr;
// a kind of degenerated face - 1 wire, 2 edges and both edges are very small
aIntersections->Add (aDEdge0);
aIntersections->Add (aDEdge1);
}
}
}
}
}
}
catch (Standard_Failure const&)
{
theDFace->SetStatus (IMeshData_Failure);
}
}
//=======================================================================
// Function: fixFaceBoundaries
// Purpose :
//=======================================================================
void BRepMesh_ModelHealer::fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const
{
#ifdef DEBUG_HEALER
TopoDS_Compound aComp;
BRep_Builder aBuilder;
aBuilder.MakeCompound(aComp);
#endif
for (int aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt)
{
const IMeshData::IWireHandle& aDWire = theDFace->GetWire(aWireIt);
BRepMesh_Deflection::ComputeDeflection(aDWire, myParameters);
for (int aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt)
{
const int aPrevEdgeIt = (aEdgeIt + aDWire->EdgesNb() - 1) % aDWire->EdgesNb();
const int aNextEdgeIt = (aEdgeIt + 1) % aDWire->EdgesNb();
const IMeshData::IEdgeHandle aPrevEdge = aDWire->GetEdge(aPrevEdgeIt);
const IMeshData::IEdgeHandle aCurrEdge = aDWire->GetEdge(aEdgeIt);
const IMeshData::IEdgeHandle aNextEdge = aDWire->GetEdge(aNextEdgeIt);
Standard_Boolean isConnected = !getCommonVertex(aCurrEdge, aNextEdge).IsNull() &&
!getCommonVertex(aPrevEdge, aCurrEdge).IsNull();
if (isConnected)
{
const IMeshData::IPCurveHandle& aPrevPCurve =
aPrevEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aPrevEdgeIt));
const IMeshData::IPCurveHandle& aCurrPCurve =
aCurrEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt));
const IMeshData::IPCurveHandle& aNextPCurve =
aNextEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aNextEdgeIt));
isConnected = connectClosestPoints(aPrevPCurve, aCurrPCurve, aNextPCurve);
#ifdef DEBUG_HEALER
BRepBuilderAPI_MakePolygon aPoly;
for (int i = 0; i < aCurrPCurve->ParametersNb(); ++i)
{
const gp_Pnt2d& aPnt = aCurrPCurve->GetPoint(i);
aPoly.Add(gp_Pnt(aPnt.X(), aPnt.Y(), 0.));
}
if (aPoly.IsDone())
{
aBuilder.Add(aComp, aPoly.Shape());
}
TCollection_AsciiString aName("face_discr.brep");
BRepTools::Write(aComp, aName.ToCString());
#endif
}
if (!isConnected || aCurrEdge->IsSet(IMeshData_Outdated))
{
// We have to clean face from triangulation.
theDFace->SetStatus(IMeshData_Outdated);
if (!isConnected)
{
// Just mark wire as open, but continue fixing other inconsistencies
// in hope that this data could be suitable to build mesh somehow.
aDWire->SetStatus(IMeshData_OpenWire);
}
}
}
}
#ifdef DEBUG_HEALER
TCollection_AsciiString aName ("face_discr.brep");
TCollection_AsciiString aFaceName("face_geom.brep");
BRepTools::Write(aComp, aName.ToCString());
BRepTools::Write(theDFace->GetFace(), aFaceName.ToCString());
#endif
BRepMesh_Deflection::ComputeDeflection(theDFace, myParameters);
}
//=======================================================================
// Function: hasCommonVertex
// Purpose :
//=======================================================================
TopoDS_Vertex BRepMesh_ModelHealer::getCommonVertex(
const IMeshData::IEdgeHandle& theEdge1,
const IMeshData::IEdgeHandle& theEdge2) const
{
TopoDS_Vertex aVertex1_1, aVertex1_2;
TopExp::Vertices(theEdge1->GetEdge(), aVertex1_1, aVertex1_2);
//Test bugs moddata_2 bug428.
// restore [locate_data_file OCC428.brep] rr
// explode rr f
// explode rr_91 w
// explode rr_91_2 e
// nbshapes rr_91_2_2
// # 0 vertices; 1 edge
//This shape is invalid and can lead to exception in this code.
if (aVertex1_1.IsNull() || aVertex1_2.IsNull())
return TopoDS_Vertex();
if (theEdge1->GetEdge().IsSame(theEdge2->GetEdge()))
{
return aVertex1_1.IsSame(aVertex1_2) ? aVertex1_1 : TopoDS_Vertex();
}
TopoDS_Vertex aVertex2_1, aVertex2_2;
TopExp::Vertices(theEdge2->GetEdge(), aVertex2_1, aVertex2_2);
if (aVertex2_1.IsNull() || aVertex2_2.IsNull())
return TopoDS_Vertex();
if (isSameWithSomeOf(aVertex1_1, aVertex2_1, aVertex2_2))
{
return aVertex1_1;
}
else if (isSameWithSomeOf(aVertex1_2, aVertex2_1, aVertex2_2))
{
return aVertex1_2;
}
const gp_Pnt aPnt1_1 = BRep_Tool::Pnt(aVertex1_1);
const gp_Pnt aPnt1_2 = BRep_Tool::Pnt(aVertex1_2);
const Standard_Real aTol1_1 = BRep_Tool::Tolerance(aVertex1_1);
const Standard_Real aTol1_2 = BRep_Tool::Tolerance(aVertex1_2);
const gp_Pnt aPnt2_1 = BRep_Tool::Pnt(aVertex2_1);
const gp_Pnt aPnt2_2 = BRep_Tool::Pnt(aVertex2_2);
const Standard_Real aTol2_1 = BRep_Tool::Tolerance(aVertex2_1);
const Standard_Real aTol2_2 = BRep_Tool::Tolerance(aVertex2_2);
if (isInToleranceWithSomeOf(aPnt1_1, aPnt2_1, aPnt2_2, aTol1_1 + Max(aTol2_1, aTol2_2)))
{
return aVertex1_1;
}
else if (isInToleranceWithSomeOf(aPnt1_2, aPnt2_1, aPnt2_2, aTol1_2 + Max(aTol2_1, aTol2_2)))
{
return aVertex1_2;
}
return TopoDS_Vertex();
}
//=======================================================================
// Function: connectClosestPoints
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ModelHealer::connectClosestPoints(
const IMeshData::IPCurveHandle& thePrevDEdge,
const IMeshData::IPCurveHandle& theCurrDEdge,
const IMeshData::IPCurveHandle& theNextDEdge) const
{
if (thePrevDEdge->IsInternal() ||
theCurrDEdge->IsInternal() ||
theNextDEdge->IsInternal())
{
return Standard_True;
}
gp_Pnt2d& aPrevFirstUV = thePrevDEdge->GetPoint(0);
gp_Pnt2d& aPrevLastUV = thePrevDEdge->GetPoint(thePrevDEdge->ParametersNb() - 1);
if (thePrevDEdge == theCurrDEdge)
{
// Wire consists of a single edge.
aPrevFirstUV = aPrevLastUV;
return Standard_True;
}
gp_Pnt2d& aCurrFirstUV = theCurrDEdge->GetPoint(0);
gp_Pnt2d& aCurrLastUV = theCurrDEdge->GetPoint(theCurrDEdge->ParametersNb() - 1);
gp_Pnt2d *aPrevUV = NULL, *aCurrPrevUV = NULL;
const Standard_Real aPrevSqDist = closestPoints(aPrevFirstUV, aPrevLastUV,
aCurrFirstUV, aCurrLastUV,
aPrevUV, aCurrPrevUV);
gp_Pnt2d *aNextUV = NULL, *aCurrNextUV = NULL;
if (thePrevDEdge == theNextDEdge)
{
// Wire consists of two edges. Connect both ends.
aNextUV = (aPrevUV == &aPrevFirstUV) ? &aPrevLastUV : &aPrevFirstUV;
aCurrNextUV = (aCurrPrevUV == &aCurrFirstUV) ? &aCurrLastUV : &aCurrFirstUV;
*aNextUV = *aCurrNextUV;
*aPrevUV = *aCurrPrevUV;
return Standard_True;
}
gp_Pnt2d& aNextFirstUV = theNextDEdge->GetPoint(0);
gp_Pnt2d& aNextLastUV = theNextDEdge->GetPoint(theNextDEdge->ParametersNb() - 1);
const Standard_Real aNextSqDist = closestPoints(aNextFirstUV, aNextLastUV,
aCurrFirstUV, aCurrLastUV,
aNextUV, aCurrNextUV);
#ifdef DEBUG_HEALER
std::cout << "PrevSqDist = " << aPrevSqDist << std::endl;
std::cout << "NextSqDist = " << aNextSqDist << std::endl;
#endif
// Connect closest points first. This can help to identify
// which ends should be connected in case of gap.
if (aPrevSqDist - aNextSqDist > gp::Resolution())
{
adjustSamePoints(aCurrNextUV, aNextUV, aCurrPrevUV, aPrevUV, aCurrFirstUV, aCurrLastUV, aPrevFirstUV, aPrevLastUV);
}
else
{
adjustSamePoints(aCurrPrevUV, aPrevUV, aCurrNextUV, aNextUV, aCurrFirstUV, aCurrLastUV, aNextFirstUV, aNextLastUV);
}
return Standard_True;
}

View File

@@ -0,0 +1,185 @@
// Created on: 2016-06-23
// 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.
#ifndef _BRepMesh_ModelHealer_HeaderFile
#define _BRepMesh_ModelHealer_HeaderFile
#include <IMeshTools_ModelAlgo.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
#include <IMeshData_Model.hxx>
#include <TopoDS_Vertex.hxx>
//! Class implements functionality of model healer tool.
//! Iterates over model's faces and checks consistency of their wires,
//! i.e.whether wires are closed and do not contain self - intersections.
//! In case if wire contains disconnected parts, ends of adjacent edges
//! forming the gaps are connected in parametric space forcibly. The notion
//! of this operation is to create correct discrete model defined relatively
//! parametric space of target face taking into account connectivity and
//! tolerances of 3D space only. This means that there are no specific
//! computations are made for the sake of determination of U and V tolerance.
//! Registers intersections on edges forming the face's shape and tries to
//! amplify discrete represenation by decreasing of deflection for the target edge.
//! Checks can be performed in parallel mode.
class BRepMesh_ModelHealer : public IMeshTools_ModelAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_ModelHealer();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_ModelHealer();
//! Functor API to discretize the given edge.
inline void operator() (const Standard_Integer theEdgeIndex) const {
process(theEdgeIndex);
}
//! Functor API to discretize the given edge.
inline void operator() (const IMeshData::IFaceHandle& theDFace) const {
process(theDFace);
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelHealer, IMeshTools_ModelAlgo)
protected:
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean performInternal (
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
private:
//! Checks existing discretization of the face and updates data model.
inline void process(const Standard_Integer theFaceIndex) const
{
const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex);
process(aDFace);
}
//! Checks existing discretization of the face and updates data model.
void process(const IMeshData::IFaceHandle& theDFace) const;
//! Amplifies discretization of edges in case if self-intersection problem has been found.
void amplifyEdges();
//! Returns common vertex of two edges or null ptr in case if there is no such vertex.
TopoDS_Vertex getCommonVertex(
const IMeshData::IEdgeHandle& theEdge1,
const IMeshData::IEdgeHandle& theEdge2) const;
//! Connects pcurves of previous and current edge on the specified face
//! according to topological connectivity. Uses next edge in order to
//! identify closest point in case of signle vertex shared between both
//! ends of edge (degenerative edge)
Standard_Boolean connectClosestPoints(
const IMeshData::IPCurveHandle& thePrevDEdge,
const IMeshData::IPCurveHandle& theCurrDEdge,
const IMeshData::IPCurveHandle& theNextDEdge) const;
//! Chooses the most closest point to reference one from the given pair.
//! Returns square distance between reference point and closest one as
//! well as pointer to closest point.
inline Standard_Real closestPoint(
gp_Pnt2d& theRefPnt,
gp_Pnt2d& theFristPnt,
gp_Pnt2d& theSecondPnt,
gp_Pnt2d*& theClosestPnt) const
{
// Find the most closest end-points.
const Standard_Real aSqDist1 = theRefPnt.SquareDistance(theFristPnt);
const Standard_Real aSqDist2 = theRefPnt.SquareDistance(theSecondPnt);
if (aSqDist1 < aSqDist2)
{
theClosestPnt = &theFristPnt;
return aSqDist1;
}
theClosestPnt = &theSecondPnt;
return aSqDist2;
}
//! Chooses the most closest points among the given to reference one from the given pair.
//! Returns square distance between reference point and closest one as
//! well as pointer to closest point.
inline Standard_Real closestPoints(
gp_Pnt2d& theFirstPnt1,
gp_Pnt2d& theSecondPnt1,
gp_Pnt2d& theFirstPnt2,
gp_Pnt2d& theSecondPnt2,
gp_Pnt2d*& theClosestPnt1,
gp_Pnt2d*& theClosestPnt2) const
{
gp_Pnt2d *aCurrPrevUV1 = NULL, *aCurrPrevUV2 = NULL;
const Standard_Real aSqDist1 = closestPoint(theFirstPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV1);
const Standard_Real aSqDist2 = closestPoint(theSecondPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV2);
if (aSqDist1 - aSqDist2 < gp::Resolution())
{
theClosestPnt1 = &theFirstPnt1;
theClosestPnt2 = aCurrPrevUV1;
return aSqDist1;
}
theClosestPnt1 = &theSecondPnt1;
theClosestPnt2 = aCurrPrevUV2;
return aSqDist2;
}
//! Adjusts the given pair of points supposed to be the same.
//! In addition, adjusts another end-point of an edge in order
//! to perform correct matching in case of gap.
inline void adjustSamePoints(
gp_Pnt2d*& theMajorSamePnt1,
gp_Pnt2d*& theMinorSamePnt1,
gp_Pnt2d*& theMajorSamePnt2,
gp_Pnt2d*& theMinorSamePnt2,
gp_Pnt2d& theMajorFirstPnt,
gp_Pnt2d& theMajorLastPnt,
gp_Pnt2d& theMinorFirstPnt,
gp_Pnt2d& theMinorLastPnt) const
{
if (theMajorSamePnt2 == theMajorSamePnt1)
{
theMajorSamePnt2 = (theMajorSamePnt2 == &theMajorFirstPnt) ? &theMajorLastPnt : &theMajorFirstPnt;
closestPoint(*theMajorSamePnt2, theMinorFirstPnt, theMinorLastPnt, theMinorSamePnt2);
}
*theMajorSamePnt1 = *theMinorSamePnt1;
*theMajorSamePnt2 = *theMinorSamePnt2;
}
//! Connects ends of pcurves of face's wires according to topological coherency.
void fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const;
//! Returns True if check can be done in parallel.
inline Standard_Boolean isParallel() const
{
return (myParameters.InParallel && myModel->FacesNb() > 1);
}
//! Collects unique edges to be updated from face map. Clears data stored in face map.
Standard_Boolean popEdgesToUpdate(IMeshData::MapOfIEdgePtr& theEdgesToUpdate);
private:
Handle(IMeshData_Model) myModel;
IMeshTools_Parameters myParameters;
Handle(IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs) myFaceIntersectingEdges;
};
#endif

View File

@@ -0,0 +1,192 @@
// 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_ModelPostProcessor.hxx>
#include <BRepMesh_ShapeTool.hxx>
#include <IMeshData_Model.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <OSD_Parallel.hxx>
namespace
{
//! Commits 3D polygons and polygons on triangulations for corresponding edges.
class PolygonCommitter
{
public:
//! Constructor
PolygonCommitter(const Handle(IMeshData_Model)& theModel)
: myModel(theModel)
{
}
//! Main functor.
void operator()(const Standard_Integer theEdgeIndex) const
{
const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge(theEdgeIndex);
if (aDEdge->GetCurve()->ParametersNb() == 0)
return;
if (aDEdge->IsFree())
{
if (!aDEdge->IsSet(IMeshData_Reused))
{
commitPolygon3D(aDEdge);
}
}
else
{
commitPolygons(aDEdge);
}
}
private:
//! Commits 3d polygon to topological edge
void commitPolygon3D(const IMeshData::IEdgeHandle& theDEdge) const
{
const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve();
TColgp_Array1OfPnt aNodes (1, aCurve->ParametersNb());
TColStd_Array1OfReal aUVNodes(1, aCurve->ParametersNb());
for (Standard_Integer i = 1; i <= aCurve->ParametersNb(); ++i)
{
aNodes (i) = aCurve->GetPoint (i - 1);
aUVNodes(i) = aCurve->GetParameter(i - 1);
}
Handle(Poly_Polygon3D) aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes);
aPoly3D->Deflection(theDEdge->GetDeflection());
BRepMesh_ShapeTool::UpdateEdge(theDEdge->GetEdge(), aPoly3D);
}
//! Commits all polygons on triangulations correspondent to the given edge.
void commitPolygons(const IMeshData::IEdgeHandle& theDEdge) const
{
// Collect pcurves associated with the given edge on the specific surface.
IMeshData::IDMapOfIFacePtrsListOfIPCurves aMapOfPCurves;
for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt)
{
const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt);
const IMeshData::IFacePtr& aDFacePtr = aPCurve->GetFace();
const IMeshData::IFaceHandle aDFace = aDFacePtr;
if (aDFace->IsSet(IMeshData_Failure) ||
aDFace->IsSet(IMeshData_Reused))
{
continue;
}
if (!aMapOfPCurves.Contains(aDFacePtr))
{
aMapOfPCurves.Add(aDFacePtr, IMeshData::ListOfIPCurves());
}
IMeshData::ListOfIPCurves& aPCurves = aMapOfPCurves.ChangeFromKey(aDFacePtr);
aPCurves.Append(aPCurve);
}
// Commit polygons related to separate face.
const TopoDS_Edge& aEdge = theDEdge->GetEdge();
IMeshData::IDMapOfIFacePtrsListOfIPCurves::Iterator aPolygonIt(aMapOfPCurves);
for (; aPolygonIt.More(); aPolygonIt.Next())
{
const TopoDS_Face& aFace = aPolygonIt.Key()->GetFace();
TopLoc_Location aLoc;
const Handle(Poly_Triangulation)& aTriangulation =
BRep_Tool::Triangulation(aFace, aLoc);
if (!aTriangulation.IsNull())
{
const IMeshData::ListOfIPCurves& aPCurves = aPolygonIt.Value();
if (aPCurves.Size() == 2)
{
BRepMesh_ShapeTool::UpdateEdge(
aEdge,
collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
collectPolygon(aPCurves.Last (), theDEdge->GetDeflection()),
aTriangulation, aLoc);
}
else
{
BRepMesh_ShapeTool::UpdateEdge(
aEdge,
collectPolygon(aPCurves.First(), theDEdge->GetDeflection()),
aTriangulation, aLoc);
}
}
}
}
//! Collects polygonal data for the given pcurve
Handle(Poly_PolygonOnTriangulation) collectPolygon(
const IMeshData::IPCurveHandle& thePCurve,
const Standard_Real theDeflection) const
{
TColStd_Array1OfInteger aNodes (1, thePCurve->ParametersNb());
TColStd_Array1OfReal aParams(1, thePCurve->ParametersNb());
for (Standard_Integer i = 1; i <= thePCurve->ParametersNb(); ++i)
{
aNodes (i) = thePCurve->GetIndex (i - 1);
aParams(i) = thePCurve->GetParameter(i - 1);
}
Handle(Poly_PolygonOnTriangulation) aPolygon =
new Poly_PolygonOnTriangulation(aNodes, aParams);
aPolygon->Deflection(theDeflection);
return aPolygon;
}
private:
Handle(IMeshData_Model) myModel;
};
}
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_ModelPostProcessor::BRepMesh_ModelPostProcessor()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ModelPostProcessor::performInternal(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& /*theParameters*/)
{
if (theModel.IsNull())
{
return Standard_False;
}
// TODO: Force single threaded solution due to data races on edges sharing the same TShape
OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/);
return Standard_True;
}

View File

@@ -0,0 +1,45 @@
// Created on: 2016-07-22
// 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.
#ifndef _BRepMesh_ModelPostProcessor_HeaderFile
#define _BRepMesh_ModelPostProcessor_HeaderFile
#include <IMeshTools_ModelAlgo.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
//! Class implements functionality of model post-processing tool.
//! Stores polygons on triangulations to TopoDS_Edge.
class BRepMesh_ModelPostProcessor : public IMeshTools_ModelAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_ModelPostProcessor();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_ModelPostProcessor();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPostProcessor, IMeshTools_ModelAlgo)
protected:
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean performInternal (
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
};
#endif

View File

@@ -0,0 +1,307 @@
// 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::performInternal(
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;
}

View File

@@ -0,0 +1,46 @@
// 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.
#ifndef _BRepMesh_ModelPreProcessor_HeaderFile
#define _BRepMesh_ModelPreProcessor_HeaderFile
#include <IMeshTools_ModelAlgo.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
//! Class implements functionality of model pre-processing tool.
//! Nullifies existing polygonal data in case if model elements
//! have IMeshData_Outdated status.
class BRepMesh_ModelPreProcessor : public IMeshTools_ModelAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_ModelPreProcessor();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_ModelPreProcessor();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPreProcessor, IMeshTools_ModelAlgo)
protected:
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean performInternal (
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
};
#endif

View File

@@ -0,0 +1,583 @@
// Created on: 2016-04-19
// 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_NURBSRangeSplitter.hxx>
#include <algorithm>
#include <BRepMesh_GeomTool.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomLib.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Wire.hxx>
#include <NCollection_Handle.hxx>
namespace
{
class AnalyticalFilter
{
public:
//! Constructor.
AnalyticalFilter(
const IMeshData::IFaceHandle& theDFace,
const GeomAbs_IsoType theIsoType,
const Handle(IMeshData::SequenceOfReal)& theParams,
const Handle(IMeshData::SequenceOfReal)& theControlParams,
const Handle(IMeshData::MapOfReal)& theParamsForbiddenToRemove,
const Handle(IMeshData::MapOfReal)& theControlParamsForbiddenToRemove)
: myDFace(theDFace),
mySurface(myDFace->GetSurface()->ChangeSurface().Surface().Surface()),
myIsoU(theIsoType == GeomAbs_IsoU),
myParams(theParams),
myControlParams(theControlParams),
myParamsForbiddenToRemove(theParamsForbiddenToRemove),
myControlParamsForbiddenToRemove(theControlParamsForbiddenToRemove),
myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)),
myControlParamsToRemove(new IMeshData::MapOfReal(1, myAllocator))
{
}
//! Returns map of parameters supposed to be removed.
const Handle(IMeshData::MapOfReal)& GetControlParametersToRemove(
const IMeshTools_Parameters& theParameters)
{
myParameters = theParameters;
Standard_Integer aStartIndex, aEndIndex;
if (myIsoU)
{
aStartIndex = 1;
aEndIndex = myParams->Length();
}
else
{
aStartIndex = 2;
aEndIndex = myParams->Length() - 1;
}
for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i)
{
myCurrParam = myParams->Value(i);
myIso = new GeomAdaptor_Curve(myIsoU ? mySurface->UIso(myCurrParam) : mySurface->VIso(myCurrParam));
myPrevControlParam = myControlParams->Value(1);
myIso->D1(myPrevControlParam, myPrevControlPnt, myPrevControlVec);
for (Standard_Integer j = 2; j <= myControlParams->Length();)
{
j += checkControlPointAndMoveOn(j);
}
}
return myControlParamsToRemove;
}
private:
//! Checks the given control point for deviation.
//! Returns number of steps to be used to move point iterator.
Standard_Integer checkControlPointAndMoveOn(const Standard_Integer theIndex)
{
Standard_Integer aMoveSteps = 0;
myCurrControlParam = myControlParams->Value(theIndex);
myIso->D1(myCurrControlParam, myCurrControlPnt, myCurrControlVec);
const Standard_Real aMidParam = 0.5 * (myPrevControlParam + myCurrControlParam);
const gp_Pnt aMidPnt = myIso->Value(aMidParam);
const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment(
myPrevControlPnt, myCurrControlPnt, aMidPnt);
Standard_Real anAngle = 0.0;
if ((myPrevControlVec.SquareMagnitude() > Precision::SquareConfusion()) &&
(myCurrControlVec.SquareMagnitude() > Precision::SquareConfusion()))
{
anAngle = myPrevControlVec.Angle(myCurrControlVec);
}
const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() *
myDFace->GetDeflection();
if (((aSqDist > aSqMaxDeflection) || (anAngle > myParameters.AngleInterior)) &&
aSqDist > myParameters.MinSize * myParameters.MinSize)
{
// insertion
myControlParams->InsertBefore(theIndex, aMidParam);
}
else
{
// Here we should leave at least 3 parameters as far as
// we must have at least one parameter related to surface
// internals in order to prevent movement of triangle body
// outside the surface in case of highly curved ones, e.g.
// BSpline springs.
if (((aSqDist < aSqMaxDeflection) || (anAngle < myParameters.AngleInterior)) &&
myControlParams->Length() > 3 && theIndex < myControlParams->Length())
{
// Remove too dense points
const Standard_Real aTmpParam = myControlParams->Value(theIndex + 1);
if (checkParameterForDeflectionAndUpdateCache(aTmpParam))
{
++aMoveSteps;
}
}
myPrevControlParam = myCurrControlParam;
myPrevControlPnt = myCurrControlPnt;
myPrevControlVec = myCurrControlVec;
++aMoveSteps;
}
return aMoveSteps;
}
//! Checks whether the given param suits specified deflection. Updates cache.
Standard_Boolean checkParameterForDeflectionAndUpdateCache(const Standard_Real theParam)
{
gp_Pnt aTmpPnt;
gp_Vec aTmpVec;
myIso->D1(theParam, aTmpPnt, aTmpVec);
const Standard_Real aTmpMidParam = 0.5 * (myPrevControlParam + theParam);
const gp_Pnt aTmpMidPnt = myIso->Value(aTmpMidParam);
// Lets check next parameter.
// If it also fits deflection, we can remove previous parameter.
const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment(
myPrevControlPnt, aTmpPnt, aTmpMidPnt);
if (aSqDist < myDFace->GetDeflection() * myDFace->GetDeflection())
{
// Lets check parameters for angular deflection.
if (myPrevControlVec.SquareMagnitude() < gp::Resolution() ||
aTmpVec.SquareMagnitude() < gp::Resolution() ||
myPrevControlVec.Angle(aTmpVec) < myParameters.AngleInterior)
{
// For current Iso line we can remove this parameter.
myControlParamsToRemove->Add(myCurrControlParam);
myCurrControlParam = theParam;
myCurrControlPnt = aTmpPnt;
myCurrControlVec = aTmpVec;
return Standard_True;
}
else
{
// We have found a place on the surface refusing
// removement of this parameter.
myParamsForbiddenToRemove ->Add(myCurrParam);
myControlParamsForbiddenToRemove->Add(myCurrControlParam);
}
}
return Standard_False;
}
private:
IMeshData::IFaceHandle myDFace;
Handle(Geom_Surface) mySurface;
Standard_Boolean myIsoU;
Handle(IMeshData::SequenceOfReal) myParams;
Handle(IMeshData::SequenceOfReal) myControlParams;
Handle(IMeshData::MapOfReal) myParamsForbiddenToRemove;
Handle(IMeshData::MapOfReal) myControlParamsForbiddenToRemove;
Handle(NCollection_IncAllocator) myAllocator;
Handle(IMeshData::MapOfReal) myControlParamsToRemove;
IMeshTools_Parameters myParameters;
NCollection_Handle<GeomAdaptor_Curve> myIso;
Standard_Real myCurrParam;
Standard_Real myCurrControlParam;
gp_Pnt myCurrControlPnt;
gp_Vec myCurrControlVec;
Standard_Real myPrevControlParam;
gp_Pnt myPrevControlPnt;
gp_Vec myPrevControlVec;
};
//! Adds param to map if it fits specified range.
inline Standard_Boolean addParam(
const Standard_Real& theParam,
const std::pair<Standard_Real, Standard_Real>& theRange,
IMeshData::IMapOfReal& theParams)
{
if (theParam < theRange.first ||
theParam > theRange.second)
{
return Standard_False;
}
theParams.Add(theParam);
return Standard_True;
}
//! Initializes parameters map using CN intervals.
inline Standard_Boolean initParamsFromIntervals(
const TColStd_Array1OfReal& theIntervals,
const std::pair<Standard_Real, Standard_Real>& theRange,
const Standard_Boolean isSplitIntervals,
IMeshData::IMapOfReal& theParams)
{
Standard_Boolean isAdded = Standard_False;
for (Standard_Integer i = theIntervals.Lower(); i <= theIntervals.Upper(); ++i)
{
const Standard_Real aStartParam = theIntervals.Value(i);
if (addParam(aStartParam, theRange, theParams))
{
isAdded = Standard_True;
}
if (isSplitIntervals && i < theIntervals.Upper())
{
const Standard_Real aMidParam = (aStartParam + theIntervals.Value(i + 1)) / 2.;
if (addParam(aMidParam, theRange, theParams))
{
isAdded = Standard_True;
}
}
}
return isAdded;
}
//! Checks whether intervals should be split.
//! Returns true in case if it is impossible to compute normal
//! directly on intervals, false is returned elsewhere.
Standard_Boolean toSplitIntervals (const Handle (Geom_Surface)& theSurf,
const TColStd_Array1OfReal (&theIntervals)[2])
{
Standard_Integer aIntervalU = theIntervals[0].Lower ();
for (; aIntervalU <= theIntervals[0].Upper (); ++aIntervalU)
{
const Standard_Real aParamU = theIntervals[0].Value(aIntervalU);
Standard_Integer aIntervalV = theIntervals[1].Lower ();
for (; aIntervalV <= theIntervals[1].Upper (); ++aIntervalV)
{
gp_Dir aNorm;
const Standard_Real aParamV = theIntervals[1].Value(aIntervalV);
if (GeomLib::NormEstim (theSurf, gp_Pnt2d (aParamU, aParamV), Precision::Confusion (), aNorm) != 0)
{
return Standard_True;
}
// TODO: do not split intervals if there is no normal in the middle of interval.
}
}
return Standard_False;
}
}
//=======================================================================
// Function: AdjustRange
// Purpose :
//=======================================================================
void BRepMesh_NURBSRangeSplitter::AdjustRange()
{
BRepMesh_DefaultRangeSplitter::AdjustRange();
mySurfaceType = GetSurface()->GetType();
if (mySurfaceType == GeomAbs_BezierSurface)
{
const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
myIsValid = !(aRangeU.first < -0.5 ||
aRangeU.second > 1.5 ||
aRangeV.first < -0.5 ||
aRangeV.second > 1.5);
}
}
//=======================================================================
// Function: GenerateSurfaceNodes
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& theParameters) const
{
if (!initParameters())
{
return Handle(IMeshData::ListOfPnt2d)();
}
const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
const std::pair<Standard_Real, Standard_Real>& aDelta = GetDelta ();
const Standard_Real aDefFace = GetDFace()->GetDeflection();
const Handle(BRepAdaptor_HSurface)& gFace = GetSurface();
Handle(Geom_Surface) aSurface = gFace->ChangeSurface().Surface().Surface();
const Handle(NCollection_IncAllocator) aTmpAlloc =
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
const Handle(IMeshData::SequenceOfReal) aParams[2] = {
computeGrainAndFilterParameters(GetParametersU(), gFace->UResolution(aDefFace),
(aRangeU.second - aRangeU.first), aDelta.first, theParameters, aTmpAlloc),
computeGrainAndFilterParameters(GetParametersV(), gFace->VResolution(aDefFace),
(aRangeV.second - aRangeV.first), aDelta.second, theParameters, aTmpAlloc)
};
// check intermediate isolines
Handle(IMeshData::MapOfReal) aFixedParams[2] = {
new IMeshData::MapOfReal(1, aTmpAlloc),
new IMeshData::MapOfReal(1, aTmpAlloc)
};
const Handle(IMeshData::MapOfReal) aParamsToRemove[2] = {
AnalyticalFilter(GetDFace(), GeomAbs_IsoV, aParams[1], aParams[0],
aFixedParams[1], aFixedParams[0]).GetControlParametersToRemove(theParameters),
AnalyticalFilter(GetDFace(), GeomAbs_IsoU, aParams[0], aParams[1],
aFixedParams[0], aFixedParams[1]).GetControlParametersToRemove(theParameters),
};
aParamsToRemove[0]->Subtract(*aFixedParams[0]);
aParamsToRemove[1]->Subtract(*aFixedParams[1]);
// insert nodes of the regular grid
Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE));
// insert nodes of the regular grid
for (Standard_Integer i = 1; i <= aParams[0]->Length(); ++i)
{
const Standard_Real aParam1 = aParams[0]->Value(i);
if (aParamsToRemove[0]->Contains(aParam1))
{
continue;
}
for (Standard_Integer j = 1; j <= aParams[1]->Length(); ++j)
{
const Standard_Real aParam2 = aParams[1]->Value(j);
if (aParamsToRemove[1]->Contains(aParam2))
{
continue;
}
aNodes->Append(gp_Pnt2d(aParam1, aParam2));
}
}
return aNodes;
}
//=======================================================================
// Function: initParameters
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_NURBSRangeSplitter::initParameters() const
{
const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface();
const GeomAbs_Shape aContinuity = GeomAbs_CN;
const std::pair<Standard_Integer, Standard_Integer> aIntervalsNb(
aSurface->NbUIntervals(aContinuity),
aSurface->NbVIntervals(aContinuity)
);
TColStd_Array1OfReal aIntervals[2] = {
TColStd_Array1OfReal(1, aIntervalsNb.first + 1),
TColStd_Array1OfReal(1, aIntervalsNb.second + 1)
};
aSurface->UIntervals(aIntervals[0], aContinuity);
aSurface->VIntervals(aIntervals[1], aContinuity);
const Standard_Boolean isSplitIntervals = toSplitIntervals (
aSurface->ChangeSurface().Surface().Surface(), aIntervals);
if (!initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals,
const_cast<IMeshData::IMapOfReal&>(GetParametersU())))
{
//if (!grabParamsOfEdges (Edge_Frontier, Param_U))
{
return Standard_False;
}
}
if (!initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals,
const_cast<IMeshData::IMapOfReal&>(GetParametersV())))
{
//if (!grabParamsOfEdges (Edge_Frontier, Param_V))
{
return Standard_False;
}
}
return grabParamsOfEdges(Edge_Internal, Param_U | Param_V);
}
//=======================================================================
//function : grabParamsOfInternalEdges
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_NURBSRangeSplitter::grabParamsOfEdges (
const EdgeType theEdgeType,
const Standard_Integer theParamDimensionFlag) const
{
if ((theParamDimensionFlag & (Param_U | Param_V)) == 0)
{
return Standard_False;
}
const IMeshData::IFaceHandle& aDFace = GetDFace ();
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb (); ++aWireIt)
{
const IMeshData::IWireHandle& aDWire = aDFace->GetWire (aWireIt);
for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb (); ++aEdgeIt)
{
const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIt);
for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt)
{
const IMeshData::IPCurveHandle& aDPCurve = aDEdge->GetPCurve (aPCurveIt);
if (aDPCurve->GetFace () == aDFace)
{
if (theEdgeType == Edge_Internal && !aDPCurve->IsInternal ())
{
continue;
}
for (Standard_Integer aPointIt = 0; aPointIt < aDPCurve->ParametersNb (); ++aPointIt)
{
const gp_Pnt2d& aPnt2d = aDPCurve->GetPoint (aPointIt);
if (theParamDimensionFlag & Param_U)
{
const_cast<IMeshData::IMapOfReal&>(GetParametersU ()).Add (aPnt2d.X ());
}
if (theParamDimensionFlag & Param_V)
{
const_cast<IMeshData::IMapOfReal&>(GetParametersV ()).Add (aPnt2d.Y ());
}
}
}
}
}
}
return Standard_True;
}
//=======================================================================
//function : computeGrainAndFilterParameters
//purpose :
//=======================================================================
Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::computeGrainAndFilterParameters(
const IMeshData::IMapOfReal& theSourceParams,
const Standard_Real theTol2d,
const Standard_Real theRangeDiff,
const Standard_Real theDelta,
const IMeshTools_Parameters& theParameters,
const Handle(NCollection_IncAllocator)& theAllocator) const
{
// Sort and filter sequence of parameters
Standard_Real aMinDiff = Precision::PConfusion();
if (theDelta < 1.)
{
aMinDiff /= theDelta;
}
aMinDiff = Max(theParameters.MinSize, aMinDiff);
const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff;
const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff,
2. * theTol2d);
const Standard_Real aDiff = Max(theParameters.MinSize,
Min(aDiffMaxLim, aDiffMinLim));
return filterParameters(theSourceParams, aMinDiff, aDiff, theAllocator);
}
//=======================================================================
//function : filterParameters
//purpose :
//=======================================================================
Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::filterParameters(
const IMeshData::IMapOfReal& theParams,
const Standard_Real theMinDist,
const Standard_Real theFilterDist,
const Handle(NCollection_IncAllocator)& theAllocator) const
{
Handle(IMeshData::SequenceOfReal) aResult = new IMeshData::SequenceOfReal(theAllocator);
// Sort sequence of parameters
const Standard_Integer anInitLen = theParams.Extent();
if (anInitLen < 1)
{
return aResult;
}
TColStd_Array1OfReal aParamArray(1, anInitLen);
Standard_Integer j;
for (j = 1; j <= anInitLen; j++)
aParamArray(j) = theParams(j);
std::sort(aParamArray.begin(), aParamArray.end());
// mandatory pre-filtering using the first (minimal) filter value
Standard_Integer aParamLength = 1;
for (j = 2; j <= anInitLen; j++)
{
if ((aParamArray(j) - aParamArray(aParamLength)) > theMinDist)
{
if (++aParamLength < j)
aParamArray(aParamLength) = aParamArray(j);
}
}
//perform filtering on series
Standard_Real aLastAdded, aLastCandidate;
Standard_Boolean isCandidateDefined = Standard_False;
aLastAdded = aParamArray(1);
aLastCandidate = aLastAdded;
aResult->Append(aLastAdded);
for (j = 2; j < aParamLength; j++)
{
Standard_Real aVal = aParamArray(j);
if (aVal - aLastAdded > theFilterDist)
{
//adds the parameter
if (isCandidateDefined)
{
aLastAdded = aLastCandidate;
isCandidateDefined = Standard_False;
j--;
}
else
{
aLastAdded = aVal;
}
aResult->Append(aLastAdded);
continue;
}
aLastCandidate = aVal;
isCandidateDefined = Standard_True;
}
aResult->Append(aParamArray(aParamLength));
return aResult;
}

View File

@@ -0,0 +1,91 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_NURBSRangeSplitter_HeaderFile
#define _BRepMesh_NURBSRangeSplitter_HeaderFile
#include <BRepMesh_UVParamRangeSplitter.hxx>
#include <IMeshData_Types.hxx>
#include <IMeshTools_Parameters.hxx>
//! Auxiliary class extending UV range splitter in order to generate
//! internal nodes for NURBS surface.
class BRepMesh_NURBSRangeSplitter : public BRepMesh_UVParamRangeSplitter
{
public:
//! Constructor.
BRepMesh_NURBSRangeSplitter()
{
}
//! Destructor.
virtual ~BRepMesh_NURBSRangeSplitter()
{
}
//! Updates discrete range of surface according to its geometric range.
Standard_EXPORT virtual void AdjustRange() Standard_OVERRIDE;
//! 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;
protected:
//! Initializes U and V parameters lists using CN continuity intervals.
Standard_EXPORT virtual Standard_Boolean initParameters() const;
private:
//! Computes parameters of filter and applies it to the source parameters.
Handle(IMeshData::SequenceOfReal) computeGrainAndFilterParameters(
const IMeshData::IMapOfReal& theSourceParams,
const Standard_Real theTol2d,
const Standard_Real theRangeDiff,
const Standard_Real theDelta,
const IMeshTools_Parameters& theParameters,
const Handle(NCollection_IncAllocator)& theAllocator) const;
//! Filters parameters in order to avoid too dence distribution.
Handle(IMeshData::SequenceOfReal) filterParameters(
const IMeshData::IMapOfReal& theParams,
const Standard_Real theMinDist,
const Standard_Real theFilterDist,
const Handle(NCollection_IncAllocator)& theAllocator) const;
enum EdgeType
{
Edge_Internal,
Edge_Frontier
};
enum ParamDimension
{
Param_U = 0x1,
Param_V = 0x2
};
//! Finds edges of discrete face and uses its points
//! as auxiliary control parameters for generation of nodes.
Standard_Boolean grabParamsOfEdges (const EdgeType theEdgeType,
const Standard_Integer theParamDimensionFlag) const;
private:
GeomAbs_SurfaceType mySurfaceType;
};
#endif

View File

@@ -0,0 +1,237 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
#define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
#include <BRepMesh_Classifier.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <BRepMesh_Vertex.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Vertex.hxx>
#include <BRep_Tool.hxx>
#include <Standard_ErrorHandler.hxx>
#include <BRepMesh_Delaun.hxx>
//! Extends base meshing algo in order to enable possibility
//! of addition of free vertices into the mesh.
template<class RangeSplitter, class BaseAlgo>
class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo
{
public:
//! Constructor.
BRepMesh_NodeInsertionMeshAlgo()
{
}
//! Destructor.
virtual ~BRepMesh_NodeInsertionMeshAlgo()
{
}
//! Performs processing of the given face.
virtual void Perform(
const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE
{
myRangeSplitter.Reset(theDFace, theParameters);
myClassifier = new BRepMesh_Classifier;
BaseAlgo::Perform(theDFace, theParameters);
myClassifier.Nullify();
}
protected:
typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*> > SequenceOfPnt2d;
//! Performs initialization of data structure using existing model data.
virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
{
Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator;
const IMeshData::IFaceHandle& aDFace = this->getDFace();
NCollection_Array1<Handle(SequenceOfPnt2d)> aWires(0, aDFace->WiresNb() - 1);
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
{
const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
if (aDWire->IsSet(IMeshData_SelfIntersectingWire) ||
(aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
{
continue;
}
aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
}
myRangeSplitter.AdjustRange();
if (!myRangeSplitter.IsValid())
{
aDFace->SetStatus(IMeshData_Failure);
return Standard_False;
}
const std::pair<Standard_Real, Standard_Real>& aDelta = myRangeSplitter.GetDelta();
const std::pair<Standard_Real, Standard_Real>& aTolUV = myRangeSplitter.GetToleranceUV();
const Standard_Real uCellSize = 14.0 * aTolUV.first;
const Standard_Real vCellSize = 14.0 * aTolUV.second;
this->getStructure()->Data()->SetCellSize (uCellSize / aDelta.first, vCellSize / aDelta.second);
this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second);
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
{
const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt);
if (!aWire.IsNull() && !aWire->IsEmpty())
{
myClassifier->RegisterWire(*aWire, aTolUV,
myRangeSplitter.GetRangeU(),
myRangeSplitter.GetRangeV());
}
}
if (this->getParameters().InternalVerticesMode)
{
insertInternalVertices();
}
return BaseAlgo::initDataStructure();
}
//! Adds the given 2d point to mesh data structure.
//! Returns index of node in the structure.
virtual Standard_Integer addNodeToStructure(
const gp_Pnt2d& thePoint,
const Standard_Integer theLocation3d,
const BRepMesh_DegreeOfFreedom theMovability,
const Standard_Boolean isForceAdd) Standard_OVERRIDE
{
return BaseAlgo::addNodeToStructure(
myRangeSplitter.Scale(thePoint, Standard_True),
theLocation3d, theMovability, isForceAdd);
}
//! Returns 2d point associated to the given vertex.
virtual gp_Pnt2d getNodePoint2d(
const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE
{
return myRangeSplitter.Scale(theVertex.Coord(), Standard_False);
}
//! Returns range splitter.
const RangeSplitter& getRangeSplitter() const
{
return myRangeSplitter;
}
//! Returns classifier.
const Handle(BRepMesh_Classifier)& getClassifier() const
{
return myClassifier;
}
private:
//! Creates collection of points representing discrete wire.
Handle(SequenceOfPnt2d) collectWirePoints(
const IMeshData::IWireHandle& theDWire,
const Handle(NCollection_IncAllocator)& theAllocator)
{
Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator);
for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
{
const IMeshData::IEdgeHandle aDEdge = theDWire->GetEdge(aEdgeIt);
const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
Standard_Integer aPointIt, aEndIndex, aInc;
if (aPCurve->IsForward())
{
// For an infinite cylinder (for example)
// aPCurve->ParametersNb() == 0
aEndIndex = aPCurve->ParametersNb() - 1;
aPointIt = Min(0, aEndIndex);
aInc = 1;
}
else
{
// For an infinite cylinder (for example)
// aPCurve->ParametersNb() == 0
aPointIt = aPCurve->ParametersNb() - 1;
aEndIndex = Min(0, aPointIt);
aInc = -1;
}
// For an infinite cylinder (for example)
// this cycle will not be executed.
for (; aPointIt != aEndIndex; aPointIt += aInc)
{
const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
aWirePoints->Append(&aPnt2d);
myRangeSplitter.AddPoint(aPnt2d);
}
}
return aWirePoints;
}
//! Iterates over internal vertices of a face and
//! creates corresponding nodes in data structure.
void insertInternalVertices()
{
TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
for (; aExplorer.More(); aExplorer.Next())
{
const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
if (aVertex.Orientation() != TopAbs_INTERNAL)
{
continue;
}
insertInternalVertex(aVertex);
}
}
//! Inserts the given vertex into mesh.
void insertInternalVertex(const TopoDS_Vertex& theVertex)
{
try
{
OCC_CATCH_SIGNALS
gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
// check UV values for internal vertices
if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
return;
this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d,
BRepMesh_Fixed, Standard_False);
}
catch (Standard_Failure const&)
{
}
}
private:
RangeSplitter myRangeSplitter;
Handle(BRepMesh_Classifier) myClassifier;
};
#endif

View File

@@ -54,12 +54,12 @@ public:
return myLastNode;
}
//! Returns hash code for this edge.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer theUpper) const
//! Computes a hash code for this oriented edge, in the range [1, theUpperBound]
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const Standard_Integer theUpperBound) const
{
return ::HashCode(myFirstNode + myLastNode, theUpper);
return ::HashCode (myFirstNode + myLastNode, theUpperBound);
}
//! Checks this and other edge for equality.
@@ -71,7 +71,7 @@ public:
}
//! Alias for IsEqual.
Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const
inline Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const
{
return IsEqual(Other);
}
@@ -82,10 +82,13 @@ private:
Standard_Integer myLastNode;
};
inline Standard_Integer HashCode(const BRepMesh_OrientedEdge& theEdge,
const Standard_Integer theUpper)
//! Computes a hash code for the given oriented edge, in the range [1, theUpperBound]
//! @param theOrientedEdge the oriented edge which hash code is to be computed
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const BRepMesh_OrientedEdge& theOrientedEdge, const Standard_Integer theUpperBound)
{
return theEdge.HashCode(theUpper);
return theOrientedEdge.HashCode (theUpperBound);
}
#endif

View File

@@ -1,81 +0,0 @@
// Copyright (c) 2013 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.
#ifndef _BRepMesh_PairOfPolygon_HeaderFile
#define _BRepMesh_PairOfPolygon_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
class Poly_PolygonOnTriangulation;
class BRepMesh_PairOfPolygon
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor. Creates empty pair with null fileds.
BRepMesh_PairOfPolygon()
{
}
//! Clears pair handles.
inline void Clear()
{
myFirst.Nullify();
myLast.Nullify();
}
//! Sets the first element of the pair.
//! If last element is empty, also assignes the given polygon to it.
//! @param thePolygon plygon to be set.
inline void Prepend(const Handle(Poly_PolygonOnTriangulation)& thePolygon)
{
myFirst = thePolygon;
if (myLast.IsNull())
myLast = thePolygon;
}
//! Sets the last element of the pair.
//! If first element is empty, also assignes the given polygon to it.
//! @param thePolygon plygon to be set.
inline void Append(const Handle(Poly_PolygonOnTriangulation)& thePolygon)
{
if (myFirst.IsNull())
myFirst = thePolygon;
myLast = thePolygon;
}
//! Returns first polygon on triangulation.
inline const Handle(Poly_PolygonOnTriangulation)& First() const
{
return myFirst;
}
//! Returns last polygon on triangulation.
inline const Handle(Poly_PolygonOnTriangulation)& Last() const
{
return myLast;
}
private:
Handle(Poly_PolygonOnTriangulation) myFirst;
Handle(Poly_PolygonOnTriangulation) myLast;
};
#endif

View File

@@ -16,17 +16,13 @@
#include <BRepMesh_SelectorOfDataStructureOfDelaun.hxx>
#include <BRepMesh_PairOfIndex.hxx>
#include <BRepMesh_Edge.hxx>
//=======================================================================
//function : Default constructor
//purpose :
//=======================================================================
BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun()
: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)),
myNodes (10, myAllocator),
myLinks (10, myAllocator),
myElements(10, myAllocator),
myFrontier(10, myAllocator)
{
}
@@ -36,12 +32,7 @@ BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDela
//=======================================================================
BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun(
const Handle(BRepMesh_DataStructureOfDelaun)& theMesh)
: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)),
myMesh (theMesh),
myNodes (10, myAllocator),
myLinks (10, myAllocator),
myElements(10, myAllocator),
myFrontier(10, myAllocator)
: myMesh(theMesh)
{
}
@@ -76,7 +67,7 @@ void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOf(
void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOfNode(
const Standard_Integer theNodeIndex)
{
BRepMesh::ListOfInteger::Iterator aLinkIt(
IMeshData::ListOfInteger::Iterator aLinkIt(
myMesh->LinksConnectedTo(theNodeIndex));
for (; aLinkIt.More(); aLinkIt.Next())
@@ -135,10 +126,7 @@ void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOfElement(
void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursByEdgeOf(
const BRepMesh_Triangle& theElement)
{
Standard_Integer e[3];
Standard_Boolean o[3];
theElement.Edges(e, o);
const Standard_Integer(&e)[3] = theElement.myEdges;
for (Standard_Integer i = 0; i < 3; ++i)
elementsOfLink(e[i]);
}

View File

@@ -14,25 +14,20 @@
#ifndef _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile
#define _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <Standard_Transient.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh.hxx>
#include <Standard_Integer.hxx>
#include <BRepMesh_Triangle.hxx>
#include <IMeshData_Types.hxx>
class BRepMesh_Vertex;
class BRepMesh_Edge;
//! Describes a selector and an iterator on a
//! selector of components of a mesh.
class BRepMesh_SelectorOfDataStructureOfDelaun
class BRepMesh_SelectorOfDataStructureOfDelaun : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
//! Default constructor.
Standard_EXPORT BRepMesh_SelectorOfDataStructureOfDelaun();
@@ -75,41 +70,42 @@ public:
}
//! Returns selected nodes.
inline const BRepMesh::MapOfInteger& Nodes() const
inline const IMeshData::MapOfInteger& Nodes() const
{
return myNodes;
}
//! Returns selected links.
inline const BRepMesh::MapOfInteger& Links() const
inline const IMeshData::MapOfInteger& Links() const
{
return myLinks;
}
//! Returns selected elements.
inline const BRepMesh::MapOfInteger& Elements() const
inline const IMeshData::MapOfInteger& Elements() const
{
return myElements;
}
//! Gives the list of incices of frontier links.
inline const BRepMesh::MapOfInteger& FrontierLinks() const
inline const IMeshData::MapOfInteger& FrontierLinks() const
{
return myFrontier;
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_SelectorOfDataStructureOfDelaun, Standard_Transient)
private:
//! Collects elements connected to link with the given index.
void elementsOfLink(const Standard_Integer theIndex);
private:
Handle(NCollection_IncAllocator) myAllocator;
Handle(BRepMesh_DataStructureOfDelaun) myMesh;
BRepMesh::MapOfInteger myNodes;
BRepMesh::MapOfInteger myLinks;
BRepMesh::MapOfInteger myElements;
BRepMesh::MapOfInteger myFrontier;
IMeshData::MapOfInteger myNodes;
IMeshData::MapOfInteger myLinks;
IMeshData::MapOfInteger myElements;
IMeshData::MapOfInteger myFrontier;
};
#endif

View File

@@ -1,5 +1,6 @@
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
// Created on: 2016-04-19
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
@@ -13,21 +14,20 @@
// commercial license or contractual agreement.
#include <BRepMesh_ShapeTool.hxx>
#include <Bnd_Box.hxx>
#include <TopoDS_Edge.hxx>
#include <BRepBndLib.hxx>
#include <TopoDS.hxx>
#include <BRep_Tool.hxx>
#include <TopExp_Explorer.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <Poly_Triangulation.hxx>
#include <BRep_Builder.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <ShapeAnalysis_Edge.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <Precision.hxx>
#include <Bnd_Box.hxx>
namespace {
namespace
{
//! Auxilary struct to take a tolerance of edge.
struct EdgeTolerance
{
@@ -64,7 +64,7 @@ namespace {
}
//=======================================================================
//function : BoxMaxDimension
//function : MaxFaceTolerance
//purpose :
//=======================================================================
Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace)
@@ -95,98 +95,102 @@ void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox,
}
//=======================================================================
//function : RelativeEdgeDeflection
//function : CheckAndUpdateFlags
//purpose :
//=======================================================================
Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection(
const TopoDS_Edge& theEdge,
const Standard_Real theDeflection,
const Standard_Real theMaxShapeSize,
Standard_Real& theAdjustmentCoefficient)
void BRepMesh_ShapeTool::CheckAndUpdateFlags (
const IMeshData::IEdgeHandle& theEdge,
const IMeshData::IPCurveHandle& thePCurve)
{
theAdjustmentCoefficient = 1.;
Standard_Real aDefEdge = theDeflection;
if(theEdge.IsNull())
return aDefEdge;
Bnd_Box aBox;
BRepBndLib::Add(theEdge, aBox, Standard_False);
BoxMaxDimension(aBox, aDefEdge);
// Adjust resulting value in relation to the total size
theAdjustmentCoefficient = theMaxShapeSize / (2 * aDefEdge);
if (theAdjustmentCoefficient < 0.5)
theAdjustmentCoefficient = 0.5;
else if (theAdjustmentCoefficient > 2.)
theAdjustmentCoefficient = 2.;
return (theAdjustmentCoefficient * aDefEdge * theDeflection);
if (!theEdge->GetSameParam () &&
!theEdge->GetSameRange () &&
theEdge->GetDegenerated ())
{
// Nothing to do worse.
return;
}
//=======================================================================
//function : FindUV
//purpose :
//=======================================================================
gp_XY BRepMesh_ShapeTool::FindUV(
const Standard_Integer theIndexOfPnt3d,
const gp_Pnt2d& thePnt2d,
const Standard_Real theMinDistance,
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute)
{
const gp_XY& aPnt2d = thePnt2d.Coord();
BRepMesh::HDMapOfIntegerListOfXY& aLocation2D =
theFaceAttribute->ChangeLocation2D();
const TopoDS_Edge& aEdge = theEdge->GetEdge ();
const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
if (!aLocation2D->IsBound(theIndexOfPnt3d))
Handle (Geom_Curve) aCurve;
Standard_Real aFirstParam, aLastParam;
Range (aEdge, aCurve, aFirstParam, aLastParam);
if (aCurve.IsNull())
{
BRepMesh::ListOfXY aPoints2d;
aPoints2d.Append(aPnt2d);
aLocation2D->Bind(theIndexOfPnt3d, aPoints2d);
return aPnt2d;
theEdge->SetDegenerated(Standard_True);
return;
}
BRepMesh::ListOfXY& aPoints2d = aLocation2D->ChangeFind(theIndexOfPnt3d);
// Find the most closest 2d point to the given one.
gp_XY aUV;
Standard_Real aMinDist = RealLast();
BRepMesh::ListOfXY::Iterator aPoint2dIt(aPoints2d);
for (; aPoint2dIt.More(); aPoint2dIt.Next())
BRepAdaptor_Curve aCurveOnSurf(aEdge, aFace);
if (theEdge->GetSameParam () || theEdge->GetSameRange ())
{
const gp_XY& aCurPnt2d = aPoint2dIt.Value();
Standard_Real aDist = (aPnt2d - aCurPnt2d).Modulus();
if (aDist < aMinDist)
if (theEdge->GetSameRange ())
{
aUV = aCurPnt2d;
aMinDist = aDist;
const Standard_Real aDiffFirst = aCurveOnSurf.FirstParameter () - aFirstParam;
const Standard_Real aDiffLast = aCurveOnSurf.LastParameter () - aLastParam;
theEdge->SetSameRange (
Abs (aDiffFirst) < Precision::PConfusion () &&
Abs (aDiffLast ) < Precision::PConfusion ());
if (!theEdge->GetSameRange())
{
theEdge->SetSameParam(Standard_False);
}
}
}
const Standard_Real aTolerance = theMinDistance;
// Get face limits
Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin();
Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin();
const Standard_Real Utol2d = .5 * aDiffU;
const Standard_Real Vtol2d = .5 * aDiffV;
const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface();
const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y());
const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y());
//! If selected point is too far from the given one in parametric space
//! or their positions in 3d are different, add the given point as unique.
if (Abs(aUV.X() - aPnt2d.X()) > Utol2d ||
Abs(aUV.Y() - aPnt2d.Y()) > Vtol2d ||
!aPnt1.IsEqual(aPnt2, aTolerance))
if (!theEdge->GetDegenerated ()/* || theEdge->GetSameParam ()*/)
{
aUV = aPnt2d;
aPoints2d.Append(aUV);
TopoDS_Vertex aStartVertex, aEndVertex;
TopExp::Vertices (aEdge, aStartVertex, aEndVertex);
if (aStartVertex.IsNull() || aEndVertex.IsNull())
{
theEdge->SetDegenerated(Standard_True);
return;
}
return aUV;
if (aStartVertex.IsSame(aEndVertex))
{
const Standard_Integer aPointsNb = 20;
const Standard_Real aVertexTolerance = BRep_Tool::Tolerance (aStartVertex);
const Standard_Real aDu = (aLastParam - aFirstParam) / aPointsNb;
//const Standard_Real aEdgeTolerance = BRep_Tool::Tolerance (aEdge);
//const Standard_Real aSqEdgeTolerance = aEdgeTolerance * aEdgeTolerance;
gp_Pnt aPrevPnt;
aCurve->D0 (aFirstParam, aPrevPnt);
Standard_Real aLength = 0.0;
for (Standard_Integer i = 1; i <= aPointsNb; ++i)
{
const Standard_Real aParameter = aFirstParam + i * aDu;
// Calculation of the length of the edge in 3D
// in order to check degenerativity
gp_Pnt aPnt;
aCurve->D0 (aParameter, aPnt);
aLength += aPrevPnt.Distance (aPnt);
//if (theEdge->GetSameParam ())
//{
// // Check that points taken at the 3d and pcurve using
// // same parameter are within tolerance of an edge.
// gp_Pnt aPntOnSurf;
// aCurveOnSurf.D0 (aParameter, aPntOnSurf);
// theEdge->SetSameParam (aPnt.SquareDistance (aPntOnSurf) < aSqEdgeTolerance);
//}
if (aLength > aVertexTolerance /*&& !theEdge->GetSameParam()*/)
{
break;
}
aPrevPnt = aPnt;
}
theEdge->SetDegenerated (aLength < aVertexTolerance);
}
}
}
//=======================================================================
@@ -212,6 +216,7 @@ void BRepMesh_ShapeTool::AddInFace(
aBuilder.UpdateFace(theFace, theTriangulation);
}
//=======================================================================
//function : NullifyFace
//purpose :
@@ -235,6 +240,18 @@ void BRepMesh_ShapeTool::NullifyEdge(
theTriangulation, theLocation);
}
//=======================================================================
//function : NullifyEdge
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::NullifyEdge (
const TopoDS_Edge& theEdge,
const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge (theEdge, Handle (Poly_Polygon3D)(), theLocation);
}
//=======================================================================
//function : UpdateEdge
//purpose :
@@ -265,64 +282,91 @@ void BRepMesh_ShapeTool::UpdateEdge(
theTriangulation, theLocation);
}
//=======================================================================
//function : UpdateEdge
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::UpdateEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_Polygon3D)& thePolygon)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge(theEdge, thePolygon);
}
//=======================================================================
//function : UseLocation
//purpose :
//=======================================================================
gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt,
gp_Pnt BRepMesh_ShapeTool::UseLocation (
const gp_Pnt& thePnt,
const TopLoc_Location& theLoc)
{
if (theLoc.IsIdentity())
{
return thePnt;
}
return thePnt.Transformed (theLoc.Transformation ());
}
//=======================================================================
//function : IsDegenerated
//function : UVPoints
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeTool::IsDegenerated(
Standard_Boolean BRepMesh_ShapeTool::UVPoints (
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace)
const TopoDS_Face& theFace,
gp_Pnt2d& theFirstPoint2d,
gp_Pnt2d& theLastPoint2d,
const Standard_Boolean isConsiderOrientation)
{
// Get vertices
TopoDS_Vertex pBegin, pEnd;
TopExp::Vertices(theEdge, pBegin, pEnd);
if (pBegin.IsNull() || pEnd.IsNull())
return Standard_True;
if (BRep_Tool::Degenerated(theEdge))
return Standard_True;
if (!pBegin.IsSame(pEnd))
return Standard_False;
Standard_Real wFirst, wLast;
BRep_Tool::Range(theEdge, theFace, wFirst, wLast);
// calculation of the length of the edge in 3D
Standard_Real longueur = 0.0;
Standard_Real du = (wLast - wFirst) * 0.05;
gp_Pnt P1, P2;
BRepAdaptor_Curve BC(theEdge);
BC.D0(wFirst, P1);
Standard_Real tolV = BRep_Tool::Tolerance(pBegin);
Standard_Real tolV2 = 1.2 * tolV;
for (Standard_Integer l = 1; l <= 20; ++l)
Handle (Geom2d_Curve) aCurve2d;
Standard_Real aFirstParam, aLastParam;
if (!Range(theEdge, theFace, aCurve2d, aFirstParam, aLastParam, isConsiderOrientation))
{
BC.D0(wFirst + l * du, P2);
longueur += P1.Distance(P2);
if (longueur > tolV2)
break;
P1 = P2;
}
if (longueur < tolV2)
return Standard_True;
return Standard_False;
}
aCurve2d->D0 (aFirstParam, theFirstPoint2d);
aCurve2d->D0 (aLastParam, theLastPoint2d);
return Standard_True;
}
//=======================================================================
//function : Range
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeTool::Range (
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
Handle (Geom2d_Curve)& thePCurve,
Standard_Real& theFirstParam,
Standard_Real& theLastParam,
const Standard_Boolean isConsiderOrientation)
{
ShapeAnalysis_Edge aEdge;
return aEdge.PCurve (theEdge, theFace, thePCurve,
theFirstParam, theLastParam,
isConsiderOrientation);
}
//=======================================================================
//function : Range
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeTool::Range (
const TopoDS_Edge& theEdge,
Handle (Geom_Curve)& theCurve,
Standard_Real& theFirstParam,
Standard_Real& theLastParam,
const Standard_Boolean isConsiderOrientation)
{
ShapeAnalysis_Edge aEdge;
return aEdge.Curve3d (theEdge, theCurve,
theFirstParam, theLastParam,
isConsiderOrientation);
}

View File

@@ -1,4 +1,6 @@
// Copyright (c) 2013 OPEN CASCADE SAS
// Created on: 2016-04-19
// Copyright (c) 2016 OPEN CASCADE SAS
// Created by: Oleg AGASHIN
//
// This file is part of Open CASCADE Technology software library.
//
@@ -11,31 +13,29 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _BRepMesh_ShapeTool_HeaderFile
#define _BRepMesh_ShapeTool_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <BRepAdaptor_HSurface.hxx>
#include <BRepMesh_FaceAttribute.hxx>
#include <BRepMesh.hxx>
#include <Standard_Transient.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Type.hxx>
#include <IMeshData_Types.hxx>
#include <Poly_Triangulation.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
class Poly_Triangulation;
class Geom_Curve;
class Geom2d_Curve;
class Poly_Polygon3D;
class TopoDS_Face;
class TopoDS_Edge;
class Bnd_Box;
class TopoDS_Vertex;
class gp_XY;
class gp_Pnt2d;
class BRepMesh_ShapeTool
//! Auxiliary class providing functionality to compute,
//! retrieve and store data to TopoDS and model shape.
class BRepMesh_ShapeTool : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
//! Returns maximum tolerance of the given face.
//! Considers tolerances of edges and vertices contained in the given face.
Standard_EXPORT static Standard_Real MaxFaceTolerance(
@@ -48,39 +48,15 @@ public:
Standard_EXPORT static void BoxMaxDimension(const Bnd_Box& theBox,
Standard_Real& theMaxDimension);
//! Returns relative deflection for edge with respect to shape size.
//! @param theEdge edge for which relative deflection should be computed.
//! @param theDeflection absolute deflection.
//! @param theMaxShapeSize maximum size of a shape.
//! @param theAdjustmentCoefficient coefficient of adjustment between maximum
//! size of shape and calculated relative deflection.
//! @return relative deflection for the edge.
Standard_EXPORT static Standard_Real RelativeEdgeDeflection(
const TopoDS_Edge& theEdge,
const Standard_Real theDeflection,
const Standard_Real theMaxShapeSize,
Standard_Real& theAdjustmentCoefficient);
//! Checks 2d representations of 3d point with the
//! given index for equality to avoid duplications.
//! @param theIndexOfPnt3d index of 3d point with which 2d
//! representation should be associated.
//! @param thePnt2d 2d representation of the point with the
//! given index.
//! @param theMinDistance minimum distance between vertices
//! regarding which they could be treated as distinct ones.
//! @param theFaceAttribute attributes contining data calculated
//! according to face geomtry and define limits of face in parametric
//! space. If defined, will be used instead of surface parameter.
//! @param theLocation2dMap map of 2d representations of 3d points.
//! @return given 2d point in case if 3d poind does not alredy have
//! the similar representation, otherwice 2d point corresponding to
//! existing representation will be returned.
Standard_EXPORT static gp_XY FindUV(
const Standard_Integer theIndexOfPnt3d,
const gp_Pnt2d& thePnt2d,
const Standard_Real theMinDistance,
const Handle(BRepMesh_FaceAttribute)& theFaceAttribute);
//! Checks same parameter, same range and degenerativity attributes
//! using geometrical data of the given edge and updates edge model
//! by computed parameters in case of worst case - it can drop flags
//! same parameter and same range to False but never to True if it is
//! already set to False. In contrary, it can also drop degenerated
//! flag to True, but never to False if it is already set to True.
Standard_EXPORT static void CheckAndUpdateFlags (
const IMeshData::IEdgeHandle& theEdge,
const IMeshData::IPCurveHandle& thePCurve);
//! Stores the given triangulation into the given face.
//! @param theFace face to be updated by triangulation.
@@ -102,6 +78,13 @@ public:
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
//! Nullifies 3d polygon stored in the edge.
//! @param theEdge edge to be updated by null polygon.
//! @param theLocation face location.
Standard_EXPORT static void NullifyEdge (
const TopoDS_Edge& theEdge,
const TopLoc_Location& theLocation);
//! Updates the given edge by the given tessellated representation.
//! @param theEdge edge to be updated.
//! @param thePolygon tessellated representation of the edge to be stored.
@@ -113,6 +96,13 @@ public:
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
//! Updates the given edge by the given tessellated representation.
//! @param theEdge edge to be updated.
//! @param thePolygon tessellated representation of the edge to be stored.
Standard_EXPORT static void UpdateEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_Polygon3D)& thePolygon);
//! Updates the given seam edge by the given tessellated representations.
//! @param theEdge edge to be updated.
//! @param thePolygon1 tessellated representation corresponding to
@@ -131,17 +121,36 @@ public:
//! Applies location to the given point and return result.
//! @param thePnt point to be transformed.
//! @param theLoc location to be applied.
Standard_EXPORT static gp_Pnt UseLocation(const gp_Pnt& thePnt,
Standard_EXPORT static gp_Pnt UseLocation (
const gp_Pnt& thePnt,
const TopLoc_Location& theLoc);
//! Checks is the given edge degenerated.
//! Checks geometrical parameters in case if IsDegenerated flag is not set.
//! @param theEdge edge to be checked.
//! @param theFace face within which parametric space edge will be checked
//! for geometrical degenerativity.
Standard_EXPORT static Standard_Boolean IsDegenerated(
//! Gets the strict UV locations of the extremities of the edge using pcurve.
Standard_EXPORT static Standard_Boolean UVPoints (
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace);
const TopoDS_Face& theFace,
gp_Pnt2d& theFirstPoint2d,
gp_Pnt2d& theLastPoint2d,
const Standard_Boolean isConsiderOrientation = Standard_False);
//! Gets the parametric range of the given edge on the given face.
Standard_EXPORT static Standard_Boolean Range (
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
Handle (Geom2d_Curve)& thePCurve,
Standard_Real& theFirstParam,
Standard_Real& theLastParam,
const Standard_Boolean isConsiderOrientation = Standard_False);
//! Gets the 3d range of the given edge.
Standard_EXPORT static Standard_Boolean Range (
const TopoDS_Edge& theEdge,
Handle (Geom_Curve)& theCurve,
Standard_Real& theFirstParam,
Standard_Real& theLastParam,
const Standard_Boolean isConsiderOrientation = Standard_False);
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeTool, Standard_Transient)
};
#endif

View File

@@ -0,0 +1,151 @@
// Created on: 2016-04-07
// 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_ShapeVisitor.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <ShapeAnalysis.hxx>
#include <TopExp_Explorer.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Face.hxx>
#include <ShapeAnalysis_Wire.hxx>
#include <ShapeAnalysis_WireOrder.hxx>
#include <ShapeExtend_WireData.hxx>
#include <Precision.hxx>
#include <IMeshData_Status.hxx>
#include <IMeshTools_Context.hxx>
#include <BRepTools.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_ShapeVisitor::BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel)
: myModel (theModel),
myDEdgeMap(1, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE))
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_ShapeVisitor::~BRepMesh_ShapeVisitor ()
{
}
//=======================================================================
// Function: Visit (edge)
// Purpose :
//=======================================================================
void BRepMesh_ShapeVisitor::Visit(const TopoDS_Edge& theEdge)
{
if (!myDEdgeMap.IsBound (theEdge))
{
myModel->AddEdge (theEdge);
myDEdgeMap.Bind (theEdge, myModel->EdgesNb () - 1);
}
}
//=======================================================================
// Function: Visit (face)
// Purpose :
//=======================================================================
void BRepMesh_ShapeVisitor::Visit (const TopoDS_Face& theFace)
{
BRepTools::Update(theFace);
const IMeshData::IFaceHandle& aDFace = myModel->AddFace (theFace);
// Outer wire should always be the first in the model.
TopoDS_Wire aOuterWire = ShapeAnalysis::OuterWire (theFace);
if (!addWire (aOuterWire, aDFace))
{
aDFace->SetStatus (IMeshData_Failure);
return;
}
TopExp_Explorer aWireIt (theFace, TopAbs_WIRE);
for (; aWireIt.More (); aWireIt.Next ())
{
const TopoDS_Wire& aWire = TopoDS::Wire (aWireIt.Current ());
if (aWire.IsSame(aOuterWire))
{
continue;
}
if (!addWire (aWire, aDFace))
{
// If there is a failure on internal wire, just skip it.
// The most significant is an outer wire.
aDFace->SetStatus (IMeshData_UnorientedWire);
}
}
}
//=======================================================================
// Function: addWire
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeVisitor::addWire (
const TopoDS_Wire& theWire,
const IMeshData::IFaceHandle& theDFace)
{
if (theWire.IsNull())
{
return Standard_False;
}
Handle(ShapeExtend_WireData) aWireData = new ShapeExtend_WireData(theWire, Standard_True, Standard_False);
ShapeAnalysis_Wire aWireTool (aWireData, theDFace->GetFace (), Precision::Confusion ());
ShapeAnalysis_WireOrder aOrderTool;
aWireTool.CheckOrder (aOrderTool, Standard_True, Standard_False);
if (aWireTool.LastCheckStatus(ShapeExtend_FAIL))
{
return Standard_False;
}
if (aWireTool.LastCheckStatus(ShapeExtend_DONE3))
{
theDFace->SetStatus(IMeshData_UnorientedWire);
}
const Standard_Integer aEdgesNb = aOrderTool.NbEdges ();
if (aEdgesNb != aWireData->NbEdges())
{
return Standard_False;
}
const IMeshData::IWireHandle& aDWire = theDFace->AddWire (theWire, aEdgesNb);
for (Standard_Integer i = 1; i <= aEdgesNb; ++i)
{
const Standard_Integer aEdgeIndex = aOrderTool.Ordered (i);
const TopoDS_Edge& aEdge = aWireData->Edge (aEdgeIndex);
if (aEdge.Orientation() != TopAbs_EXTERNAL)
{
const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (myDEdgeMap.Find (aEdge));
aDEdge->AddPCurve (theDFace.get(), aEdge.Orientation());
aDWire->AddEdge (aDEdge.get(), aEdge.Orientation());
}
}
return Standard_True;
}

View File

@@ -0,0 +1,67 @@
// Created on: 2016-04-07
// 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.
#ifndef _BRepMesh_ShapeVisitor_HeaderFile
#define _BRepMesh_ShapeVisitor_HeaderFile
#include <IMeshTools_ShapeVisitor.hxx>
#include <IMeshData_Model.hxx>
#include <Standard_Transient.hxx>
#include <Standard_Type.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Types.hxx>
class TopoDS_Face;
class TopoDS_Edge;
class TopoDS_Wire;
class IMeshTools_Context;
class IMeshData_Wire;
//! Builds discrete model of a shape by adding faces and free edges.
//! Computes deflection for corresponded shape and checks whether it
//! fits existing polygonal representation. If not, cleans shape from
//! outdated info.
class BRepMesh_ShapeVisitor : public IMeshTools_ShapeVisitor
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel);
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_ShapeVisitor ();
//! Handles TopoDS_Face object.
Standard_EXPORT virtual void Visit (const TopoDS_Face& theFace) Standard_OVERRIDE;
//! Handles TopoDS_Edge object.
Standard_EXPORT virtual void Visit (const TopoDS_Edge& theEdge) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeVisitor, IMeshTools_ShapeVisitor)
private:
//! Adds wire to face discrete model.
Standard_Boolean addWire (
const TopoDS_Wire& theWire,
const IMeshData::IFaceHandle& theDFace);
private:
Handle (IMeshData_Model) myModel;
IMeshData::DMapOfShapeInteger myDEdgeMap;
};
#endif

View File

@@ -0,0 +1,59 @@
// Created on: 2016-07-07
// 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_SphereRangeSplitter.hxx>
#include <GCPnts_TangentialDeflection.hxx>
//=======================================================================
// Function: GenerateSurfaceNodes
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_SphereRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& theParameters) const
{
// Calculate parameters for iteration in V direction
Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep(
GetDFace()->GetSurface()->Sphere().Radius(), GetDFace()->GetDeflection(),
theParameters.Angle, theParameters.MinSize);
const std::pair<Standard_Real, Standard_Real>* aRange[2] = {
&GetRangeV(),
&GetRangeU()
};
std::pair<Standard_Real, Standard_Real> aStepAndOffset[2];
computeStep(*aRange[0], aStep, aStepAndOffset[0]);
computeStep(*aRange[1], aStep, aStepAndOffset[1]);
const Handle(NCollection_IncAllocator) aTmpAlloc =
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
const Standard_Real aHalfDu = aStepAndOffset[1].first * 0.5;
Standard_Boolean Shift = Standard_False;
Standard_Real aPasV = aRange[0]->first + aStepAndOffset[0].first;
for (; aPasV < aStepAndOffset[0].second; aPasV += aStepAndOffset[0].first)
{
Shift = !Shift;
const Standard_Real d = (Shift) ? aHalfDu : 0.;
Standard_Real aPasU = aRange[1]->first + d;
for (; aPasU < aStepAndOffset[1].second; aPasU += aStepAndOffset[1].first)
{
aNodes->Append(gp_Pnt2d(aPasU, aPasV));
}
}
return aNodes;
}

View File

@@ -0,0 +1,56 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_SphereRangeSplitter_HeaderFile
#define _BRepMesh_SphereRangeSplitter_HeaderFile
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <IMeshTools_Parameters.hxx>
//! Auxiliary class extending default range splitter in
//! order to generate internal nodes for spherical surface.
class BRepMesh_SphereRangeSplitter : public BRepMesh_DefaultRangeSplitter
{
public:
//! Constructor.
BRepMesh_SphereRangeSplitter()
{
}
//! Destructor.
virtual ~BRepMesh_SphereRangeSplitter()
{
}
//! 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;
private:
//! Computes step for the given range.
inline void computeStep(
const std::pair<Standard_Real, Standard_Real>& theRange,
const Standard_Real theDefaultStep,
std::pair<Standard_Real, Standard_Real>& theStepAndOffset) const
{
const Standard_Real aDiff = theRange.second - theRange.first;
theStepAndOffset.first = aDiff / ((Standard_Integer) (aDiff / theDefaultStep) + 1);
theStepAndOffset.second = theRange.second - Precision::PConfusion();
}
};
#endif

View File

@@ -0,0 +1,218 @@
// Created on: 2016-07-07
// 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_TorusRangeSplitter.hxx>
#include <GCPnts_TangentialDeflection.hxx>
//=======================================================================
// Function: GenerateSurfaceNodes
// Purpose :
//=======================================================================
Handle(IMeshData::ListOfPnt2d) BRepMesh_TorusRangeSplitter::GenerateSurfaceNodes(
const IMeshTools_Parameters& theParameters) const
{
const std::pair<Standard_Real, Standard_Real>& aRangeU = GetRangeU();
const std::pair<Standard_Real, Standard_Real>& aRangeV = GetRangeV();
const Standard_Real aDiffU = aRangeU.second - aRangeU.first;
const Standard_Real aDiffV = aRangeV.second - aRangeV.first;
const gp_Torus aTorus = GetDFace()->GetSurface()->Torus();
const Standard_Real r = aTorus.MinorRadius();
const Standard_Real R = aTorus.MajorRadius();
const Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep(
r, GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv;
Dv = oldDv;
const Standard_Integer nbV = Max((Standard_Integer) (aDiffV / Dv), 2);
Dv = aDiffV / (nbV + 1);
Standard_Real Du;
const Standard_Real ru = R + r;
if (ru > 1.e-16)
{
Du = GCPnts_TangentialDeflection::ArcAngularStep(ru,
GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize);
const Standard_Real aa = sqrt(Du*Du + oldDv*oldDv);
if (aa < gp::Resolution())
{
return Handle(IMeshData::ListOfPnt2d)();
}
Du *= Min(oldDv, Du) / aa;
}
else
{
Du = Dv;
}
Standard_Integer nbU = Max((Standard_Integer) (aDiffU / Du), 2);
nbU = Max(nbU, (Standard_Integer) (nbV * aDiffU * R / (aDiffV * r) / 5.));
Du = aDiffU / (nbU + 1);
const Handle(NCollection_IncAllocator) aTmpAlloc =
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
Handle(IMeshData::SequenceOfReal) aParamU, aParamV;
if (R < r)
{
// As the points of edges are returned.
// in this case, the points are not representative.
//-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid
aParamU = new IMeshData::SequenceOfReal(aTmpAlloc);
for (Standard_Integer i = 0; i <= nbU; i++)
{
aParamU->Append(aRangeU.first + i * Du);
}
}//R<r
else //U if R > r
{
aParamU = fillParams(GetParametersU(), GetRangeU(), nbU, 0.5, aTmpAlloc);
}
aParamV = fillParams(GetParametersV(), GetRangeV(), nbV, 2. / 3., aTmpAlloc);
const std::pair<Standard_Real, Standard_Real> aNewRangeU(aRangeU.first + Du * 0.1,
aRangeU.second - Du * 0.1);
const std::pair<Standard_Real, Standard_Real> aNewRangeV(aRangeV.first + Dv * 0.1,
aRangeV.second - Dv * 0.1);
Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc);
for (Standard_Integer i = 1; i <= aParamU->Length(); ++i)
{
const Standard_Real aPasU = aParamU->Value(i);
if (aPasU >= aNewRangeU.first && aPasU < aNewRangeU.second)
{
for (Standard_Integer j = 1; j <= aParamV->Length(); ++j)
{
const Standard_Real aPasV = aParamV->Value(j);
if (aPasV >= aNewRangeV.first && aPasV < aNewRangeV.second)
{
aNodes->Append(gp_Pnt2d(aPasU, aPasV));
}
}
}
}
return aNodes;
}
//=======================================================================
// Function: AddPoint
// Purpose :
//=======================================================================
void BRepMesh_TorusRangeSplitter::AddPoint(const gp_Pnt2d& thePoint)
{
BRepMesh_DefaultRangeSplitter::AddPoint(thePoint);
GetParametersU().Add(thePoint.X());
GetParametersV().Add(thePoint.Y());
}
//=======================================================================
// Function: fillParams
// Purpose :
//=======================================================================
Handle(IMeshData::SequenceOfReal) BRepMesh_TorusRangeSplitter::fillParams(
const IMeshData::IMapOfReal& theParams,
const std::pair<Standard_Real, Standard_Real>& theRange,
const Standard_Integer theStepsNb,
const Standard_Real theScale,
const Handle(NCollection_IncAllocator)& theAllocator) const
{
Handle(IMeshData::SequenceOfReal) aParams =
new IMeshData::SequenceOfReal(theAllocator);
const Standard_Integer aLength = theParams.Size();
TColStd_Array1OfReal aParamArray(1, aLength);
for (Standard_Integer j = 1; j <= aLength; ++j)
{
aParamArray(j) = theParams(j);
}
// Calculate DU, leave array of parameters
const Standard_Real aDiff = Abs(theRange.second - theRange.first);
Standard_Real aStep = FUN_CalcAverageDUV(aParamArray, aLength);
aStep = Max(aStep, aDiff / (Standard_Real) theStepsNb / 2.);
Standard_Real aStdStep = aDiff / (Standard_Real) aLength;
if (aStep > aStdStep)
{
aStdStep = aStep;
}
aStdStep *= theScale;
// Add parameters
for (Standard_Integer j = 1; j <= aLength; ++j)
{
const Standard_Real pp = aParamArray(j);
Standard_Boolean isToInsert = Standard_True;
const Standard_Integer aParamsLength = aParams->Length();
for (Standard_Integer i = 1; i <= aParamsLength && isToInsert; ++i)
{
isToInsert = (Abs(aParams->Value(i) - pp) > aStdStep);
}
if (isToInsert)
{
aParams->Append(pp);
}
}
return aParams;
}
//=======================================================================
// Function: FUN_CalcAverageDUV
// Purpose :
//=======================================================================
Standard_Real BRepMesh_TorusRangeSplitter::FUN_CalcAverageDUV(
TColStd_Array1OfReal& P, const Standard_Integer PLen) const
{
Standard_Integer i, j, n = 0;
Standard_Real p, result = 0.;
for (i = 1; i <= PLen; i++)
{
// Sort
for (j = i + 1; j <= PLen; j++)
{
if (P(i) > P(j))
{
p = P(i);
P(i) = P(j);
P(j) = p;
}
}
// Accumulate
if (i != 1)
{
p = Abs(P(i) - P(i - 1));
if (p > 1.e-7)
{
result += p;
n++;
}
}
}
return (n ? (result / (Standard_Real) n) : -1.);
}

View File

@@ -0,0 +1,57 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_TorusRangeSplitter_HeaderFile
#define _BRepMesh_TorusRangeSplitter_HeaderFile
#include <BRepMesh_UVParamRangeSplitter.hxx>
#include <IMeshTools_Parameters.hxx>
//! Auxiliary class extending UV range splitter in order to generate
//! internal nodes for NURBS surface.
class BRepMesh_TorusRangeSplitter : public BRepMesh_UVParamRangeSplitter
{
public:
//! Constructor.
BRepMesh_TorusRangeSplitter()
{
}
//! Destructor.
virtual ~BRepMesh_TorusRangeSplitter()
{
}
//! 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;
//! Registers border point.
Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE;
private:
Handle(IMeshData::SequenceOfReal) fillParams(
const IMeshData::IMapOfReal& theParams,
const std::pair<Standard_Real, Standard_Real>& theRange,
const Standard_Integer theStepsNb,
const Standard_Real theScale,
const Handle(NCollection_IncAllocator)& theAllocator) const;
Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen) const;
};
#endif

View File

@@ -34,14 +34,14 @@ public:
//! Default constructor.
BRepMesh_Triangle()
: myEdge1(0),
myEdge2(0),
myEdge3(0),
myOrientation1(Standard_False),
myOrientation2(Standard_False),
myOrientation3(Standard_False),
myMovability (BRepMesh_Free)
: myMovability (BRepMesh_Free)
{
myEdges[0] = 0;
myEdges[1] = 0;
myEdges[2] = 0;
myOrientations[0] = Standard_False;
myOrientations[1] = Standard_False;
myOrientations[2] = Standard_False;
}
//! Constructor.
@@ -65,12 +65,8 @@ public:
const Standard_Boolean (&theOrientations)[3],
const BRepMesh_DegreeOfFreedom theMovability)
{
myEdge1 = theEdges[0];
myEdge2 = theEdges[1];
myEdge3 = theEdges[2];
myOrientation1 = theOrientations[0];
myOrientation2 = theOrientations[1];
myOrientation3 = theOrientations[2];
memcpy(myEdges, theEdges, sizeof(theEdges));
memcpy(myOrientations, theOrientations, sizeof(theOrientations));
myMovability = theMovability;
}
@@ -80,12 +76,8 @@ public:
inline void Edges(Standard_Integer (&theEdges)[3],
Standard_Boolean (&theOrientations)[3]) const
{
theEdges[0] = myEdge1;
theEdges[1] = myEdge2;
theEdges[2] = myEdge3;
theOrientations[0] = myOrientation1;
theOrientations[1] = myOrientation2;
theOrientations[2] = myOrientation3;
memcpy(theEdges, myEdges, sizeof(myEdges));
memcpy(theOrientations, myOrientations, sizeof(myOrientations));
}
//! Returns movability of the triangle.
@@ -100,39 +92,39 @@ public:
myMovability = theMovability;
}
//! Returns hash code for this triangle.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer theUpper) const
//! Computes a hash code for this triangle, in the range [1, theUpperBound]
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const Standard_Integer theUpperBound) const
{
return ::HashCode(myEdge1 + myEdge2 + myEdge3, theUpper);
return ::HashCode (myEdges[0] + myEdges[1] + myEdges[2], theUpperBound);
}
//! Checks for equality with another triangle.
//! @param theOther triangle to be checked against this one.
//! @return TRUE if equal, FALSE if not.
Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const
inline Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const
{
if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted)
return Standard_False;
if (myEdge1 == theOther.myEdge1 &&
myEdge2 == theOther.myEdge2 &&
myEdge3 == theOther.myEdge3)
if (myEdges[0] == theOther.myEdges[0] &&
myEdges[1] == theOther.myEdges[1] &&
myEdges[2] == theOther.myEdges[2])
{
return Standard_True;
}
if (myEdge1 == theOther.myEdge2 &&
myEdge2 == theOther.myEdge3 &&
myEdge3 == theOther.myEdge1)
if (myEdges[0] == theOther.myEdges[1] &&
myEdges[1] == theOther.myEdges[2] &&
myEdges[2] == theOther.myEdges[0])
{
return Standard_True;
}
if (myEdge1 == theOther.myEdge3 &&
myEdge2 == theOther.myEdge1 &&
myEdge3 == theOther.myEdge2)
if (myEdges[0] == theOther.myEdges[2] &&
myEdges[1] == theOther.myEdges[0] &&
myEdges[2] == theOther.myEdges[1])
{
return Standard_True;
}
@@ -141,26 +133,23 @@ public:
}
//! Alias for IsEqual.
Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const
inline Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const
{
return IsEqual(theOther);
}
private:
Standard_Integer myEdge1;
Standard_Integer myEdge2;
Standard_Integer myEdge3;
Standard_Boolean myOrientation1;
Standard_Boolean myOrientation2;
Standard_Boolean myOrientation3;
Standard_Integer myEdges[3];
Standard_Boolean myOrientations[3];
BRepMesh_DegreeOfFreedom myMovability;
};
inline Standard_Integer HashCode(const BRepMesh_Triangle& theTriangle,
const Standard_Integer theUpper)
//! Computes a hash code for the given triangle, in the range [1, theUpperBound]
//! @param theTriangle the triangle which hash code is to be computed
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const BRepMesh_Triangle& theTriangle, const Standard_Integer theUpperBound)
{
return theTriangle.HashCode(theUpper);
return theTriangle.HashCode (theUpperBound);
}
#endif

View File

@@ -0,0 +1,81 @@
// Created on: 2016-07-07
// 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.
#ifndef _BRepMesh_UVParamRangeSplitter_HeaderFile
#define _BRepMesh_UVParamRangeSplitter_HeaderFile
#include <BRepMesh_DefaultRangeSplitter.hxx>
#include <IMeshData_Types.hxx>
//! Intended to generate internal mesh nodes using UV parameters of boundary discrete points.
class BRepMesh_UVParamRangeSplitter : public BRepMesh_DefaultRangeSplitter
{
public:
//! Constructor.
BRepMesh_UVParamRangeSplitter()
: myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)),
myUParams(1, myAllocator),
myVParams(1, myAllocator)
{
}
//! Destructor.
virtual ~BRepMesh_UVParamRangeSplitter()
{
}
//! Resets this splitter.
virtual void Reset(const IMeshData::IFaceHandle& theDFace,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE
{
BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters);
myUParams.Clear();
myVParams.Clear();
myAllocator->Reset(Standard_False);
}
public:
//! Returns U parameters.
inline const IMeshData::IMapOfReal& GetParametersU() const
{
return myUParams;
}
//! Returns U parameters.
inline IMeshData::IMapOfReal& GetParametersU()
{
return myUParams;
}
//! Returns V parameters.
inline const IMeshData::IMapOfReal& GetParametersV() const
{
return myVParams;
}
//! Returns V parameters.
inline IMeshData::IMapOfReal& GetParametersV()
{
return myVParams;
}
private:
Handle(NCollection_IncAllocator) myAllocator;
IMeshData::IMapOfReal myUParams;
IMeshData::IMapOfReal myVParams;
};
#endif

View File

@@ -20,6 +20,7 @@
#include <Standard_Macro.hxx>
#include <gp_XY.hxx>
#include <BRepMesh_DegreeOfFreedom.hxx>
#include <Precision.hxx>
//! Light weighted structure representing vertex
//! of the mesh in parametric space. Vertex could be
@@ -103,18 +104,18 @@ public:
myMovability = theMovability;
}
//! Returns hash code for this vertex.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer Upper) const
//! Computes a hash code for this vertex, in the range [1, theUpperBound]
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode(const Standard_Integer theUpperBound) const
{
return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), Upper);
return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), theUpperBound);
}
//! Checks for equality with another vertex.
//! @param theOther vertex to be checked against this one.
//! @return TRUE if equal, FALSE if not.
Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const
inline Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const
{
if (myMovability == BRepMesh_Deleted ||
theOther.myMovability == BRepMesh_Deleted)
@@ -126,7 +127,7 @@ public:
}
//! Alias for IsEqual.
Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const
inline Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const
{
return IsEqual(Other);
}
@@ -138,9 +139,13 @@ private:
BRepMesh_DegreeOfFreedom myMovability;
};
inline Standard_Integer HashCode(const BRepMesh_Vertex& me, const Standard_Integer Upper)
//! Computes a hash code for the given vertex, in the range [1, theUpperBound]
//! @param theVertex the vertex which hash code is to be computed
//! @param theUpperBound the upper bound of the range a computing hash code must be within
//! @return a computed hash code, in the range [1, theUpperBound]
inline Standard_Integer HashCode (const BRepMesh_Vertex& theVertex, const Standard_Integer theUpperBound)
{
return me.HashCode(Upper);
return theVertex.HashCode (theUpperBound);
}
#endif

View File

@@ -19,7 +19,7 @@
#include <Precision.hxx>
#include <gp_XY.hxx>
#include <gp_XYZ.hxx>
#include <BRepMesh.hxx>
#include <IMeshData_Types.hxx>
#include <NCollection_CellFilter.hxx>
#include <BRepMesh_Vertex.hxx>
@@ -33,8 +33,9 @@ public:
//! @param theAllocator memory allocator to be used by internal collections.
BRepMesh_VertexInspector(
const Handle(NCollection_IncAllocator)& theAllocator)
: myResIndices(theAllocator),
myVertices (new BRepMesh::VectorOfVertex),
: myIndex(0),
myMinSqDist(RealLast()),
myVertices(new IMeshData::VectorOfVertex),
myDelNodes(theAllocator)
{
SetTolerance(Precision::Confusion());
@@ -106,35 +107,32 @@ public:
//! Set reference point to be checked.
inline void SetPoint(const gp_XY& thePoint)
{
myResIndices.Clear();
myIndex = 0;
myMinSqDist = RealLast();
myPoint = thePoint;
}
//! Returns index of point coinciding with regerence one.
inline Standard_Integer GetCoincidentPoint() const
{
if ( myResIndices.Size() > 0 )
{
return myResIndices.First();
}
return 0;
return myIndex;
}
//! Returns list with indexes of vertices that have movability attribute
//! equal to BRepMesh_Deleted and can be replaced with another node.
inline const BRepMesh::ListOfInteger& GetListOfDelPoints() const
inline const IMeshData::ListOfInteger& GetListOfDelPoints() const
{
return myDelNodes;
}
//! Returns set of mesh vertices.
inline const BRepMesh::HVectorOfVertex& Vertices() const
inline const Handle(IMeshData::VectorOfVertex)& Vertices() const
{
return myVertices;
}
//! Returns set of mesh vertices for modification.
inline BRepMesh::HVectorOfVertex& ChangeVertices()
inline Handle(IMeshData::VectorOfVertex)& ChangeVertices()
{
return myVertices;
}
@@ -153,10 +151,11 @@ public:
private:
Standard_Integer myIndex;
Standard_Real myMinSqDist;
Standard_Real myTolerance[2];
BRepMesh::ListOfInteger myResIndices;
BRepMesh::HVectorOfVertex myVertices;
BRepMesh::ListOfInteger myDelNodes;
Handle(IMeshData::VectorOfVertex) myVertices;
IMeshData::ListOfInteger myDelNodes;
gp_XY myPoint;
};

View File

@@ -14,11 +14,7 @@
// commercial license or contractual agreement.
#include <BRepMesh_VertexTool.hxx>
#include <gp_XY.hxx>
#include <gp_XYZ.hxx>
#include <Precision.hxx>
#include <BRepMesh_Vertex.hxx>
#include <BRepMesh_VertexInspector.hxx>
//=======================================================================
//function : Inspect
@@ -45,8 +41,16 @@ NCollection_CellFilter_Action BRepMesh_VertexInspector::Inspect(
inTol = ((aVec.X() * aVec.X()) < myTolerance[0]) &&
((aVec.Y() * aVec.Y()) < myTolerance[1]);
}
if (inTol)
myResIndices.Append(theTarget);
{
const Standard_Real aSqDist = aVec.SquareModulus();
if (aSqDist < myMinSqDist)
{
myMinSqDist = aSqDist;
myIndex = theTarget;
}
}
return CellFilter_Keep;
}
@@ -90,7 +94,7 @@ Standard_Integer BRepMesh_VertexTool::Add(
//function : Delete
//purpose :
//=======================================================================
void BRepMesh_VertexTool::Delete(const Standard_Integer theIndex)
void BRepMesh_VertexTool::DeleteVertex(const Standard_Integer theIndex)
{
BRepMesh_Vertex& aV = mySelector.GetVertex(theIndex);

View File

@@ -15,26 +15,21 @@
#define _BRepMesh_VertexTool_HeaderFile
#include <NCollection_Array1.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <Standard_Transient.hxx>
#include <BRepMesh_VertexInspector.hxx>
#include <BRepMesh.hxx>
#include <Standard_OStream.hxx>
#include <gp_XYZ.hxx>
#include <gp_XY.hxx>
#include <IMeshData_Types.hxx>
class BRepMesh_Vertex;
//! Describes data structure intended to keep mesh nodes
//! defined in UV space and implements functionality
//! providing their uniqueness regarding thir position.
class BRepMesh_VertexTool
//! providing their uniqueness regarding their position.
class BRepMesh_VertexTool : public Standard_Transient
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
//! @param theAllocator memory allocator to be used by internal collections.
Standard_EXPORT BRepMesh_VertexTool(
@@ -101,16 +96,16 @@ public:
const Standard_Boolean isForceAdd);
//! Deletes vertex with the given index from the tool.
Standard_EXPORT void Delete(const Standard_Integer theIndex);
Standard_EXPORT void DeleteVertex(const Standard_Integer theIndex);
//! Returns set of mesh vertices.
inline const BRepMesh::HVectorOfVertex& Vertices() const
inline const Handle(IMeshData::VectorOfVertex)& Vertices() const
{
return mySelector.Vertices();
}
//! Returns set of mesh vertices.
inline BRepMesh::HVectorOfVertex& ChangeVertices()
inline Handle(IMeshData::VectorOfVertex)& ChangeVertices()
{
return mySelector.ChangeVertices();
}
@@ -150,12 +145,12 @@ public:
//! Remove last node from the structure.
inline void RemoveLast()
{
Delete(Extent());
DeleteVertex(Extent());
}
//! Returns the list with indexes of vertices that have movability attribute
//! equal to BRepMesh_Deleted and can be replaced with another node.
inline const BRepMesh::ListOfInteger& GetListOfDelNodes() const
inline const IMeshData::ListOfInteger& GetListOfDelNodes() const
{
return mySelector.GetListOfDelPoints();
}
@@ -163,6 +158,8 @@ public:
//! Prints statistics.
Standard_EXPORT void Statistics(Standard_OStream& theStream) const;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_VertexTool, Standard_Transient)
private:
//! Expands the given point according to specified tolerance.
@@ -182,7 +179,7 @@ private:
private:
Handle(NCollection_IncAllocator) myAllocator;
BRepMesh::VertexCellFilter myCellFilter;
IMeshData::VertexCellFilter myCellFilter;
BRepMesh_VertexInspector mySelector;
Standard_Real myTolerance[2];
};

View File

@@ -1,410 +0,0 @@
// Created on: 2014-06-03
// Created by: Oleg AGASHIN
// Copyright (c) 1997-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 <BRepMesh_WireChecker.hxx>
#include <Precision.hxx>
#include <TColStd_Array1OfInteger.hxx>
#include <gp_Pnt2d.hxx>
#include <BRepTools_WireExplorer.hxx>
#include <TopAbs_Orientation.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Iterator.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <BRepMesh_PairOfPolygon.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh_Classifier.hxx>
#include <BRepMesh_WireInterferenceChecker.hxx>
#include <OSD_Parallel.hxx>
//=======================================================================
//function : Selector::Constructor
//purpose :
//=======================================================================
BRepMesh_WireChecker::BndBox2dTreeSelector::BndBox2dTreeSelector(
const Standard_Integer theReservedSize)
: mySkippedIndex(-1),
myIndices(0, theReservedSize - 1),
myIndicesNb(0)
{
}
//=======================================================================
//function : Reject
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Reject(
const Bnd_Box2d& theBox2D) const
{
return myBox2D.IsOut(theBox2D);
}
//=======================================================================
//function : Accept
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Accept(
const Standard_Integer& theIndex)
{
if (theIndex <= mySkippedIndex)
return Standard_False;
myIndices(myIndicesNb++) = theIndex;
return Standard_True;
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::Clear()
{
mySkippedIndex = -1;
myIndicesNb = 0;
}
//=======================================================================
//function : SetBox
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::SetBox(
const Bnd_Box2d& theBox2D)
{
myBox2D = theBox2D;
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepMesh_WireChecker::BndBox2dTreeSelector::SetSkippedIndex(
const Standard_Integer theIndex)
{
mySkippedIndex = theIndex;
}
//=======================================================================
//function : Indices
//purpose :
//=======================================================================
const BRepMesh::Array1OfInteger&
BRepMesh_WireChecker::BndBox2dTreeSelector::Indices() const
{
return myIndices;
}
//=======================================================================
//function : IndicesNb
//purpose :
//=======================================================================
Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const
{
return myIndicesNb;
}
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireChecker::BRepMesh_WireChecker(
const TopoDS_Face& theFace,
const Standard_Real theTolUV,
const BRepMesh::HDMapOfShapePairOfPolygon& theEdges,
const BRepMesh::HIMapOfInteger& theVertexMap,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax,
const Standard_Boolean isInParallel)
: myTolUV(theTolUV),
myEdges(theEdges),
myVertexMap(theVertexMap),
myStructure(theStructure),
myUmin(theUmin),
myUmax(theUmax),
myVmin(theVmin),
myVmax(theVmax),
myStatus(BRepMesh_NoError),
myIsInParallel(isInParallel)
{
TopoDS_Face aFace = theFace;
aFace.Orientation(TopAbs_FORWARD);
for (TopoDS_Iterator aFaceIt(aFace); aFaceIt.More(); aFaceIt.Next())
{
if (aFaceIt.Value().IsNull() || aFaceIt.Value().ShapeType() != TopAbs_WIRE) // may be inner vertex
continue;
const TopoDS_Wire& aWire = TopoDS::Wire(aFaceIt.Value());
myWiresEdges.Append(ListOfEdges());
ListOfEdges& aEdges = myWiresEdges.ChangeLast();
// Start traversing the wires
BRepTools_WireExplorer aWireExplorer(aWire, aFace);
for (; aWireExplorer.More(); aWireExplorer.Next())
{
const TopoDS_Edge& aEdge = aWireExplorer.Current();
TopAbs_Orientation aOrient = aEdge.Orientation();
if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
continue;
aEdges.Append(aEdge);
}
if (aEdges.IsEmpty())
myWiresEdges.Remove(myWiresEdges.Size());
}
}
//=======================================================================
//function : ReCompute
//purpose :
//=======================================================================
void BRepMesh_WireChecker::ReCompute(BRepMesh::HClassifier& theClassifier)
{
if (theClassifier.IsNull())
return;
theClassifier->Destroy();
myStatus = BRepMesh_NoError;
SeqOfDWires aDWires;
if (!collectDiscretizedWires(aDWires))
return;
const Standard_Integer aNbWires = aDWires.Size();
BRepMesh::Array1OfSegmentsTree aWiresBiPoints(1, aNbWires);
fillSegmentsTree(aDWires, aWiresBiPoints);
if (myIsInParallel && aNbWires > 1)
{
// Check wires in parallel threads.
Standard_Mutex aWireMutex;
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus, &aWireMutex);
OSD_Parallel::For(1, aNbWires + 1, aIntChecker);
}
else
{
BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus);
OSD_Parallel::For(1, aNbWires + 1, aIntChecker, Standard_True);
}
if (myStatus == BRepMesh_SelfIntersectingWire)
return;
// Find holes
SeqOfDWires::Iterator aDWiresIt(aDWires);
for (; aDWiresIt.More(); aDWiresIt.Next())
{
const SeqOfPnt2d& aDWire = aDWiresIt.Value();
theClassifier->RegisterWire(aDWire, myTolUV, myUmin, myUmax, myVmin, myVmax);
}
}
//=======================================================================
//function : collectDiscretizedWires
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires(
SeqOfDWires& theDWires)
{
SeqOfWireEdges::Iterator aWireIt(myWiresEdges);
for(; aWireIt.More(); aWireIt.Next())
{
const ListOfEdges& aEdges = aWireIt.Value();
// For each wire we create a data map, linking vertices (only
// the ends of edges) with their positions in the sequence of
// all 2d points from this wire.
// When we meet some vertex for the second time - the piece
// of sequence is treated for a HOLE and quits the sequence.
// Actually, we must unbind the vertices belonging to the
// loop from the map, but since they can't appear twice on the
// valid wire, leave them for a little speed up.
SeqOfPnt2d aSeqPnt2d;
BRepMesh::MapOfIntegerInteger aNodeInSeq;
Standard_Integer aFirstIndex = 0, aLastIndex = 0;
// Start traversing the wire
ListOfEdges::Iterator aEdgeIt(aEdges);
for (; aEdgeIt.More(); aEdgeIt.Next())
{
const TopoDS_Edge& aEdge = aEdgeIt.Value();
TopAbs_Orientation aOrient = aEdge.Orientation();
if (!myEdges->IsBound(aEdge))
continue;
// Retrieve polygon
// Define the direction for adding points to aSeqPnt2d
Standard_Integer aStartId, aEndId, aIncrement;
const BRepMesh_PairOfPolygon& aPair = myEdges->Find(aEdge);
Handle(Poly_PolygonOnTriangulation) aNOD;
if (aOrient == TopAbs_FORWARD)
{
aNOD = aPair.First();
aStartId = 1;
aEndId = aNOD->NbNodes();
aIncrement = 1;
}
else
{
aNOD = aPair.Last();
aStartId = aNOD->NbNodes();
aEndId = 1;
aIncrement = -1;
}
const TColStd_Array1OfInteger& aIndices = aNOD->Nodes();
const Standard_Integer aFirstVertexId = myVertexMap->FindKey(aIndices(aStartId));
const Standard_Integer aLastVertexId = myVertexMap->FindKey(aIndices(aEndId) );
if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement)
{
// case of continuous set of degenerated edges
aLastIndex = aLastVertexId;
continue;
}
if (aFirstIndex != 0)
{
if (aFirstVertexId != aLastIndex)
{
// there's a gap between edges
myStatus = BRepMesh_OpenWire;
return Standard_False;
}
}
else
aFirstIndex = aFirstVertexId;
aLastIndex = aLastVertexId;
// Record first vertex (to detect loops)
aNodeInSeq.Bind(aFirstVertexId, (aSeqPnt2d.Length() + 1));
// Add vertices in sequence
for (Standard_Integer i = aStartId; i != aEndId; i += aIncrement)
{
Standard_Integer aIndex = ((i == aStartId) ?
aFirstVertexId :
myVertexMap->FindKey(aIndices(i)));
aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord()));
}
// Now, is there a loop?
if (aNodeInSeq.IsBound(aLastVertexId))
{
// Yes, treat it separately as a hole
// Divide points into main wire and a loop
const Standard_Integer aIdxWireStart = aNodeInSeq(aLastVertexId);
if(aIdxWireStart < aSeqPnt2d.Length())
{
theDWires.Append(SeqOfPnt2d());
SeqOfPnt2d& aWire = theDWires.ChangeLast();
aSeqPnt2d.Split(aIdxWireStart, aWire);
}
}
}
if (aFirstIndex == 0)
continue;
// Isn't wire open?
if (aFirstIndex != aLastIndex || aSeqPnt2d.Length() > 1)
{
myStatus = BRepMesh_OpenWire;
return Standard_False;
}
}
return Standard_True;
}
//=======================================================================
//function : fillSegmentsTree
//purpose :
//=======================================================================
void BRepMesh_WireChecker::fillSegmentsTree(
const SeqOfDWires& theDWires,
BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree)
{
const Standard_Integer aNbWires = theDWires.Size();
for (Standard_Integer aWireIt = 1; aWireIt <= aNbWires; ++aWireIt)
{
const SeqOfPnt2d& aWire = theDWires(aWireIt);
const Standard_Integer aWireLen = aWire.Size();
BRepMesh::HArray1OfSegments aWireSegments =
new BRepMesh::Array1OfSegments(1, aWireLen);
BRepMesh::HBndBox2dTree aBndBoxTree =
new BRepMesh::BndBox2dTree;
BRepMesh::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree);
Standard_Real x1 = 0., y1 = 0., aXstart = 0., aYstart = 0.;
for (Standard_Integer aPntIt = 0; aPntIt <= aWireLen; ++aPntIt)
{
Standard_Real x2, y2;
// Obtain last point of the segment
if (aPntIt == aWireLen)
{
x2 = aXstart;
y2 = aYstart;
}
else
{
const gp_Pnt2d& aPnt = aWire(aPntIt + 1);
x2 = aPnt.X();
y2 = aPnt.Y();
}
// Build segment (bi-point)
if (aPntIt == 0)
{
aXstart = x2;
aYstart = y2;
}
else
{
gp_Pnt2d aStartPnt(x1, y1);
gp_Pnt2d aEndPnt(x2, y2);
BRepMesh::Segment& aSegment = aWireSegments->ChangeValue(aPntIt);
aSegment.StartPnt = aStartPnt.XY();
aSegment.EndPnt = aEndPnt.XY();
Bnd_Box2d aBox;
aBox.Add(aStartPnt);
aBox.Add( aEndPnt);
aBndBoxTreeFiller.Add(aPntIt, aBox);
}
x1 = x2;
y1 = y2;
}
aBndBoxTreeFiller.Fill();
BRepMesh::SegmentsTree& aSegmentsTree = theWiresSegmentsTree(aWireIt);
aSegmentsTree.first = aWireSegments;
aSegmentsTree.second = aBndBoxTree;
}
}

View File

@@ -1,142 +0,0 @@
// Created on: 2014-06-03
// Created by: Oleg AGASHIN
// Copyright (c) 1997-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.
#ifndef _BRepMesh_WireChecker_HeaderFile
#define _BRepMesh_WireChecker_HeaderFile
#include <Standard.hxx>
#include <TopoDS_Face.hxx>
#include <BRepMesh_Status.hxx>
#include <BRepMesh_DataStructureOfDelaun.hxx>
#include <BRepMesh.hxx>
#include <TColStd_IndexedMapOfInteger.hxx>
#include <TopoDS_Edge.hxx>
#include <Bnd_Box2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_XY.hxx>
#include <vector>
//! Auxilary class intended to check correctness of discretized face.
//! In particular, checks boundaries of discretized face for self
//! intersections and gaps.
class BRepMesh_WireChecker
{
public:
//! Selector.
//! Used to identify segments with overlapped bounding boxes.
//! Note that instance of selector can be used only once due to
//! unextentable array of indices.
class BndBox2dTreeSelector : public BRepMesh::BndBox2dTree::Selector
{
public:
Standard_EXPORT BndBox2dTreeSelector(const Standard_Integer theReservedSize);
Standard_EXPORT virtual Standard_Boolean Reject(const Bnd_Box2d& theBox2D) const;
Standard_EXPORT virtual Standard_Boolean Accept(const Standard_Integer& theIndex);
Standard_EXPORT void Clear();
Standard_EXPORT void SetBox(const Bnd_Box2d& theBox2D);
Standard_EXPORT void SetSkippedIndex(const Standard_Integer theIndex);
Standard_EXPORT const BRepMesh::Array1OfInteger& Indices() const;
Standard_EXPORT Standard_Integer IndicesNb() const;
protected:
Bnd_Box2d myBox2D;
Standard_Integer mySkippedIndex;
BRepMesh::Array1OfInteger myIndices;
Standard_Integer myIndicesNb;
};
private:
typedef NCollection_List<TopoDS_Edge> ListOfEdges;
typedef NCollection_Sequence<ListOfEdges> SeqOfWireEdges;
typedef NCollection_Sequence<gp_Pnt2d> SeqOfPnt2d;
typedef NCollection_Sequence<SeqOfPnt2d> SeqOfDWires;
public:
//! Constructor.
//! @param theFace Face to be checked.
//! @param theTolUV Tolerance to be used for calculations in parametric space.
//! @param theEdges Map of edges with associated polygon on triangulation.
//! @param theVertexMap Map of face vertices.
//! @param theStructure Discretized representation of face in parametric space.
//! @param theUmin Lower U boundary of the face in parametric space.
//! @param theUmax Upper U boundary of the face in parametric space.
//! @param theVmin Lower V boundary of the face in parametric space.
//! @param theVmax Upper V boundary of the face in parametric space.
Standard_EXPORT BRepMesh_WireChecker(
const TopoDS_Face& theFace,
const Standard_Real theTolUV,
const BRepMesh::HDMapOfShapePairOfPolygon& theEdges,
const BRepMesh::HIMapOfInteger& theVertexMap,
const Handle(BRepMesh_DataStructureOfDelaun)& theStructure,
const Standard_Real theUmin,
const Standard_Real theUmax,
const Standard_Real theVmin,
const Standard_Real theVmax,
const Standard_Boolean isInParallel);
//! Recompute data using parameters passed in constructor.
//! @param[out] theClassifier Classifier to be updated using calculated data.
Standard_EXPORT void ReCompute(BRepMesh::HClassifier& theClassifier);
//! Returns status of the check.
inline BRepMesh_Status Status() const
{
return myStatus;
}
private:
//! Collects discrete wires.
//! @param[out] theDWires sequence of discretized wires to be filled.
//! @return TRUE on success, FALSE in case of open wire.
Standard_Boolean collectDiscretizedWires(SeqOfDWires& theDWires);
//! Fills array of BiPoints for corresponding wire.
//! @param theDWires Sequence of wires to be processed.
//! @param theWiresSegmentsTree Array of segments with corresponding
//! bounding boxes trees to be filled.
void fillSegmentsTree(
const SeqOfDWires& theDWires,
BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree);
//! Assignment operator.
void operator =(BRepMesh_WireChecker& /*theOther*/)
{
}
private:
const Standard_Real myTolUV;
const BRepMesh::HDMapOfShapePairOfPolygon& myEdges;
const BRepMesh::HIMapOfInteger& myVertexMap;
const Handle(BRepMesh_DataStructureOfDelaun)& myStructure;
const Standard_Real myUmin;
const Standard_Real myUmax;
const Standard_Real myVmin;
const Standard_Real myVmax;
BRepMesh_Status myStatus;
SeqOfWireEdges myWiresEdges;
Standard_Boolean myIsInParallel;
};
#endif

View File

@@ -1,134 +0,0 @@
// Created on: 2014-06-18
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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 <BRepMesh_WireInterferenceChecker.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <Precision.hxx>
// TODO: remove this variable after implementation of LoopChecker2d.
static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5;
//=======================================================================
//function : Constructor
//purpose :
//=======================================================================
BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex)
: myWires (theWires),
myStatus(theStatus),
myMutex (theMutex)
{
}
//=======================================================================
//function : Checker's body
//purpose :
//=======================================================================
void BRepMesh_WireInterferenceChecker::operator ()(
const Standard_Integer& theWireId) const
{
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const BRepMesh::SegmentsTree& aWireSegTree1 = myWires(theWireId);
const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first;
const BRepMesh::HBndBox2dTree& aWireBoxTree1 = aWireSegTree1.second;
for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt)
{
// Break execution in case if flag was raised by another thread.
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId);
const BRepMesh::SegmentsTree& aWireSegTree2 =
isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt);
const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first;
const BRepMesh::HBndBox2dTree& aWireBoxTree2 = aWireSegTree2.second;
BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size());
Standard_Integer aSegmentId1 = aWireSegments1->Lower();
for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1)
{
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
aSelector.Clear();
aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd());
if (isSelfIntCheck)
aSelector.SetSkippedIndex(aSegmentId1);
if (aWireBoxTree2->Select(aSelector) == 0)
continue;
const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1);
const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices();
const Standard_Integer aSelectedNb = aSelector.IndicesNb();
for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt)
{
// Break execution in case if flag was raised by another thread
if (*myStatus == BRepMesh_SelfIntersectingWire)
return;
const Standard_Integer aSegmentId2 = aSelected(aBndIt);
const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2);
gp_Pnt2d aIntPnt;
BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg(
aSegment1.StartPnt, aSegment1.EndPnt,
aSegment2.StartPnt, aSegment2.EndPnt,
Standard_False, Standard_False,
aIntPnt);
if (aIntStatus == BRepMesh_GeomTool::Cross)
{
// TODO: remove this block after implementation of LoopChecker2d.
if (isSelfIntCheck)
{
gp_XY aPrevVec;
Standard_Real aSumS = 0.;
const gp_XY& aRefPnt = aIntPnt.Coord();
for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i)
{
const BRepMesh::Segment& aSeg = aWireSegments1->Value(i);
gp_XY aCurVec = aSeg.EndPnt - aRefPnt;
if (aCurVec.SquareModulus() < gp::Resolution())
continue;
if (aPrevVec.SquareModulus() > gp::Resolution())
aSumS += aPrevVec ^ aCurVec;
aPrevVec = aCurVec;
}
if (Abs(aSumS / 2.) < MIN_LOOP_S)
continue;
}
Standard_Mutex::Sentry aSentry(myMutex);
*myStatus = BRepMesh_SelfIntersectingWire;
return;
}
}
}
}
}

View File

@@ -1,67 +0,0 @@
// Created on: 2014-06-18
// Created by: Oleg AGASHIN
// Copyright (c) 2011-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.
#ifndef _BRepMesh_WireInterferenceChecker_HeaderFile
#define _BRepMesh_WireInterferenceChecker_HeaderFile
#include <Standard.hxx>
#include <Standard_Mutex.hxx>
#include <BRepMesh_WireChecker.hxx>
#include <BRepMesh_Status.hxx>
//! Auxilary class implementing functionality for
//! checking interference between two discretized wires.
class BRepMesh_WireInterferenceChecker
{
public:
//! Enumerates states of segments intersection check.
enum IntFlag
{
NoIntersection,
Cross,
EndPointTouch,
PointOnSegment,
Glued,
Same
};
//! Constructor
//! @param theWires wires that should be checked.
//! @param theStatus shared flag to set status of the check.
//! @param theMutex shared mutex for parallel processing.
BRepMesh_WireInterferenceChecker(
const BRepMesh::Array1OfSegmentsTree& theWires,
BRepMesh_Status* theStatus,
Standard_Mutex* theMutex = NULL);
//! Checker's body.
//! @param theWireId Id of discretized wire to be checked.
void operator ()(const Standard_Integer& theWireId) const;
private:
//! Assignment operator.
void operator =(const BRepMesh_WireInterferenceChecker& /*theOther*/)
{
}
private:
const BRepMesh::Array1OfSegmentsTree& myWires;
BRepMesh_Status* myStatus;
Standard_Mutex* myMutex;
};
#endif

View File

@@ -1,55 +1,88 @@
BRepMesh.hxx
BRepMesh_BaseMeshAlgo.cxx
BRepMesh_BaseMeshAlgo.hxx
BRepMesh_ConstrainedBaseMeshAlgo.hxx
BRepMesh_BoundaryParamsRangeSplitter.hxx
BRepMesh_Circle.hxx
BRepMesh_CircleInspector.hxx
BRepMesh_CircleTool.cxx
BRepMesh_CircleTool.hxx
BRepMesh_Classifier.cxx
BRepMesh_Classifier.hxx
BRepMesh_ConeRangeSplitter.cxx
BRepMesh_ConeRangeSplitter.hxx
BRepMesh_Context.cxx
BRepMesh_Context.hxx
BRepMesh_CurveTessellator.cxx
BRepMesh_CurveTessellator.hxx
BRepMesh_CylinderRangeSplitter.cxx
BRepMesh_CylinderRangeSplitter.hxx
BRepMesh_DataStructureOfDelaun.cxx
BRepMesh_DataStructureOfDelaun.hxx
BRepMesh_DefaultRangeSplitter.cxx
BRepMesh_DefaultRangeSplitter.hxx
BRepMesh_Deflection.cxx
BRepMesh_Deflection.hxx
BRepMesh_DegreeOfFreedom.hxx
BRepMesh_Delaun.cxx
BRepMesh_Delaun.hxx
BRepMesh_DelaunayBaseMeshAlgo.cxx
BRepMesh_DelaunayBaseMeshAlgo.hxx
BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx
BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx
BRepMesh_DiscretFactory.cxx
BRepMesh_DiscretFactory.hxx
BRepMesh_DiscretRoot.cxx
BRepMesh_DiscretRoot.hxx
BRepMesh_Edge.hxx
BRepMesh_EdgeParameterProvider.cxx
BRepMesh_EdgeDiscret.cxx
BRepMesh_EdgeDiscret.hxx
BRepMesh_EdgeParameterProvider.hxx
BRepMesh_EdgeTessellationExtractor.cxx
BRepMesh_EdgeTessellationExtractor.hxx
BRepMesh_EdgeTessellator.cxx
BRepMesh_EdgeTessellator.hxx
BRepMesh_FaceAttribute.cxx
BRepMesh_FaceAttribute.hxx
BRepMesh_FaceChecker.cxx
BRepMesh_FaceChecker.hxx
BRepMesh_FaceDiscret.cxx
BRepMesh_FaceDiscret.hxx
BRepMesh_FactoryError.hxx
BRepMesh_FastDiscret.cxx
BRepMesh_FastDiscret.hxx
BRepMesh_FastDiscretFace.cxx
BRepMesh_FastDiscretFace.hxx
BRepMesh_GeomTool.cxx
BRepMesh_GeomTool.hxx
BRepMesh_IEdgeTool.cxx
BRepMesh_IEdgeTool.hxx
BRepMesh_IncrementalMesh.cxx
BRepMesh_IncrementalMesh.hxx
BRepMesh_MeshAlgoFactory.cxx
BRepMesh_MeshAlgoFactory.hxx
BRepMesh_MeshTool.cxx
BRepMesh_MeshTool.hxx
BRepMesh_ModelBuilder.cxx
BRepMesh_ModelBuilder.hxx
BRepMesh_ModelHealer.cxx
BRepMesh_ModelHealer.hxx
BRepMesh_ModelPostProcessor.cxx
BRepMesh_ModelPostProcessor.hxx
BRepMesh_ModelPreProcessor.cxx
BRepMesh_ModelPreProcessor.hxx
BRepMesh_NURBSRangeSplitter.cxx
BRepMesh_NURBSRangeSplitter.hxx
BRepMesh_NodeInsertionMeshAlgo.hxx
BRepMesh_OrientedEdge.hxx
BRepMesh_PairOfIndex.hxx
BRepMesh_PairOfPolygon.hxx
BRepMesh_PluginEntryType.hxx
BRepMesh_PluginMacro.hxx
BRepMesh_SelectorOfDataStructureOfDelaun.cxx
BRepMesh_SelectorOfDataStructureOfDelaun.hxx
BRepMesh_ShapeTool.cxx
BRepMesh_ShapeTool.hxx
BRepMesh_Status.hxx
BRepMesh_ShapeVisitor.cxx
BRepMesh_ShapeVisitor.hxx
BRepMesh_SphereRangeSplitter.cxx
BRepMesh_SphereRangeSplitter.hxx
BRepMesh_TorusRangeSplitter.cxx
BRepMesh_TorusRangeSplitter.hxx
BRepMesh_Triangle.hxx
BRepMesh_UVParamRangeSplitter.hxx
BRepMesh_Vertex.hxx
BRepMesh_VertexInspector.hxx
BRepMesh_VertexTool.cxx
BRepMesh_VertexTool.hxx
BRepMesh_WireChecker.cxx
BRepMesh_WireChecker.hxx
BRepMesh_WireInterferenceChecker.cxx
BRepMesh_WireInterferenceChecker.hxx
BRepMesh_CustomBaseMeshAlgo.hxx
BRepMesh_CustomDelaunayBaseMeshAlgo.hxx

View File

@@ -0,0 +1,126 @@
// Created on: 2016-04-07
// 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 <BRepMeshData_Curve.hxx>
#include <gp_Pnt.hxx>
#include <BRepMesh_OrientedEdge.hxx>
#include <BRepMesh_Vertex.hxx>
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMeshData_Curve::BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator)
: myPoints (NCollection_StdAllocator<gp_Pnt>(theAllocator)),
myParameters (NCollection_StdAllocator<Standard_Real>(theAllocator))
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMeshData_Curve::~BRepMeshData_Curve ()
{
}
//=======================================================================
// Function: InsertPoint
// Purpose :
//=======================================================================
void BRepMeshData_Curve::InsertPoint(
const Standard_Integer thePosition,
const gp_Pnt& thePoint,
const Standard_Real theParamOnPCurve)
{
myPoints .insert(myPoints .begin() + thePosition, thePoint);
myParameters.insert(myParameters.begin() + thePosition, theParamOnPCurve);
}
//=======================================================================
// Function: AddPoint
// Purpose :
//=======================================================================
void BRepMeshData_Curve::AddPoint (
const gp_Pnt& thePoint,
const Standard_Real theParamOnPCurve)
{
myPoints .push_back(thePoint);
myParameters.push_back(theParamOnPCurve);
}
//=======================================================================
// Function: GetPoint
// Purpose :
//=======================================================================
gp_Pnt& BRepMeshData_Curve::GetPoint (const Standard_Integer theIndex)
{
return myPoints[theIndex];
}
//=======================================================================
// Function: GetParameter
// Purpose :
//=======================================================================
Standard_Real& BRepMeshData_Curve::GetParameter (const Standard_Integer theIndex)
{
return myParameters[theIndex];
}
//=======================================================================
// Function: ParameterNb
// Purpose :
//=======================================================================
Standard_Integer BRepMeshData_Curve::ParametersNb() const
{
return static_cast<Standard_Integer>(myParameters.size());
}
//=======================================================================
// Function: RemovePoint
// Purpose :
//=======================================================================
void BRepMeshData_Curve::RemovePoint (const Standard_Integer theIndex)
{
myPoints.erase(myPoints.begin() + theIndex);
removeParameter (theIndex);
}
//=======================================================================
// Function: removeParameter
// Purpose :
//=======================================================================
void BRepMeshData_Curve::removeParameter (const Standard_Integer theIndex)
{
myParameters.erase(myParameters.begin() + theIndex);
}
//=======================================================================
// Function: Clear
// Purpose :
//=======================================================================
void BRepMeshData_Curve::Clear(const Standard_Boolean isKeepEndPoints)
{
if (!isKeepEndPoints)
{
myPoints .clear();
myParameters.clear();
}
else if (ParametersNb() > 2)
{
myPoints .erase(myPoints .begin() + 1, myPoints .begin() + (myPoints .size() - 1));
myParameters.erase(myParameters.begin() + 1, myParameters.begin() + (myParameters.size() - 1));
}
}

View File

@@ -0,0 +1,76 @@
// Created on: 2016-04-07
// 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.
#ifndef _BRepMeshData_Curve_HeaderFile
#define _BRepMeshData_Curve_HeaderFile
#include <IMeshData_Curve.hxx>
#include <Standard_Type.hxx>
#include <NCollection_IncAllocator.hxx>
#include <IMeshData_Types.hxx>
//! Default implementation of curve data model entity.
class BRepMeshData_Curve : public IMeshData_Curve
{
public:
DEFINE_INC_ALLOC
//! Constructor.
Standard_EXPORT BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator);
//! Destructor.
Standard_EXPORT virtual ~BRepMeshData_Curve ();
//! Inserts new discretization point at the given position.
Standard_EXPORT virtual void InsertPoint(
const Standard_Integer thePosition,
const gp_Pnt& thePoint,
const Standard_Real theParamOnPCurve) Standard_OVERRIDE;
//! Adds new discretization point to pcurve.
Standard_EXPORT virtual void AddPoint (
const gp_Pnt& thePoint,
const Standard_Real theParamOnCurve) Standard_OVERRIDE;
//! Returns discretization point with the given index.
Standard_EXPORT virtual gp_Pnt& GetPoint (const Standard_Integer theIndex) Standard_OVERRIDE;
//! Removes point with the given index.
Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) Standard_OVERRIDE;
//! Returns parameter with the given index.
Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
//! Returns number of parameters stored in curve.
Standard_EXPORT virtual Standard_Integer ParametersNb() const Standard_OVERRIDE;
//! Clears parameters list.
Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Curve, IMeshData_Curve)
protected:
//! Removes parameter with the given index.
Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) Standard_OVERRIDE;
private:
IMeshData::Model::SequenceOfPnt myPoints;
IMeshData::Model::SequenceOfReal myParameters;
};
#endif

Some files were not shown because too many files have changed in this diff Show More