0030345: Mesh, BRepMesh_CurveTessellator - GCPnts_TangentialDeflection throws Standar...
[occt.git] / src / BRepMesh / BRepMesh_NodeInsertionMeshAlgo.hxx
CommitLineData
7bd071ed 1// Created on: 2016-07-07
2// Copyright (c) 2016 OPEN CASCADE SAS
3// Created by: Oleg AGASHIN
4//
5// This file is part of Open CASCADE Technology software library.
6//
7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
12//
13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
15
16#ifndef _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
17#define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile
18
19#include <BRepMesh_Classifier.hxx>
20#include <IMeshData_Wire.hxx>
21#include <IMeshData_Edge.hxx>
22#include <IMeshData_PCurve.hxx>
23#include <BRepMesh_Vertex.hxx>
24#include <TopExp_Explorer.hxx>
25#include <TopoDS_Vertex.hxx>
26#include <BRep_Tool.hxx>
27#include <Standard_ErrorHandler.hxx>
28#include <BRepMesh_Delaun.hxx>
29
30//! Extends base meshing algo in order to enable possibility
31//! of addition of free vertices into the mesh.
32template<class RangeSplitter, class BaseAlgo>
33class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo
34{
35public:
36
37 //! Constructor.
38 BRepMesh_NodeInsertionMeshAlgo()
39 {
40 }
41
42 //! Destructor.
43 virtual ~BRepMesh_NodeInsertionMeshAlgo()
44 {
45 }
46
47 //! Performs processing of the given face.
48 virtual void Perform(
49 const IMeshData::IFaceHandle& theDFace,
50 const IMeshTools_Parameters& theParameters) Standard_OVERRIDE
51 {
52 myRangeSplitter.Reset(theDFace, theParameters);
53 myClassifier = new BRepMesh_Classifier;
54 BaseAlgo::Perform(theDFace, theParameters);
55 myClassifier.Nullify();
56 }
57
58protected:
59
60 typedef NCollection_Shared<NCollection_Sequence<const gp_Pnt2d*> > SequenceOfPnt2d;
61
62 //! Performs initialization of data structure using existing model data.
63 virtual Standard_Boolean initDataStructure() Standard_OVERRIDE
64 {
65 Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator;
66
67 const IMeshData::IFaceHandle& aDFace = this->getDFace();
68 NCollection_Array1<Handle(SequenceOfPnt2d)> aWires(0, aDFace->WiresNb() - 1);
69 for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
70 {
71 const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt);
72 if (aDWire->IsSet(IMeshData_SelfIntersectingWire) ||
73 (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0))
74 {
75 continue;
76 }
77
78 aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc);
79 }
80
81 myRangeSplitter.AdjustRange();
82 if (!myRangeSplitter.IsValid())
83 {
84 aDFace->SetStatus(IMeshData_Failure);
85 return Standard_False;
86 }
87
88 const std::pair<Standard_Real, Standard_Real>& aDelta = myRangeSplitter.GetDelta();
89 const std::pair<Standard_Real, Standard_Real>& aTolUV = myRangeSplitter.GetToleranceUV();
90 const Standard_Real uCellSize = 14.0 * aTolUV.first;
91 const Standard_Real vCellSize = 14.0 * aTolUV.second;
92
93 this->getStructure()->Data()->SetCellSize (uCellSize / aDelta.first, vCellSize / aDelta.second);
94 this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second);
95
96 for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt)
97 {
98 const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt);
99 if (!aWire.IsNull() && !aWire->IsEmpty())
100 {
101 myClassifier->RegisterWire(*aWire, aTolUV,
102 myRangeSplitter.GetRangeU(),
103 myRangeSplitter.GetRangeV());
104 }
105 }
106
107 if (this->getParameters().InternalVerticesMode)
108 {
109 insertInternalVertices();
110 }
111
112 return BaseAlgo::initDataStructure();
113 }
114
115 //! Adds the given 2d point to mesh data structure.
116 //! Returns index of node in the structure.
117 virtual Standard_Integer addNodeToStructure(
118 const gp_Pnt2d& thePoint,
119 const Standard_Integer theLocation3d,
120 const BRepMesh_DegreeOfFreedom theMovability,
121 const Standard_Boolean isForceAdd) Standard_OVERRIDE
122 {
123 return BaseAlgo::addNodeToStructure(
124 myRangeSplitter.Scale(thePoint, Standard_True),
125 theLocation3d, theMovability, isForceAdd);
126 }
127
128 //! Returns 2d point associated to the given vertex.
129 virtual gp_Pnt2d getNodePoint2d(
130 const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE
131 {
132 return myRangeSplitter.Scale(theVertex.Coord(), Standard_False);
133 }
134
135 //! Returns range splitter.
136 const RangeSplitter& getRangeSplitter() const
137 {
138 return myRangeSplitter;
139 }
140
141 //! Returns classifier.
142 const Handle(BRepMesh_Classifier)& getClassifier() const
143 {
144 return myClassifier;
145 }
146
147private:
148
149 //! Creates collection of points representing discrete wire.
150 Handle(SequenceOfPnt2d) collectWirePoints(
151 const IMeshData::IWireHandle& theDWire,
152 const Handle(NCollection_IncAllocator)& theAllocator)
153 {
154 Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator);
155 for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt)
156 {
157 const IMeshData::IEdgeHandle aDEdge = theDWire->GetEdge(aEdgeIt);
158 const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(
159 this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt));
160
161 Standard_Integer aPointIt, aEndIndex, aInc;
162 if (aPCurve->IsForward())
163 {
164 // For an infinite cylinder (for example)
165 // aPCurve->ParametersNb() == 0
166
167 aEndIndex = aPCurve->ParametersNb() - 1;
168 aPointIt = Min(0, aEndIndex);
169 aInc = 1;
170 }
171 else
172 {
173 // For an infinite cylinder (for example)
174 // aPCurve->ParametersNb() == 0
175
176 aPointIt = aPCurve->ParametersNb() - 1;
177 aEndIndex = Min(0, aPointIt);
178 aInc = -1;
179 }
180
181 // For an infinite cylinder (for example)
182 // this cycle will not be executed.
183 for (; aPointIt != aEndIndex; aPointIt += aInc)
184 {
185 const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt);
186 aWirePoints->Append(&aPnt2d);
187 myRangeSplitter.AddPoint(aPnt2d);
188 }
189 }
190
191 return aWirePoints;
192 }
193
194 //! Iterates over internal vertices of a face and
195 //! creates corresponding nodes in data structure.
196 void insertInternalVertices()
197 {
198 TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE);
199 for (; aExplorer.More(); aExplorer.Next())
200 {
201 const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current());
202 if (aVertex.Orientation() != TopAbs_INTERNAL)
203 {
204 continue;
205 }
206
207 insertInternalVertex(aVertex);
208 }
209 }
210
211 //! Inserts the given vertex into mesh.
212 void insertInternalVertex(const TopoDS_Vertex& theVertex)
213 {
214 try
215 {
216 OCC_CATCH_SIGNALS
217
218 gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace());
219 // check UV values for internal vertices
220 if (myClassifier->Perform(aPnt2d) != TopAbs_IN)
221 return;
222
223 this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d,
224 BRepMesh_Fixed, Standard_False);
225 }
226 catch (Standard_Failure)
227 {
228 }
229 }
230
231private:
232
233 RangeSplitter myRangeSplitter;
234 Handle(BRepMesh_Classifier) myClassifier;
235};
236
237#endif