1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
25 cfMesh utility to convert a surface file to VTK multiblock dataset
26 format, including the patches, feature edges and surface features.
29 Ivor Clifford <ivor.clifford@psi.ch>
31 \*---------------------------------------------------------------------------*/
37 #include "triSurfModifier.H"
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 //- Write the supplied pointList in serial vtkPolyData format
49 const UList<point>& points
52 xmlTag xmlRoot("VTKFile");
53 xmlRoot.addAttribute("type", "PolyData");
55 xmlTag& xmlPolyData = xmlRoot.addChild("PolyData");
57 xmlTag& xmlPiece = xmlPolyData.addChild("Piece");
58 xmlPiece.addAttribute("NumberOfPoints", points.size());
60 xmlTag& xmlPoints = xmlPiece.addChild("Points");
62 xmlTag& xmlPointData = xmlPoints.addChild("DataArray");
63 xmlPointData.addAttribute("type", "Float32");
64 xmlPointData.addAttribute("NumberOfComponents", 3);
65 xmlPointData.addAttribute("format", "ascii");
66 xmlPointData << points;
69 os << xmlRoot << endl;
71 Info << "Created " << fn << endl;
75 //- Write the supplied addressed pointList in serial vtkPolyData format
80 const UList<point>& points,
81 unallocLabelList& addr
84 // Create subaddressed points
85 pointField newPoints(addr.size());
89 newPoints[i] = points[addr[i]];
101 //- Write the supplied edgeList in serial vtkPolyData format
106 const UList<point>& points,
107 const LongList<edge>& edges
110 labelList connectivity(edges.size());
114 connectivity[edgeI] = 2*(edgeI+1);
117 xmlTag xmlRoot("VTKFile");
118 xmlRoot.addAttribute("type", "PolyData");
120 xmlTag& xmlPolyData = xmlRoot.addChild("PolyData");
122 xmlTag& xmlPiece = xmlPolyData.addChild("Piece");
123 xmlPiece.addAttribute("NumberOfPoints", points.size());
124 xmlPiece.addAttribute("NumberOfLines", edges.size());
126 xmlTag& xmlPoints = xmlPiece.addChild("Points");
128 xmlTag& xmlPointData = xmlPoints.addChild("DataArray");
129 xmlPointData.addAttribute("type", "Float32");
130 xmlPointData.addAttribute("NumberOfComponents", 3);
131 xmlPointData.addAttribute("format", "ascii");
132 xmlPointData << points;
134 xmlTag& xmlEdges = xmlPiece.addChild("Lines");
136 xmlTag& xmlEdgeData = xmlEdges.addChild("DataArray");
137 xmlEdgeData.addAttribute("type", "Int32");
138 xmlEdgeData.addAttribute("Name", "connectivity");
139 xmlEdgeData.addAttribute("format", "ascii");
140 xmlEdgeData << edges;
142 xmlTag& xmlConnectData = xmlEdges.addChild("DataArray");
143 xmlConnectData.addAttribute("type", "Int32");
144 xmlConnectData.addAttribute("Name", "offsets");
145 xmlConnectData.addAttribute("format", "ascii");
146 xmlConnectData << connectivity;
149 os << xmlRoot << endl;
151 Info << "Created " << fn << endl;
154 //- Write the supplied edgeList subset in serial vtkPolyData format
159 const UList<point>& points,
160 const LongList<edge>& edges,
161 const unallocLabelList& addr
164 // Remove unused points and create subaddressed edges
165 DynamicList<point> newPoints;
166 labelList newPointAddr(points.size(), -1);
167 LongList<edge> newEdges(addr.size());
171 label edgeI = addr[addrI];
173 const edge& curEdge = edges[edgeI];
174 edge& newEdge = newEdges[addrI];
178 label pointId = curEdge[i];
180 if (newPointAddr[pointId] == -1)
182 newPoints.append(points[pointId]);
183 newPointAddr[pointId] = newPoints.size()-1;
186 newEdge[i] = newPointAddr[pointId];
200 //- Write the supplied facet list in serial vtkPolyData format
201 void writeFacetsToVTK
205 const UList<point>& points,
206 const LongList<labelledTri>& facets
209 labelList connectivity(facets.size());
211 forAll(facets, faceI)
213 connectivity[faceI] = 3*(faceI+1);
216 labelList regionData(facets.size());
218 forAll(facets, faceI)
220 regionData[faceI] = facets[faceI].region();
223 xmlTag xmlRoot("VTKFile");
224 xmlRoot.addAttribute("type", "PolyData");
226 xmlTag& xmlPolyData = xmlRoot.addChild("PolyData");
228 xmlTag& xmlPiece = xmlPolyData.addChild("Piece");
229 xmlPiece.addAttribute("NumberOfPoints", points.size());
230 xmlPiece.addAttribute("NumberOfPolys", facets.size());
232 xmlTag& xmlPoints = xmlPiece.addChild("Points");
234 xmlTag& xmlPointData = xmlPoints.addChild("DataArray");
235 xmlPointData.addAttribute("type", "Float32");
236 xmlPointData.addAttribute("NumberOfComponents", 3);
237 xmlPointData.addAttribute("format", "ascii");
238 xmlPointData << points;
240 xmlTag& xmlPolys = xmlPiece.addChild("Polys");
242 xmlTag& xmlPolyDataArray = xmlPolys.addChild("DataArray");
243 xmlPolyDataArray.addAttribute("type", "Int32");
244 xmlPolyDataArray.addAttribute("Name", "connectivity");
245 xmlPolyDataArray.addAttribute("format", "ascii");
246 xmlPolyDataArray << facets;
248 xmlTag& xmlConnectData = xmlPolys.addChild("DataArray");
249 xmlConnectData.addAttribute("type", "Int32");
250 xmlConnectData.addAttribute("Name", "offsets");
251 xmlConnectData.addAttribute("format", "ascii");
252 xmlConnectData << connectivity;
254 xmlTag& xmlCellData = xmlPiece.addChild("CellData");
256 xmlTag& xmlCellDataArray = xmlCellData.addChild("DataArray");
257 xmlCellDataArray.addAttribute("type", "Int32");
258 xmlCellDataArray.addAttribute("Name", "region");
259 xmlCellDataArray.addAttribute("format", "ascii");
260 xmlCellDataArray << regionData;
263 os << xmlRoot << endl;
265 Info << "Created " << fn << endl;
269 //- Write an addressed subset of the supplied facet list
270 //- in serial vtkPolyData format
271 void writeFacetsToVTK
275 const pointField& points,
276 const LongList<labelledTri>& facets,
277 const unallocLabelList& addr
280 // Remove unused points and create subaddressed facets
281 DynamicList<point> newPoints;
282 labelList newPointAddr(points.size(), -1);
283 LongList<labelledTri> newFacets(addr.size());
287 label faceI = addr[addrI];
289 const labelledTri& facet = facets[faceI];
290 const FixedList<label, 3>& pointIds = facet;
291 FixedList<label, 3> newPointIds;
295 label pointId = pointIds[i];
297 if (newPointAddr[pointId] == -1)
299 newPoints.append(points[pointId]);
300 newPointAddr[pointId] = newPoints.size()-1;
303 newPointIds[i] = newPointAddr[pointId];
306 newFacets[addrI] = labelledTri
325 int main(int argc, char *argv[])
327 argList::noParallel();
328 argList::validArgs.clear();
330 argList::validArgs.append("input surface file");
331 argList::validArgs.append("output prefix");
332 argList args(argc, argv);
334 // Process commandline arguments
335 fileName inFileName(args.args()[1]);
336 fileName outPrefix(args.args()[2]);
338 // Read original surface
339 triSurf origSurf(inFileName);
341 const pointField& points = origSurf.points();
342 const LongList<labelledTri>& facets = origSurf.facets();
343 const LongList<edge>& edges = origSurf.featureEdges();
344 const geometricSurfacePatchList& patches = origSurf.patches();
348 // Create file structure for multiblock dataset
350 mkDir(outPrefix + "/patches");
351 mkDir(outPrefix + "/pointSubsets");
352 mkDir(outPrefix + "/edgeSubsets");
353 mkDir(outPrefix + "/faceSubsets");
355 // Create VTK multiblock dataset file
356 xmlTag xmlRoot("VTKFile");
357 xmlRoot.addAttribute("type", "vtkMultiBlockDataSet");
358 xmlRoot.addAttribute("version", "1.0");
359 xmlRoot.addAttribute("byte_order", "LittleEndian");
361 xmlTag& xmlDataSet = xmlRoot.addChild("vtkMultiBlockDataSet");
363 // Write faces and feature edges
365 fileName fn = outPrefix / "facets.vtp";
369 outPrefix / "facets.vtp",
375 xmlTag& tag = xmlDataSet.addChild("DataSet");
376 tag.addAttribute("index", Foam::name(index++));
377 tag.addAttribute("name", "facets");
378 tag.addAttribute("file", fn);
382 fileName fn = outPrefix / "featureEdges.vtp";
386 outPrefix / "featureEdges.vtp",
392 xmlTag& tag = xmlDataSet.addChild("DataSet");
393 tag.addAttribute("index", Foam::name(index++));
394 tag.addAttribute("name", "featureEdges");
395 tag.addAttribute("file", fn);
399 // Create patch addressing
400 List<DynamicList<label> > patchAddr(patches.size());
402 forAll(facets, faceI)
404 patchAddr[facets[faceI].region()].append(faceI);
408 xmlTag& xmlBlock = xmlDataSet.addChild("Block");
409 xmlBlock.addAttribute("index", Foam::name(index++));
410 xmlBlock.addAttribute("name", "patches");
412 forAll(patches, patchI)
414 word patchName = patches[patchI].name();
416 fileName fn = outPrefix / "patches" / patchName + ".vtp";
427 xmlTag& tag = xmlBlock.addChild("DataSet");
428 tag.addAttribute("index", Foam::name(patchI));
429 tag.addAttribute("name", patchName);
430 tag.addAttribute("file", fn);
434 // Write point subsets
436 xmlTag& xmlBlock = xmlDataSet.addChild("Block");
437 xmlBlock.addAttribute("index", Foam::name(index++));
438 xmlBlock.addAttribute("name", "pointSubsets");
440 DynList<label> subsetIndices;
441 labelList subsetAddr;
443 origSurf.pointSubsetIndices(subsetIndices);
445 forAll(subsetIndices, id)
447 word subsetName = origSurf.pointSubsetName(id);
448 origSurf.pointsInSubset(id, subsetAddr);
450 fileName fn = outPrefix / "pointSubsets" / subsetName + ".vtp";
460 xmlTag& tag = xmlBlock.addChild("DataSet");
461 tag.addAttribute("index", Foam::name(id));
462 tag.addAttribute("name", subsetName);
463 tag.addAttribute("file", fn);
467 // Write edge subsets
469 xmlTag& xmlBlock = xmlDataSet.addChild("Block");
470 xmlBlock.addAttribute("index", Foam::name(index++));
471 xmlBlock.addAttribute("name", "edgeSubsets");
473 DynList<label> subsetIndices;
474 labelList subsetAddr;
476 origSurf.edgeSubsetIndices(subsetIndices);
478 forAll(subsetIndices, id)
480 word subsetName = origSurf.edgeSubsetName(id);
481 origSurf.edgesInSubset(id, subsetAddr);
483 fileName fn = outPrefix / "edgeSubsets" / subsetName + ".vtp";
494 xmlTag& tag = xmlBlock.addChild("DataSet");
495 tag.addAttribute("index", Foam::name(id));
496 tag.addAttribute("name", subsetName);
497 tag.addAttribute("file", fn);
501 // Write facet subsets
503 xmlTag& xmlBlock = xmlDataSet.addChild("Block");
504 xmlBlock.addAttribute("index", Foam::name(index++));
505 xmlBlock.addAttribute("name", "faceSubsets");
507 DynList<label> subsetIndices;
508 labelList subsetAddr;
510 origSurf.facetSubsetIndices(subsetIndices);
512 forAll(subsetIndices, id)
514 word subsetName = origSurf.facetSubsetName(id);
515 origSurf.facetsInSubset(id, subsetAddr);
517 fileName fn = outPrefix / "faceSubsets" / subsetName + ".vtp";
528 xmlTag& tag = xmlBlock.addChild("DataSet");
529 tag.addAttribute("index", Foam::name(id));
530 tag.addAttribute("name", subsetName);
531 tag.addAttribute("file", fn);
535 OFstream os(outPrefix + ".vtm");
536 os << xmlRoot << endl;
538 Info << "Created " << outPrefix + ".vtm" << endl;
540 Info << "End\n" << endl;
545 // ************************************************************************* //