1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-08-04 13:13:25 +03:00

0026106: BRepMesh - revision of data model

Removed tight connections between data structures, auxiliary tools and algorithms in order to create extensible solution, easy for maintenance and improvements;
Code is separated on several functional units responsible for specific operation for the sake of simplification of debugging and readability;
Introduced new data structures enabling possibility to manipulate discrete model of particular entity (edge, wire, face) in order to perform computations locally instead of processing an entire model.

The workflow of updated component can be divided on six parts:
* Creation of model data structure: source TopoDS_Shape passed to algorithm is analyzed and exploded on faces and edges. For each topological entity corresponding reflection is created in data model. Note that underlying algorithms use data model as input and access it via common interface which allows user to create custom data model with necessary dependencies between particular entities;
* Discretize edges 3D & 2D curves: 3D curve as well as associated set of 2D curves of each model edge is discretized in order to create coherent skeleton used as a base in faces meshing process. In case if some edge of source shape already contains polygonal data which suites specified parameters, it is extracted from shape and stored to the model as is. Each edge is processed separately, adjacency is not taken into account;
* Heal discrete model: source TopoDS_Shape can contain problems, such as open-wire or self-intersections, introduced during design, exchange or modification of model. In addition, some problems like self-intersections can be introduced by roughly discretized edges. This stage is responsible for analysis of discrete model in order to detect and repair faced problems or refuse model’s part for further processing in case if problem cannot be solved;
* Preprocess discrete model: defines actions specific for implemented approach to be performed before meshing of faces. By default, iterates over model faces and checks consistency of existing triangulations. Cleans topological faces and its adjacent edges from polygonal data in case of inconsistency or marks face of discrete model as not required for computation;
* Discretize faces: represents core part performing mesh generation for particular face based on 2D discrete data related to processing face. Caches polygonal data associated with face’s edges in data model for further processing and stores generated mesh to TopoDS_Face;
* Postprocess discrete model: defines actions specific for implemented approach to be performed after meshing of faces. By default, stores polygonal data obtained on previous stage to TopoDS_Edge objects of source model.

Component is now spread over IMeshData, IMeshTools, BRepMeshData and BRepMesh units.

<!break>

1. Extend "tricheck" DRAW-command in order to find degenerated triangles.

2. Class BRepMesh_FastDiscret::Parameters has been declared as deprecated.

3. NURBS range splitter: do not split intervals without necessity. Intervals are split only in case if it is impossible to compute normals directly on intervals.

4. Default value of IMeshTools_Parameters::MinSize has been changed. New value is equal to 0.1*Deflection.

5. Correction of test scripts:

1) perf mesh bug27119: requested deflection is increased from 1e-6 to 1e-5 to keep reasonable performance (but still reproducing original issue)
2) bugs mesh bug26692_1, 2: make snapshot of triangulation instead of wireframe (irrelevant)

Correction in upgrade guide.
This commit is contained in:
oan
2017-10-09 13:04:54 +03:00
committed by bugmaster
parent 80da8585f4
commit 7bd071edb1
261 changed files with 19333 additions and 7480 deletions

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& /*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,49 @@
// 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:
};
#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,10 +128,10 @@ public:
}
private:
Standard_Real myTolerance;
BRepMesh::ListOfInteger myResIndices;
BRepMesh::VectorOfCircle myCircles;
gp_XY myPoint;
Standard_Real mySqTolerance;
IMeshData::ListOfInteger myResIndices;
IMeshData::VectorOfCircle myCircles;
gp_XY myPoint;
};
#endif

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.
@@ -125,7 +125,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 +141,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,19 +45,23 @@ 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.
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,61 @@
// 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: 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();
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);
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;
}

View File

@@ -0,0 +1,43 @@
// 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 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,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,17 +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
public:
//! Constructor.
Standard_EXPORT BRepMesh_Context ();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_Context ();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Context, IMeshTools_Context)
};
#endif
#endif

View File

@@ -0,0 +1,331 @@
// 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>
//=======================================================================
//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;
}
mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef;
mySquareMinSize = Max(mySquareEdgeDef, myParameters.MinSize * myParameters.MinSize);
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(), myParameters.MinSize);
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,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();
@@ -502,7 +479,7 @@ void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) con
theStream << "\n Deleted links : " << myDelLinks.Extent() << endl;
theStream << "\n\n Map of elements : \n";
myElements.Statistics(theStream);
theStream << "\n Elements : " << myElements.Size() << endl;
}
//=======================================================================
@@ -521,7 +498,7 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr,
return "Error: file name or mesh data is null";
}
Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
*(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
if (aMeshData.IsNull())
@@ -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(aDeflectionUV, Precision::Confusion() * aDiffU);
myTolerance.second = Max(aDeflectionUV, Precision::Confusion() * 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,164 @@
// 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 <BRepMesh_ShapeTool.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Face.hxx>
#include <BRep_Tool.hxx>
#include <Bnd_Box.hxx>
#include <BRepBndLib.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
//=======================================================================
//function : RelativeEdgeDeflection
//purpose :
//=======================================================================
Standard_Real BRepMesh_Deflection::RelativeEdgeDeflection(
const TopoDS_Edge& theEdge,
const Standard_Real theDeflection,
const Standard_Real theMaxShapeSize,
Standard_Real& theAdjustmentCoefficient)
{
theAdjustmentCoefficient = 1.;
Standard_Real aEdgeDeflection = theDeflection;
if (theEdge.IsNull())
{
return aEdgeDeflection;
}
Bnd_Box aBox;
BRepBndLib::Add (theEdge, aBox, Standard_False);
BRepMesh_ShapeTool::BoxMaxDimension (aBox, aEdgeDeflection);
// Adjust resulting value in relation to the total size
theAdjustmentCoefficient = theMaxShapeSize / (2 * aEdgeDeflection);
if (theAdjustmentCoefficient < 0.5)
{
theAdjustmentCoefficient = 0.5;
}
else if (theAdjustmentCoefficient > 2.)
{
theAdjustmentCoefficient = 2.;
}
return (theAdjustmentCoefficient * aEdgeDeflection * theDeflection);
}
//=======================================================================
// Function: ComputeDeflection (edge)
// Purpose :
//=======================================================================
void BRepMesh_Deflection::ComputeDeflection (
const IMeshData::IEdgeHandle& theDEdge,
const Standard_Real theMaxShapeSize,
const IMeshTools_Parameters& theParameters)
{
Standard_Real aLinDeflection;
Standard_Real aAngDeflection;
if (theParameters.Relative)
{
Standard_Real aScale;
aLinDeflection = RelativeEdgeDeflection (theDEdge->GetEdge (),
theParameters.Deflection, theMaxShapeSize, aScale);
// Is it OK?
aAngDeflection = theParameters.Angle * aScale;
}
else
{
aLinDeflection = theParameters.Deflection;
aAngDeflection = theParameters.Angle;
}
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 aFaceDeflection = 0.;
if (theDFace->WiresNb () > 0)
{
for (Standard_Integer aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt)
{
aFaceDeflection += theDFace->GetWire(aWireIt)->GetDeflection();
}
aFaceDeflection /= theDFace->WiresNb ();
}
else
{
aFaceDeflection = theParameters.Deflection;
}
theDFace->SetDeflection (Max(2.* BRepMesh_ShapeTool::MaxFaceTolerance(
theDFace->GetFace()), aFaceDeflection));
}

View File

@@ -0,0 +1,66 @@
// 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 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);
//! 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

View File

@@ -82,14 +82,14 @@ namespace {
//function : BRepMesh_Delaun
//purpose : Creates the triangulation with an empty Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun(BRepMesh::Array1OfVertexOfDelaun& theVertices)
BRepMesh_Delaun::BRepMesh_Delaun(IMeshData::Array1OfVertexOfDelaun& theVertices)
: myCircles (theVertices.Length(), new NCollection_IncAllocator(
BRepMesh::MEMORY_BLOCK_SIZE_HUGE))
IMeshData::MEMORY_BLOCK_SIZE_HUGE))
{
if ( theVertices.Length() > 2 )
{
myMeshData = new BRepMesh_DataStructureOfDelaun(
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE),
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE),
theVertices.Length() );
Init( theVertices );
}
@@ -100,8 +100,8 @@ BRepMesh_Delaun::BRepMesh_Delaun(BRepMesh::Array1OfVertexOfDelaun& theVertices)
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun(
const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
BRepMesh::Array1OfVertexOfDelaun& theVertices)
const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
IMeshData::Array1OfVertexOfDelaun& theVertices)
: myMeshData( theOldMesh ),
myCircles ( theVertices.Length(), theOldMesh->Allocator() )
{
@@ -116,12 +116,12 @@ BRepMesh_Delaun::BRepMesh_Delaun(
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun(
const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh,
BRepMesh::Array1OfInteger& theVertexIndices)
const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh,
IMeshData::VectorOfInteger& theVertexIndices)
: myMeshData( theOldMesh ),
myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() )
{
perform( theVertexIndices );
perform(theVertexIndices);
}
//=======================================================================
@@ -129,10 +129,10 @@ BRepMesh_Delaun::BRepMesh_Delaun(
//purpose : Creates the triangulation with and existent Mesh data structure
//=======================================================================
BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh,
BRepMesh::Array1OfInteger& theVertexIndices,
IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV)
: myMeshData (theOldMesh),
: myMeshData (theOldMesh),
myCircles (theVertexIndices.Length (), theOldMesh->Allocator ())
{
perform (theVertexIndices, theCellsCountU, theCellsCountV);
@@ -142,16 +142,16 @@ BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)&
//function : Init
//purpose : Initializes the triangulation with an Array of Vertex
//=======================================================================
void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
void BRepMesh_Delaun::Init(IMeshData::Array1OfVertexOfDelaun& theVertices)
{
Standard_Integer aLowerIdx = theVertices.Lower();
Standard_Integer anUpperIdx = theVertices.Upper();
BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx );
IMeshData::VectorOfInteger aVertexIndexes(theVertices.Size());
Standard_Integer anIndex = aLowerIdx;
for ( ; anIndex <= anUpperIdx; ++anIndex )
{
aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) );
aVertexIndexes.Append(myMeshData->AddNode( theVertices( anIndex ) ));
}
perform( aVertexIndexes );
@@ -161,9 +161,9 @@ void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices)
//function : perform
//purpose : Create super mesh and run triangulation procedure
//=======================================================================
void BRepMesh_Delaun::perform (BRepMesh::Array1OfInteger& theVertexIndices,
const Standard_Integer theCellsCountU /* = -1 */,
const Standard_Integer theCellsCountV /* = -1 */)
void BRepMesh_Delaun::perform(IMeshData::VectorOfInteger& theVertexIndices,
const Standard_Integer theCellsCountU /* = -1 */,
const Standard_Integer theCellsCountV /* = -1 */)
{
if (theVertexIndices.Length () <= 2)
{
@@ -204,28 +204,28 @@ void BRepMesh_Delaun::perform (BRepMesh::Array1OfInteger& theVertexIndices,
//function : superMesh
//purpose : Build the super mesh
//=======================================================================
void BRepMesh_Delaun::superMesh (const Bnd_Box2d& theBox,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV)
void BRepMesh_Delaun::superMesh(const Bnd_Box2d& theBox,
const Standard_Integer theCellsCountU,
const Standard_Integer theCellsCountV)
{
Standard_Real aMinX, aMinY, aMaxX, aMaxY;
theBox.Get( aMinX, aMinY, aMaxX, aMaxY );
theBox.Get ( aMinX, aMinY, aMaxX, aMaxY );
Standard_Real aDeltaX = aMaxX - aMinX;
Standard_Real aDeltaY = aMaxY - aMinY;
Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY );
Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY );
Standard_Real aDelta = aDeltaX + aDeltaY;
myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) );
myCircles.SetCellSize( aDeltaX / theCellsCountU, aDeltaY / theCellsCountV);
mySupVert[0] = myMeshData->AddNode(
BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) );
mySupVert[1] = myMeshData->AddNode(
BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
mySupVert[2] = myMeshData->AddNode(
BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) );
@@ -235,13 +235,13 @@ void BRepMesh_Delaun::superMesh (const Bnd_Box2d& theBox,
{
Standard_Integer aFirstNode = aNodeId;
Standard_Integer aLastNode = (aNodeId + 1) % 3;
Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge(
mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) );
e[aNodeId] = Abs(aLinkIndex);
o[aNodeId] = (aLinkIndex > 0);
}
mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free);
}
@@ -251,15 +251,15 @@ void BRepMesh_Delaun::superMesh (const Bnd_Box2d& theBox,
// edges into the map.
// When an edge is suppressed more than one time it is destroyed.
//=======================================================================
void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
BRepMesh::MapOfIntegerInteger& theLoopEdges )
void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
IMeshData::MapOfIntegerInteger& theLoopEdges )
{
myCircles.Delete( theIndex );
Standard_Integer e[3];
Standard_Boolean o[3];
GetTriangle( theIndex ).Edges( e, o );
const BRepMesh_Triangle& aElement = GetTriangle(theIndex);
const Standard_Integer(&e)[3] = aElement.myEdges;
const Standard_Boolean(&o)[3] = aElement.myOrientations;
myMeshData->RemoveElement( theIndex );
for ( Standard_Integer i = 0; i < 3; ++i )
@@ -277,13 +277,11 @@ void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex,
//purpose : Computes the triangulation and add the vertices edges and
// triangles to the Mesh data structure
//=======================================================================
void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
void BRepMesh_Delaun::compute(IMeshData::VectorOfInteger& theVertexIndexes)
{
// Insertion of edges of super triangles in the list of free edges:
BRepMesh::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
Standard_Integer e[3];
Standard_Boolean o[3];
mySupTrian.Edges( e, o );
IMeshData::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator());
const Standard_Integer(&e)[3] = mySupTrian.myEdges;
aLoopEdges.Bind( e[0], Standard_True );
aLoopEdges.Bind( e[1], Standard_True );
@@ -305,13 +303,13 @@ void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
aSelector.NeighboursOfNode( mySupVert[aSupVertId] );
aLoopEdges.Clear();
BRepMesh::MapOfInteger::Iterator aFreeTriangles( aSelector.Elements() );
IMeshData::IteratorOfMapOfInteger aFreeTriangles( aSelector.Elements() );
for ( ; aFreeTriangles.More(); aFreeTriangles.Next() )
deleteTriangle( aFreeTriangles.Key(), aLoopEdges );
// All edges that remain free are removed from aLoopEdges;
// only the boundary edges of the triangulation remain there
BRepMesh::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
IMeshData::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges );
for ( ; aFreeEdges.More(); aFreeEdges.Next() )
{
if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() )
@@ -327,19 +325,19 @@ void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes)
//function : createTriangles
//purpose : Creates the triangles beetween the node and the polyline.
//=======================================================================
void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
BRepMesh::MapOfIntegerInteger& thePoly)
void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex,
IMeshData::MapOfIntegerInteger& thePoly)
{
BRepMesh::ListOfInteger aLoopEdges, anExternalEdges;
IMeshData::ListOfInteger aLoopEdges, anExternalEdges;
const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord();
BRepMesh::MapOfIntegerInteger::Iterator anEdges( thePoly );
IMeshData::MapOfIntegerInteger::Iterator anEdges( thePoly );
for ( ; anEdges.More(); anEdges.Next() )
{
Standard_Integer anEdgeId = anEdges.Key();
const BRepMesh_Edge& anEdge = GetEdge( anEdgeId );
const Standard_Boolean isPositive = thePoly (anEdgeId) != 0;
Standard_Boolean isPositive = thePoly( anEdgeId ) != 0;
Standard_Integer aNodes[3];
if ( isPositive )
@@ -449,10 +447,10 @@ void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIn
//purpose : Creation of triangles from the new nodes
//=======================================================================
void BRepMesh_Delaun::createTrianglesOnNewVertices(
BRepMesh::Array1OfInteger& theVertexIndexes)
IMeshData::VectorOfInteger& theVertexIndexes)
{
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
Standard_Real aTolU, aTolV;
myMeshData->Data()->GetTolerance(aTolU, aTolV);
@@ -466,16 +464,16 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices(
for( ; anIndex <= anUpper; ++anIndex )
{
aAllocator->Reset(Standard_False);
BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
Standard_Integer aVertexIdx = theVertexIndexes( anIndex );
const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx );
// Iterator in the list of indexes of circles containing the node
BRepMesh::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
IMeshData::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() );
Standard_Integer onEgdeId = 0, aTriangleId = 0;
BRepMesh::ListOfInteger::Iterator aCircleIt( aCirclesList );
IMeshData::ListOfInteger::Iterator aCircleIt( aCirclesList );
for ( ; aCircleIt.More(); aCircleIt.Next() )
{
// To add a node in the mesh it is necessary to check conditions:
@@ -509,12 +507,11 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices(
while ( isModify && !aCirclesList.IsEmpty() )
{
isModify = Standard_False;
BRepMesh::ListOfInteger::Iterator aCircleIt1( aCirclesList );
IMeshData::ListOfInteger::Iterator aCircleIt1( aCirclesList );
for ( ; aCircleIt1.More(); aCircleIt1.Next() )
{
Standard_Integer e[3];
Standard_Boolean o[3];
GetTriangle( aCircleIt1.Value() ).Edges( e, o );
const BRepMesh_Triangle& aElement = GetTriangle(aCircleIt1.Value());
const Standard_Integer(&e)[3] = aElement.myEdges;
if ( aLoopEdges.IsBound( e[0] ) ||
aLoopEdges.IsBound( e[1] ) ||
@@ -546,13 +543,11 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices(
//=======================================================================
void BRepMesh_Delaun::insertInternalEdges()
{
BRepMesh::HMapOfInteger anInternalEdges = InternalEdges();
Handle(IMeshData::MapOfInteger) anInternalEdges = InternalEdges();;
// Destruction of triancles intersecting internal edges
// and their replacement by makeshift triangles
Standard_Integer e[3];
Standard_Boolean o[3];
BRepMesh::MapOfInteger::Iterator anInernalEdgesIt( *anInternalEdges );
IMeshData::IteratorOfMapOfInteger anInernalEdgesIt( *anInternalEdges );
for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() )
{
const Standard_Integer aLinkIndex = anInernalEdgesIt.Key();
@@ -562,7 +557,10 @@ void BRepMesh_Delaun::insertInternalEdges()
Standard_Boolean isGo[2] = { Standard_True, Standard_True };
for (Standard_Integer aTriangleIt = 1; aTriangleIt <= aPair.Extent(); ++aTriangleIt)
{
GetTriangle(aPair.Index(aTriangleIt)).Edges(e, o);
const BRepMesh_Triangle& aElement = GetTriangle(aPair.Index(aTriangleIt));
const Standard_Integer(&e)[3] = aElement.myEdges;
const Standard_Boolean(&o)[3] = aElement.myOrientations;
for (Standard_Integer i = 0; i < 3; ++i)
{
if (e[i] == aLinkIndex)
@@ -611,9 +609,8 @@ Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
if ( aTriId < 0 || aTriId == thePrevElementId )
continue;
Standard_Integer anEdges[3];
Standard_Boolean anEdgesOri[3];
GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
const Standard_Integer(&anEdges)[3] = aElement.myEdges;
for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
{
@@ -648,16 +645,16 @@ Standard_Boolean BRepMesh_Delaun::isBoundToFrontier(
void BRepMesh_Delaun::cleanupMesh()
{
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
for(;;)
{
aAllocator->Reset(Standard_False);
BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
BRepMesh::MapOfInteger aDelTriangles(10, aAllocator);
IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
IMeshData::MapOfInteger aDelTriangles;
BRepMesh::HMapOfInteger aFreeEdges = FreeEdges();
BRepMesh::MapOfInteger::Iterator aFreeEdgesIt( *aFreeEdges );
Handle(IMeshData::MapOfInteger) aFreeEdges = FreeEdges();
IMeshData::IteratorOfMapOfInteger aFreeEdgesIt( *aFreeEdges );
for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() )
{
const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key();
@@ -676,9 +673,8 @@ void BRepMesh_Delaun::cleanupMesh()
Standard_Integer aTriId = aPair.FirstIndex();
// Check that the connected triangle is not surrounded by another triangles
Standard_Integer anEdges[3];
Standard_Boolean anEdgesOri[3];
GetTriangle( aTriId ).Edges( anEdges, anEdgesOri );
const BRepMesh_Triangle& aElement = GetTriangle(aTriId);
const Standard_Integer(&anEdges)[3] = aElement.myEdges;
Standard_Boolean isCanNotBeRemoved = Standard_True;
for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx )
@@ -719,7 +715,7 @@ void BRepMesh_Delaun::cleanupMesh()
// Destruction of triangles :
Standard_Integer aDeletedTrianglesNb = 0;
BRepMesh::MapOfInteger::Iterator aDelTrianglesIt( aDelTriangles );
IMeshData::IteratorOfMapOfInteger aDelTrianglesIt( aDelTriangles );
for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() )
{
deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges );
@@ -727,7 +723,7 @@ void BRepMesh_Delaun::cleanupMesh()
}
// Destruction of remaining hanging edges
BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() )
@@ -745,15 +741,14 @@ void BRepMesh_Delaun::cleanupMesh()
//=======================================================================
void BRepMesh_Delaun::frontierAdjust()
{
BRepMesh::HMapOfInteger aFrontier = Frontier();
Handle(IMeshData::MapOfInteger) aFrontier = Frontier();
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
BRepMesh::VectorOfInteger aFailedFrontiers(256, aAllocator);
BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
BRepMesh::HMapOfInteger aIntFrontierEdges =
new BRepMesh::MapOfInteger(10, aAllocator);
IMeshData::VectorOfInteger aFailedFrontiers(256, aAllocator);
IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
Handle(IMeshData::MapOfInteger) aIntFrontierEdges = new IMeshData::MapOfInteger;
for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass )
{
@@ -761,7 +756,7 @@ void BRepMesh_Delaun::frontierAdjust()
// 2 pass): find external triangles on boundary edges appeared
// during triangles replacement.
BRepMesh::MapOfInteger::Iterator aFrontierIt( *aFrontier );
IMeshData::IteratorOfMapOfInteger aFrontierIt( *aFrontier );
for ( ; aFrontierIt.More(); aFrontierIt.Next() )
{
Standard_Integer aFrontierId = aFrontierIt.Key();
@@ -773,9 +768,9 @@ void BRepMesh_Delaun::frontierAdjust()
if( aPriorElemId < 0 )
continue;
Standard_Integer e[3];
Standard_Boolean o[3];
GetTriangle( aPriorElemId ).Edges( e, o );
const BRepMesh_Triangle& aElement = GetTriangle(aPriorElemId);
const Standard_Integer(&e)[3] = aElement.myEdges;
const Standard_Boolean(&o)[3] = aElement.myOrientations;
Standard_Boolean isTriangleFound = Standard_False;
for ( Standard_Integer n = 0; n < 3; ++n )
@@ -795,7 +790,7 @@ void BRepMesh_Delaun::frontierAdjust()
}
// destrucrion of remaining hanging edges :
BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key();
@@ -826,7 +821,7 @@ void BRepMesh_Delaun::frontierAdjust()
// situation when frontier edge has a triangle at a right side, but its free
// links cross another frontieres and meshLeftPolygonOf itself can't collect
// a closed polygon.
BRepMesh::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
IMeshData::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers );
for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() )
{
Standard_Integer aFrontierId = aFailedFrontiersIt.Value();
@@ -842,9 +837,9 @@ void BRepMesh_Delaun::frontierAdjust()
//purpose : Add boundig box for edge defined by start & end point to
// the given vector of bounding boxes for triangulation edges
//=======================================================================
void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes,
const BRepMesh_Vertex& theV1,
const BRepMesh_Vertex& theV2)
void BRepMesh_Delaun::fillBndBox(IMeshData::SequenceOfBndB2d& theBoxes,
const BRepMesh_Vertex& theV1,
const BRepMesh_Vertex& theV2)
{
Bnd_B2d aBox;
UpdateBndBox(theV1.Coord(), theV2.Coord(), aBox);
@@ -856,16 +851,16 @@ void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes,
//purpose : Collect the polygon at the left of the given edge (material side)
//=======================================================================
Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
const Standard_Integer theStartEdgeId,
const Standard_Boolean isForward,
BRepMesh::HMapOfInteger theSkipped )
const Standard_Integer theStartEdgeId,
const Standard_Boolean isForward,
Handle(IMeshData::MapOfInteger) theSkipped)
{
if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) )
return Standard_True;
const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId );
BRepMesh::SequenceOfInteger aPolygon;
IMeshData::SequenceOfInteger aPolygon;
Standard_Integer aStartNode, aPivotNode;
if ( isForward )
{
@@ -893,14 +888,14 @@ Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
// Auxilary structures.
// Bounding boxes of polygon links to be used for preliminary
// analysis of intersections
BRepMesh::SequenceOfBndB2d aBoxes;
IMeshData::SequenceOfBndB2d aBoxes;
fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex );
// Hanging ends
BRepMesh::MapOfInteger aDeadLinks;
IMeshData::MapOfInteger aDeadLinks;
// Links are temporarily excluded from consideration
BRepMesh::MapOfInteger aLeprousLinks;
IMeshData::MapOfInteger aLeprousLinks;
aLeprousLinks.Add( theStartEdgeId );
Standard_Boolean isSkipLeprous = Standard_True;
@@ -985,26 +980,26 @@ Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf(
// consideration next time until a hanging end is occured.
//=======================================================================
Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
const Standard_Integer& theFirstNode,
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 Standard_Boolean& isSkipLeprous,
BRepMesh::MapOfInteger& theLeprousLinks,
BRepMesh::MapOfInteger& theDeadLinks,
Standard_Integer& theNextPivotNode,
gp_Vec2d& theNextLinkDir,
Bnd_B2d& theNextLinkBndBox )
const Standard_Integer& theFirstNode,
const Standard_Integer& thePivotNode,
const BRepMesh_Vertex& thePivotVertex,
const gp_Vec2d& theRefLinkDir,
const IMeshData::SequenceOfBndB2d& theBoxes,
const IMeshData::SequenceOfInteger& thePolygon,
const Handle(IMeshData::MapOfInteger) theSkipped,
const Standard_Boolean& isSkipLeprous,
IMeshData::MapOfInteger& theLeprousLinks,
IMeshData::MapOfInteger& theDeadLinks,
Standard_Integer& theNextPivotNode,
gp_Vec2d& theNextLinkDir,
Bnd_B2d& theNextLinkBndBox )
{
// Find the next link having the greatest angle
// respect to a direction of a reference one
Standard_Real aMaxAngle = RealFirst();
Standard_Integer aNextLinkId = 0;
BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) );
for ( ; aLinkIt.More(); aLinkIt.Next() )
{
const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value();
@@ -1094,13 +1089,13 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink(
// <theLinkBndBox> parameter.
//=======================================================================
Standard_Boolean BRepMesh_Delaun::checkIntersection(
const BRepMesh_Edge& theLink,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
const Standard_Boolean isSkipLastEdge,
Bnd_B2d& theLinkBndBox ) const
const BRepMesh_Edge& theLink,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
const Standard_Boolean isSkipLastEdge,
Bnd_B2d& theLinkBndBox ) const
{
UpdateBndBox(GetVertex(theLink.FirstNode()).Coord(),
GetVertex(theLink.LastNode()).Coord(), theLinkBndBox);
@@ -1126,7 +1121,7 @@ Standard_Boolean BRepMesh_Delaun::checkIntersection(
continue;
gp_Pnt2d anIntPnt;
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink,
isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt );
if ( aIntFlag != BRepMesh_GeomTool::NoIntersection )
@@ -1142,17 +1137,10 @@ Standard_Boolean BRepMesh_Delaun::checkIntersection(
//function : addTriangle
//purpose : Add a triangle based on the given oriented edges into mesh
//=======================================================================
void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
const Standard_Boolean (&theEdgesOri)[3],
const Standard_Integer (&theNodesId)[3])
inline void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
const Standard_Boolean (&theEdgesOri)[3],
const Standard_Integer (&theNodesId)[3] )
{
for (Standard_Integer i = 0; i < 3; ++i)
{
const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(theEdgesId[i]);
if (aPair.Extent() == 2)
// it is forbidden to have more than two triangles connected to the same link
return;
}
Standard_Integer aNewTriangleId =
myMeshData->AddElement(BRepMesh_Triangle(theEdgesId,
theEdgesOri, BRepMesh_Free));
@@ -1171,20 +1159,20 @@ void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3],
//function : cleanupPolygon
//purpose : Remove internal triangles from the given polygon
//=======================================================================
void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes )
void BRepMesh_Delaun::cleanupPolygon(const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes )
{
Standard_Integer aPolyLen = thePolygon.Length();
if ( aPolyLen < 3 )
return;
Handle(NCollection_IncAllocator) aAllocator =
new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE);
new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE);
BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator);
BRepMesh::MapOfInteger anIgnoredEdges(10, aAllocator);
BRepMesh::MapOfInteger aPolyVerticesFindMap(10, aAllocator);
BRepMesh::VectorOfInteger aPolyVertices(256, aAllocator);
IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator);
IMeshData::MapOfInteger anIgnoredEdges;
IMeshData::MapOfInteger aPolyVerticesFindMap;
IMeshData::VectorOfInteger aPolyVertices(256, aAllocator);
// Collect boundary vertices of the polygon
for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt )
{
@@ -1203,9 +1191,9 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg
if ( anElemId < 0 )
continue;
Standard_Integer anEdges[3];
Standard_Boolean anEdgesOri[3];
GetTriangle( anElemId ).Edges(anEdges, anEdgesOri);
const BRepMesh_Triangle& aElement = GetTriangle(anElemId);
const Standard_Integer(&anEdges)[3] = aElement.myEdges;
const Standard_Boolean(&anEdgesOri)[3] = aElement.myOrientations;
Standard_Integer isTriangleFound = Standard_False;
for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt )
@@ -1250,7 +1238,7 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg
if ( aPolyVertices.First() != aPolyVertices.Last() )
aPolyVertices.Append( aPolyVertices.First() );
BRepMesh::MapOfInteger aSurvivedLinks( anIgnoredEdges );
IMeshData::MapOfInteger aSurvivedLinks( anIgnoredEdges );
Standard_Integer aPolyVertIt = 0;
Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1;
@@ -1261,7 +1249,7 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg
thePolyBoxes, aSurvivedLinks, aLoopEdges );
}
BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() )
{
const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key();
@@ -1279,19 +1267,19 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg
// inside the polygon or crossed it.
//=======================================================================
void BRepMesh_Delaun::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 Standard_Integer theZombieNodeId,
const IMeshData::VectorOfInteger& thePolyVertices,
const IMeshData::MapOfInteger& thePolyVerticesFindMap,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
IMeshData::MapOfInteger& theSurvivedLinks,
IMeshData::MapOfIntegerInteger& theLoopEdges )
{
BRepMesh::ListOfInteger::Iterator aNeighborsIt =
IMeshData::ListOfInteger::Iterator aNeighborsIt =
myMeshData->LinksConnectedTo( theZombieNodeId );
// Try to infect neighbor nodes
BRepMesh::VectorOfInteger aVictimNodes;
IMeshData::VectorOfInteger aVictimNodes;
for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
{
const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value();
@@ -1349,7 +1337,7 @@ void BRepMesh_Delaun::killTrianglesAroundVertex(
}
// Go and do your job!
BRepMesh::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
IMeshData::VectorOfInteger::Iterator aVictimIt( aVictimNodes );
for ( ; aVictimIt.More(); aVictimIt.Next() )
{
killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices,
@@ -1363,8 +1351,8 @@ void BRepMesh_Delaun::killTrianglesAroundVertex(
//purpose : Checks is the given vertex lies inside the polygon
//=======================================================================
Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
const Standard_Integer& theVertexId,
const BRepMesh::VectorOfInteger& thePolygonVertices ) const
const Standard_Integer& theVertexId,
const IMeshData::VectorOfInteger& thePolygonVertices ) const
{
Standard_Integer aPolyLen = thePolygonVertices.Length();
if ( aPolyLen < 3 )
@@ -1404,13 +1392,13 @@ Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon(
// boundary intersection. Does nothing elsewhere.
//=======================================================================
void BRepMesh_Delaun::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 Standard_Integer& theLinkToCheckId,
const BRepMesh_Edge& theLinkToCheck,
const Standard_Integer& theEndPoint,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
IMeshData::MapOfInteger& theSurvivedLinks,
IMeshData::MapOfIntegerInteger& theLoopEdges )
{
if ( theSurvivedLinks.Contains( theLinkToCheckId ) )
return;
@@ -1428,7 +1416,7 @@ void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
killLinkTriangles( theLinkToCheckId, theLoopEdges );
BRepMesh::ListOfInteger::Iterator aNeighborsIt(
IMeshData::ListOfInteger::Iterator aNeighborsIt(
myMeshData->LinksConnectedTo(theEndPoint));
for ( ; aNeighborsIt.More(); aNeighborsIt.Next() )
@@ -1450,8 +1438,8 @@ void BRepMesh_Delaun::killTrianglesOnIntersectingLinks(
//purpose : Kill triangles bound to the given link.
//=======================================================================
void BRepMesh_Delaun::killLinkTriangles(
const Standard_Integer& theLinkId,
BRepMesh::MapOfIntegerInteger& theLoopEdges )
const Standard_Integer& theLinkId,
IMeshData::MapOfIntegerInteger& theLoopEdges )
{
const BRepMesh_PairOfIndex& aPair =
myMeshData->ElementsConnectedTo( theLinkId );
@@ -1493,17 +1481,17 @@ void BRepMesh_Delaun::getOrientedNodes(const BRepMesh_Edge& theEdge,
//purpose : Processes loop within the given polygon formed by range of
// its links specified by start and end link indices.
//=======================================================================
void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
const Standard_Integer theLinkTo,
const BRepMesh::SequenceOfInteger& thePolygon,
const BRepMesh::SequenceOfBndB2d& thePolyBoxes)
void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom,
const Standard_Integer theLinkTo,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes)
{
Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1;
if ( aNbOfLinksInLoop < 3 )
return;
BRepMesh::SequenceOfInteger aPolygon;
BRepMesh::SequenceOfBndB2d aPolyBoxes;
IMeshData::SequenceOfInteger aPolygon;
IMeshData::SequenceOfBndB2d aPolyBoxes;
for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop )
{
Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop;
@@ -1521,10 +1509,10 @@ void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom
Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
const Standard_Integer *theNodes,
const gp_Pnt2d *thePnts,
const Standard_Integer theRootIndex,
const ReplaceFlag theReplaceFlag,
BRepMesh::SequenceOfInteger& thePolygon,
BRepMesh::SequenceOfBndB2d& thePolyBoxes )
const Standard_Integer theRootIndex,
const ReplaceFlag theReplaceFlag,
IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes )
{
Standard_Integer aNewEdgeId =
myMeshData->AddLink( BRepMesh_Edge(
@@ -1558,9 +1546,9 @@ Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink(
//function : meshPolygon
//purpose :
//=======================================================================
void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
BRepMesh::SequenceOfBndB2d& thePolyBoxes,
BRepMesh::HMapOfInteger theSkipped )
void BRepMesh_Delaun::meshPolygon(IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes,
Handle(IMeshData::MapOfInteger) theSkipped)
{
// Check is the source polygon elementary
if ( meshElementaryPolygon( thePolygon ) )
@@ -1607,7 +1595,7 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
};
gp_Pnt2d anIntPnt;
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge,
Standard_False, Standard_True, anIntPnt );
if ( aIntFlag == BRepMesh_GeomTool::NoIntersection )
@@ -1774,14 +1762,14 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
}
}
BRepMesh::SequenceOfInteger* aPolygon1 = &thePolygon;
BRepMesh::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
IMeshData::SequenceOfInteger* aPolygon1 = &thePolygon;
IMeshData::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes;
BRepMesh::HSequenceOfInteger aPolygon2 = new BRepMesh::SequenceOfInteger;
BRepMesh::HSequenceOfBndB2d aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
Handle(IMeshData::SequenceOfInteger) aPolygon2 = new IMeshData::SequenceOfInteger;
Handle(IMeshData::SequenceOfBndB2d) aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
NCollection_Sequence<BRepMesh::HSequenceOfInteger> aPolyStack;
NCollection_Sequence<BRepMesh::HSequenceOfBndB2d> aPolyBoxStack;
NCollection_Sequence<Handle(IMeshData::SequenceOfInteger)> aPolyStack;
NCollection_Sequence<Handle(IMeshData::SequenceOfBndB2d)> aPolyBoxStack;
for (;;)
{
decomposeSimplePolygon(*aPolygon1, *aPolyBoxes1, *aPolygon2, *aPolyBoxes2);
@@ -1790,8 +1778,8 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
aPolyStack.Append(aPolygon2);
aPolyBoxStack.Append(aPolyBoxes2);
aPolygon2 = new BRepMesh::SequenceOfInteger;
aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d;
aPolygon2 = new IMeshData::SequenceOfInteger;
aPolyBoxes2 = new IMeshData::SequenceOfBndB2d;
}
if (aPolygon1->IsEmpty())
@@ -1816,7 +1804,7 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon,
//purpose : Triangulation of closed polygon containing only three edges.
//=======================================================================
inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
const BRepMesh::SequenceOfInteger& thePolygon)
const IMeshData::SequenceOfInteger& thePolygon)
{
Standard_Integer aPolyLen = thePolygon.Length();
if ( aPolyLen < 3 )
@@ -1856,10 +1844,10 @@ inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon(
//purpose :
//=======================================================================
void BRepMesh_Delaun::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)
{
// Check is the given polygon elementary
if ( meshElementaryPolygon( thePolygon ) )
@@ -1951,7 +1939,7 @@ void BRepMesh_Delaun::decomposeSimplePolygon(
// intersection is possible...
gp_Pnt2d anIntPnt;
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink,
Standard_False, Standard_False, anIntPnt );
if( aIntFlag != BRepMesh_GeomTool::NoIntersection )
@@ -2043,17 +2031,17 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData );
aSelector.NeighboursOf( theVertex );
BRepMesh::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
IMeshData::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() );
// Loop on triangles to be destroyed :
BRepMesh::MapOfInteger::Iterator aTriangleIt( aSelector.Elements() );
IMeshData::IteratorOfMapOfInteger aTriangleIt( aSelector.Elements() );
for ( ; aTriangleIt.More(); aTriangleIt.Next() )
deleteTriangle( aTriangleIt.Key(), aLoopEdges );
BRepMesh::SequenceOfBndB2d aBoxes;
BRepMesh::SequenceOfInteger aPolygon;
IMeshData::SequenceOfBndB2d aBoxes;
IMeshData::SequenceOfInteger aPolygon;
Standard_Integer aLoopEdgesCount = aLoopEdges.Extent();
BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges );
if ( aLoopEdgesIt.More() )
{
@@ -2063,7 +2051,7 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
Standard_Integer aPivotNode = anEdge.LastNode();
Standard_Integer anEdgeId = aLoopEdgesIt.Key();
Standard_Boolean isPositive = (aLoopEdges (anEdgeId) != 0);
Standard_Boolean isPositive = aLoopEdges( anEdgeId ) != 0;
if ( !isPositive )
{
Standard_Integer aTmp;
@@ -2083,7 +2071,7 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
aLastNode = aFirstNode;
while ( aPivotNode != aLastNode )
{
BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) );
for ( ; aLinkIt.More(); aLinkIt.Next() )
{
if ( aLinkIt.Value() != anEdgeId &&
@@ -2124,19 +2112,13 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex )
//function : AddVertices
//purpose : Adds some vertices in the triangulation.
//=======================================================================
void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices)
void BRepMesh_Delaun::AddVertices(IMeshData::VectorOfInteger& theVertices)
{
std::make_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
std::sort_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun());
ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData);
std::make_heap(theVertices.begin(), theVertices.end(), aCmp);
std::sort_heap(theVertices.begin(), theVertices.end(), aCmp);
Standard_Integer aLower = theVertices.Lower();
Standard_Integer anUpper = theVertices.Upper();
BRepMesh::Array1OfInteger aVertexIndexes( aLower, anUpper );
for ( Standard_Integer i = aLower; i <= anUpper; ++i )
aVertexIndexes(i) = myMeshData->AddNode( theVertices(i) );
createTrianglesOnNewVertices( aVertexIndexes );
createTrianglesOnNewVertices(theVertices);
}
//=======================================================================
@@ -2231,12 +2213,12 @@ Standard_Boolean BRepMesh_Delaun::UseEdge( const Standard_Integer /*theIndex*/ )
//function : getEdgesByType
//purpose : Gives the list of edges with type defined by input parameter
//=======================================================================
BRepMesh::HMapOfInteger BRepMesh_Delaun::getEdgesByType(
Handle(IMeshData::MapOfInteger) BRepMesh_Delaun::getEdgesByType(
const BRepMesh_DegreeOfFreedom theEdgeType ) const
{
Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
BRepMesh::HMapOfInteger aResult = new BRepMesh::MapOfInteger(1, anAlloc);
BRepMesh::MapOfInteger::Iterator anEdgeIt( myMeshData->LinksOfDomain() );
Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger;
IMeshData::IteratorOfMapOfInteger anEdgeIt( myMeshData->LinksOfDomain() );
for ( ; anEdgeIt.More(); anEdgeIt.Next() )
{
@@ -2299,12 +2281,10 @@ Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId
{
theEdgeOn = 0;
Standard_Integer e[3];
Standard_Boolean o[3];
Standard_Integer p[3];
const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId );
aElement.Edges(e, o);
const Standard_Integer(&e)[3] = aElement.myEdges;
const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ),
&GetEdge( e[1] ),
@@ -2354,7 +2334,7 @@ Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId
//function : intSegSeg
//purpose : Checks intersection between the two segments.
//=============================================================================
BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
const BRepMesh_Edge& theEdg1,
const BRepMesh_Edge& theEdg2,
const Standard_Boolean isConsiderEndPointTouch,
@@ -2376,9 +2356,9 @@ BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg(
//purpose : Returns area of the loop of the given polygon defined by indices
// of its start and end links.
//=============================================================================
Standard_Real BRepMesh_Delaun::polyArea(const BRepMesh::SequenceOfInteger& thePolygon,
const Standard_Integer theStartIndex,
const Standard_Integer theEndIndex) const
Standard_Real BRepMesh_Delaun::polyArea(const IMeshData::SequenceOfInteger& thePolygon,
const Standard_Integer theStartIndex,
const Standard_Integer theEndIndex) const
{
Standard_Real aArea = 0.0;
Standard_Integer aPolyLen = thePolygon.Length();
@@ -2431,9 +2411,9 @@ Standard_CString BRepMesh_DumpPoly(void* thePolygon,
return "Error: file name or polygon data is null";
}
BRepMesh::SequenceOfInteger& aPolygon = *(BRepMesh::SequenceOfInteger*)thePolygon;
IMeshData::SequenceOfInteger& aPolygon = *(IMeshData::SequenceOfInteger*)thePolygon;
Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
Handle(BRepMesh_DataStructureOfDelaun) aMeshData =
*(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr;
if (aMeshData.IsNull())
@@ -2447,7 +2427,7 @@ Standard_CString BRepMesh_DumpPoly(void* thePolygon,
{
OCC_CATCH_SIGNALS
BRepMesh::SequenceOfInteger::Iterator aLinksIt(aPolygon);
IMeshData::SequenceOfInteger::Iterator aLinksIt(aPolygon);
for (; aLinksIt.More(); aLinksIt.Next())
{
const BRepMesh_Edge& aLink = aMeshData->GetLink(Abs(aLinksIt.Value()));

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>
@@ -42,30 +42,30 @@ public:
DEFINE_STANDARD_ALLOC
//! 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,
BRepMesh::Array1OfInteger& theVertexIndices,
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);
//! 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);
Standard_EXPORT void AddVertices (IMeshData::VectorOfInteger& theVerticesIndices);
//! Modify mesh to use the edge.
//! @return True if done
@@ -78,19 +78,19 @@ public:
}
//! 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);
}
@@ -137,23 +137,23 @@ private:
InsertBefore
};
typedef NCollection_DataMap<Standard_Integer, BRepMesh::MapOfInteger> DataMapOfMap;
typedef NCollection_DataMap<Standard_Integer, IMeshData::MapOfInteger> DataMapOfMap;
//! 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;
//! Run triangulation procedure.
void perform (BRepMesh::Array1OfInteger& theVertexIndices,
const Standard_Integer theCellsCountU = -1,
const Standard_Integer theCellsCountV = -1);
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,
@@ -162,52 +162,52 @@ private:
//! 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();
//! Find left polygon of the given edge and call meshPolygon.
Standard_Boolean meshLeftPolygonOf(
const Standard_Integer theEdgeIndex,
const Standard_Boolean isForward,
BRepMesh::HMapOfInteger theSkipped = NULL);
const Standard_Integer theEdgeIndex,
const Standard_Boolean isForward,
Handle(IMeshData::MapOfInteger) theSkipped = NULL);
//! Find next link starting from the given node and has maximum
//! angle respect the given reference link.
//! Each time the next link is found other neighbor links at the pivot
//! node are marked as leprous and will be excluded from consideration
//! next time until a hanging end is occured.
Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode,
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 Standard_Boolean& isSkipLeprous,
BRepMesh::MapOfInteger& theLeprousLinks,
BRepMesh::MapOfInteger& theDeadLinks,
Standard_Integer& theNextPivotNode,
gp_Vec2d& theNextLinkDir,
Bnd_B2d& theNextLinkBndBox);
Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode,
const Standard_Integer& thePivotNode,
const BRepMesh_Vertex& thePivotVertex,
const gp_Vec2d& theRefLinkDir,
const IMeshData::SequenceOfBndB2d& theBoxes,
const IMeshData::SequenceOfInteger& thePolygon,
const Handle(IMeshData::MapOfInteger) theSkipped,
const Standard_Boolean& isSkipLeprous,
IMeshData::MapOfInteger& theLeprousLinks,
IMeshData::MapOfInteger& theDeadLinks,
Standard_Integer& theNextPivotNode,
gp_Vec2d& theNextLinkDir,
Bnd_B2d& theNextLinkBndBox);
//! 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 Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
const Standard_Boolean isSkipLastEdge,
Bnd_B2d& theLinkBndBox) const;
Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink,
const IMeshData::SequenceOfInteger& thePolygon,
const IMeshData::SequenceOfBndB2d& thePolyBoxes,
const Standard_Boolean isConsiderEndPointTouch,
const Standard_Boolean isConsiderPointOnEdge,
const Standard_Boolean isSkipLastEdge,
Bnd_B2d& theLinkBndBox) const;
//! 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
@@ -219,27 +219,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);
IMeshData::MapOfIntegerInteger& thePoly);
//! Add a triangle based on the given oriented edges into mesh
void addTriangle (const Standard_Integer (&theEdgesId)[3],
const Standard_Boolean (&theEdgesOri)[3],
const Standard_Integer (&theNodesId)[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,
@@ -248,21 +248,21 @@ private:
//! Processes loop within the given polygon formed by range of its
//! 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);
void processLoop (const Standard_Integer theLinkFrom,
const Standard_Integer theLinkTo,
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);
Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[],
const gp_Pnt2d thePnts [],
const Standard_Integer theRootIndex,
const ReplaceFlag theReplaceFlag,
IMeshData::SequenceOfInteger& thePolygon,
IMeshData::SequenceOfBndB2d& thePolyBoxes);
//! Creates the triangles on new nodes.
void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices);
void createTrianglesOnNewVertices (IMeshData::VectorOfInteger& theVertexIndices);
//! Cleanup mesh from the free triangles.
void cleanupMesh();
@@ -278,35 +278,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;
Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId,
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);
void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId,
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);
void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId,
const BRepMesh_Edge& theLinkToCheck,
const Standard_Integer& theEndPoint,
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);
void killLinkTriangles (const Standard_Integer& theLinkId,
IMeshData::MapOfIntegerInteger& theLoopEdges);
//! Calculates distances between the given point and edges of triangle.
Standard_Real calculateDist (const gp_XY theVEdges[3],
@@ -325,9 +325,9 @@ 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,
const Standard_Integer theStartIndex,
const Standard_Integer theEndIndex) const;
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();

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,58 @@
// 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_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_DelaunayBaseMeshAlgo : public BRepMesh_BaseMeshAlgo
{
public:
//! Constructor.
Standard_EXPORT BRepMesh_DelaunayBaseMeshAlgo();
//! Destructor.
Standard_EXPORT virtual ~BRepMesh_DelaunayBaseMeshAlgo();
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DelaunayBaseMeshAlgo, 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);
}
//! Generates mesh for the contour stored in data structure.
Standard_EXPORT virtual void generateMesh() Standard_OVERRIDE;
//! Perfroms processing of generated mesh.
//! By default does nothing.
virtual void postProcessMesh(BRepMesh_Delaun& /*theMesher*/)
{
}
};
#endif

View File

@@ -0,0 +1,408 @@
// 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>
//! Extends node insertion Delaunay meshing algo in order to control
//! deflection of generated trianges. Splits triangles failing the check.
template<class RangeSplitter>
class BRepMesh_DelaunayDeflectionControlMeshAlgo : public BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter>
{
private:
// Typedef for OCCT RTTI
typedef BRepMesh_DelaunayNodeInsertionMeshAlgo<RangeSplitter> 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.;
usePoint(aMidPnt2d, LineDeviation(theNodesInfo[i].Point, theNodesInfo[j].Point));
}
}
}
//! 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 void 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);
}
}
//! 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,90 @@
// 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 BRepMesh_DelaunayNodeInsertionMeshAlgo : public BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo>
{
private:
// Typedef for OCCT RTTI
typedef BRepMesh_NodeInsertionMeshAlgo<RangeSplitter, BRepMesh_DelaunayBaseMeshAlgo> InsertionBaseClass;
public:
//! Constructor.
BRepMesh_DelaunayNodeInsertionMeshAlgo()
{
}
//! Destructor.
virtual ~BRepMesh_DelaunayNodeInsertionMeshAlgo()
{
}
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) Standard_OVERRIDE
{
return BRepMesh_GeomTool::CellsCount (this->getDFace()->GetSurface(), theVerticesNb,
this->getParameters().Deflection, &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);
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();
}
};
#endif

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);
}

View File

@@ -0,0 +1,324 @@
// 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::Perform (
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);
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);
}
}
//=======================================================================
// 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,96 @@
// 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);
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean Perform (
const Handle (IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
//! 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)
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,48 +14,60 @@
// 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)
BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor (
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 ();
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value(
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));
thePoint = BRepMesh_ShapeTool::UseLocation(theRefPnt, myLoc);
theParameter = myProvider.Parameter(theIndex, thePoint);
theUV = myPCurve->Value(theParameter);
const gp_Pnt& theRefPnt = (*myNodes) ((*myIndices) (theIndex));
thePoint = BRepMesh_ShapeTool::UseLocation (theRefPnt, myLoc);
theParameter = myProvider.Parameter (theIndex, thePoint);
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
#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,315 @@
// 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>
#include <BRepMesh_IncAllocator.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.
//! 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,86 @@
// 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::Perform(
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;
}
Handle(IMeshTools_MeshAlgo) aMeshingAlgo =
myAlgoFactory->GetAlgo(aDFace->GetSurface()->GetType(), myParameters);
if (aMeshingAlgo.IsNull())
{
aDFace->SetStatus(IMeshData_Failure);
return;
}
aMeshingAlgo->Perform(aDFace, myParameters);
}

View File

@@ -0,0 +1,63 @@
// 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 instace 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();
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean Perform(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
//! 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)
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,978 +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 <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, (Standard_Integer )aFaces.size());
}
//=======================================================================
//function : Process
//purpose :
//=======================================================================
void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const
{
Handle(BRepMesh_FaceAttribute) anAttribute;
if (GetFaceAttribute(theFace, anAttribute))
{
try
{
OCC_CATCH_SIGNALS
BRepMesh_FastDiscretFace aTool(myParameters.Angle, myParameters.MinSize,
myParameters.InternalVerticesMode, myParameters.ControlSurfaceDeflection);
aTool.Perform(anAttribute);
}
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,351 +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;
//! 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;
};
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;
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;
Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package")
typedef IMeshTools_Parameters Parameters;
};
DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient)
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,194 +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;
//! 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);
DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient)
private:
void add(const Handle(BRepMesh_FaceAttribute)& theAttribute);
void add(const TopoDS_Vertex& theVertex);
Standard_Real control(BRepMesh_Delaun& theMeshBuilder,
const Standard_Boolean theIsFirst);
//! 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);
//! 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);
//! 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,11 +224,12 @@ Standard_Boolean BRepMesh_GeomTool::Value(
//function : Value
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex,
const Standard_Real theIsoParam,
Standard_Real& theParam,
gp_Pnt& thePoint,
gp_Pnt2d& theUV) const
Standard_Boolean BRepMesh_GeomTool::Value(
const Standard_Integer theIndex,
const Standard_Real theIsoParam,
Standard_Real& theParam,
gp_Pnt& thePoint,
gp_Pnt2d& theUV) const
{
if (theIndex < 1 || theIndex > NbPoints())
return Standard_False;
@@ -286,13 +416,63 @@ BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg(
const Standard_Real aEndPrec = 1 - aPrec;
for (Standard_Integer i = 0; i < 2; ++i)
{
if( aParam[i] < aPrec || aParam[i] > aEndPrec )
if(aParam[i] < aPrec || aParam[i] > aEndPrec )
return BRepMesh_GeomTool::NoIntersection;
}
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,13 +62,14 @@ 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,
const Standard_Real theFirstParam,
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
Standard_EXPORT BRepMesh_GeomTool(
const BRepAdaptor_Curve& theCurve,
const Standard_Real theFirstParam,
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
//! Constructor.
//! Initiates discretization of geometric curve corresponding
@@ -79,15 +82,16 @@ 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,
const GeomAbs_IsoType theIsoType,
const Standard_Real theParamIso,
const Standard_Real theFirstParam,
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
Standard_EXPORT BRepMesh_GeomTool(
const Handle(BRepAdaptor_HSurface)& theSurface,
const GeomAbs_IsoType theIsoType,
const Standard_Real theParamIso,
const Standard_Real theFirstParam,
const Standard_Real theLastParam,
const Standard_Real theLinDeflection,
const Standard_Real theAngDeflection,
const Standard_Integer theMinPointsNb = 2,
const Standard_Real theMinSize = Precision::Confusion());
//! Adds point to already calculated points (or replaces existing).
//! @param thePoint point to be added.
@@ -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

@@ -1,48 +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_IEdgeTool_HeaderFile
#define _BRepMesh_IEdgeTool_HeaderFile
#include <Standard.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <Standard_Transient.hxx>
//! Interface class providing API for edge tessellation tools.
class BRepMesh_IEdgeTool : public Standard_Transient
{
public:
//! Returns number of tessellation points.
virtual Standard_Integer NbPoints() const = 0;
//! 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) = 0;
DEFINE_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient)
};
DEFINE_STANDARD_HANDLE(BRepMesh_IEdgeTool, Standard_Transient)
#endif

View File

@@ -0,0 +1,50 @@
// Created on: 2016-06-20
// Created by: Oleg AGASHIN
// Copyright (c) 2016 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_IncAllocator_HeaderFile
#define _BRepMesh_IncAllocator_HeaderFile
#include <NCollection_IncAllocator.hxx>
#include <Standard_Mutex.hxx>
//! Extension for NCollection_IncAllocator implementing simple thread safety
//! by introduction of Mutex. Intended for use in couple with BRepMeshData
//! entities in order to prevent data races while building data model in
//! parallel mode. Note that this allocator is supposed for use by collections
//! which allocate memory by huge blocks at arbitrary moment, thus it should
//! not introduce significant performance slow down.
class BRepMesh_IncAllocator : public NCollection_IncAllocator
{
public:
//! Constructor
BRepMesh_IncAllocator(const size_t theBlockSize = DefaultBlockSize)
: NCollection_IncAllocator(theBlockSize)
{
}
//! Allocate memory with given size. Returns NULL on failure
virtual void* Allocate(const size_t size) Standard_OVERRIDE
{
Standard_Mutex::Sentry aSentry(myMutex);
return NCollection_IncAllocator::Allocate(size);
}
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncAllocator, NCollection_IncAllocator)
private:
Standard_Mutex myMutex;
};
#endif

View File

@@ -15,46 +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>
IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
#include <IMeshData_Status.hxx>
#include <IMeshData_Face.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshTools_MeshBuilder.hxx>
namespace
{
@@ -63,15 +29,13 @@ namespace
static Standard_Boolean IS_IN_PARALLEL = Standard_False;
}
//=======================================================================
//function : Default constructor
//purpose :
//=======================================================================
BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh()
: myMaxShapeSize(0.),
myModified(Standard_False),
myStatus(0)
: myModified(Standard_False),
myStatus(IMeshData_NoError)
{
}
@@ -83,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.Angle = theAngDeflection;
myParameters.Relative = isRelative;
myParameters.InParallel = isInParallel;
myParameters.AdaptiveMin = adaptiveMin;
myShape = theShape;
Perform();
@@ -103,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;
myShape = theShape;
Perform();
}
@@ -120,437 +81,37 @@ 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()
{
init();
initParameters();
if (myMesh.IsNull())
return;
Handle(BRepMesh_Context) aContext = new BRepMesh_Context;
aContext->SetShape(Shape());
aContext->ChangeParameters() = myParameters;
aContext->ChangeParameters().CleanModel = Standard_False;
update();
}
IMeshTools_MeshBuilder aIncMesh(aContext);
aIncMesh.Perform();
//=======================================================================
//function : update()
//purpose :
//=======================================================================
void BRepMesh_IncrementalMesh::update()
{
// Update edges data
TopExp_Explorer aExplorer(myShape, TopAbs_EDGE);
for (; aExplorer.More(); aExplorer.Next())
myStatus = IMeshData_NoError;
const Handle(IMeshData_Model)& aModel = aContext->GetModel();
for (Standard_Integer aFaceIt = 0; aFaceIt < aModel->FacesNb(); ++aFaceIt)
{
const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current());
if(!BRep_Tool::IsGeometric(aEdge))
continue;
const IMeshData::IFaceHandle& aDFace = aModel->GetFace(aFaceIt);
myStatus |= aDFace->GetStatusMask();
update(aEdge);
}
// Update faces data
NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
for (; aFaceIt.More(); aFaceIt.Next())
update(aFaceIt.Value());
// Mesh faces
OSD_Parallel::ForEach(myFaces.begin(), myFaces.end(), *myMesh, !myParameters.InParallel, myFaces.Size());
commit();
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)
for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
{
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;
}
const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
myStatus |= aDWire->GetStatusMask();
}
}
// 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()
{
NCollection_Vector<TopoDS_Face>::Iterator aFaceIt(myFaces);
for (; aFaceIt.More(); aFaceIt.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();
}
//=======================================================================
@@ -565,9 +126,9 @@ Standard_Integer BRepMesh_IncrementalMesh::Discret(
{
BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh();
anAlgo->ChangeParameters().Deflection = theDeflection;
anAlgo->ChangeParameters().Angle = theAngle;
anAlgo->ChangeParameters().Angle = theAngle;
anAlgo->ChangeParameters().InParallel = IS_IN_PARALLEL;
anAlgo->SetShape (theShape);
anAlgo->SetShape (theShape);
theAlgo = anAlgo;
return 0; // no error
}

View File

@@ -14,21 +14,8 @@
#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 Poly_Triangulation;
class TopoDS_Shape;
class TopoDS_Edge;
class TopoDS_Face;
#include <IMeshTools_Parameters.hxx>
//! Builds the mesh of a shape with respect of their
//! correctly triangulated parts
@@ -51,20 +38,18 @@ 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,
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);
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);
//! 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);
Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters);
//! Performs meshing ot the shape.
Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
@@ -72,17 +57,17 @@ public: //! @name mesher API
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;
}
//! Returns modified flag.
inline Standard_Boolean IsModified() const
{
@@ -95,6 +80,18 @@ public: //! @name accessing to parameters.
return myStatus;
}
private:
//! Initializes specific parameters
inline void initParameters()
{
if (myParameters.MinSize < Precision::Confusion())
{
myParameters.MinSize =
Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection,
Precision::Confusion());
}
}
public: //! @name plugin API
@@ -117,78 +114,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();
//! 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();
//! Stores mesh of internal edges to the face.
void commitEdges(const TopoDS_Face& theFace);
//! Clears internal data structures.
void clear();
protected:
BRepMesh::DMapOfEdgeListOfTriangulationBool myEdges;
Handle(BRepMesh_FastDiscret) myMesh;
TopTools_DataMapOfShapeReal myEdgeDeflection;
NCollection_Vector<TopoDS_Face> myFaces;
BRepMesh_FastDiscret::Parameters myParameters;
Standard_Real myMaxShapeSize;
Standard_Boolean myModified;
Standard_Integer myStatus;
IMeshTools_Parameters myParameters;
Standard_Boolean myModified;
Standard_Integer myStatus;
};
DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot)
#endif

View File

@@ -0,0 +1,103 @@
// 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> Type;
};
template<class RangeSplitter>
struct DeflectionControlMeshAlgo
{
typedef BRepMesh_DelaunayDeflectionControlMeshAlgo<RangeSplitter> 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 new NodeInsertionMeshAlgo<BRepMesh_CylinderRangeSplitter>::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,94 @@
// 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 <Standard_ErrorHandler.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::Perform (
const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters)
{
ClearStatus ();
Handle (BRepMeshData_Model) aModel;
try
{
OCC_CATCH_SIGNALS
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(theParameters.Deflection);
}
Handle (IMeshTools_ShapeVisitor) aVisitor =
new BRepMesh_ShapeVisitor (aModel);
IMeshTools_ShapeExplorer aExplorer (theShape);
aExplorer.Accept (aVisitor);
SetStatus (Message_Done1);
}
else
{
SetStatus(Message_Fail1);
}
}
catch (Standard_Failure&)
{
SetStatus (Message_Fail2);
}
return aModel;
}

View File

@@ -0,0 +1,48 @@
// 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 ();
//! Creates discrete model for the given shape.
//! Returns nullptr in case of failure.
Standard_EXPORT virtual Handle (IMeshData_Model) Perform (
const TopoDS_Shape& theShape,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelBuilder, IMeshTools_ModelBuilder)
};
#endif

View File

@@ -0,0 +1,466 @@
// 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::Perform(
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
{
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();
}
}
}
//=======================================================================
// 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,183 @@
// 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<63>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();
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean Perform(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
//! 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)
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,189 @@
// 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->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::Perform(
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,43 @@
// 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();
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean Perform(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPostProcessor, IMeshTools_ModelAlgo)
};
#endif

View File

@@ -0,0 +1,174 @@
// 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>
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;
};
}
//=======================================================================
// Function: Constructor
// Purpose :
//=======================================================================
BRepMesh_ModelPreProcessor::BRepMesh_ModelPreProcessor()
{
}
//=======================================================================
// Function: Destructor
// Purpose :
//=======================================================================
BRepMesh_ModelPreProcessor::~BRepMesh_ModelPreProcessor()
{
}
//=======================================================================
// Function: Perform
// Purpose :
//=======================================================================
Standard_Boolean BRepMesh_ModelPreProcessor::Perform(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters)
{
if (theModel.IsNull())
{
return Standard_False;
}
OSD_Parallel::For(0, theModel->FacesNb(), 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,44 @@
// 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();
//! Performs processing of edges of the given model.
Standard_EXPORT virtual Standard_Boolean Perform(
const Handle(IMeshData_Model)& theModel,
const IMeshTools_Parameters& theParameters) Standard_OVERRIDE;
DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPreProcessor, IMeshTools_ModelAlgo)
};
#endif

View File

@@ -0,0 +1,498 @@
// 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 <GeomAdaptor_Curve.hxx>
#include <IMeshTools_Parameters.hxx>
#include <IMeshData_Wire.hxx>
#include <IMeshData_Edge.hxx>
#include <IMeshData_PCurve.hxx>
#include <GeomAbs_IsoType.hxx>
#include <BRepMesh_GeomTool.hxx>
#include <NCollection_Handle.hxx>
#include <algorithm>
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;
if (myParameters.MinSize <= Precision::Confusion())
{
myParameters.MinSize =
Max(IMeshTools_Parameters::RelMinSize() * myParameters.Deflection,
Precision::Confusion());
}
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);
const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * myDFace->GetDeflection();
if ((aSqDist > aSqMaxDeflection) &&
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 &&
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.Angle)
{
// 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;
}
}
//=======================================================================
// 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
{
initParameters();
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 :
//=======================================================================
void 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);
Standard_Boolean isSplitIntervals =
(aIntervalsNb.first > 1 || aIntervalsNb.second > 1);
if (!isSplitIntervals &&
(aSurface->GetType() == GeomAbs_BezierSurface ||
aSurface->GetType() == GeomAbs_BSplineSurface))
{
isSplitIntervals = (aSurface->NbUPoles() > 2 && aSurface->NbVPoles() > 2);
}
initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals,
const_cast<IMeshData::IMapOfReal&>(GetParametersU()));
initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals,
const_cast<IMeshData::IMapOfReal&>(GetParametersV()));
}
//=======================================================================
//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;
}
const Standard_Real aMinSize =
theParameters.MinSize > Precision::Confusion() ? theParameters.MinSize :
Max(IMeshTools_Parameters::RelMinSize() * theParameters.Deflection,
Precision::Confusion());
aMinDiff = Max(aMinSize, aMinDiff);
const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff;
const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, 2. * theTol2d);
const Standard_Real aDiff = Max(aMinSize, 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,74 @@
// 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 void 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;
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)
{
}
}
private:
RangeSplitter myRangeSplitter;
Handle(BRepMesh_Classifier) myClassifier;
};
#endif

View File

@@ -35,8 +35,8 @@ public:
//! Constructs a link between two vertices.
BRepMesh_OrientedEdge(
const Standard_Integer theFirstNode,
const Standard_Integer theLastNode)
const Standard_Integer theFirstNode,
const Standard_Integer theLastNode)
: myFirstNode(theFirstNode),
myLastNode(theLastNode)
{
@@ -57,7 +57,7 @@ public:
//! Returns hash code for this edge.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer theUpper) const
inline Standard_Integer HashCode(const Standard_Integer theUpper) const
{
return ::HashCode(myFirstNode + myLastNode, theUpper);
}
@@ -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);
}

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)
@@ -72,7 +72,7 @@ Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace)
Standard_Real aMaxTolerance = BRep_Tool::Tolerance(theFace);
Standard_Real aTolerance = Max(
MaxTolerance<TopAbs_EDGE, EdgeTolerance >(theFace),
MaxTolerance<TopAbs_EDGE, EdgeTolerance >(theFace),
MaxTolerance<TopAbs_VERTEX, VertexTolerance>(theFace));
return Max(aMaxTolerance, aTolerance);
@@ -85,7 +85,7 @@ Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace)
void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox,
Standard_Real& theMaxDimension)
{
if(theBox.IsVoid())
if (theBox.IsVoid())
return;
Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ;
@@ -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);
}
//=======================================================================
//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();
if (!aLocation2D->IsBound(theIndexOfPnt3d))
if (!theEdge->GetSameParam () &&
!theEdge->GetSameRange () &&
theEdge->GetDegenerated ())
{
BRepMesh::ListOfXY aPoints2d;
aPoints2d.Append(aPnt2d);
aLocation2D->Bind(theIndexOfPnt3d, aPoints2d);
return aPnt2d;
// Nothing to do worse.
return;
}
BRepMesh::ListOfXY& aPoints2d = aLocation2D->ChangeFind(theIndexOfPnt3d);
const TopoDS_Edge& aEdge = theEdge->GetEdge ();
const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace ();
// 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())
Handle (Geom_Curve) aCurve;
Standard_Real aFirstParam, aLastParam;
Range (aEdge, aCurve, aFirstParam, aLastParam);
if (aCurve.IsNull())
{
const gp_XY& aCurPnt2d = aPoint2dIt.Value();
theEdge->SetDegenerated(Standard_True);
return;
}
Standard_Real aDist = (aPnt2d - aCurPnt2d).Modulus();
if (aDist < aMinDist)
BRepAdaptor_Curve aCurveOnSurf(aEdge, aFace);
if (theEdge->GetSameParam () || theEdge->GetSameRange ())
{
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);
}
}
}
//=======================================================================
@@ -204,7 +208,7 @@ void BRepMesh_ShapeTool::AddInFace(
aTrsf.Invert();
TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes();
for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i)
for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i)
aNodes(i).Transform(aTrsf);
}
@@ -212,26 +216,69 @@ void BRepMesh_ShapeTool::AddInFace(
aBuilder.UpdateFace(theFace, theTriangulation);
}
//=======================================================================
//function : NullifyFace
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::NullifyFace(const TopoDS_Face& theFace)
void BRepMesh_ShapeTool::NullifyFace (const TopoDS_Face& theFace)
{
BRep_Builder aBuilder;
aBuilder.UpdateFace(theFace, Handle(Poly_Triangulation)());
aBuilder.UpdateFace (theFace, Handle (Poly_Triangulation)());
}
//=======================================================================
//function : NullifyEdge
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::NullifyEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
void BRepMesh_ShapeTool::NullifyEdge (
const TopoDS_Edge& theEdge,
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
{
UpdateEdge(theEdge, Handle(Poly_PolygonOnTriangulation)(),
UpdateEdge (theEdge, Handle (Poly_PolygonOnTriangulation)(),
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 :
//=======================================================================
void BRepMesh_ShapeTool::UpdateEdge (
const TopoDS_Edge& theEdge,
const Handle (Poly_PolygonOnTriangulation)& thePolygon,
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge (theEdge, thePolygon, theTriangulation, theLocation);
}
//=======================================================================
//function : UpdateEdge
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::UpdateEdge (
const TopoDS_Edge& theEdge,
const Handle (Poly_PolygonOnTriangulation)& thePolygon1,
const Handle (Poly_PolygonOnTriangulation)& thePolygon2,
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge (theEdge, thePolygon1, thePolygon2,
theTriangulation, theLocation);
}
@@ -240,89 +287,86 @@ void BRepMesh_ShapeTool::NullifyEdge(
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::UpdateEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_PolygonOnTriangulation)& thePolygon,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
const TopoDS_Edge& theEdge,
const Handle(Poly_Polygon3D)& thePolygon)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge(theEdge, thePolygon, theTriangulation, theLocation);
}
//=======================================================================
//function : UpdateEdge
//purpose :
//=======================================================================
void BRepMesh_ShapeTool::UpdateEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_PolygonOnTriangulation)& thePolygon1,
const Handle(Poly_PolygonOnTriangulation)& thePolygon2,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation)
{
BRep_Builder aBuilder;
aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2,
theTriangulation, theLocation);
aBuilder.UpdateEdge(theEdge, thePolygon);
}
//=======================================================================
//function : UseLocation
//purpose :
//=======================================================================
gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt,
const TopLoc_Location& theLoc)
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
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeTool::IsDegenerated(
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace)
{
// 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)
{
BC.D0(wFirst + l * du, P2);
longueur += P1.Distance(P2);
if (longueur > tolV2)
break;
P1 = P2;
return thePnt;
}
if (longueur < tolV2)
return Standard_True;
return Standard_False;
return thePnt.Transformed (theLoc.Transformation ());
}
//=======================================================================
//function : UVPoints
//purpose :
//=======================================================================
Standard_Boolean BRepMesh_ShapeTool::UVPoints (
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace,
gp_Pnt2d& theFirstPoint2d,
gp_Pnt2d& theLastPoint2d,
const Standard_Boolean isConsiderOrientation)
{
Handle (Geom2d_Curve) aCurve2d;
Standard_Real aFirstParam, aLastParam;
if (!Range(theEdge, theFace, aCurve2d, aFirstParam, aLastParam, isConsiderOrientation))
{
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.
@@ -91,27 +67,41 @@ public:
//! Nullifies triangulation stored in the face.
//! @param theFace face to be updated by null triangulation.
Standard_EXPORT static void NullifyFace(const TopoDS_Face& theFace);
Standard_EXPORT static void NullifyFace (const TopoDS_Face& theFace);
//! Nullifies polygon on triangulation stored in the edge.
//! @param theEdge edge to be updated by null polygon.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
Standard_EXPORT static void NullifyEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
Standard_EXPORT static void NullifyEdge (
const TopoDS_Edge& theEdge,
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.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
Standard_EXPORT static void UpdateEdge (
const TopoDS_Edge& theEdge,
const Handle (Poly_PolygonOnTriangulation)& thePolygon,
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_PolygonOnTriangulation)& thePolygon,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
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.
@@ -121,27 +111,46 @@ public:
//! reversed direction of the seam edge.
//! @param theTriangulation triangulation the given edge is associated to.
//! @param theLocation face location.
Standard_EXPORT static void UpdateEdge(
const TopoDS_Edge& theEdge,
const Handle(Poly_PolygonOnTriangulation)& thePolygon1,
const Handle(Poly_PolygonOnTriangulation)& thePolygon2,
const Handle(Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
Standard_EXPORT static void UpdateEdge (
const TopoDS_Edge& theEdge,
const Handle (Poly_PolygonOnTriangulation)& thePolygon1,
const Handle (Poly_PolygonOnTriangulation)& thePolygon2,
const Handle (Poly_Triangulation)& theTriangulation,
const TopLoc_Location& theLocation);
//! 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,
const TopLoc_Location& theLoc);
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(
const TopoDS_Edge& theEdge,
const TopoDS_Face& theFace);
//! 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,
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
#endif

View File

@@ -0,0 +1,148 @@
// 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)
{
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.
@@ -103,36 +95,36 @@ public:
//! Returns hash code for this triangle.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer theUpper) const
inline Standard_Integer HashCode(const Standard_Integer theUpper) const
{
return ::HashCode(myEdge1 + myEdge2 + myEdge3, theUpper);
return ::HashCode(myEdges[0] + myEdges[1] + myEdges[2], theUpper);
}
//! 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,19 +133,13 @@ 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;
};

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

@@ -15,8 +15,11 @@
#ifndef _BRepMesh_Vertex_HeaderFile
#define _BRepMesh_Vertex_HeaderFile
#include <BRepMesh_DegreeOfFreedom.hxx>
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Macro.hxx>
#include <gp_XY.hxx>
#include <BRepMesh_DegreeOfFreedom.hxx>
#include <Precision.hxx>
//! Light weighted structure representing vertex
@@ -104,7 +107,7 @@ public:
//! Returns hash code for this vertex.
//! @param theUpper upper index in the container.
//! @return hash code.
Standard_Integer HashCode(const Standard_Integer Upper) const
inline Standard_Integer HashCode(const Standard_Integer Upper) const
{
return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), Upper);
}
@@ -112,7 +115,7 @@ public:
//! 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)
@@ -124,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);
}

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>
@@ -31,13 +31,14 @@ public:
//! Constructor.
//! @param theAllocator memory allocator to be used by internal collections.
BRepMesh_VertexInspector (
BRepMesh_VertexInspector(
const Handle(NCollection_IncAllocator)& theAllocator)
: myResIndices(theAllocator),
myVertices (new BRepMesh::VectorOfVertex),
myDelNodes (theAllocator)
: myIndex(0),
myMinSqDist(RealLast()),
myVertices(new IMeshData::VectorOfVertex),
myDelNodes(theAllocator)
{
SetTolerance( Precision::Confusion() );
SetTolerance(Precision::Confusion());
}
//! Registers the given vertex.
@@ -106,35 +107,32 @@ public:
//! Set reference point to be checked.
inline void SetPoint(const gp_XY& thePoint)
{
myResIndices.Clear();
myPoint = thePoint;
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,11 +151,12 @@ public:
private:
Standard_Real myTolerance[2];
BRepMesh::ListOfInteger myResIndices;
BRepMesh::HVectorOfVertex myVertices;
BRepMesh::ListOfInteger myDelNodes;
gp_XY myPoint;
Standard_Integer myIndex;
Standard_Real myMinSqDist;
Standard_Real myTolerance[2];
Handle(IMeshData::VectorOfVertex) myVertices;
IMeshData::ListOfInteger myDelNodes;
gp_XY myPoint;
};
#endif

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.
@@ -181,10 +178,10 @@ private:
private:
Handle(NCollection_IncAllocator) myAllocator;
BRepMesh::VertexCellFilter myCellFilter;
BRepMesh_VertexInspector mySelector;
Standard_Real myTolerance[2];
Handle(NCollection_IncAllocator) myAllocator;
IMeshData::VertexCellFilter myCellFilter;
BRepMesh_VertexInspector mySelector;
Standard_Real myTolerance[2];
};
#endif

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,86 @@
BRepMesh.hxx
BRepMesh_BaseMeshAlgo.cxx
BRepMesh_BaseMeshAlgo.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_IncAllocator.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_VertexTool.hxx