1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2004-2011 OpenCFD Ltd.
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "vtkPV3Foam.H"
27 #include "vtkPV3FoamReader.h"
31 #include "cellModeller.H"
32 #include "vtkOpenFOAMPoints.H"
37 #include "vtkCellArray.h"
38 #include "vtkIdTypeArray.h"
39 #include "vtkUnstructuredGrid.h"
41 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 vtkUnstructuredGrid* Foam::vtkPV3Foam::volumeVTKMesh
46 polyDecomp& decompInfo
49 const cellModel& tet = *(cellModeller::lookup("tet"));
50 const cellModel& pyr = *(cellModeller::lookup("pyr"));
51 const cellModel& prism = *(cellModeller::lookup("prism"));
52 const cellModel& wedge = *(cellModeller::lookup("wedge"));
53 const cellModel& tetWedge = *(cellModeller::lookup("tetWedge"));
54 const cellModel& hex = *(cellModeller::lookup("hex"));
56 vtkUnstructuredGrid* vtkmesh = vtkUnstructuredGrid::New();
60 Info<< "<beg> Foam::vtkPV3Foam::volumeVTKMesh" << endl;
64 const cellShapeList& cellShapes = mesh.cellShapes();
66 // Number of additional points needed by the decomposition of polyhedra
69 // Number of additional cells generated by the decomposition of polyhedra
72 // face owner is needed to determine the face orientation
73 const labelList& owner = mesh.faceOwner();
75 labelList& superCells = decompInfo.superCells();
76 labelList& addPointCellLabels = decompInfo.addPointCellLabels();
78 // Scan for cells which need to be decomposed and count additional points
80 if (!reader_->GetUseVTKPolyhedron())
84 Info<< "... scanning for polyhedra" << endl;
87 forAll(cellShapes, cellI)
89 const cellModel& model = cellShapes[cellI].model();
101 const cell& cFaces = mesh.cells()[cellI];
103 forAll(cFaces, cFaceI)
105 const face& f = mesh.faces()[cFaces[cFaceI]];
109 f.nTrianglesQuads(mesh.points(), nTris, nQuads);
111 nAddCells += nQuads + nTris;
120 // Set size of additional point addressing array
121 // (from added point to original cell)
122 addPointCellLabels.setSize(nAddPoints);
124 // Set size of additional cells mapping array
125 // (from added cell to original cell)
129 Info<<" mesh nCells = " << mesh.nCells() << nl
130 <<" nPoints = " << mesh.nPoints() << nl
131 <<" nAddCells = " << nAddCells << nl
132 <<" nAddPoints = " << nAddPoints << endl;
135 superCells.setSize(mesh.nCells() + nAddCells);
139 Info<< "... converting points" << endl;
142 // Convert OpenFOAM mesh vertices to VTK
143 vtkPoints* vtkpoints = vtkPoints::New();
144 vtkpoints->Allocate(mesh.nPoints() + nAddPoints);
146 const Foam::pointField& points = mesh.points();
150 vtkInsertNextOpenFOAMPoint(vtkpoints, points[i]);
156 Info<< "... converting cells" << endl;
159 vtkmesh->Allocate(mesh.nCells() + nAddCells);
161 // Set counters for additional points and additional cells
162 label addPointI = 0, addCellI = 0;
164 // Create storage for points - needed for mapping from OpenFOAM to VTK
165 // data types - max 'order' = hex = 8 points
166 vtkIdType nodeIds[8];
168 // face-stream for a polyhedral cell
169 // [numFace0Pts, id1, id2, id3, numFace1Pts, id1, id2, id3, ...]
170 DynamicList<vtkIdType> faceStream(256);
172 forAll(cellShapes, cellI)
174 const cellShape& cellShape = cellShapes[cellI];
175 const cellModel& cellModel = cellShape.model();
177 superCells[addCellI++] = cellI;
179 if (cellModel == tet)
181 for (int j = 0; j < 4; j++)
183 nodeIds[j] = cellShape[j];
185 vtkmesh->InsertNextCell
192 else if (cellModel == pyr)
194 for (int j = 0; j < 5; j++)
196 nodeIds[j] = cellShape[j];
198 vtkmesh->InsertNextCell
205 else if (cellModel == prism)
207 // VTK has a different node order for VTK_WEDGE
208 // their triangles point outwards!
209 nodeIds[0] = cellShape[0];
210 nodeIds[1] = cellShape[2];
211 nodeIds[2] = cellShape[1];
212 nodeIds[3] = cellShape[3];
213 nodeIds[4] = cellShape[5];
214 nodeIds[5] = cellShape[4];
216 vtkmesh->InsertNextCell
223 else if (cellModel == tetWedge)
225 // Treat as squeezed prism
227 nodeIds[0] = cellShape[0];
228 nodeIds[1] = cellShape[2];
229 nodeIds[2] = cellShape[1];
230 nodeIds[3] = cellShape[3];
231 nodeIds[4] = cellShape[4];
232 nodeIds[5] = cellShape[4];
234 vtkmesh->InsertNextCell
241 else if (cellModel == wedge)
243 // Treat as squeezed hex
245 nodeIds[0] = cellShape[0];
246 nodeIds[1] = cellShape[1];
247 nodeIds[2] = cellShape[2];
248 nodeIds[3] = cellShape[2];
249 nodeIds[4] = cellShape[3];
250 nodeIds[5] = cellShape[4];
251 nodeIds[6] = cellShape[5];
252 nodeIds[7] = cellShape[6];
254 vtkmesh->InsertNextCell
261 else if (cellModel == hex)
263 for (int j = 0; j < 8; j++)
265 nodeIds[j] = cellShape[j];
267 vtkmesh->InsertNextCell
274 else if (reader_->GetUseVTKPolyhedron())
276 // Polyhedral cell - use VTK_POLYHEDRON
277 const labelList& cFaces = mesh.cells()[cellI];
279 #ifdef HAS_VTK_POLYHEDRON
280 vtkIdType nFaces = cFaces.size();
281 vtkIdType nLabels = nFaces;
283 // count size for face stream
284 forAll(cFaces, cFaceI)
286 const face& f = mesh.faces()[cFaces[cFaceI]];
291 // [numFace0Pts, id1, id2, id3, numFace1Pts, id1, id2, id3, ...]
292 // point Ids are global
294 faceStream.reserve(nLabels + nFaces);
296 forAll(cFaces, cFaceI)
298 const face& f = mesh.faces()[cFaces[cFaceI]];
299 const bool isOwner = (owner[cFaces[cFaceI]] == cellI);
300 const label nFacePoints = f.size();
302 // number of labels for this face
303 faceStream.append(nFacePoints);
309 faceStream.append(f[fp]);
314 // fairly immaterial if we reverse the list
315 // or use face::reverseFace()
318 faceStream.append(f[fp]);
323 vtkmesh->InsertNextCell(VTK_POLYHEDRON, nFaces, faceStream.data());
325 // this is a horrible substitute
326 // but avoids crashes when there is no vtkPolyhedron support
328 // establish unique node ids used
329 HashSet<vtkIdType, Hash<label> > hashUniqId(2*256);
331 forAll(cFaces, cFaceI)
333 const face& f = mesh.faces()[cFaces[cFaceI]];
337 hashUniqId.insert(f[fp]);
341 // use face stream to store unique node ids:
342 faceStream = hashUniqId.sortedToc();
344 vtkmesh->InsertNextCell
346 VTK_CONVEX_POINT_SET,
347 vtkIdType(faceStream.size()),
354 // Polyhedral cell. Decompose into tets + prisms.
356 // Mapping from additional point to cell
357 addPointCellLabels[addPointI] = cellI;
359 // The new vertex from the cell-centre
360 const label newVertexLabel = mesh.nPoints() + addPointI;
361 vtkInsertNextOpenFOAMPoint(vtkpoints, mesh.C()[cellI]);
363 // Whether to insert cell in place of original or not.
364 bool substituteCell = true;
366 const labelList& cFaces = mesh.cells()[cellI];
367 forAll(cFaces, cFaceI)
369 const face& f = mesh.faces()[cFaces[cFaceI]];
370 const bool isOwner = (owner[cFaces[cFaceI]] == cellI);
372 // Number of triangles and quads in decomposition
375 f.nTrianglesQuads(mesh.points(), nTris, nQuads);
377 // Do actual decomposition into triFcs and quadFcs.
378 faceList triFcs(nTris);
379 faceList quadFcs(nQuads);
382 f.trianglesQuads(mesh.points(), trii, quadi, triFcs, quadFcs);
384 forAll(quadFcs, quadI)
388 substituteCell = false;
392 superCells[addCellI++] = cellI;
395 const face& quad = quadFcs[quadI];
397 // Ensure we have the correct orientation for the
398 // base of the primitive cell shape.
399 // If the cell is face owner, the orientation needs to be
401 // At the moment, VTK doesn't actually seem to care if
402 // negative cells are defined, but we'll do it anyhow
406 nodeIds[0] = quad[3];
407 nodeIds[1] = quad[2];
408 nodeIds[2] = quad[1];
409 nodeIds[3] = quad[0];
413 nodeIds[0] = quad[0];
414 nodeIds[1] = quad[1];
415 nodeIds[2] = quad[2];
416 nodeIds[3] = quad[3];
418 nodeIds[4] = newVertexLabel;
419 vtkmesh->InsertNextCell
431 substituteCell = false;
435 superCells[addCellI++] = cellI;
438 const face& tri = triFcs[triI];
440 // See note above about the orientation.
453 nodeIds[3] = newVertexLabel;
455 vtkmesh->InsertNextCell
468 vtkmesh->SetPoints(vtkpoints);
473 Info<< "<end> Foam::vtkPV3Foam::volumeVTKMesh" << endl;
481 // ************************************************************************* //