2 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 // + This file is part of enGrid. +
6 // + Copyright 2008 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 #include "vtkEgNormalExtrusion.h"
25 vtkStandardNewMacro(vtkEgNormalExtrusion
)
27 void vtkEgNormalExtrusion::ExecuteEg()
29 QVector
<vtkIdType
> cells
, nodes
, n1
, n2
;
30 QVector
<vec3_t
> cell_normals
, node_normals
;
31 ExtractBoundary(cells
, nodes
, m_BoundaryCodes
, m_Input
);
33 computeNormals(cell_normals
, node_normals
, cells
, nodes
,m_Input
);
34 } else if (mode
== cylinder
) {
36 node_normals
.resize(nodes
.size());
37 for (int i
= 0; i
< node_normals
.size(); ++i
) {
39 m_Input
->GetPoint(nodes
[i
],x
.data());
40 vec3_t x0
= x
- ((x
-origin
)*axis
)*axis
;
41 node_normals
[i
] = x0
- origin
;
42 node_normals
[i
].normalise();
44 } else if ((mode
== fixed
) || (mode
== planar
)) {
45 fixed_normal
.normalise();
46 node_normals
.resize(nodes
.size());
47 for (int i
= 0; i
< node_normals
.size(); ++i
) {
48 node_normals
[i
] = fixed_normal
;
51 for (int i
= 0; i
< node_normals
.size(); ++ i
) {
52 node_normals
[i
][0] *= m_ScaleX
;
53 node_normals
[i
][1] *= m_ScaleY
;
54 node_normals
[i
][2] *= m_ScaleZ
;
56 n1
.resize(nodes
.size());
57 n2
.resize(nodes
.size());
60 QVector
<int> _cells
, _nodes
;
61 createNodeMapping(nodes
, _nodes
, m_Input
);
62 createCellMapping(cells
, _cells
, m_Input
);
63 QVector
<QSet
<int> > n2c
;
64 createNodeToCell(cells
, nodes
, _nodes
, n2c
, m_Input
);
66 vtkIdType NnewNodes
= m_Input
->GetNumberOfPoints() + (layer_y
.size()-1)*nodes
.size();
67 vtkIdType NnewCells
= m_Input
->GetNumberOfCells() + (layer_y
.size()-1)*cells
.size();
69 // count the number of new surface elements (side walls)
70 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
73 m_Input
->GetCellPoints(cells
[i_cell
], Npts
, pts
);
74 QVector
<vtkIdType
> surf_pts(Npts
);
75 for (int i_pts
= 0; i_pts
< Npts
; ++i_pts
) {
76 surf_pts
[i_pts
] = _nodes
[pts
[i_pts
]];
78 for (int i_surf_pts
= 0; i_surf_pts
< Npts
; ++i_surf_pts
) {
79 vtkIdType p1
= surf_pts
[i_surf_pts
];
81 if (i_surf_pts
< Npts
- 1) {
82 p2
= surf_pts
[i_surf_pts
+ 1];
90 foreach(cell
, n2c
[p1
]) {
91 if (n2c
[p2
].contains(cell
)) ++N
;
93 if (N
== 1) add_bd
= true;
96 NnewCells
+= layer_y
.size();
101 // count the number of new surface elements (base)
102 QVector
<bool> is_boundary
;
103 is_boundary
.fill(false, cells
.size());
108 nvol
.fill(0, nodes
.size());
109 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
110 if (isVolume(id_cell
, m_Input
)) {
111 vtkIdType Npts
, *pts
;
112 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
113 for (int i
= 0; i
< Npts
; ++i
) {
114 if (_nodes
[pts
[i
]] >= 0) {
115 ++nvol
[_nodes
[pts
[i
]]];
120 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
121 vtkIdType id_cell
= cells
[i_cell
];
122 vtkIdType Npts
, *pts
;
123 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
124 for (int i
= 0; i
< Npts
; ++i
) {
125 if (nvol
[_nodes
[pts
[i
]]] == 0) {
126 is_boundary
[i_cell
] = true;
129 if (is_boundary
[i_cell
]) {
136 qDebug() << Nvol
<< Nsurf
;
139 // allocate memory for the new grid
140 allocateGrid(m_Output
, NnewCells
, NnewNodes
);
142 // boundary conditions
143 EG_VTKDCC(vtkIntArray
, cell_code1
, m_Input
, "cell_code");
144 EG_VTKDCC(vtkIntArray
, cell_code2
, m_Output
, "cell_code");
145 EG_VTKDCC(vtkIntArray
, orgdir
, m_Output
, "cell_orgdir");
146 EG_VTKDCC(vtkIntArray
, voldir
, m_Output
, "cell_voldir");
147 EG_VTKDCC(vtkIntArray
, curdir
, m_Output
, "cell_curdir");
150 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
151 if (isSurface(id_cell
, m_Input
)) {
152 if (cell_code1
->GetValue(id_cell
) >= new_bc
) {
153 new_bc
= cell_code1
->GetValue(id_cell
) + 1;
158 for (int i
= 0; i
< nodes
.size(); ++i
) {
161 m_Input
->GetPoint(nodes
[i
],x
.data());
162 m_Output
->GetPoints()->SetPoint(n2
[i
],x
.data());
164 double total_layers
= layer_y
[layer_y
.size()-1] - layer_y
[0];
165 QVector
<double> total_dist(nodes
.size());
166 double L_max
= -1e99
;
168 if (mode
== planar
) {
169 for (int i
= 0; i
< nodes
.size(); ++i
) {
170 total_dist
[i
] = total_layers
;
171 vec3_t x_origin
, x_target
;
172 m_Input
->GetPoint(nodes
[i
],x_origin
.data());
173 x_target
= x_origin
+ total_layers
*node_normals
[i
];
174 double L
= x_target
*fixed_normal
;
181 m_Input
->GetPoint(nodes
[i_max
],x_far
.data());
182 x_far
+= min_dist
*fixed_normal
;
183 for (int i
= 0; i
< nodes
.size(); ++i
) {
184 total_dist
[i
] = total_layers
;
185 if (mode
== planar
) {
187 m_Input
->GetPoint(nodes
[i
],x_origin
.data());
188 total_dist
[i
] = (x_far
-x_origin
)*fixed_normal
;
192 for (int i_layer
= 0; i_layer
< layer_y
.size() - 1; ++i_layer
) {
193 for (int i
= 0; i
< n1
.size(); ++i
) {
195 n2
[i
] = i_layer
*nodes
.size() + i
+ m_Input
->GetNumberOfPoints();
197 m_Output
->GetPoint(n1
[i
],x1
.data());
198 if (mode
== rotation
) {
200 double alpha
= (layer_y
[i_layer
+ 1] - layer_y
[i_layer
])*M_PI
/180.0;
201 x2
= GeometryTools::rotate(x2
,axis
,alpha
);
204 double dist
= (layer_y
[i_layer
+ 1] - layer_y
[i_layer
]);
205 if (mode
== planar
) {
206 dist
*= total_dist
[i
]/total_layers
;
208 x2
= x1
+ dist
*node_normals
[i
];
210 m_Output
->GetPoints()->SetPoint(n2
[i
],x2
.data());
213 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
216 m_Input
->GetCellPoints(cells
[i_cell
], Npts
, pts
);
217 QVector
<vtkIdType
> surf_pts(Npts
);
218 for (int i_pts
= 0; i_pts
< Npts
; ++i_pts
) {
219 surf_pts
[i_pts
] = _nodes
[pts
[i_pts
]];
221 for (int i_surf_pts
= 0; i_surf_pts
< Npts
; ++i_surf_pts
) {
222 vtkIdType p1
= surf_pts
[i_surf_pts
];
224 if (i_surf_pts
< Npts
- 1) {
225 p2
= surf_pts
[i_surf_pts
+ 1];
233 foreach(cell
, n2c
[p1
]) {
234 if (n2c
[p2
].contains(cell
)) ++N
;
236 if (N
== 1) add_bd
= true;
239 vtkIdType quad_pts
[4];
240 quad_pts
[0] = n1
[p1
];
241 quad_pts
[1] = n1
[p2
];
242 quad_pts
[2] = n2
[p2
];
243 quad_pts
[3] = n2
[p1
];
244 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_QUAD
,4,quad_pts
);
245 cell_code2
->SetValue(id_new_cell
, new_bc
);
246 orgdir
->SetValue(id_new_cell
, 0);
247 curdir
->SetValue(id_new_cell
, 0);
248 voldir
->SetValue(id_new_cell
, 0);
253 vtkIdType pri_pts
[6];
254 pri_pts
[0] = n1
[surf_pts
[0]];
255 pri_pts
[1] = n1
[surf_pts
[2]];
256 pri_pts
[2] = n1
[surf_pts
[1]];
257 pri_pts
[3] = n2
[surf_pts
[0]];
258 pri_pts
[4] = n2
[surf_pts
[2]];
259 pri_pts
[5] = n2
[surf_pts
[1]];
260 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_WEDGE
,6,pri_pts
);
261 cell_code2
->SetValue(id_new_cell
, 0);
262 orgdir
->SetValue(id_new_cell
, 0);
263 curdir
->SetValue(id_new_cell
, 0);
264 voldir
->SetValue(id_new_cell
, 0);
266 if (i_layer
== layer_y
.size() - 2) {
267 vtkIdType tri_pts
[3];
268 tri_pts
[0] = n2
[surf_pts
[0]];
269 tri_pts
[1] = n2
[surf_pts
[1]];
270 tri_pts
[2] = n2
[surf_pts
[2]];
271 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_TRIANGLE
,3,tri_pts
);
272 cell_code2
->SetValue(id_new_cell
, cell_code1
->GetValue(cells
[i_cell
]));
273 orgdir
->SetValue(id_new_cell
, 0);
274 curdir
->SetValue(id_new_cell
, 0);
275 voldir
->SetValue(id_new_cell
, 0);
280 vtkIdType pri_pts
[8];
281 pri_pts
[0] = n1
[surf_pts
[0]];
282 pri_pts
[1] = n1
[surf_pts
[1]];
283 pri_pts
[2] = n1
[surf_pts
[2]];
284 pri_pts
[3] = n1
[surf_pts
[3]];
285 pri_pts
[4] = n2
[surf_pts
[0]];
286 pri_pts
[5] = n2
[surf_pts
[1]];
287 pri_pts
[6] = n2
[surf_pts
[2]];
288 pri_pts
[7] = n2
[surf_pts
[3]];
289 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_HEXAHEDRON
,8,pri_pts
);
290 cell_code2
->SetValue(id_new_cell
, 0);
291 orgdir
->SetValue(id_new_cell
, 0);
292 curdir
->SetValue(id_new_cell
, 0);
293 voldir
->SetValue(id_new_cell
, 0);
295 if (i_layer
== layer_y
.size() - 2) {
296 vtkIdType quad_pts
[4];
297 quad_pts
[0] = n2
[surf_pts
[0]];
298 quad_pts
[1] = n2
[surf_pts
[1]];
299 quad_pts
[2] = n2
[surf_pts
[2]];
300 quad_pts
[3] = n2
[surf_pts
[3]];
301 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_QUAD
,4,quad_pts
);
302 cell_code2
->SetValue(id_new_cell
, cell_code1
->GetValue(cells
[i_cell
]));
303 orgdir
->SetValue(id_new_cell
, 0);
304 curdir
->SetValue(id_new_cell
, 0);
305 voldir
->SetValue(id_new_cell
, 0);
312 for (vtkIdType nodeId
= 0; nodeId
< m_Input
->GetNumberOfPoints(); ++nodeId
) {
314 m_Input
->GetPoints()->GetPoint(nodeId
, x
.data());
315 m_Output
->GetPoints()->SetPoint(nodeId
, x
.data());
318 // copy all original cells that were not part of the extrusion
319 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
320 if (_cells
[id_cell
] == -1) {
323 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
324 vtkIdType id_new_cell
= m_Output
->InsertNextCell(m_Input
->GetCellType(id_cell
), Npts
, pts
);
325 copyCellData(m_Input
, id_cell
, m_Output
, id_new_cell
);
329 // close boundary where no volume cells were present in the original grid
331 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
332 if (is_boundary
[i_cell
]) {
333 vtkIdType id_cell
= cells
[i_cell
];
336 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
337 vtkIdType id_new_cell
= m_Output
->InsertNextCell(m_Input
->GetCellType(id_cell
), Npts
, pts
);
338 m_Output
->GetCellPoints(id_new_cell
, Npts
, pts
);
339 QVector
<vtkIdType
> nodes(Npts
);
340 for (vtkIdType j
= 0; j
< Npts
; ++j
) nodes
[j
] = pts
[j
];
341 for (vtkIdType j
= 0; j
< Npts
; ++j
) pts
[Npts
- j
- 1] = nodes
[j
];
342 copyCellData(m_Input
, id_cell
, m_Output
, id_new_cell
);
346 UpdateCellIndex(m_Output
);
349 void vtkEgNormalExtrusion::SetLayers(const QVector
<double> &y
)
351 layer_y
.resize(y
.size());
352 qCopy(y
.begin(), y
.end(), layer_y
.begin());