ITK  6.0.0
Insight Toolkit
itkVTKPolyDataMeshIO.h
Go to the documentation of this file.
1/*=========================================================================
2 *
3 * Copyright NumFOCUS
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * https://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18#ifndef itkVTKPolyDataMeshIO_h
19#define itkVTKPolyDataMeshIO_h
20#include "ITKIOMeshVTKExport.h"
21
22#include "itkByteSwapper.h"
23#include "itkMetaDataObject.h"
24#include "itkMeshIOBase.h"
25#include "itkVectorContainer.h"
26#include "itkNumberToString.h"
28
29#include <fstream>
30#include <vector>
31
32namespace itk
33{
42class ITKIOMeshVTK_EXPORT VTKPolyDataMeshIO : public MeshIOBase
43{
44public:
45 ITK_DISALLOW_COPY_AND_MOVE(VTKPolyDataMeshIO);
46
52
54
55 using StringType = std::string;
56 using StringVectorType = std::vector<StringType>;
57 using StringStreamType = std::stringstream;
58 using PointIdVector = std::vector<SizeValueType>;
61
63 itkNewMacro(Self);
64
66 itkOverrideGetNameOfClassMacro(VTKPolyDataMeshIO);
67
75 bool
76 CanReadFile(const char * fileName) override;
77
79 void
81
83 void
84 ReadPoints(void * buffer) override;
85
86 void
87 ReadCells(void * buffer) override;
88
89 void
90 ReadPointData(void * buffer) override;
91
92 void
93 ReadCellData(void * buffer) override;
94
95 /*-------- This part of the interfaces deals with writing data. ----- */
101 bool
102 CanWriteFile(const char * fileName) override;
103
105 void
107
110 void
111 WritePoints(void * buffer) override;
112
113 void
114 WriteCells(void * buffer) override;
115
116 void
117 WritePointData(void * buffer) override;
118
119 void
120 WriteCellData(void * buffer) override;
121
122 void
123 Write() override;
124
125protected:
128
129 void
130 PrintSelf(std::ostream & os, Indent indent) const override;
131
132 // Internal function to get next line from a given file (*.vtk)
133 int
134 GetNextLine(std::ifstream & ifs, std::string & line, bool lowerCase = true, SizeValueType count = 0);
135
136 template <typename T>
137 void
139 {
140 unsigned int numberOfVertices = 0;
141 unsigned int numberOfVertexIndices = 0;
142 unsigned int numberOfLines = 0;
143 SizeValueType numberOfLineIndices = 0;
144 unsigned int numberOfPolygons = 0;
145 unsigned int numberOfPolygonIndices = 0;
146
147 SizeValueType index = 0;
148
149 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
150 {
151 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
152 auto nn = static_cast<unsigned int>(buffer[index++]);
153 switch (cellType)
154 {
156 ++numberOfVertices;
157 numberOfVertexIndices += nn + 1;
158 break;
160 ++numberOfLines;
161 numberOfLineIndices += nn + 1;
162 break;
164 ++numberOfLines;
165 numberOfLineIndices += nn + 1;
166 break;
168 ++numberOfPolygons;
169 numberOfPolygonIndices += nn + 1;
170 break;
172 ++numberOfPolygons;
173 numberOfPolygonIndices += nn + 1;
174 break;
176 ++numberOfPolygons;
177 numberOfPolygonIndices += nn + 1;
178 break;
179 default:
180 itkExceptionMacro("Currently we dont support this cell type");
181 }
182
183 index += nn;
184 }
185
186 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
187 EncapsulateMetaData<unsigned int>(metaDic, "numberOfVertices", numberOfVertices);
188 EncapsulateMetaData<unsigned int>(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
189 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
190 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLineIndices", numberOfLineIndices);
191 EncapsulateMetaData<unsigned int>(metaDic, "numberOfPolygons", numberOfPolygons);
192 EncapsulateMetaData<unsigned int>(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
193 return;
194 }
195
196 template <typename T>
197 void
198 ReadPointsBufferAsASCII(std::ifstream & inputFile, T * buffer)
199 {
200 std::string line;
201
202 while (!inputFile.eof())
203 {
204 std::getline(inputFile, line, '\n');
205
206 if (line.find("POINTS") != std::string::npos)
207 {
209 Self::ReadComponentsAsASCII(inputFile, buffer, this->m_NumberOfPoints * this->m_PointDimension);
210 }
211 }
212 }
213
214 template <typename T>
215 void
216 ReadPointsBufferAsBINARY(std::ifstream & inputFile, T * buffer)
217 {
218 std::string line;
219
220 while (!inputFile.eof())
221 {
222 std::getline(inputFile, line, '\n');
223
224 if (line.find("POINTS") != std::string::npos)
225 {
227 SizeValueType numberOfComponents = this->m_NumberOfPoints * this->m_PointDimension;
228 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
230 {
231 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
232 }
233 }
234 }
235 }
238 void
239 ReadCellsBufferAsASCII(std::ifstream & inputFile, void * buffer);
240
241 void
242 ReadCellsBufferAsBINARY(std::ifstream & inputFile, void * buffer);
243
244 template <typename T>
245 void
246 ReadPointDataBufferAsASCII(std::ifstream & inputFile, T * buffer)
247 {
248 StringType line;
249
250 while (!inputFile.eof())
251 {
252 std::getline(inputFile, line, '\n');
253 if (line.find("POINT_DATA") != std::string::npos)
254 {
255 if (!inputFile.eof())
256 {
257 std::getline(inputFile, line, '\n');
258 }
259 else
260 {
261 itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
262 }
263
265 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
266 {
267 if (!inputFile.eof())
268 {
269 std::getline(inputFile, line, '\n');
270 if (line.find("LOOKUP_TABLE") == std::string::npos)
271 {
272 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
273 }
274 }
275 else
276 {
277 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
278 }
279 }
283 Self::ReadComponentsAsASCII(
284 inputFile, buffer, this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents);
285 }
286 }
287 }
288
289 template <typename T>
290 void
291 ReadPointDataBufferAsBINARY(std::ifstream & inputFile, T * buffer)
292 {
293 StringType line;
294
295 while (!inputFile.eof())
296 {
297 std::getline(inputFile, line, '\n');
298 if (line.find("POINT_DATA") != std::string::npos)
299 {
300 if (!inputFile.eof())
301 {
302 std::getline(inputFile, line, '\n');
303 }
304 else
305 {
306 itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
307 }
308
310 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
311 {
312 if (!inputFile.eof())
313 {
314 std::getline(inputFile, line, '\n');
315 if (line.find("LOOKUP_TABLE") == std::string::npos)
316 {
317 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
318 }
319 }
320 else
321 {
322 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
323 }
324 }
328 SizeValueType numberOfComponents = this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents;
329 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
331 {
332 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
333 }
334 }
335 }
336 }
339 template <typename T>
340 void
341 ReadCellDataBufferAsASCII(std::ifstream & inputFile, T * buffer)
342 {
343 StringType line;
344
345 while (!inputFile.eof())
346 {
347 std::getline(inputFile, line, '\n');
348 if (line.find("CELL_DATA") != std::string::npos)
349 {
350 if (!inputFile.eof())
351 {
352 std::getline(inputFile, line, '\n');
353 }
354 else
355 {
356 itkExceptionMacro("UnExpected end of line while trying to read CELL_DATA");
357 }
358
360 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
361 {
362 if (!inputFile.eof())
363 {
364 std::getline(inputFile, line, '\n');
365 if (line.find("LOOKUP_TABLE") == std::string::npos)
366 {
367 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
368 }
369 }
370 else
371 {
372 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
373 }
374 }
378 Self::ReadComponentsAsASCII(
379 inputFile, buffer, this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents);
380 }
381 }
382 }
383
384 template <typename T>
385 void
386 ReadCellDataBufferAsBINARY(std::ifstream & inputFile, T * buffer)
387 {
388 StringType line;
389
390 while (!inputFile.eof())
391 {
392 std::getline(inputFile, line, '\n');
393 if (line.find("POINT_DATA") != std::string::npos)
394 {
395 if (!inputFile.eof())
396 {
397 std::getline(inputFile, line, '\n');
398 }
399 else
400 {
401 itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
402 }
403
405 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
406 {
407 if (!inputFile.eof())
408 {
409 std::getline(inputFile, line, '\n');
410 if (line.find("LOOKUP_TABLE") == std::string::npos)
411 {
412 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
413 }
414 }
415 else
416 {
417 itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
418 }
419 }
420
422 SizeValueType numberOfComponents = this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents;
423 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
425 {
426 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
427 }
428 }
429 }
430 }
433 template <typename T>
434 void
435 WritePointsBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & pointComponentType)
436 {
438 outputFile << "POINTS " << this->m_NumberOfPoints;
439
440 outputFile << pointComponentType << '\n';
441 for (SizeValueType ii = 0; ii < this->m_NumberOfPoints; ++ii)
442 {
443 for (unsigned int jj = 0; jj < this->m_PointDimension - 1; ++jj)
444 {
445 outputFile << ConvertNumberToString(buffer[ii * this->m_PointDimension + jj]) << ' ';
446 }
447
448 outputFile << ConvertNumberToString(buffer[ii * this->m_PointDimension + this->m_PointDimension - 1]) << '\n';
449 }
450
451 return;
452 }
453
454 template <typename T>
455 void
456 WritePointsBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & pointComponentType)
457 {
459 outputFile << "POINTS " << this->m_NumberOfPoints << pointComponentType << '\n';
461 buffer, this->m_NumberOfPoints * this->m_PointDimension, &outputFile);
462 outputFile << '\n';
463
464 return;
465 }
466
467 template <typename T>
468 void
469 WriteCellsBufferAsASCII(std::ofstream & outputFile, T * buffer)
470 {
471 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
472 unsigned int numberOfVertices = 0;
473 unsigned int numberOfVertexIndices = 0;
474 unsigned int numberOfLines = 0;
475 unsigned int numberOfLineIndices = 0;
476 unsigned int numberOfPolygons = 0;
477 unsigned int numberOfPolygonIndices = 0;
478
480 SizeValueType index = 0;
481
482 ExposeMetaData<unsigned int>(metaDic, "numberOfVertices", numberOfVertices);
483 if (numberOfVertices)
484 {
485 ExposeMetaData<unsigned int>(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
486 outputFile << "VERTICES " << numberOfVertices << ' ' << numberOfVertexIndices << '\n';
487 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
488 {
489 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
490 auto nn = static_cast<unsigned int>(buffer[index++]);
491 if (cellType == CellGeometryEnum::VERTEX_CELL)
492 {
493 outputFile << nn;
494 for (unsigned int jj = 0; jj < nn; ++jj)
495 {
496 outputFile << ' ' << buffer[index++];
497 }
498 outputFile << '\n';
499 }
500 else
501 {
502 index += nn;
503 }
504 }
505 }
506
508 index = 0;
509 ExposeMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
510 if (numberOfLines)
511 {
512 numberOfLineIndices = 0;
513 SizeValueType numberOfPolylines = 0;
515 PointIdVector pointIds;
516 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
517 {
518 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
519 auto nn = static_cast<unsigned int>(buffer[index++]);
522 pointIds.clear();
523 if (cellType == CellGeometryEnum::LINE_CELL)
524 {
525 pointIds.push_back(static_cast<SizeValueType>(buffer[index]));
526 pointIds.push_back(static_cast<SizeValueType>(buffer[index + 1]));
527 }
528 else if (cellType == CellGeometryEnum::POLYLINE_CELL)
529 {
530 for (unsigned int jj = 0; jj < nn; ++jj)
531 {
532 pointIds.push_back(static_cast<SizeValueType>(buffer[index + jj]));
533 }
534 }
535
536 polylines->InsertElement(numberOfPolylines++, pointIds);
537 numberOfLineIndices += pointIds.size();
538 index += nn;
539 }
540
541 numberOfLines = polylines->Size();
542 numberOfLineIndices += numberOfLines;
543 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
544 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLineIndices", numberOfLineIndices);
545 outputFile << "LINES " << numberOfLines << ' ' << numberOfLineIndices << '\n';
546 for (SizeValueType ii = 0; ii < polylines->Size(); ++ii)
547 {
548 auto nn = static_cast<unsigned int>(polylines->ElementAt(ii).size());
549 outputFile << nn;
550 for (unsigned int jj = 0; jj < nn; ++jj)
551 {
552 outputFile << ' ' << polylines->ElementAt(ii)[jj];
553 }
554 outputFile << '\n';
555 }
556 }
557
559 index = 0;
560 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygons", numberOfPolygons);
561 if (numberOfPolygons)
562 {
563 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
564 outputFile << "POLYGONS " << numberOfPolygons << ' ' << numberOfPolygonIndices << '\n';
565 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
566 {
567 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
568 auto nn = static_cast<unsigned int>(buffer[index++]);
571 {
572 outputFile << nn;
573 for (unsigned int jj = 0; jj < nn; ++jj)
574 {
575 outputFile << ' ' << buffer[index++];
576 }
577 outputFile << '\n';
578 }
579 else
580 {
581 index += nn;
582 }
583 }
584 }
585 }
588 template <typename T>
589 void
590 WriteCellsBufferAsBINARY(std::ofstream & outputFile, T * buffer)
591 {
592 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
593 unsigned int numberOfVertices = 0;
594 unsigned int numberOfVertexIndices = 0;
595 unsigned int numberOfLines = 0;
596 unsigned int numberOfLineIndices = 0;
597 unsigned int numberOfPolygons = 0;
598 unsigned int numberOfPolygonIndices = 0;
599
601 SizeValueType index = 0;
602
603 ExposeMetaData<unsigned int>(metaDic, "numberOfVertices", numberOfVertices);
604 if (numberOfVertices)
605 {
606 ExposeMetaData<unsigned int>(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
607 outputFile << "VERTICES " << numberOfVertices << ' ' << numberOfVertexIndices << '\n';
608 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfVertexIndices);
609 ReadCellsBuffer(buffer, data.get());
611 data.get(), numberOfVertexIndices, &outputFile);
612 outputFile << '\n';
613 }
614
616 index = 0;
617 ExposeMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
618 if (numberOfLines)
619 {
620 numberOfLineIndices = 0;
621 SizeValueType numberOfPolylines = 0;
623 PointIdVector pointIds;
624 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
625 {
626 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
627 auto nn = static_cast<unsigned int>(buffer[index++]);
628 pointIds.clear();
631 if (cellType == CellGeometryEnum::LINE_CELL)
632 {
633 pointIds.push_back(static_cast<SizeValueType>(buffer[index]));
634 pointIds.push_back(static_cast<SizeValueType>(buffer[index + 1]));
635 }
636 else if (cellType == CellGeometryEnum::POLYLINE_CELL)
637 {
638 for (unsigned int jj = 0; jj < nn; ++jj)
639 {
640 pointIds.push_back(static_cast<SizeValueType>(buffer[index + jj]));
641 }
642 }
643 polylines->InsertElement(numberOfPolylines++, pointIds);
644 numberOfLineIndices += pointIds.size();
645 index += nn;
646 }
647
648 numberOfLines = polylines->Size();
649 numberOfLineIndices += numberOfLines;
650 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
651 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLineIndices", numberOfLineIndices);
652
653 outputFile << "LINES " << numberOfLines << ' ' << numberOfLineIndices << '\n';
654 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfLineIndices);
655 unsigned long outputIndex = 0;
656 for (SizeValueType ii = 0; ii < polylines->Size(); ++ii)
657 {
658 auto nn = static_cast<unsigned int>(polylines->ElementAt(ii).size());
659 data[outputIndex++] = nn;
660 for (unsigned int jj = 0; jj < nn; ++jj)
661 {
662 data[outputIndex++] = polylines->ElementAt(ii)[jj];
663 }
664 }
665
666 itk::ByteSwapper<unsigned int>::SwapWriteRangeFromSystemToBigEndian(data.get(), numberOfLineIndices, &outputFile);
667 outputFile << '\n';
668 }
669
671 index = 0;
672 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygons", numberOfPolygons);
673 if (numberOfPolygons)
674 {
675 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
676 outputFile << "POLYGONS " << numberOfPolygons << ' ' << numberOfPolygonIndices << '\n';
677 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfPolygonIndices);
678 ReadCellsBuffer(buffer, data.get());
680 data.get(), numberOfPolygonIndices, &outputFile);
681 outputFile << '\n';
682 }
683 }
686 template <typename T>
687 void
688 WritePointDataBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & pointPixelComponentName)
689 {
690 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
691 StringType dataName;
692
693 outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << '\n';
694 switch (this->m_PointPixelType)
695 {
697 {
698 outputFile << "SCALARS ";
699 ExposeMetaData<StringType>(metaDic, "pointScalarDataName", dataName);
700 outputFile << dataName << " ";
701 break;
702 }
707 {
708 outputFile << "VECTORS ";
709 ExposeMetaData<StringType>(metaDic, "pointVectorDataName", dataName);
710 outputFile << dataName << " ";
711 break;
712 }
715 {
716 outputFile << "TENSORS ";
717 ExposeMetaData<StringType>(metaDic, "pointTensorDataName", dataName);
718 outputFile << dataName << " ";
719 break;
720 }
723 {
724 outputFile << "COLOR_SCALARS ";
725 ExposeMetaData<StringType>(metaDic, "pointColorScalarDataName", dataName);
726 outputFile << dataName << " ";
727 WriteColorScalarBufferAsASCII(
728 outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
729 return;
730 }
731 default:
732 {
733 itkExceptionMacro("Unknown point pixel type");
734 }
735 }
736
737 outputFile << pointPixelComponentName << '\n';
738
739 if (this->m_PointPixelType == IOPixelEnum::SCALAR)
740 {
741 outputFile << "LOOKUP_TABLE default" << '\n';
742 }
743
744 Indent indent(2);
745 if (this->m_PointPixelType == IOPixelEnum::SYMMETRICSECONDRANKTENSOR)
746 {
747 T * ptr = buffer;
748 SizeValueType i = 0;
749 const SizeValueType num = this->m_NumberOfPointPixelComponents * this->m_NumberOfPointPixels;
750 // Note that only the 3D tensors are supported in the VTK File Format
751 // documentation.
752 if (this->m_NumberOfPointPixelComponents == 3)
753 {
754 T zero(T{});
755 T e12;
756 while (i < num)
757 {
758 // row 1
759 outputFile << ConvertNumberToString(*ptr++) << indent;
760 e12 = *ptr++;
761 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(zero) << '\n';
762 // row 2
763 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent
764 << ConvertNumberToString(zero) << '\n';
765 // row 3
766 outputFile << ConvertNumberToString(zero) << indent << ConvertNumberToString(zero) << indent
767 << ConvertNumberToString(zero) << "\n\n";
768 i += 3;
769 }
770 }
771 else if (this->m_NumberOfPointPixelComponents == 6)
772 {
773 T e12;
774 T e13;
775 T e23;
776 while (i < num)
777 {
778 // row 1
779 outputFile << ConvertNumberToString(*ptr++) << indent;
780 e12 = *ptr++;
781 outputFile << ConvertNumberToString(e12) << indent;
782 e13 = *ptr++;
783 outputFile << ConvertNumberToString(e13) << '\n';
784 // row 2
785 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent;
786 e23 = *ptr++;
787 outputFile << ConvertNumberToString(e23) << '\n';
788 // row 3
789 outputFile << ConvertNumberToString(e13) << indent << ConvertNumberToString(e23) << indent
790 << ConvertNumberToString(*ptr++) << "\n\n";
791 i += 6;
792 }
793 }
794 else
795 {
796 itk::ExceptionObject e_(
797 __FILE__, __LINE__, "itk::ERROR: VTKImageIO2: Unsupported number of components in tensor.", ITK_LOCATION);
798 throw e_;
799 }
800 }
801 else // not tensor
802 {
803 unsigned int jj;
804 for (SizeValueType ii = 0; ii < this->m_NumberOfPointPixels; ++ii)
805 {
806 for (jj = 0; jj < this->m_NumberOfPointPixelComponents - 1; ++jj)
807 {
808 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfPointPixelComponents + jj]) << indent;
809 }
810 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfPointPixelComponents + jj]) << '\n';
811 }
812 }
813
814 return;
815 }
816
817 template <typename T>
818 void
819 WritePointDataBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & pointPixelComponentName)
820 {
821 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
822 StringType dataName;
823
824 outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << '\n';
825 switch (this->m_PointPixelType)
826 {
828 {
829 outputFile << "SCALARS ";
830 ExposeMetaData<StringType>(metaDic, "pointScalarDataName", dataName);
831 outputFile << dataName << " ";
832 break;
833 }
838 {
839 outputFile << "VECTORS ";
840 ExposeMetaData<StringType>(metaDic, "pointVectorDataName", dataName);
841 outputFile << dataName << " ";
842 break;
843 }
846 {
847 outputFile << "TENSORS ";
848 ExposeMetaData<StringType>(metaDic, "pointTensorDataName", dataName);
849 outputFile << dataName << " ";
850 break;
851 }
854 {
855 outputFile << "COLOR_SCALARS ";
856 ExposeMetaData<StringType>(metaDic, "pointColorScalarDataName", dataName);
857 outputFile << dataName << " ";
858 WriteColorScalarBufferAsBINARY(
859 outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
860 return;
861 }
862 default:
863 {
864 itkExceptionMacro("Unknown point pixel type");
865 }
866 }
867
868 outputFile << pointPixelComponentName << '\n';
869 if (this->m_PointPixelType == IOPixelEnum::SCALAR)
870 {
871 outputFile << "LOOKUP_TABLE default\n";
872 }
873
875 buffer, this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents, &outputFile);
876 outputFile << '\n';
877 return;
878 }
879
880 template <typename T>
881 void
882 WriteCellDataBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & cellPixelComponentName)
883 {
884 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
885 StringType dataName;
886
887 outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << '\n';
888 switch (this->m_CellPixelType)
889 {
891 {
892 outputFile << "SCALARS ";
893 ExposeMetaData<StringType>(metaDic, "cellScalarDataName", dataName);
894 outputFile << dataName << " ";
895 break;
896 }
901 {
902 outputFile << "VECTORS ";
903 ExposeMetaData<StringType>(metaDic, "cellVectorDataName", dataName);
904 outputFile << dataName << " ";
905 break;
906 }
909 {
910 outputFile << "TENSORS ";
911 ExposeMetaData<StringType>(metaDic, "cellTensorDataName", dataName);
912 outputFile << dataName << " ";
913 break;
914 }
917 {
918 outputFile << "COLOR_SCALARS ";
919 ExposeMetaData<StringType>(metaDic, "cellColorScalarDataName", dataName);
920 outputFile << dataName << " ";
921 WriteColorScalarBufferAsASCII(
922 outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
923 return;
924 }
925 default:
926 {
927 itkExceptionMacro("Unknown cell pixel type");
928 }
929 }
930
931 outputFile << cellPixelComponentName << '\n';
932 if (this->m_CellPixelType == IOPixelEnum::SCALAR)
933 {
934 outputFile << "LOOKUP_TABLE default" << '\n';
935 }
936
937 Indent indent(2);
938 if (this->m_CellPixelType == IOPixelEnum::SYMMETRICSECONDRANKTENSOR)
939 {
940 T * ptr = buffer;
941 SizeValueType i = 0;
942 const SizeValueType num = this->m_NumberOfCellPixelComponents * this->m_NumberOfCellPixels;
943 if (this->m_NumberOfCellPixelComponents == 2)
944 {
945 T zero(T{});
946 T e12;
947 while (i < num)
948 {
949 // row 1
950 outputFile << *ptr++ << indent;
951 e12 = *ptr++;
952 outputFile << e12 << indent << zero << '\n';
953 // row 2
954 outputFile << e12 << indent << *ptr++ << indent << zero << '\n';
955 // row 3
956 outputFile << zero << indent << zero << indent << zero << "\n\n";
957 i += 3;
958 }
959 }
960 else if (this->m_NumberOfCellPixelComponents == 3)
961 {
962 T e12;
963 T e13;
964 T e23;
965 while (i < num)
966 {
967 // row 1
968 outputFile << *ptr++ << indent;
969 e12 = *ptr++;
970 outputFile << e12 << indent;
971 e13 = *ptr++;
972 outputFile << e13 << '\n';
973 // row 2
974 outputFile << e12 << indent << *ptr++ << indent;
975 e23 = *ptr++;
976 outputFile << e23 << '\n';
977 // row 3
978 outputFile << e13 << indent << e23 << indent << *ptr++ << "\n\n";
979 i += 6;
980 }
981 }
982 else
983 {
984 ExceptionObject e_(__FILE__,
985 __LINE__,
986 "itk::ERROR: VTKPolyDataMeshIO: Unsupported number of components in tensor.",
987 ITK_LOCATION);
988 throw e_;
989 }
990 }
991 else // not tensor
992 {
993 unsigned int jj;
994 for (SizeValueType ii = 0; ii < this->m_NumberOfCellPixels; ++ii)
995 {
996 for (jj = 0; jj < this->m_NumberOfCellPixelComponents - 1; ++jj)
997 {
998 outputFile << buffer[ii * this->m_NumberOfCellPixelComponents + jj] << indent;
999 }
1000 outputFile << buffer[ii * this->m_NumberOfCellPixelComponents + jj] << '\n';
1001 }
1002 }
1003
1004 return;
1005 }
1006
1007 template <typename T>
1008 void
1009 WriteCellDataBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & cellPixelComponentName)
1010 {
1011 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
1012 StringType dataName;
1013
1014 outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << '\n';
1015 switch (this->m_CellPixelType)
1016 {
1018 {
1019 outputFile << "SCALARS ";
1020 ExposeMetaData<StringType>(metaDic, "cellScalarDataName", dataName);
1021 outputFile << dataName << " ";
1022 break;
1023 }
1025 case IOPixelEnum::POINT:
1028 {
1029 outputFile << "VECTORS ";
1030 ExposeMetaData<StringType>(metaDic, "cellVectorDataName", dataName);
1031 outputFile << dataName << " ";
1032 break;
1033 }
1036 {
1037 outputFile << "TENSORS ";
1038 ExposeMetaData<StringType>(metaDic, "cellTensorDataName", dataName);
1039 outputFile << dataName << " ";
1040 break;
1041 }
1042 case IOPixelEnum::ARRAY:
1044 {
1045 outputFile << "COLOR_SCALARS ";
1046 ExposeMetaData<StringType>(metaDic, "cellColorScalarDataName", dataName);
1047 outputFile << dataName << " ";
1048 WriteColorScalarBufferAsBINARY(
1049 outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
1050 return;
1051 }
1052 default:
1053 {
1054 itkExceptionMacro("Unknown cell pixel type");
1055 }
1056 }
1057
1058 outputFile << cellPixelComponentName << '\n';
1059 if (this->m_CellPixelType == IOPixelEnum::SCALAR)
1060 {
1061 outputFile << "LOOKUP_TABLE default\n";
1062 }
1063
1065 buffer, this->m_NumberOfCells * this->m_NumberOfCellPixelComponents, &outputFile);
1066 outputFile << '\n';
1067 return;
1068 }
1069
1070 template <typename T>
1071 void
1072 WriteColorScalarBufferAsASCII(std::ofstream & outputFile,
1073 T * buffer,
1074 unsigned int numberOfPixelComponents,
1075 SizeValueType numberOfPixels)
1076 {
1077 outputFile << numberOfPixelComponents << '\n';
1078 Indent indent(2);
1079 for (SizeValueType ii = 0; ii < numberOfPixels; ++ii)
1080 {
1081 for (unsigned int jj = 0; jj < numberOfPixelComponents; ++jj)
1082 {
1083 outputFile << ConvertNumberToString(static_cast<float>(buffer[ii * numberOfPixelComponents + jj])) << indent;
1084 }
1085
1086 outputFile << '\n';
1087 }
1088
1089 return;
1090 }
1091
1092 template <typename T>
1093 void
1094 WriteColorScalarBufferAsBINARY(std::ofstream & outputFile,
1095 T * buffer,
1096 unsigned int numberOfPixelComponents,
1097 SizeValueType numberOfPixels)
1098 {
1099 outputFile << numberOfPixelComponents << '\n';
1100 SizeValueType numberOfElements = numberOfPixelComponents * numberOfPixels;
1101 const auto data = make_unique_for_overwrite<unsigned char[]>(numberOfElements);
1102 for (SizeValueType ii = 0; ii < numberOfElements; ++ii)
1103 {
1104 data[ii] = static_cast<unsigned char>(buffer[ii]);
1105 }
1106
1107 outputFile.write(reinterpret_cast<char *>(data.get()), numberOfElements);
1108 outputFile << '\n';
1109 return;
1110 }
1111
1114 template <typename TInput, typename TOutput>
1115 void
1116 ReadCellsBuffer(TInput * input, TOutput * output)
1117 {
1118 SizeValueType inputIndex = 0;
1119 SizeValueType outputIndex = 0;
1120
1121 if (input && output)
1122 {
1123 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
1124 {
1125 ++inputIndex;
1126 auto nn = static_cast<unsigned int>(input[inputIndex++]);
1127 output[outputIndex++] = nn;
1128 for (unsigned int jj = 0; jj < nn; ++jj)
1129 {
1130 output[outputIndex++] = static_cast<TOutput>(input[inputIndex++]);
1131 }
1132 }
1133 }
1134 }
1135
1138 GetComponentTypeFromString(const std::string & pointType);
1139
1140private:
1145 template <typename T>
1146 static void
1147 ReadComponentsAsASCII(std::ifstream & inputFile, T * const buffer, const SizeValueType numberOfComponents)
1148 {
1149 for (SizeValueType i = 0; i < numberOfComponents; ++i)
1150 {
1151 if (!(inputFile >> buffer[i]))
1152 {
1153 itkGenericExceptionMacro("Failed to read a component from the specified ASCII input file!");
1154 }
1155 }
1156 }
1159 static void
1160 ReadComponentsAsASCII(std::ifstream & inputFile, float * const buffer, const SizeValueType numberOfComponents);
1161
1162 static void
1163 ReadComponentsAsASCII(std::ifstream & inputFile, double * const buffer, const SizeValueType numberOfComponents);
1164
1165 template <typename TOffset>
1166 void
1167 ReadCellsBufferAsBINARYOffsetType(std::ifstream & inputFile, void * buffer);
1168
1169 template <typename TOffset, typename TConnectivity>
1170 void
1171 ReadCellsBufferAsBINARYConnectivityType(std::ifstream & inputFile, void * buffer);
1172
1173 uint8_t m_ReadMeshVersionMajor{ 4 };
1174};
1175} // end namespace itk
1176
1177#endif // itkVTKPolyDataMeshIO_h
static constexpr bool SystemIsLittleEndian()
static void SwapWriteRangeFromSystemToBigEndian(const T *p, int num, std::ostream *fp)
static void SwapRangeFromSystemToBigEndian(T *p, BufferSizeType num)
Control indentation during Print() invocation.
Definition: itkIndent.h:50
Light weight base class for most itk classes.
Abstract superclass defines mesh IO interface.
Definition: itkMeshIOBase.h:73
IdentifierType SizeValueType
Definition: itkMeshIOBase.h:89
Provides a mechanism for storing a collection of arbitrary data types.
Base class for most ITK classes.
Definition: itkObject.h:62
This class defines how to read and write vtk legacy file format.
void ReadCellsBufferAsBINARYConnectivityType(std::ifstream &inputFile, void *buffer)
static void ReadComponentsAsASCII(std::ifstream &inputFile, float *const buffer, const SizeValueType numberOfComponents)
void ReadPointDataBufferAsASCII(std::ifstream &inputFile, T *buffer)
static void ReadComponentsAsASCII(std::ifstream &inputFile, double *const buffer, const SizeValueType numberOfComponents)
void WriteCellDataBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &cellPixelComponentName)
void WritePointDataBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &pointPixelComponentName)
IOComponentEnum GetComponentTypeFromString(const std::string &pointType)
void WriteCells(void *buffer) override
void WritePointData(void *buffer) override
void ReadCellData(void *buffer) override
std::vector< SizeValueType > PointIdVector
bool CanWriteFile(const char *fileName) override
void ReadPointData(void *buffer) override
void WriteMeshInformation() override
void WriteCellData(void *buffer) override
void ReadCellsBufferAsASCII(std::ifstream &inputFile, void *buffer)
void WritePointDataBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &pointPixelComponentName)
void ReadPointDataBufferAsBINARY(std::ifstream &inputFile, T *buffer)
void WriteCellsBufferAsBINARY(std::ofstream &outputFile, T *buffer)
void WriteCellDataBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &cellPixelComponentName)
void PrintSelf(std::ostream &os, Indent indent) const override
void WritePointsBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &pointComponentType)
void WriteColorScalarBufferAsBINARY(std::ofstream &outputFile, T *buffer, unsigned int numberOfPixelComponents, SizeValueType numberOfPixels)
void ReadCellsBufferAsBINARYOffsetType(std::ifstream &inputFile, void *buffer)
void ReadCellsBuffer(TInput *input, TOutput *output)
void ReadPointsBufferAsBINARY(std::ifstream &inputFile, T *buffer)
void ReadCellsBufferAsBINARY(std::ifstream &inputFile, void *buffer)
std::vector< StringType > StringVectorType
~VTKPolyDataMeshIO() override
void Write() override
void WritePoints(void *buffer) override
void WritePointsBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &pointComponentType)
void ReadCellDataBufferAsBINARY(std::ifstream &inputFile, T *buffer)
void WriteColorScalarBufferAsASCII(std::ofstream &outputFile, T *buffer, unsigned int numberOfPixelComponents, SizeValueType numberOfPixels)
void UpdateCellInformation(T *buffer)
void ReadPointsBufferAsASCII(std::ifstream &inputFile, T *buffer)
void WriteCellsBufferAsASCII(std::ofstream &outputFile, T *buffer)
void ReadCells(void *buffer) override
bool CanReadFile(const char *fileName) override
void ReadMeshInformation() override
static void ReadComponentsAsASCII(std::ifstream &inputFile, T *const buffer, const SizeValueType numberOfComponents)
std::stringstream StringStreamType
int GetNextLine(std::ifstream &ifs, std::string &line, bool lowerCase=true, SizeValueType count=0)
void ReadPoints(void *buffer) override
void ReadCellDataBufferAsASCII(std::ifstream &inputFile, T *buffer)
Define a front-end to the STL "vector" container that conforms to the IndexedContainerInterface.
static Pointer New()
SmartPointer< Self > Pointer
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
std::string ConvertNumberToString(const TValue val)
unsigned long SizeValueType
Definition: itkIntTypes.h:86