1 #include "surfacealgorithm.h"
3 #include "insertpoints.h"
4 #include "removepoints.h"
5 #include "updatedesiredmeshdensity.h"
6 #include "smoothingutilities.h"
7 #include "swaptriangles.h"
8 #include "laplacesmoother.h"
9 #include "guimainwindow.h"
12 SurfaceAlgorithm::SurfaceAlgorithm()
15 getSet("surface meshing", "maximal number of iterations", 20, m_NumMaxIter
);
16 getSet("surface meshing", "number of smoothing steps" , 1, m_NumSmoothSteps
);
17 getSet("surface meshing", "number of Delaunay sweeps" , 1, m_NumDelaunaySweeps
);
18 m_NodesPerQuarterCircle
= 0;
19 m_RespectFeatureEdgesForDeleteNodes
= false;
20 m_FeatureAngleForDeleteNodes
= deg2rad(45);
21 m_PerformGeometricTests
= true;
22 m_UseProjectionForSmoothing
= true;
23 m_UseNormalCorrectionForSmoothing
= false;
24 m_AllowFeatureEdgeSwapping
= true;
25 m_AllowSmallAreaSwapping
= false;
29 void SurfaceAlgorithm::readVMD()
31 QString buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/table").replace("\n", " ");
36 if(!buffer
.isEmpty()) {
37 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
38 in
>> row_count
>> column_count
;
40 GuiMainWindow::pointer()->getAllBoundaryCodes(tmp_bcs
);
41 if (column_count
== tmp_bcs
.size() + 3) {
42 m_VMDvector
.fill(VertexMeshDensity(), row_count
);
43 for (int i
= 0; i
< row_count
; ++i
) {
46 foreach (int bc
, tmp_bcs
) {
47 in
>> row
>> column
>> formula
;
48 m_VMDvector
[row
].BCmap
[bc
] = formula
.toInt();
50 in
>> row
>> column
>> formula
;
51 m_VMDvector
[row
].type
= Str2VertexType(formula
);
52 in
>> row
>> column
>> formula
;
53 if (formula
== "{{{empty}}}") {
56 m_VMDvector
[i
].setNodes(formula
);
57 in
>> row
>> column
>> formula
;
58 m_VMDvector
[i
].density
= formula
.toDouble();
59 cout
<< m_VMDvector
[i
] << endl
;
62 EG_ERR_RETURN(QObject::tr("The number of boundary conditions don't match between the mesh and the settings table.\n column_count=%1 tmp_bcs.size()=%2").arg(column_count
).arg(tmp_bcs
.size()));
67 void SurfaceAlgorithm::readSettings()
69 QString buffer
= GuiMainWindow::pointer()->getXmlSection("engrid/surface/settings").replace("\n", " ");
70 QTextStream
in(&buffer
, QIODevice::ReadOnly
);
71 in
>> m_MaxEdgeLength
;
73 in
>> m_NodesPerQuarterCircle
;
77 GuiMainWindow::pointer()->getAllBoundaryCodes(tmp_bcs
);
78 m_BoundaryCodes
.clear();
79 if (num_bcs
== tmp_bcs
.size()) {
80 foreach (int bc
, tmp_bcs
) {
83 if (check_state
== 1) {
84 m_BoundaryCodes
.insert(bc
);
90 void SurfaceAlgorithm::prepare()
96 EG_VTKDCN(vtkCharArray
, node_type
, m_Grid
, "node_type");//node type
102 void SurfaceAlgorithm::computeMeshDensity()
104 ///\todo Optimize by using only one loop through nodes!
105 UpdateDesiredMeshDensity update_desired_mesh_density
;
106 update_desired_mesh_density
.setGrid(m_Grid
);
107 update_desired_mesh_density
.setVertexMeshDensityVector(m_VMDvector
);
108 update_desired_mesh_density
.setMaxEdgeLength(m_MaxEdgeLength
);
109 update_desired_mesh_density
.setNodesPerQuarterCircle(m_NodesPerQuarterCircle
);
110 update_desired_mesh_density
.setCellGrowthFactor(m_GrowthFactor
);
111 update_desired_mesh_density
.setBoundaryCodes(m_BoundaryCodes
);
112 update_desired_mesh_density();
115 void SurfaceAlgorithm::updateNodeInfo(bool update_type
)
118 l2g_t nodes
= getPartNodes();
119 foreach (vtkIdType id_node
, nodes
) {
121 EG_VTKDCN(vtkCharArray
, node_type
, m_Grid
, "node_type");//node type
122 node_type
->SetValue(id_node
, getNodeType(id_node
, true));
124 EG_VTKDCN(vtkDoubleArray
, node_meshdensity_current
, m_Grid
, "node_meshdensity_current");//what we have
125 node_meshdensity_current
->SetValue(id_node
, CurrentVertexAvgDist(id_node
));
127 EG_VTKDCN(vtkIntArray
, node_specified_density
, m_Grid
, "node_specified_density");//density index from table
128 VertexMeshDensity nodeVMD
= getVMD(id_node
);
129 // int idx = m_VMDvector.indexOf(nodeVMD);
130 int idx
= nodeVMD
.findSmallestVMD(m_VMDvector
);
131 // qWarning()<<"idx="<<idx;
132 node_specified_density
->SetValue(id_node
, idx
);
134 // writeGrid(m_Grid, "info");
137 void SurfaceAlgorithm::swap()
140 swap
.setGrid(m_Grid
);
141 swap
.setRespectBC(true);
142 swap
.setFeatureSwap(m_AllowFeatureEdgeSwapping
);
143 swap
.setFeatureAngle(m_FeatureAngle
);
144 swap
.setMaxNumLoops(m_NumDelaunaySweeps
);
145 swap
.setSmallAreaSwap(m_AllowSmallAreaSwapping
);
147 GuiMainWindow::pointer()->getAllBoundaryCodes(rest_bcs
);
148 rest_bcs
-= m_BoundaryCodes
;
149 swap
.setBoundaryCodes(rest_bcs
);
153 void SurfaceAlgorithm::smooth(int N_iter
)
157 QVector
<vtkIdType
> cls
;
158 getSurfaceCells(m_BoundaryCodes
, cls
, m_Grid
);
160 lap
.setNumberOfIterations(N_iter
);
161 lap
.setBoundaryCodes(m_BoundaryCodes
);//IMPORTANT: so that unselected nodes become fixed when node types are updated!
162 if (m_UseProjectionForSmoothing
) {
163 lap
.setProjectionOn();
165 lap
.setProjectionOff();
167 if (m_UseNormalCorrectionForSmoothing
) {
168 lap
.setNormalCorrectionOn();
170 lap
.setNormalCorrectionOff();
173 m_SmoothSuccess
= lap
.succeeded();
176 int SurfaceAlgorithm::insertNodes()
178 InsertPoints insert_points
;
179 insert_points
.setGrid(m_Grid
);
180 insert_points
.setBoundaryCodes(m_BoundaryCodes
);
182 return insert_points
.getNumInserted();
185 int SurfaceAlgorithm::deleteNodes()
187 RemovePoints remove_points
;
188 remove_points
.setGrid(m_Grid
);
189 remove_points
.setBoundaryCodes(m_BoundaryCodes
);
190 if (m_RespectFeatureEdgesForDeleteNodes
) {
191 remove_points
.setProtectFeatureEdgesOn();
193 remove_points
.setProtectFeatureEdgesOff();
195 remove_points
.setFeatureAngle(m_FeatureAngleForDeleteNodes
);
196 if (m_PerformGeometricTests
) {
197 remove_points
.setPerformGeometricChecksOn();
199 remove_points
.setPerformGeometricChecksOff();
202 return remove_points
.getNumRemoved();