Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / applications / utilities / mesh / generation / cfMesh / FMSToVTK / FMSToVTK.C
blob02f74e65a34bb6d0971a8433978396ca0ec78d60
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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/>.
24 Description
25     cfMesh utility to convert a surface file to VTK multiblock dataset
26     format, including the patches, feature edges and surface features.
28 Author
29     Ivor Clifford <ivor.clifford@psi.ch>
31 \*---------------------------------------------------------------------------*/
33 #include "argList.H"
34 #include "autoPtr.H"
35 #include "OFstream.H"
36 #include "triSurf.H"
37 #include "triSurfModifier.H"
38 #include "xmlTag.H"
40 using namespace Foam;
42 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44 //- Write the supplied pointList in serial vtkPolyData format
45 void writePointsToVTK
47     const fileName& fn,
48     const string& title,
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;
68     OFstream os(fn);
69     os << xmlRoot << endl;
71     Info << "Created " << fn << endl;
75 //- Write the supplied addressed pointList in serial vtkPolyData format
76 void writePointsToVTK
78     const fileName& fn,
79     const string& title,
80     const UList<point>& points,
81     unallocLabelList& addr
84     // Create subaddressed points
85     pointField newPoints(addr.size());
87     forAll(addr, i)
88     {
89         newPoints[i] = points[addr[i]];
90     }
92     writePointsToVTK
93     (
94         fn,
95         title,
96         newPoints
97     );
101 //- Write the supplied edgeList in serial vtkPolyData format
102 void writeEdgesToVTK
104     const fileName& fn,
105     const string& title,
106     const UList<point>& points,
107     const LongList<edge>& edges
110     labelList connectivity(edges.size());
112     forAll(edges, edgeI)
113     {
114         connectivity[edgeI] = 2*(edgeI+1);
115     }
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;
148     OFstream os(fn);
149     os << xmlRoot << endl;
151     Info << "Created " << fn << endl;
154 //- Write the supplied edgeList subset in serial vtkPolyData format
155 void writeEdgesToVTK
157     const fileName& fn,
158     const string& title,
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());
169     forAll(addr, addrI)
170     {
171         label edgeI = addr[addrI];
173         const edge& curEdge = edges[edgeI];
174         edge& newEdge = newEdges[addrI];
176         forAll(curEdge, i)
177         {
178             label pointId = curEdge[i];
180             if (newPointAddr[pointId] == -1)
181             {
182                 newPoints.append(points[pointId]);
183                 newPointAddr[pointId] = newPoints.size()-1;
184             }
186             newEdge[i] = newPointAddr[pointId];
187         }
188     }
190     writeEdgesToVTK
191     (
192         fn,
193         title,
194         newPoints,
195         newEdges
196     );
200 //- Write the supplied facet list in serial vtkPolyData format
201 void writeFacetsToVTK
203     const fileName& fn,
204     const string& title,
205     const UList<point>& points,
206     const LongList<labelledTri>& facets
209     labelList connectivity(facets.size());
211     forAll(facets, faceI)
212     {
213         connectivity[faceI] = 3*(faceI+1);
214     }
216     labelList regionData(facets.size());
218     forAll(facets, faceI)
219     {
220         regionData[faceI] =  facets[faceI].region();
221     }
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;
262     OFstream os(fn);
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
273     const fileName& fn,
274     const string& title,
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());
285     forAll(addr, addrI)
286     {
287         label faceI = addr[addrI];
289         const labelledTri& facet = facets[faceI];
290         const FixedList<label, 3>& pointIds = facet;
291         FixedList<label, 3> newPointIds;
293         forAll(pointIds, i)
294         {
295             label pointId = pointIds[i];
297             if (newPointAddr[pointId] == -1)
298             {
299                 newPoints.append(points[pointId]);
300                 newPointAddr[pointId] = newPoints.size()-1;
301             }
303             newPointIds[i] = newPointAddr[pointId];
304         }
306         newFacets[addrI] = labelledTri
307         (
308             newPointIds[0],
309             newPointIds[1],
310             newPointIds[2],
311             facet.region()
312         );
313     }
315     writeFacetsToVTK
316     (
317         fn,
318         title,
319         newPoints,
320         newFacets
321     );
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();
346     label index = 0;
348     // Create file structure for multiblock dataset
349     mkDir(outPrefix);
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
364     {
365         fileName fn = outPrefix / "facets.vtp";
367         writeFacetsToVTK
368         (
369             outPrefix / "facets.vtp",
370             outPrefix,
371             points,
372             facets
373         );
375         xmlTag& tag = xmlDataSet.addChild("DataSet");
376         tag.addAttribute("index", Foam::name(index++));
377         tag.addAttribute("name", "facets");
378         tag.addAttribute("file", fn);
379     }
381     {
382         fileName fn = outPrefix / "featureEdges.vtp";
384         writeEdgesToVTK
385         (
386             outPrefix / "featureEdges.vtp",
387             "featureEdges",
388             points,
389             edges
390         );
392         xmlTag& tag = xmlDataSet.addChild("DataSet");
393         tag.addAttribute("index", Foam::name(index++));
394         tag.addAttribute("name", "featureEdges");
395         tag.addAttribute("file", fn);
396     }
398     // Write patches
399     // Create patch addressing
400     List<DynamicList<label> > patchAddr(patches.size());
402     forAll(facets, faceI)
403     {
404         patchAddr[facets[faceI].region()].append(faceI);
405     }
407     {
408         xmlTag& xmlBlock = xmlDataSet.addChild("Block");
409         xmlBlock.addAttribute("index", Foam::name(index++));
410         xmlBlock.addAttribute("name", "patches");
412         forAll(patches, patchI)
413         {
414             word patchName = patches[patchI].name();
416             fileName fn = outPrefix / "patches" / patchName + ".vtp";
418             writeFacetsToVTK
419             (
420                 fn,
421                 patchName,
422                 points,
423                 facets,
424                 patchAddr[patchI]
425             );
427             xmlTag& tag = xmlBlock.addChild("DataSet");
428             tag.addAttribute("index", Foam::name(patchI));
429             tag.addAttribute("name", patchName);
430             tag.addAttribute("file", fn);
431         }
432     }
434     // Write point subsets
435     {
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)
446         {
447             word subsetName = origSurf.pointSubsetName(id);
448             origSurf.pointsInSubset(id, subsetAddr);
450             fileName fn = outPrefix / "pointSubsets" / subsetName + ".vtp";
452             writePointsToVTK
453             (
454                 fn,
455                 subsetName,
456                 points,
457                 subsetAddr
458             );
460             xmlTag& tag = xmlBlock.addChild("DataSet");
461             tag.addAttribute("index", Foam::name(id));
462             tag.addAttribute("name", subsetName);
463             tag.addAttribute("file", fn);
464         }
465     }
467     // Write edge subsets
468     {
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)
479         {
480             word subsetName = origSurf.edgeSubsetName(id);
481             origSurf.edgesInSubset(id, subsetAddr);
483             fileName fn = outPrefix / "edgeSubsets" / subsetName + ".vtp";
485             writeEdgesToVTK
486             (
487                 fn,
488                 subsetName,
489                 points,
490                 edges,
491                 subsetAddr
492             );
494             xmlTag& tag = xmlBlock.addChild("DataSet");
495             tag.addAttribute("index", Foam::name(id));
496             tag.addAttribute("name", subsetName);
497             tag.addAttribute("file", fn);
498         }
499     }
501     // Write facet subsets
502     {
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)
513         {
514             word subsetName = origSurf.facetSubsetName(id);
515             origSurf.facetsInSubset(id, subsetAddr);
517             fileName fn = outPrefix / "faceSubsets"  / subsetName + ".vtp";
519             writeFacetsToVTK
520             (
521                 fn,
522                 subsetName,
523                 points,
524                 facets,
525                 subsetAddr
526             );
528             xmlTag& tag = xmlBlock.addChild("DataSet");
529             tag.addAttribute("index", Foam::name(id));
530             tag.addAttribute("name", subsetName);
531             tag.addAttribute("file", fn);
532         }
533     }
535     OFstream os(outPrefix + ".vtm");
536     os << xmlRoot << endl;
538     Info << "Created " << outPrefix + ".vtm" << endl;
540     Info << "End\n" << endl;
542     return 0;
545 // ************************************************************************* //