1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
21 #include "surfacealgorithm.h"
23 #include "insertpoints.h"
24 #include "removepoints.h"
25 #include "updatedesiredmeshdensity.h"
26 #include "smoothingutilities.h"
27 #include "swaptriangles.h"
28 #include "laplacesmoother.h"
29 #include "guimainwindow.h"
32 SurfaceAlgorithm::SurfaceAlgorithm()
35 getSet("surface meshing", "maximal number of iterations", 5, m_NumMaxIter
);
36 getSet("surface meshing", "number of smoothing steps" , 2, m_NumSmoothSteps
);
37 getSet("surface meshing", "number of Delaunay sweeps" , 1, m_NumDelaunaySweeps
);
38 m_NodesPerQuarterCircle
= 0;
39 m_RespectFeatureEdgesForDeleteNodes
= false;
40 m_FeatureAngleForDeleteNodes
= deg2rad(45);
41 m_PerformGeometricTests
= true;
42 m_UseProjectionForSmoothing
= true;
43 m_UseNormalCorrectionForSmoothing
= false;
44 m_AllowFeatureEdgeSwapping
= true;
45 m_AllowSmallAreaSwapping
= false;
47 m_FeatureResolution2D
= 0;
48 m_FeatureResolution3D
= 0;
53 void SurfaceAlgorithm::readSettings()
55 QString buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings").replace("\n", " ");
56 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
57 in
>> m_MaxEdgeLength
;
58 in
>> m_MinEdgeLength
;
60 in
>> m_NodesPerQuarterCircle
;
64 GuiMainWindow::pointer()->getAllBoundaryCodes(tmp_bcs
);
65 m_BoundaryCodes
.clear();
66 if (num_bcs
== tmp_bcs
.size()) {
67 foreach (int bc
, tmp_bcs
) {
70 if (check_state
== 1) {
71 m_BoundaryCodes
.insert(bc
);
76 in
>> m_FeatureResolution2D
;
77 in
>> m_FeatureResolution3D
;
81 void SurfaceAlgorithm::prepare()
86 EG_VTKDCN(vtkCharArray
, node_type
, m_Grid
, "node_type");//node type
92 void SurfaceAlgorithm::computeMeshDensity()
94 ///\todo Optimize by using only one loop through nodes!
95 UpdateDesiredMeshDensity update_desired_mesh_density
;
96 update_desired_mesh_density
.setGrid(m_Grid
);
97 update_desired_mesh_density
.setVertexMeshDensityVector(m_VMDvector
);
98 update_desired_mesh_density
.setMaxEdgeLength(m_MaxEdgeLength
);
99 update_desired_mesh_density
.setMinEdgeLength(m_MinEdgeLength
);
100 update_desired_mesh_density
.setNodesPerQuarterCircle(m_NodesPerQuarterCircle
);
101 update_desired_mesh_density
.setCellGrowthFactor(m_GrowthFactor
);
102 update_desired_mesh_density
.setBoundaryCodes(m_BoundaryCodes
);
103 update_desired_mesh_density
.setFeatureResolution2D(m_FeatureResolution2D
);
104 update_desired_mesh_density
.setFeatureResolution3D(m_FeatureResolution3D
);
105 update_desired_mesh_density();
108 void SurfaceAlgorithm::swap(double delaunay_threshold
, bool verbose
)
111 swap
.setGrid(m_Grid
);
112 swap
.setRespectBC(true);
113 swap
.setFeatureSwap(m_AllowFeatureEdgeSwapping
);
114 swap
.setFeatureAngle(m_FeatureAngle
);
115 swap
.setMaxNumLoops(m_NumDelaunaySweeps
);
116 swap
.setSmallAreaSwap(m_AllowSmallAreaSwapping
);
117 swap
.setDelaunayThreshold(delaunay_threshold
);
121 QSet
<int> rest_bcs
= GuiMainWindow::pointer()->getAllBoundaryCodes();
122 rest_bcs
-= m_BoundaryCodes
;
123 swap
.setBoundaryCodes(rest_bcs
);
127 void SurfaceAlgorithm::smooth(int N_iter
, bool correct_curveture
)
131 QVector
<vtkIdType
> cls
;
132 getSurfaceCells(m_BoundaryCodes
, cls
, m_Grid
);
134 lap
.setNumberOfIterations(N_iter
);
135 lap
.setBoundaryCodes(m_BoundaryCodes
);//IMPORTANT: so that unselected nodes become fixed when node types are updated!
136 lap
.setCorrectCurvature(correct_curveture
);
137 if (m_UseProjectionForSmoothing
) {
138 lap
.setProjectionOn();
140 lap
.setProjectionOff();
142 if (m_UseNormalCorrectionForSmoothing
) {
143 lap
.setNormalCorrectionOn();
145 lap
.setNormalCorrectionOff();
148 m_SmoothSuccess
= lap
.succeeded();
151 int SurfaceAlgorithm::insertNodes()
154 InsertPoints insert_points
;
155 insert_points
.setGrid(m_Grid
);
156 insert_points
.setBoundaryCodes(m_BoundaryCodes
);
158 return insert_points
.getNumInserted();
163 int SurfaceAlgorithm::deleteNodes()
166 RemovePoints remove_points
;
167 remove_points
.setGrid(m_Grid
);
168 remove_points
.setBoundaryCodes(m_BoundaryCodes
);
169 remove_points
.setStretchingFactor(m_StretchingFactor
);
170 remove_points
.setFeatureAngle(m_FeatureAngle
);
171 if (m_RespectFeatureEdgesForDeleteNodes
) {
172 remove_points
.setProtectFeatureEdgesOn();
174 remove_points
.setProtectFeatureEdgesOff();
176 //remove_points.setFeatureAngle(m_FeatureAngleForDeleteNodes);
177 if (m_PerformGeometricTests
) {
178 remove_points
.setPerformGeometricChecksOn();
180 remove_points
.setPerformGeometricChecksOff();
183 return remove_points
.getNumRemoved();