vtkUnstructuredReader.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ========= |
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4 \\ / O peration |
5 \\ / A nd | www.openfoam.com
6 \\/ M anipulation |
7-------------------------------------------------------------------------------
8 Copyright (C) 2012-2016 OpenFOAM Foundation
9 Copyright (C) 2018-2021 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
30#include "labelIOField.H"
31#include "scalarIOField.H"
32#include "stringIOList.H"
33#include "cellModel.H"
34#include "vectorIOField.H"
35#include "triPointRef.H"
36#include "stringOps.H"
37
38/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
39
40namespace Foam
41{
43}
44
45const Foam::Enum
46<
48>
50({
51 { vtkDataType::VTK_INT, "int" },
52 // Not yet required: { vtkDataType::VTK_INT64, "vtktypeint64" },
53 { vtkDataType::VTK_UINT, "unsigned_int" },
54 { vtkDataType::VTK_LONG, "long" },
55 { vtkDataType::VTK_ULONG, "unsigned_long" },
56 { vtkDataType::VTK_FLOAT, "float" },
57 { vtkDataType::VTK_DOUBLE, "double" },
58 { vtkDataType::VTK_STRING, "string" },
59 { vtkDataType::VTK_ID, "vtkIdType" },
60});
61
62
63const Foam::Enum
64<
66>
68({
69 { vtkDataSetType::VTK_FIELD, "FIELD" },
70 { vtkDataSetType::VTK_SCALARS, "SCALARS" },
71 { vtkDataSetType::VTK_VECTORS, "VECTORS" },
72});
73
74
75const Foam::Enum
76<
78>
80({
81 { parseMode::NOMODE, "NOMODE" },
82 { parseMode::UNSTRUCTURED_GRID, "UNSTRUCTURED_GRID" },
83 { parseMode::POLYDATA, "POLYDATA" },
84 { parseMode::CELL_DATA, "CELL_DATA" },
85 { parseMode::POINT_DATA, "POINT_DATA" },
86});
87
88
89// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
90
91namespace Foam
92{
93
94// Read N elements into List
95template<class T>
96static inline void readBlock(Istream& is, const label n, List<T>& list)
97{
98 list.resize(n);
99 for (T& val : list)
100 {
101 is >> val;
102 }
103}
104
105} // End namespace Foam
106
107
108// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
109
110void Foam::vtkUnstructuredReader::warnUnhandledType
111(
112 const Istream& is,
113 const label type,
114 labelHashSet& warningGiven
115)
116{
117 if (warningGiven.insert(type))
118 {
120 << "Skipping unknown cell type " << type << nl;
121 }
122}
123
124
125// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
126
127void Foam::vtkUnstructuredReader::readOffsetsConnectivity
128(
129 ISstream& is,
130 const char* entryName,
131 const label nOffsets,
132 labelList& offsets,
133 const label nConnectivity,
134 labelList& connectivity
135)
136{
137 token tok;
138
139 is.read(tok);
140 if (!tok.isWord("OFFSETS"))
141 {
143 << "Expected OFFSETS for " << entryName
144 << ", found "
145 << tok.info() << nl
146 << exit(FatalIOError);
147 }
148 is.getLine(nullptr); // Consume rest of line
149 readBlock(is, nOffsets, offsets);
150
151 is.read(tok);
152 if (!tok.isWord("CONNECTIVITY"))
153 {
155 << "Expected CONNECTIVITY for " << entryName
156 << ", found " << tok.info() << nl
157 << exit(FatalIOError);
158 }
159 is.getLine(nullptr); // Consume rest of line
160 readBlock(is, nConnectivity, connectivity);
161}
162
163
164void Foam::vtkUnstructuredReader::extractCells
165(
166 const Istream& is,
167 const labelUList& cellTypes,
168 const labelUList& elemOffsets,
169 const labelUList& elemVerts
170)
171{
172 const cellModel& hex = cellModel::ref(cellModel::HEX);
173 const cellModel& prism = cellModel::ref(cellModel::PRISM);
174 const cellModel& pyr = cellModel::ref(cellModel::PYR);
175 const cellModel& tet = cellModel::ref(cellModel::TET);
176
177 // Pass 0: sizing
178 label nCells = 0, nFaces = 0, nLines = 0;
179 forAll(cellTypes, elemi)
180 {
181 switch (cellTypes[elemi])
182 {
185 {
186 ++nLines;
187 }
188 break;
189
193 {
194 ++nFaces;
195 }
196 break;
197
202 {
203 ++nCells;
204 }
205 break;
206
207 default:
208 break;
209 }
210 }
211
212 label celli = cells_.size();
213 cells_.resize(celli + nCells);
214 cellMap_.resize(cells_.size(), -1);
215
216 label facei = faces_.size();
217 faces_.resize(facei + nFaces);
218 faceMap_.resize(faces_.size(), -1);
219
220 label linei = lines_.size();
221 lines_.resize(linei + nLines);
222 lineMap_.resize(lines_.size(), -1);
223
224 // General scratch space for cell vertices
225 labelList cellPoints(16);
226
227 label dataIndex = 0; // Addressing into vertices stream
228
229 // To mark whether unhandled type has been visited.
230 labelHashSet warningGiven;
231
232
233 forAll(cellTypes, elemi)
234 {
235 // Vertices per element - from offsets or embedded size
236 const label nVerts =
237 (
238 elemOffsets.empty()
239 ? elemVerts[dataIndex++]
240 : (elemOffsets[elemi+1] - elemOffsets[elemi])
241 );
242
243 // The addresseed vertices
244 const labelSubList verts(elemVerts, nVerts, dataIndex);
245 dataIndex += nVerts;
246
247 switch (cellTypes[elemi])
248 {
250 {
251 warnUnhandledType(is, cellTypes[elemi], warningGiven);
252 if (nVerts != 1)
253 {
255 << "Expected size 1 for VTK_VERTEX, found "
256 << nVerts << nl
257 << exit(FatalIOError);
258 }
259 }
260 break;
261
263 {
264 warnUnhandledType(is, cellTypes[elemi], warningGiven);
265 }
266 break;
267
269 {
270 if (nVerts != 2)
271 {
273 << "Expected size 2 for VTK_LINE, found "
274 << nVerts << nl
275 << exit(FatalIOError);
276 }
277 lineMap_[linei] = elemi;
278
279 // Same vertex ordering
280 lines_[linei++] = verts;
281 }
282 break;
283
285 {
286 lineMap_[linei] = elemi;
287
288 // Same vertex ordering
289 lines_[linei++] = verts;
290 }
291 break;
292
294 {
295 if (nVerts != 3)
296 {
298 << "Expected size 3 for VTK_TRIANGLE, found "
299 << nVerts << nl
300 << exit(FatalIOError);
301 }
302 faceMap_[facei] = elemi;
303
304 // Same vertex ordering
305 static_cast<labelList&>(faces_[facei++]) = verts;
306 }
307 break;
308
310 {
311 if (nVerts != 4)
312 {
314 << "Expected size 4 for VTK_QUAD, found "
315 << nVerts << nl
316 << exit(FatalIOError);
317 }
318 faceMap_[facei] = elemi;
319
320 // Same vertex ordering
321 static_cast<labelList&>(faces_[facei++]) = verts;
322 }
323 break;
324
326 {
327 faceMap_[facei] = elemi;
328
329 // Same vertex ordering
330 static_cast<labelList&>(faces_[facei++]) = verts;
331 }
332 break;
333
335 {
336 if (nVerts != 4)
337 {
339 << "Expected size 4 for VTK_TETRA, found "
340 << nVerts << nl
341 << exit(FatalIOError);
342 }
343 cellMap_[celli] = elemi;
344
345 // Same vertex ordering
346 cells_[celli++].reset(tet, verts, true);
347 }
348 break;
349
351 {
352 if (nVerts != 5)
353 {
355 << "Expected size 5 for VTK_PYRAMID, found "
356 << nVerts << nl
357 << exit(FatalIOError);
358 }
359 cellMap_[celli] = elemi;
360
361 // Same vertex ordering
362 cells_[celli++].reset(pyr, verts, true);
363 }
364 break;
365
367 {
368 if (nVerts != 6)
369 {
371 << "Expected size 6 for VTK_WEDGE, found "
372 << nVerts << nl
373 << exit(FatalIOError);
374 }
375 cellMap_[celli] = elemi;
376
377 // VTK_WEDGE triangles point outwards (swap 1<->2, 4<->5)
378 labelSubList shape(cellPoints, nVerts);
379 shape[0] = verts[0];
380 shape[2] = verts[1];
381 shape[1] = verts[2];
382 shape[3] = verts[3];
383 shape[5] = verts[4];
384 shape[4] = verts[5];
385
386 cells_[celli++].reset(prism, shape, true);
387 }
388 break;
389
391 {
392 if (nVerts != 8)
393 {
395 << "Expected size 8 for VTK_HEXAHEDRON, found "
396 << nVerts << nl
397 << exit(FatalIOError);
398 }
399 cellMap_[celli] = elemi;
400
401 // Same vertex ordering
402 cells_[celli++].reset(hex, verts, true);
403 }
404 break;
405
406 default:
407 {
408 warnUnhandledType(is, cellTypes[elemi], warningGiven);
409 }
410 break;
411 }
412 }
413
415 << "Read"
416 << " cells:" << celli
417 << " faces:" << facei
418 << " lines:" << linei
419 << nl;
420
421 cells_.resize(celli);
422 cellMap_.resize(celli);
423
424 faces_.resize(facei);
425 faceMap_.resize(facei);
426
427 lines_.resize(linei);
428 lineMap_.resize(linei);
429}
430
431
432void Foam::vtkUnstructuredReader::readField
433(
434 ISstream& inFile,
435 objectRegistry& obj,
436 const word& arrayName,
437 const word& dataType,
438 const label size
439) const
440{
441 if (vtkDataTypeNames.found(dataType))
442 {
443 switch (vtkDataTypeNames[dataType])
444 {
445 case VTK_INT:
446 case VTK_INT64:
447 case VTK_UINT:
448 case VTK_LONG:
449 case VTK_ULONG:
450 case VTK_ID:
451 {
452 auto fieldVals = autoPtr<labelIOField>::New
453 (
454 IOobject(arrayName, "", obj),
455 size
456 );
457 readBlock(inFile, fieldVals().size(), fieldVals());
458 regIOobject::store(fieldVals);
459 }
460 break;
461
462 case VTK_FLOAT:
463 case VTK_DOUBLE:
464 {
465 auto fieldVals = autoPtr<scalarIOField>::New
466 (
467 IOobject(arrayName, "", obj),
468 size
469 );
470 readBlock(inFile, fieldVals().size(), fieldVals());
471 regIOobject::store(fieldVals);
472 }
473 break;
474
475 case VTK_STRING:
476 {
478 << "Reading strings:" << size << nl;
479
480 auto fieldVals = autoPtr<stringIOList>::New
481 (
482 IOobject(arrayName, "", obj),
483 size
484 );
485 // Consume current line.
486 inFile.getLine(fieldVals()[0]);
487
488 // Read without parsing
489 for (string& s : fieldVals())
490 {
491 inFile.getLine(s);
492 }
493 regIOobject::store(fieldVals);
494 }
495 break;
496
497 default:
498 {
499 IOWarningInFunction(inFile)
500 << "Unhandled type " << dataType << nl
501 << "Skipping " << size
502 << " words." << nl;
503 scalarField fieldVals;
504 readBlock(inFile, size, fieldVals);
505 }
506 break;
507 }
508 }
509 else
510 {
511 IOWarningInFunction(inFile)
512 << "Unhandled type " << dataType << nl
513 << "Skipping " << size
514 << " words." << nl;
515 scalarField fieldVals;
516 readBlock(inFile, size, fieldVals);
517 }
518}
519
520
521Foam::wordList Foam::vtkUnstructuredReader::readFieldArray
522(
523 ISstream& inFile,
524 objectRegistry& obj,
525 const label wantedSize
526) const
527{
528 DynamicList<word> fields;
529
530 word dataName(inFile);
531
533 << "dataName:" << dataName << nl;
534
535 label numArrays(readLabel(inFile));
536 if (debug)
537 {
538 Pout<< "numArrays:" << numArrays << nl;
539 }
540 for (label i = 0; i < numArrays; i++)
541 {
542 word arrayName(inFile);
543 label numComp(readLabel(inFile));
544 label numTuples(readLabel(inFile));
545 word dataType(inFile);
546
548 << "Reading field " << arrayName
549 << " of " << numTuples << " tuples of rank " << numComp << nl;
550
551 if (wantedSize != -1 && numTuples != wantedSize)
552 {
554 << "Expected " << wantedSize << " tuples but only have "
555 << numTuples << nl
556 << exit(FatalIOError);
557 }
558
559 readField
560 (
561 inFile,
562 obj,
563 arrayName,
564 dataType,
565 numTuples*numComp
566 );
567 fields.append(arrayName);
568 }
569 return fields.shrink();
570}
571
572
573Foam::objectRegistry& Foam::vtkUnstructuredReader::selectRegistry
574(
575 const parseMode readMode
576)
577{
578 if (readMode == CELL_DATA)
579 {
580 return cellData_;
581 }
582 else if (readMode == POINT_DATA)
583 {
584 return pointData_;
585 }
586
587 return otherData_;
588}
589
590
591// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
592
594(
595 const objectRegistry& obr,
596 ISstream& is
597)
598:
599 version_(2.0),
600 cellData_(IOobject("cellData", obr)),
601 pointData_(IOobject("pointData", obr)),
602 otherData_(IOobject("otherData", obr))
603{
604 read(is);
605}
606
607
609{
610 inFile.getLine(header_);
611 DebugInfo<< "Header : " << header_ << nl;
612
613 // Extract version number from "# vtk DataFile Version 5.1"
614 const auto split = stringOps::splitSpace(header_);
615 if (split.size() >= 4 && split[split.size() - 2] == "Version")
616 {
617 float ver(0);
618 if (readFloat(split[split.size() - 1], ver))
619 {
620 version_ = ver;
621 DebugInfo<< "Version : " << version_ << nl;
622 }
623 }
624
625 inFile.getLine(title_);
626 DebugInfo<< "Title : " << title_ << nl;
627
628 inFile.getLine(dataType_);
629 DebugInfo<< "dataType : " << dataType_ << nl;
630
631 if (dataType_ == "BINARY")
632 {
634 << "Binary reading not supported" << nl
635 << exit(FatalIOError);
636 }
637
638 parseMode readMode = NOMODE;
639 label wantedSize = -1;
640
641
642 // Intermediate storage for vertices of cells.
643 labelList cellOffsets, cellVerts;
644
645 token tok;
646
647 while (inFile.read(tok).good() && tok.isWord())
648 {
649 const word tag = tok.wordToken();
650
652 << "line:" << inFile.lineNumber()
653 << " tag:" << tag << nl;
654
655 if (tag == "DATASET")
656 {
657 word geomType(inFile);
658 DebugInfo<< "geomType : " << geomType << nl;
659
660 readMode = parseModeNames[geomType];
661 wantedSize = -1;
662 }
663 else if (tag == "POINTS")
664 {
665 const label nPoints(readLabel(inFile));
666 points_.resize(nPoints);
667
669 << "Reading " << nPoints << " coordinates" << nl;
670
671 word primitiveTag(inFile);
672 if (primitiveTag != "float" && primitiveTag != "double")
673 {
675 << "Expected 'float' entry, found "
676 << primitiveTag << nl
677 << exit(FatalIOError);
678 }
679 for (point& p : points_)
680 {
681 inFile >> p.x() >> p.y() >> p.z();
682 }
683 }
684 else if (tag == "CELLS")
685 {
686 label nCells(readLabel(inFile));
687 const label nNumbers(readLabel(inFile));
688
689 if (version_ < 5.0)
690 {
691 // VTK 4.2 and earlier (single-block)
693 << "Reading " << nCells
694 << " cells/faces (single block)" << nl;
695
696 cellOffsets.clear();
697 readBlock(inFile, nNumbers, cellVerts);
698 }
699 else
700 {
701 // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
702
703 const label nOffsets(nCells);
704 --nCells;
705
707 << "Reading offsets/connectivity for "
708 << nCells << " cells/faces" << nl;
709
710 readOffsetsConnectivity
711 (
712 inFile,
713 "CELLS",
714 nOffsets, cellOffsets,
715 nNumbers, cellVerts
716 );
717 }
718 }
719 else if (tag == "CELL_TYPES")
720 {
721 const label nCellTypes(readLabel(inFile));
722
724 readBlock(inFile, nCellTypes, cellTypes);
725
726 if (!cellTypes.empty() && cellVerts.empty())
727 {
729 << "Found " << cellTypes.size()
730 << " cellTypes but no cells." << nl
731 << exit(FatalIOError);
732 }
733
734 extractCells(inFile, cellTypes, cellOffsets, cellVerts);
735 cellOffsets.clear();
736 cellVerts.clear();
737 }
738 else if (tag == "LINES")
739 {
740 label nLines(readLabel(inFile));
741 const label nNumbers(readLabel(inFile));
742
743 labelList elemOffsets, elemVerts;
744
745 if (version_ < 5.0)
746 {
747 // VTK 4.2 and earlier (single-block)
749 << "Reading " << nLines
750 << " lines (single block)" << nl;
751
752 readBlock(inFile, nNumbers, elemVerts);
753 }
754 else
755 {
756 // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
757
758 const label nOffsets(nLines);
759 --nLines;
760
762 << "Reading offsets/connectivity for "
763 << nLines << " lines" << nl;
764
765 readOffsetsConnectivity
766 (
767 inFile,
768 "LINES",
769 nOffsets, elemOffsets,
770 nNumbers, elemVerts
771 );
772 }
773
774 // Append into lines
775 label linei = lines_.size();
776 lines_.resize(linei+nLines);
777 lineMap_.resize(lines_.size());
778
779 label dataIndex = 0;
780 for (label i = 0; i < nLines; i++)
781 {
782 const label nVerts =
783 (
784 elemOffsets.empty()
785 ? elemVerts[dataIndex++]
786 : (elemOffsets[i+1] - elemOffsets[i])
787 );
788 const labelSubList verts(elemVerts, nVerts, dataIndex);
789 dataIndex += nVerts;
790
791 lineMap_[linei] = linei;
792 lines_[linei++] = verts;
793 }
794 }
795 else if (tag == "POLYGONS")
796 {
797 label nFaces(readLabel(inFile));
798 const label nNumbers(readLabel(inFile));
799
800 labelList elemOffsets, elemVerts;
801
802 if (version_ < 5.0)
803 {
804 // VTK 4.2 and earlier (single-block)
806 << "Reading " << nFaces
807 << " faces (single block)" << nl;
808
809 readBlock(inFile, nNumbers, elemVerts);
810 }
811 else
812 {
813 // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
814
815 const label nOffsets(nFaces);
816 --nFaces;
817
819 << "Reading offsets/connectivity for "
820 << nFaces << " faces" << nl;
821
822 readOffsetsConnectivity
823 (
824 inFile,
825 "POLYGONS",
826 nOffsets, elemOffsets,
827 nNumbers, elemVerts
828 );
829 }
830
831 // Append into faces
832 label facei = faces_.size();
833 faces_.resize(facei+nFaces);
834 faceMap_.resize(faces_.size());
835
836 label dataIndex = 0;
837 for (label i = 0; i < nFaces; ++i)
838 {
839 const label nVerts =
840 (
841 elemOffsets.empty()
842 ? elemVerts[dataIndex++]
843 : (elemOffsets[i+1] - elemOffsets[i])
844 );
845 const labelSubList verts(elemVerts, nVerts, dataIndex);
846 dataIndex += nVerts;
847
848 faceMap_[facei] = facei;
849 static_cast<labelList&>(faces_[facei++]) = verts;
850 }
851 }
852 else if (tag == "POINT_DATA")
853 {
854 // 'POINT_DATA 24'
855 readMode = POINT_DATA;
856 wantedSize = points_.size();
857
858 label nPoints(readLabel(inFile));
859 if (nPoints != wantedSize)
860 {
862 << "Reading POINT_DATA : expected " << wantedSize
863 << " but read " << nPoints << nl
864 << exit(FatalIOError);
865 }
866 }
867 else if (tag == "CELL_DATA")
868 {
869 readMode = CELL_DATA;
870 wantedSize = cells_.size()+faces_.size()+lines_.size();
871
872 label nCells(readLabel(inFile));
873 if (nCells != wantedSize)
874 {
876 << "Reading CELL_DATA : expected "
877 << wantedSize
878 << " but read " << nCells << nl
879 << exit(FatalIOError);
880 }
881 }
882 else if (tag == "FIELD")
883 {
884 // wantedSize already set according to type we expected to read.
885 readFieldArray(inFile, selectRegistry(readMode), wantedSize);
886 }
887 else if (tag == "SCALARS")
888 {
889 string line;
890 inFile.getLine(line);
891 IStringStream is(line);
892 word dataName(is);
893 word dataType(is);
894 //label numComp(readLabel(inFile));
895
897 << "Reading scalar " << dataName
898 << " of type " << dataType
899 << " from lookup table" << nl;
900
901 word lookupTableTag(inFile);
902 if (lookupTableTag != "LOOKUP_TABLE")
903 {
905 << "Expected tag LOOKUP_TABLE but read "
906 << lookupTableTag << nl
907 << exit(FatalIOError);
908 }
909
910 word lookupTableName(inFile);
911
912 readField
913 (
914 inFile,
915 selectRegistry(readMode),
916 dataName,
917 dataType,
918 wantedSize//*numComp
919 );
920 }
921 else if (tag == "VECTORS" || tag == "NORMALS")
922 {
923 // 'NORMALS Normals float'
924 string line;
925 inFile.getLine(line);
926 IStringStream is(line);
927 word dataName(is);
928 word dataType(is);
930 << "Reading vector " << dataName
931 << " of type " << dataType << nl;
932
933 objectRegistry& reg = selectRegistry(readMode);
934
935 readField
936 (
937 inFile,
938 reg,
939 dataName,
940 dataType,
941 3*wantedSize
942 );
943
944 if
945 (
946 vtkDataTypeNames[dataType] == VTK_FLOAT
947 || vtkDataTypeNames[dataType] == VTK_DOUBLE
948 )
949 {
950 objectRegistry::iterator iter = reg.find(dataName);
951 scalarField s(*dynamic_cast<const scalarField*>(iter()));
952 reg.erase(iter);
953 auto fieldVals = autoPtr<vectorIOField>::New
954 (
955 IOobject(dataName, "", reg),
956 s.size()/3
957 );
958
959 label elemI = 0;
960 for (vector& val : fieldVals())
961 {
962 val.x() = s[elemI++];
963 val.y() = s[elemI++];
964 val.z() = s[elemI++];
965 }
966 regIOobject::store(fieldVals);
967 }
968 }
969 else if (tag == "TEXTURE_COORDINATES")
970 {
971 // 'TEXTURE_COORDINATES TCoords 2 float'
972 string line;
973 inFile.getLine(line);
974 IStringStream is(line);
975 word dataName(is); //"Tcoords"
976 label dim(readLabel(is));
977 word dataType(is);
978
980 << "Reading texture coords " << dataName
981 << " dimension " << dim
982 << " of type " << dataType << nl;
983
984 scalarField coords(dim*points_.size());
985 readBlock(inFile, coords.size(), coords);
986 }
987 else if (tag == "TRIANGLE_STRIPS")
988 {
989 label nStrips(readLabel(inFile));
990 const label nNumbers(readLabel(inFile));
991
992 labelList elemOffsets, elemVerts;
993
994 // Total number of faces in strips
995 label nFaces = 0;
996
997 if (version_ < 5.0)
998 {
999 // VTK 4.2 and earlier (single-block)
1000 DebugInfo
1001 << "Reading " << nStrips
1002 << " strips (single block)" << nl;
1003
1004 readBlock(inFile, nNumbers, elemVerts);
1005
1006 // Count number of faces (triangles)
1007 {
1008 label dataIndex = 0;
1009 for (label i = 0; i < nStrips; ++i)
1010 {
1011 const label nVerts = elemVerts[dataIndex++];
1012 nFaces += nVerts-2;
1013 dataIndex += nVerts;
1014 }
1015 }
1016 }
1017 else
1018 {
1019 // VTK 5.0 and later (OFFSETS and CONNECTIVITY)
1020
1021 const label nOffsets(nStrips);
1022 --nStrips;
1023
1024 DebugInfo
1025 << "Reading offsets/connectivity for "
1026 << nStrips << " triangle strips." << nl;
1027
1028 readOffsetsConnectivity
1029 (
1030 inFile,
1031 "TRIANGLE_STRIPS",
1032 nOffsets, elemOffsets,
1033 nNumbers, elemVerts
1034 );
1035
1036 // Count number of faces (triangles)
1037 for (label i = 0; i < nStrips; ++i)
1038 {
1039 const label nVerts = (elemOffsets[i+1] - elemOffsets[i]);
1040 nFaces += nVerts-2;
1041 }
1042 }
1043
1044 // Append into faces
1045 label facei = faces_.size();
1046 faces_.resize(facei+nFaces);
1047 faceMap_.resize(faces_.size());
1048
1049 label dataIndex = 0;
1050 for (label i = 0; i < nStrips; ++i)
1051 {
1052 const label nVerts =
1053 (
1054 elemOffsets.empty()
1055 ? elemVerts[dataIndex++]
1056 : (elemOffsets[i+1] - elemOffsets[i])
1057 );
1058 const label nTris = nVerts-2;
1059
1060 // Advance before the first triangle
1061 if (nTris > 0)
1062 {
1063 dataIndex += 2;
1064 }
1065
1066 for (label triI = 0; triI < nTris; ++triI)
1067 {
1068 faceMap_[facei] = facei;
1069 face& f = faces_[facei++];
1070
1071 f.resize(3);
1072
1073 // NOTE: not clear if the orientation is correct
1074 if ((triI % 2) == 0)
1075 {
1076 // Even (eg, 0-1-2, 2-3-4)
1077 f[0] = elemVerts[dataIndex-2];
1078 f[1] = elemVerts[dataIndex-1];
1079 }
1080 else
1081 {
1082 // Odd (eg, 2-1-3, 4-3-5)
1083 f[0] = elemVerts[dataIndex-1];
1084 f[1] = elemVerts[dataIndex-2];
1085 }
1086 f[2] = elemVerts[dataIndex++];
1087 }
1088 }
1089 }
1090 else if (tag == "METADATA")
1091 {
1092 word infoTag(inFile);
1093 if (infoTag != "INFORMATION")
1094 {
1096 << "Unsupported tag "
1097 << infoTag << nl
1098 << exit(FatalIOError);
1099 }
1100 label nInfo(readLabel(inFile));
1101 DebugInfo
1102 << "Ignoring " << nInfo << " metadata information." << nl;
1103
1104 // Consume rest of line
1105 inFile.getLine(nullptr);
1106 for (label i = 0; i < 2*nInfo; i++)
1107 {
1108 inFile.getLine(nullptr);
1109 }
1110 }
1111 else
1112 {
1114 << "Unsupported tag "
1115 << tag << nl
1116 << exit(FatalIOError);
1117 }
1118 }
1119
1120
1121 // There is some problem with orientation of prisms - the point
1122 // ordering seems to be different for some exports (e.g. of cgns)
1123 {
1124 const cellModel& prism = cellModel::ref(cellModel::PRISM);
1125
1126 label nSwapped = 0;
1127
1128 for (cellShape& shape : cells_)
1129 {
1130 if (shape.model() == prism)
1131 {
1132 const triPointRef bottom
1133 (
1134 points_[shape[0]],
1135 points_[shape[1]],
1136 points_[shape[2]]
1137 );
1138 const triPointRef top
1139 (
1140 points_[shape[3]],
1141 points_[shape[4]],
1142 points_[shape[5]]
1143 );
1144
1145 const point bottomCc(bottom.centre());
1146 const vector bottomNormal(bottom.areaNormal());
1147 const point topCc(top.centre());
1148
1149 if (((topCc - bottomCc) & bottomNormal) < 0)
1150 {
1151 // Flip top and bottom
1152 std::swap(shape[0], shape[3]);
1153 std::swap(shape[1], shape[4]);
1154 std::swap(shape[2], shape[5]);
1155 ++nSwapped;
1156 }
1157 }
1158 }
1159 if (nSwapped)
1160 {
1161 WarningInFunction << "Swapped " << nSwapped
1162 << " prismatic cells" << nl;
1163 }
1164 }
1165
1166 if (debug)
1167 {
1168 Info<< "Read points:" << points_.size()
1169 << " cells:" << cells_.size()
1170 << " faces:" << faces_.size()
1171 << " lines:" << lines_.size()
1172 << nl << nl;
1173
1174 Info<< "Cell fields:" << nl;
1175 printFieldStats<vectorIOField>(cellData_);
1176 printFieldStats<scalarIOField>(cellData_);
1177 printFieldStats<labelIOField>(cellData_);
1178 printFieldStats<stringIOList>(cellData_);
1179 Info<< nl << nl;
1180
1181 Info<< "Point fields:" << nl;
1182 printFieldStats<vectorIOField>(pointData_);
1183 printFieldStats<scalarIOField>(pointData_);
1184 printFieldStats<labelIOField>(pointData_);
1185 printFieldStats<stringIOList>(pointData_);
1186 Info<< nl << nl;
1187
1188 Info<< "Other fields:" << nl;
1189 printFieldStats<vectorIOField>(otherData_);
1190 printFieldStats<scalarIOField>(otherData_);
1191 printFieldStats<labelIOField>(otherData_);
1192 printFieldStats<stringIOList>(otherData_);
1193 }
1194}
1195
1196
1197// ************************************************************************* //
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:39
label n
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: Enum.H:61
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:318
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:58
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:76
virtual Istream & read(token &t)
Return next token from stream.
Definition: ISstream.C:530
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
virtual bool read()
Re-read model coefficients if they have changed.
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
@ PRISM
prism
Definition: cellModel.H:83
reference ref() const
A reference to the entry (Error if not found)
Definition: dictionary.H:225
Registry of regIOobjects.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
Reader for vtk UNSTRUCTURED_GRID legacy files. Supports single CELLS, POINTS etc. entry only.
static const Enum< parseMode > parseModeNames
static const Enum< vtkDataSetType > vtkDataSetTypeNames
vtkDataSetType
Enumeration defining the vtk dataset types.
static const Enum< vtkDataType > vtkDataTypeNames
parseMode
Enumeration defining the parse mode - type of data being read.
vtkDataType
Enumeration defining the vtk data types.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
volScalarField & p
const volScalarField & T
const cellModel & hex
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
const labelList nFaces(UPstream::listGatherValues< label >(aMesh.nFaces()))
label nPoints
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define DebugInfo
Report an information message using Foam::Info.
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
Foam::SubStrings< StringType > splitSpace(const StringType &str)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
@ CELL_DATA
"CellData"
@ VTK_POLY_LINE
Definition: foamVtkCore.H:95
@ VTK_TRIANGLE
Definition: foamVtkCore.H:96
@ VTK_HEXAHEDRON
Definition: foamVtkCore.H:103
@ VTK_POLY_VERTEX
Definition: foamVtkCore.H:93
Namespace for OpenFOAM.
List< label > labelList
A List of labels.
Definition: List.H:66
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:66
messageStream Info
Information stream (stdout output on master, null elsewhere)
vector point
Point is a vector.
Definition: point.H:43
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
triangle< point, const point & > triPointRef
A triangle using referred points.
Definition: triangle.H:71
SubList< label > labelSubList
A SubList of labels.
Definition: SubList.H:59
IOerror FatalIOError
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition: HashSet.H:85
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
UList< label > labelUList
A UList of labels.
Definition: UList.H:85
static void readBlock(Istream &is, const label n, List< T > &list)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
const labelList & cellTypes
Definition: setCellMask.H:33
multivariateSurfaceInterpolationScheme< scalar >::fieldTable fields
Definition: createFields.H:97
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333