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 "vtkEgNormalExtrusion.h"
23 vtkStandardNewMacro(vtkEgNormalExtrusion
)
25 vtkEgNormalExtrusion::vtkEgNormalExtrusion()
31 m_RemoveInternalFaces
= true;
34 void vtkEgNormalExtrusion::ExecuteEg()
36 QVector
<vtkIdType
> cells
, nodes
, n1
, n2
;
37 QVector
<vec3_t
> cell_normals
, node_normals
;
38 ExtractBoundary(cells
, nodes
, m_BoundaryCodes
, m_Input
);
40 computeNormals(cell_normals
, node_normals
, cells
, nodes
,m_Input
);
41 } else if (mode
== cylinder
) {
43 node_normals
.resize(nodes
.size());
44 for (int i
= 0; i
< node_normals
.size(); ++i
) {
46 m_Input
->GetPoint(nodes
[i
],x
.data());
47 vec3_t x0
= x
- ((x
-origin
)*axis
)*axis
;
48 node_normals
[i
] = x0
- origin
;
49 node_normals
[i
].normalise();
51 } else if ((mode
== fixed
) || (mode
== planar
)) {
52 fixed_normal
.normalise();
53 node_normals
.resize(nodes
.size());
54 for (int i
= 0; i
< node_normals
.size(); ++i
) {
55 node_normals
[i
] = fixed_normal
;
58 for (int i
= 0; i
< node_normals
.size(); ++ i
) {
59 node_normals
[i
][0] *= m_ScaleX
;
60 node_normals
[i
][1] *= m_ScaleY
;
61 node_normals
[i
][2] *= m_ScaleZ
;
63 n1
.resize(nodes
.size());
64 n2
.resize(nodes
.size());
67 QVector
<int> _cells
, _nodes
;
68 createNodeMapping(nodes
, _nodes
, m_Input
);
69 createCellMapping(cells
, _cells
, m_Input
);
70 QVector
<QSet
<int> > n2c
;
71 createNodeToCell(cells
, nodes
, _nodes
, n2c
, m_Input
);
73 vtkIdType NnewNodes
= m_Input
->GetNumberOfPoints() + (layer_y
.size()-1)*nodes
.size();
74 vtkIdType NnewCells
= m_Input
->GetNumberOfCells() + (layer_y
.size()-1)*cells
.size();
76 // count the number of new surface elements (side walls)
77 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
80 m_Input
->GetCellPoints(cells
[i_cell
], Npts
, pts
);
81 QVector
<vtkIdType
> surf_pts(Npts
);
82 for (int i_pts
= 0; i_pts
< Npts
; ++i_pts
) {
83 surf_pts
[i_pts
] = _nodes
[pts
[i_pts
]];
85 for (int i_surf_pts
= 0; i_surf_pts
< Npts
; ++i_surf_pts
) {
86 vtkIdType p1
= surf_pts
[i_surf_pts
];
88 if (i_surf_pts
< Npts
- 1) {
89 p2
= surf_pts
[i_surf_pts
+ 1];
97 foreach(cell
, n2c
[p1
]) {
98 if (n2c
[p2
].contains(cell
)) ++N
;
100 if (N
== 1) add_bd
= true;
103 NnewCells
+= layer_y
.size();
108 // count the number of new surface elements (base)
109 QVector
<bool> is_boundary
;
110 is_boundary
.fill(false, cells
.size());
113 nvol
.fill(0, nodes
.size());
114 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
115 if (isVolume(id_cell
, m_Input
)) {
116 vtkIdType Npts
, *pts
;
117 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
118 for (int i
= 0; i
< Npts
; ++i
) {
119 if (_nodes
[pts
[i
]] >= 0) {
120 ++nvol
[_nodes
[pts
[i
]]];
125 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
126 vtkIdType id_cell
= cells
[i_cell
];
127 vtkIdType Npts
, *pts
;
128 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
129 for (int i
= 0; i
< Npts
; ++i
) {
130 if (nvol
[_nodes
[pts
[i
]]] == 0) {
131 is_boundary
[i_cell
] = true;
134 if (is_boundary
[i_cell
] || !m_RemoveInternalFaces
) {
140 // allocate memory for the new grid
141 allocateGrid(m_Output
, NnewCells
, NnewNodes
);
143 // boundary conditions
144 EG_VTKDCC(vtkIntArray
, cell_code1
, m_Input
, "cell_code");
145 EG_VTKDCC(vtkIntArray
, cell_code2
, m_Output
, "cell_code");
146 EG_VTKDCC(vtkIntArray
, orgdir
, m_Output
, "cell_orgdir");
147 EG_VTKDCC(vtkIntArray
, voldir
, m_Output
, "cell_voldir");
148 EG_VTKDCC(vtkIntArray
, curdir
, m_Output
, "cell_curdir");
151 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
152 if (isSurface(id_cell
, m_Input
)) {
153 if (cell_code1
->GetValue(id_cell
) >= new_bc
) {
154 new_bc
= cell_code1
->GetValue(id_cell
) + 1;
159 for (int i
= 0; i
< nodes
.size(); ++i
) {
162 m_Input
->GetPoint(nodes
[i
],x
.data());
163 m_Output
->GetPoints()->SetPoint(n2
[i
],x
.data());
165 double total_layers
= layer_y
[layer_y
.size()-1] - layer_y
[0];
166 QVector
<double> total_dist(nodes
.size());
167 double L_max
= -1e99
;
169 if (mode
== planar
) {
170 for (int i
= 0; i
< nodes
.size(); ++i
) {
171 total_dist
[i
] = total_layers
;
172 vec3_t x_origin
, x_target
;
173 m_Input
->GetPoint(nodes
[i
],x_origin
.data());
174 x_target
= x_origin
+ total_layers
*node_normals
[i
];
175 double L
= x_target
*fixed_normal
;
182 m_Input
->GetPoint(nodes
[i_max
],x_far
.data());
183 x_far
+= min_dist
*fixed_normal
;
184 for (int i
= 0; i
< nodes
.size(); ++i
) {
185 total_dist
[i
] = total_layers
;
186 if (mode
== planar
) {
188 m_Input
->GetPoint(nodes
[i
],x_origin
.data());
189 total_dist
[i
] = (x_far
-x_origin
)*fixed_normal
;
193 for (int i_layer
= 0; i_layer
< layer_y
.size() - 1; ++i_layer
) {
194 for (int i
= 0; i
< n1
.size(); ++i
) {
196 n2
[i
] = i_layer
*nodes
.size() + i
+ m_Input
->GetNumberOfPoints();
198 m_Output
->GetPoint(n1
[i
],x1
.data());
199 if (mode
== rotation
) {
201 double alpha
= (layer_y
[i_layer
+ 1] - layer_y
[i_layer
])*M_PI
/180.0;
202 x2
= GeometryTools::rotate(x2
,axis
,alpha
);
205 double dist
= (layer_y
[i_layer
+ 1] - layer_y
[i_layer
]);
206 if (mode
== planar
) {
207 dist
*= total_dist
[i
]/total_layers
;
209 x2
= x1
+ dist
*node_normals
[i
];
211 m_Output
->GetPoints()->SetPoint(n2
[i
],x2
.data());
214 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
217 m_Input
->GetCellPoints(cells
[i_cell
], Npts
, pts
);
218 QVector
<vtkIdType
> surf_pts(Npts
);
219 for (int i_pts
= 0; i_pts
< Npts
; ++i_pts
) {
220 surf_pts
[i_pts
] = _nodes
[pts
[i_pts
]];
222 for (int i_surf_pts
= 0; i_surf_pts
< Npts
; ++i_surf_pts
) {
223 vtkIdType p1
= surf_pts
[i_surf_pts
];
225 if (i_surf_pts
< Npts
- 1) {
226 p2
= surf_pts
[i_surf_pts
+ 1];
234 foreach(cell
, n2c
[p1
]) {
235 if (n2c
[p2
].contains(cell
)) ++N
;
237 if (N
== 1) add_bd
= true;
240 vtkIdType quad_pts
[4];
241 quad_pts
[0] = n1
[p1
];
242 quad_pts
[1] = n1
[p2
];
243 quad_pts
[2] = n2
[p2
];
244 quad_pts
[3] = n2
[p1
];
245 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_QUAD
,4,quad_pts
);
246 cell_code2
->SetValue(id_new_cell
, new_bc
);
247 orgdir
->SetValue(id_new_cell
, 0);
248 curdir
->SetValue(id_new_cell
, 0);
249 voldir
->SetValue(id_new_cell
, 0);
254 vtkIdType pri_pts
[6];
255 pri_pts
[0] = n1
[surf_pts
[0]];
256 pri_pts
[1] = n1
[surf_pts
[2]];
257 pri_pts
[2] = n1
[surf_pts
[1]];
258 pri_pts
[3] = n2
[surf_pts
[0]];
259 pri_pts
[4] = n2
[surf_pts
[2]];
260 pri_pts
[5] = n2
[surf_pts
[1]];
261 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_WEDGE
,6,pri_pts
);
262 cell_code2
->SetValue(id_new_cell
, 0);
263 orgdir
->SetValue(id_new_cell
, 0);
264 curdir
->SetValue(id_new_cell
, 0);
265 voldir
->SetValue(id_new_cell
, 0);
267 if (i_layer
== layer_y
.size() - 2) {
268 vtkIdType tri_pts
[3];
269 tri_pts
[0] = n2
[surf_pts
[0]];
270 tri_pts
[1] = n2
[surf_pts
[1]];
271 tri_pts
[2] = n2
[surf_pts
[2]];
272 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_TRIANGLE
,3,tri_pts
);
273 cell_code2
->SetValue(id_new_cell
, cell_code1
->GetValue(cells
[i_cell
]));
274 orgdir
->SetValue(id_new_cell
, 0);
275 curdir
->SetValue(id_new_cell
, 0);
276 voldir
->SetValue(id_new_cell
, 0);
281 vtkIdType pri_pts
[8];
282 pri_pts
[0] = n1
[surf_pts
[0]];
283 pri_pts
[1] = n1
[surf_pts
[1]];
284 pri_pts
[2] = n1
[surf_pts
[2]];
285 pri_pts
[3] = n1
[surf_pts
[3]];
286 pri_pts
[4] = n2
[surf_pts
[0]];
287 pri_pts
[5] = n2
[surf_pts
[1]];
288 pri_pts
[6] = n2
[surf_pts
[2]];
289 pri_pts
[7] = n2
[surf_pts
[3]];
290 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_HEXAHEDRON
,8,pri_pts
);
291 cell_code2
->SetValue(id_new_cell
, 0);
292 orgdir
->SetValue(id_new_cell
, 0);
293 curdir
->SetValue(id_new_cell
, 0);
294 voldir
->SetValue(id_new_cell
, 0);
296 if (i_layer
== layer_y
.size() - 2) {
297 vtkIdType quad_pts
[4];
298 quad_pts
[0] = n2
[surf_pts
[0]];
299 quad_pts
[1] = n2
[surf_pts
[1]];
300 quad_pts
[2] = n2
[surf_pts
[2]];
301 quad_pts
[3] = n2
[surf_pts
[3]];
302 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_QUAD
,4,quad_pts
);
303 cell_code2
->SetValue(id_new_cell
, cell_code1
->GetValue(cells
[i_cell
]));
304 orgdir
->SetValue(id_new_cell
, 0);
305 curdir
->SetValue(id_new_cell
, 0);
306 voldir
->SetValue(id_new_cell
, 0);
311 EG_VTKSP(vtkIdList
, stream
);
312 stream
->SetNumberOfIds(1 + 2*(Npts
+ 1) + Npts
*5);
314 stream
->SetId(id
++, 2 + Npts
);
317 stream
->SetId(id
++, Npts
);
318 for (int i
= Npts
- 1; i
>= 0; --i
) {
319 stream
->SetId(id
++, n1
[surf_pts
[i
]]);
323 stream
->SetId(id
++, Npts
);
324 for (int i
= 0; i
< Npts
; ++i
) {
325 stream
->SetId(id
++, n2
[surf_pts
[i
]]);
329 for (int i
= 0; i
< Npts
; ++i
) {
330 stream
->SetId(id
++, 4);
331 vtkIdType p1
= n1
[surf_pts
[i
]];
332 vtkIdType p2
= n1
[surf_pts
[0]];
333 vtkIdType p3
= n2
[surf_pts
[0]];
334 vtkIdType p4
= n2
[surf_pts
[i
]];
336 p2
= n1
[surf_pts
[i
+1]];
337 p3
= n2
[surf_pts
[i
+1]];
339 stream
->SetId(id
++, p1
);
340 stream
->SetId(id
++, p2
);
341 stream
->SetId(id
++, p3
);
342 stream
->SetId(id
++, p4
);
345 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_POLYHEDRON
, stream
);
346 cell_code2
->SetValue(id_new_cell
, 0);
347 orgdir
->SetValue(id_new_cell
, 0);
348 curdir
->SetValue(id_new_cell
, 0);
349 voldir
->SetValue(id_new_cell
, 0);
351 if (i_layer
== layer_y
.size() - 2) {
352 EG_VTKSP(vtkIdList
, poly_pts
);
353 poly_pts
->SetNumberOfIds(Npts
);
354 for (vtkIdType id
= 0; id
< Npts
; ++id
) {
355 poly_pts
->SetId(id
, n2
[surf_pts
[id
]]);
357 vtkIdType id_new_cell
= m_Output
->InsertNextCell(VTK_POLYGON
, poly_pts
);
358 cell_code2
->SetValue(id_new_cell
, cell_code1
->GetValue(cells
[i_cell
]));
359 orgdir
->SetValue(id_new_cell
, 0);
360 curdir
->SetValue(id_new_cell
, 0);
361 voldir
->SetValue(id_new_cell
, 0);
368 for (vtkIdType nodeId
= 0; nodeId
< m_Input
->GetNumberOfPoints(); ++nodeId
) {
370 m_Input
->GetPoints()->GetPoint(nodeId
, x
.data());
371 m_Output
->GetPoints()->SetPoint(nodeId
, x
.data());
374 // copy all original cells that were not part of the extrusion
375 for (vtkIdType id_cell
= 0; id_cell
< m_Input
->GetNumberOfCells(); ++id_cell
) {
376 if (_cells
[id_cell
] == -1 || !m_RemoveInternalFaces
) {
377 vtkIdType id_new_cell
= copyCell(m_Input
, id_cell
, m_Output
);
378 copyCellData(m_Input
, id_cell
, m_Output
, id_new_cell
);
382 // close boundary where no volume cells were present in the original grid
384 for (int i_cell
= 0; i_cell
< cells
.size(); ++i_cell
) {
385 if (is_boundary
[i_cell
]) {
386 vtkIdType id_cell
= cells
[i_cell
];
389 m_Input
->GetCellPoints(id_cell
, Npts
, pts
);
390 vtkIdType id_new_cell
= m_Output
->InsertNextCell(m_Input
->GetCellType(id_cell
), Npts
, pts
);
391 m_Output
->GetCellPoints(id_new_cell
, Npts
, pts
);
392 QVector
<vtkIdType
> nodes(Npts
);
393 for (vtkIdType j
= 0; j
< Npts
; ++j
) nodes
[j
] = pts
[j
];
394 for (vtkIdType j
= 0; j
< Npts
; ++j
) pts
[Npts
- j
- 1] = nodes
[j
];
395 copyCellData(m_Input
, id_cell
, m_Output
, id_new_cell
);
399 UpdateCellIndex(m_Output
);
402 void vtkEgNormalExtrusion::SetLayers(const QVector
<double> &y
)
404 layer_y
.resize(y
.size());
405 qCopy(y
.begin(), y
.end(), layer_y
.begin());