Merge branch 'master' of ssh://swordfish/srv/www/htdocs/git/engrid
[engrid.git] / src / surfacealgorithm.cpp
blob394c11c2d311b3f3d9b7ff9e88b024f36cfcb01a
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()
14 EG_TYPENAME;
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;
26 m_GrowthFactor = 1.5;
29 void SurfaceAlgorithm::readVMD()
31 QString buffer = GuiMainWindow::pointer()->getXmlSection("engrid/surface/table").replace("\n", " ");
32 int row_count = 0;
33 int column_count = 0;
34 m_VMDvector.clear();
36 if(!buffer.isEmpty()) {
37 QTextStream in(&buffer, QIODevice::ReadOnly);
38 in >> row_count >> column_count;
39 QSet<int> tmp_bcs;
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) {
44 int row, column;
45 QString formula;
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}}}") {
54 formula = "";
56 m_VMDvector[i].setNodes(formula);
57 in >> row >> column >> formula;
58 m_VMDvector[i].density = formula.toDouble();
59 cout << m_VMDvector[i] << endl;
61 } else {
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;
72 in >> m_GrowthFactor;
73 in >> m_NodesPerQuarterCircle;
74 int num_bcs;
75 in >> num_bcs;
76 QSet<int> tmp_bcs;
77 GuiMainWindow::pointer()->getAllBoundaryCodes(tmp_bcs);
78 m_BoundaryCodes.clear();
79 if (num_bcs == tmp_bcs.size()) {
80 foreach (int bc, tmp_bcs) {
81 int check_state;
82 in >> check_state;
83 if (check_state == 1) {
84 m_BoundaryCodes.insert(bc);
90 void SurfaceAlgorithm::prepare()
92 setAllCells();
93 readSettings();
94 readVMD();
96 EG_VTKDCN(vtkCharArray, node_type, m_Grid, "node_type");//node type
98 updateNodeInfo(true);
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)
117 setAllCells();
118 l2g_t nodes = getPartNodes();
119 foreach (vtkIdType id_node, nodes) {
120 if(update_type) {
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()
139 SwapTriangles 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);
146 QSet<int> rest_bcs;
147 GuiMainWindow::pointer()->getAllBoundaryCodes(rest_bcs);
148 rest_bcs -= m_BoundaryCodes;
149 swap.setBoundaryCodes(rest_bcs);
150 swap();
153 void SurfaceAlgorithm::smooth(int N_iter)
155 LaplaceSmoother lap;
156 lap.setGrid(m_Grid);
157 QVector<vtkIdType> cls;
158 getSurfaceCells(m_BoundaryCodes, cls, m_Grid);
159 lap.setCells(cls);
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();
164 } else {
165 lap.setProjectionOff();
167 if (m_UseNormalCorrectionForSmoothing) {
168 lap.setNormalCorrectionOn();
169 } else {
170 lap.setNormalCorrectionOff();
172 lap();
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);
181 insert_points();
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();
192 } else {
193 remove_points.setProtectFeatureEdgesOff();
195 remove_points.setFeatureAngle(m_FeatureAngleForDeleteNodes);
196 if (m_PerformGeometricTests) {
197 remove_points.setPerformGeometricChecksOn();
198 } else {
199 remove_points.setPerformGeometricChecksOff();
201 remove_points();
202 return remove_points.getNumRemoved();