2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008,2009 Oliver Gloth +
8 // + enGrid is free software: you can redistribute it and/or modify +
9 // + it under the terms of the GNU General Public License as published by +
10 // + the Free Software Foundation, either version 3 of the License, or +
11 // + (at your option) any later version. +
13 // + enGrid is distributed in the hope that it will be useful, +
14 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
15 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
16 // + GNU General Public License for more details. +
18 // + You should have received a copy of the GNU General Public License +
19 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
21 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
23 #ifndef SURFACEPROJECTION_H
24 #define SURFACEPROJECTION_H
26 class SurfaceProjection
;
28 #include "egvtkobject.h"
30 #include "guimainwindow.h"
32 class SurfaceProjection
: public EgVtkObject
35 private: // data-types
39 vtkIdType id_a
, id_b
, id_c
;
44 double smallest_length
;
55 private: // attributes
57 vtkUnstructuredGrid
* m_BGrid
;
58 QVector
<vtkIdType
> m_ProjTriangles
;
59 vtkUnstructuredGrid
* m_FGrid
;
60 QVector
<double> m_EdgeLength
;
61 QVector
<vtkIdType
> m_Cells
;
62 QVector
<vtkIdType
> m_Nodes
;
63 QVector
<vec3_t
> m_NodeNormals
;
64 QVector
<Triangle
> m_Triangles
;
65 QVector
<QVector
<int> > m_N2N
;
74 double m_WeightOffset
;
80 double m_RadiusFactor
;
88 void setBackgroundGrid_setupGrid(vtkUnstructuredGrid
* grid
, const C
& cells
);
89 void setBackgroundGrid_initOctree();
90 void setBackgroundGrid_refineFromNodes();
91 void setBackgroundGrid_refineFromEdges();
92 void setBackgroundGrid_refineFromFaces();
93 void setBackgroundGrid_initLevelSet();
94 void setBackgroundGrid_computeLevelSet();
96 vec3_t
calcGradG(vec3_t x
);
97 double calcG(vec3_t x
);
99 vec3_t
projectWithLevelSet(vec3_t x
);
101 bool projectOnTriangle(vec3_t xp
, vec3_t
&xi
, vec3_t
&ri
, double &d
, const Triangle
& T
);
102 vec3_t
projectWithGeometry(vec3_t x
, vtkIdType id_node
);
103 vec3_t
correctCurvature(int i_tri
, vec3_t r
);
110 void setBackgroundGrid(vtkUnstructuredGrid
* grid
, const C
& cells
);
112 void setForegroundGrid(vtkUnstructuredGrid
* grid
) {m_FGrid
= grid
; }
114 vec3_t
project(vec3_t x
, vtkIdType id_node
= -1);
115 int getNumOctreeCells() { return m_OTGrid
.getNumCells(); }
116 void writeOctree(QString file_name
);
117 bool usesLevelSet() { return m_UseLevelSet
; };
119 int getNumDirectProjections() { return m_NumDirect
; }
120 int getNumFullSearches() { return m_NumFull
; }
125 void SurfaceProjection::setBackgroundGrid(vtkUnstructuredGrid
* grid
, const C
& cells
)
127 setBackgroundGrid_setupGrid(grid
, cells
);
129 setBackgroundGrid_initOctree();
130 setBackgroundGrid_refineFromNodes();
131 setBackgroundGrid_refineFromEdges();
132 setBackgroundGrid_refineFromFaces();
133 setBackgroundGrid_computeLevelSet();
138 void SurfaceProjection::setBackgroundGrid_setupGrid(vtkUnstructuredGrid
* grid
, const C
& cells
)
140 QVector
<vtkIdType
> nodes
;
141 getNodesFromCells(cells
, nodes
, grid
);
142 allocateGrid(m_BGrid
, cells
.size(), nodes
.size());
143 QVector
<vtkIdType
> _nodes(grid
->GetNumberOfPoints());
144 vtkIdType id_new_node
= 0;
145 foreach (vtkIdType id_node
, nodes
) {
147 grid
->GetPoints()->GetPoint(id_node
, x
.data());
148 m_BGrid
->GetPoints()->SetPoint(id_new_node
, x
.data());
149 _nodes
[id_node
] = id_new_node
;
152 foreach (vtkIdType id_cell
, cells
) {
153 vtkIdType N_pts
, *pts
;
154 vtkIdType type_cell
= grid
->GetCellType(id_cell
);
155 grid
->GetCellPoints(id_cell
, N_pts
, pts
);
156 vtkIdType new_pts
[N_pts
];
157 for (int i
= 0; i
< N_pts
; ++i
) {
158 new_pts
[i
] = _nodes
[pts
[i
]];
160 m_BGrid
->InsertNextCell(type_cell
, N_pts
, new_pts
);
162 getAllCells(m_Cells
, m_BGrid
);
163 getNodesFromCells(m_Cells
, m_Nodes
, m_BGrid
);
164 QVector
<int> m_LNodes(m_Nodes
.size());
165 for (int i
= 0; i
< m_LNodes
.size(); ++i
) {
168 createNodeToNode(m_Cells
, m_Nodes
, m_LNodes
, m_N2N
, m_BGrid
);
169 m_EdgeLength
.fill(1e99
, m_BGrid
->GetNumberOfPoints());
170 foreach (vtkIdType id_node
, m_Nodes
) {
172 m_BGrid
->GetPoints()->GetPoint(id_node
, x
.data());
173 foreach (vtkIdType id_neigh
, m_N2N
[id_node
]) {
175 m_BGrid
->GetPoints()->GetPoint(id_neigh
, xn
.data());
176 m_EdgeLength
[id_node
] = min(m_EdgeLength
[id_node
], (x
-xn
).abs());
178 if (m_N2N
[id_node
].size() < 2) {
182 // create m_Triangles
183 m_Triangles
.resize(m_BGrid
->GetNumberOfCells());
184 for (vtkIdType id_cell
= 0; id_cell
< m_BGrid
->GetNumberOfCells(); ++id_cell
) {
185 vtkIdType Npts
, *pts
;
186 m_BGrid
->GetCellPoints(id_cell
, Npts
, pts
);
188 m_BGrid
->GetPoints()->GetPoint(pts
[0], m_Triangles
[id_cell
].a
.data());
189 m_BGrid
->GetPoints()->GetPoint(pts
[1], m_Triangles
[id_cell
].b
.data());
190 m_BGrid
->GetPoints()->GetPoint(pts
[2], m_Triangles
[id_cell
].c
.data());
191 m_Triangles
[id_cell
].id_a
= pts
[0];
192 m_Triangles
[id_cell
].id_b
= pts
[1];
193 m_Triangles
[id_cell
].id_c
= pts
[2];
194 m_Triangles
[id_cell
].g1
= m_Triangles
[id_cell
].b
- m_Triangles
[id_cell
].a
;
195 m_Triangles
[id_cell
].g2
= m_Triangles
[id_cell
].c
- m_Triangles
[id_cell
].a
;
196 m_Triangles
[id_cell
].g3
= m_Triangles
[id_cell
].g1
.cross(m_Triangles
[id_cell
].g2
);
197 m_Triangles
[id_cell
].A
= 0.5*m_Triangles
[id_cell
].g3
.abs();
198 m_Triangles
[id_cell
].g3
.normalise();
199 m_Triangles
[id_cell
].G
.column(0, m_Triangles
[id_cell
].g1
);
200 m_Triangles
[id_cell
].G
.column(1, m_Triangles
[id_cell
].g2
);
201 m_Triangles
[id_cell
].G
.column(2, m_Triangles
[id_cell
].g3
);
202 m_Triangles
[id_cell
].GI
= m_Triangles
[id_cell
].G
.inverse();
203 m_Triangles
[id_cell
].smallest_length
= (m_Triangles
[id_cell
].b
- m_Triangles
[id_cell
].a
).abs();
204 m_Triangles
[id_cell
].smallest_length
= min(m_Triangles
[id_cell
].smallest_length
, (m_Triangles
[id_cell
].c
- m_Triangles
[id_cell
].b
).abs());
205 m_Triangles
[id_cell
].smallest_length
= min(m_Triangles
[id_cell
].smallest_length
, (m_Triangles
[id_cell
].a
- m_Triangles
[id_cell
].c
).abs());
207 EG_ERR_RETURN("only triangles allowed at the moment");
211 // compute node normals
212 m_NodeNormals
.resize(m_BGrid
->GetNumberOfPoints());
213 for (vtkIdType id_node
= 0; id_node
< m_BGrid
->GetNumberOfPoints(); ++id_node
) {
214 m_NodeNormals
[id_node
] = vec3_t(0,0,0);
216 foreach (Triangle T
, m_Triangles
) {
217 m_NodeNormals
[T
.id_a
] += T
.A
*T
.g3
;
218 m_NodeNormals
[T
.id_b
] += T
.A
*T
.g3
;
219 m_NodeNormals
[T
.id_c
] += T
.A
*T
.g3
;
221 for (vtkIdType id_node
= 0; id_node
< m_BGrid
->GetNumberOfPoints(); ++id_node
) {
222 m_NodeNormals
[id_node
].normalise();
225 // compute maximum angle per node
226 QVector
<double> min_cos(m_BGrid
->GetNumberOfPoints(), 1.0);
227 foreach (Triangle T
, m_Triangles
) {
228 double cosa
= T
.g3
*m_NodeNormals
[T
.id_a
];
229 double cosb
= T
.g3
*m_NodeNormals
[T
.id_b
];
230 double cosc
= T
.g3
*m_NodeNormals
[T
.id_c
];
231 min_cos
[T
.id_a
] = min(cosa
, min_cos
[T
.id_a
]);
232 min_cos
[T
.id_b
] = min(cosb
, min_cos
[T
.id_b
]);
233 min_cos
[T
.id_c
] = min(cosc
, min_cos
[T
.id_c
]);
235 for (vtkIdType id_node
= 0; id_node
< m_BGrid
->GetNumberOfPoints(); ++id_node
) {
236 double s
= sqrt(1.0 - sqr(min(1 - 1e-20, min_cos
[id_node
])));
237 m_EdgeLength
[id_node
] *= m_RadiusFactor
*min_cos
[id_node
]/s
;
242 #endif // SURFACEPROJECTION_H