ITK 6.0.0
Insight Toolkit
 
Loading...
Searching...
No Matches
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
69
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 {
155 case CellGeometryEnum::VERTEX_CELL:
156 ++numberOfVertices;
157 numberOfVertexIndices += nn + 1;
158 break;
159 case CellGeometryEnum::LINE_CELL:
160 ++numberOfLines;
161 numberOfLineIndices += nn + 1;
162 break;
163 case CellGeometryEnum::POLYLINE_CELL:
164 ++numberOfLines;
165 numberOfLineIndices += nn + 1;
166 break;
167 case CellGeometryEnum::TRIANGLE_CELL:
168 ++numberOfPolygons;
169 numberOfPolygonIndices += nn + 1;
170 break;
171 case CellGeometryEnum::POLYGON_CELL:
172 ++numberOfPolygons;
173 numberOfPolygonIndices += nn + 1;
174 break;
175 case CellGeometryEnum::QUADRILATERAL_CELL:
176 ++numberOfPolygons;
177 numberOfPolygonIndices += nn + 1;
178 break;
179 default:
180 itkExceptionStringMacro("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 }
194
195 template <typename T>
196 void
197 ReadPointsBufferAsASCII(std::ifstream & inputFile, T * buffer)
198 {
199 std::string line;
200
201 while (!inputFile.eof())
202 {
203 std::getline(inputFile, line, '\n');
204
205 if (line.find("POINTS") != std::string::npos)
206 {
208 Self::ReadComponentsAsASCII(inputFile, buffer, this->m_NumberOfPoints * this->m_PointDimension);
209 }
210 }
211 }
212
213 template <typename T>
214 void
215 ReadPointsBufferAsBINARY(std::ifstream & inputFile, T * buffer)
216 {
217 std::string line;
218
219 while (!inputFile.eof())
220 {
221 std::getline(inputFile, line, '\n');
222
223 if (line.find("POINTS") != std::string::npos)
224 {
226 const SizeValueType numberOfComponents = this->m_NumberOfPoints * this->m_PointDimension;
227 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
229 {
230 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
231 }
232 }
233 }
234 }
235
236 void
237 ReadCellsBufferAsASCII(std::ifstream & inputFile, void * buffer);
238
239 void
240 ReadCellsBufferAsBINARY(std::ifstream & inputFile, void * buffer);
241
242 template <typename T>
243 void
244 ReadPointDataBufferAsASCII(std::ifstream & inputFile, T * buffer)
245 {
246 StringType line;
247
248 while (!inputFile.eof())
249 {
250 std::getline(inputFile, line, '\n');
251 if (line.find("POINT_DATA") != std::string::npos)
252 {
253 if (!inputFile.eof())
254 {
255 std::getline(inputFile, line, '\n');
256 }
257 else
258 {
259 itkExceptionStringMacro("UnExpected end of line while trying to read POINT_DATA");
260 }
261
263 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
264 {
265 if (!inputFile.eof())
266 {
267 std::getline(inputFile, line, '\n');
268 if (line.find("LOOKUP_TABLE") == std::string::npos)
269 {
270 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
271 }
272 }
273 else
274 {
275 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
276 }
277 }
281 else if (line.find("FIELD") != std::string::npos)
282 {
283 if (!inputFile.eof())
284 {
285 std::getline(inputFile, line, '\n');
286 }
287 else
288 {
289 itkExceptionStringMacro("UnExpected end of line while trying to read FIELD array header");
290 }
291 }
292
295 inputFile, buffer, this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents);
296 }
297 }
298 }
299
300 template <typename T>
301 void
302 ReadPointDataBufferAsBINARY(std::ifstream & inputFile, T * buffer)
303 {
304 StringType line;
305
306 while (!inputFile.eof())
307 {
308 std::getline(inputFile, line, '\n');
309 if (line.find("POINT_DATA") != std::string::npos)
310 {
311 if (!inputFile.eof())
312 {
313 std::getline(inputFile, line, '\n');
314 }
315 else
316 {
317 itkExceptionStringMacro("UnExpected end of line while trying to read POINT_DATA");
318 }
319
321 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
322 {
323 if (!inputFile.eof())
324 {
325 std::getline(inputFile, line, '\n');
326 if (line.find("LOOKUP_TABLE") == std::string::npos)
327 {
328 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
329 }
330 }
331 else
332 {
333 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
334 }
335 }
339 else if (line.find("FIELD") != std::string::npos)
340 {
341 if (!inputFile.eof())
342 {
343 std::getline(inputFile, line, '\n');
344 }
345 else
346 {
347 itkExceptionStringMacro("UnExpected end of line while trying to read FIELD array header");
348 }
349 }
350
352 const SizeValueType numberOfComponents = this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents;
353 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
355 {
356 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
357 }
358 }
359 }
360 }
361
362 template <typename T>
363 void
364 ReadCellDataBufferAsASCII(std::ifstream & inputFile, T * buffer)
365 {
366 StringType line;
367
368 while (!inputFile.eof())
369 {
370 std::getline(inputFile, line, '\n');
371 if (line.find("CELL_DATA") != std::string::npos)
372 {
373 if (!inputFile.eof())
374 {
375 std::getline(inputFile, line, '\n');
376 }
377 else
378 {
379 itkExceptionStringMacro("UnExpected end of line while trying to read CELL_DATA");
380 }
381
383 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
384 {
385 if (!inputFile.eof())
386 {
387 std::getline(inputFile, line, '\n');
388 if (line.find("LOOKUP_TABLE") == std::string::npos)
389 {
390 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
391 }
392 }
393 else
394 {
395 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
396 }
397 }
399 else if (line.find("FIELD") != std::string::npos)
400 {
401 if (!inputFile.eof())
402 {
403 std::getline(inputFile, line, '\n');
404 }
405 else
406 {
407 itkExceptionStringMacro("UnExpected end of line while trying to read FIELD array header");
408 }
409 }
410
413 inputFile, buffer, this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents);
414 }
415 }
416 }
417
418 template <typename T>
419 void
420 ReadCellDataBufferAsBINARY(std::ifstream & inputFile, T * buffer)
421 {
422 StringType line;
423
424 while (!inputFile.eof())
425 {
426 std::getline(inputFile, line, '\n');
427 if (line.find("CELL_DATA") != std::string::npos)
428 {
429 if (!inputFile.eof())
430 {
431 std::getline(inputFile, line, '\n');
432 }
433 else
434 {
435 itkExceptionStringMacro("UnExpected end of line while trying to read CELL_DATA");
436 }
437
439 if (line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos)
440 {
441 if (!inputFile.eof())
442 {
443 std::getline(inputFile, line, '\n');
444 if (line.find("LOOKUP_TABLE") == std::string::npos)
445 {
446 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
447 }
448 }
449 else
450 {
451 itkExceptionStringMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
452 }
453 }
455 else if (line.find("FIELD") != std::string::npos)
456 {
457 if (!inputFile.eof())
458 {
459 std::getline(inputFile, line, '\n');
460 }
461 else
462 {
463 itkExceptionStringMacro("UnExpected end of line while trying to read FIELD array header");
464 }
465 }
466
468 const SizeValueType numberOfComponents = this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents;
469 inputFile.read(reinterpret_cast<char *>(buffer), numberOfComponents * sizeof(T));
471 {
472 itk::ByteSwapper<T>::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
473 }
474 }
475 }
476 }
477
478 template <typename T>
479 void
480 WritePointsBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & pointComponentType)
481 {
483 outputFile << "POINTS " << this->m_NumberOfPoints;
484
485 outputFile << pointComponentType << '\n';
486 for (SizeValueType ii = 0; ii < this->m_NumberOfPoints; ++ii)
487 {
488 for (unsigned int jj = 0; jj < this->m_PointDimension - 1; ++jj)
489 {
490 outputFile << ConvertNumberToString(buffer[ii * this->m_PointDimension + jj]) << ' ';
491 }
492
493 outputFile << ConvertNumberToString(buffer[ii * this->m_PointDimension + this->m_PointDimension - 1]) << '\n';
494 }
495 }
496
497 template <typename T>
498 void
499 WritePointsBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & pointComponentType)
500 {
502 outputFile << "POINTS " << this->m_NumberOfPoints << pointComponentType << '\n';
504 buffer, this->m_NumberOfPoints * this->m_PointDimension, &outputFile);
505 outputFile << '\n';
506 }
507
508 template <typename T>
509 void
510 WriteCellsBufferAsASCII(std::ofstream & outputFile, T * buffer)
511 {
512 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
513 unsigned int numberOfVertices = 0;
514 unsigned int numberOfVertexIndices = 0;
515 unsigned int numberOfLines = 0;
516 unsigned int numberOfLineIndices = 0;
517 unsigned int numberOfPolygons = 0;
518 unsigned int numberOfPolygonIndices = 0;
519
521 SizeValueType index = 0;
522
523 ExposeMetaData<unsigned int>(metaDic, "numberOfVertices", numberOfVertices);
524 if (numberOfVertices)
525 {
526 ExposeMetaData<unsigned int>(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
527 outputFile << "VERTICES " << numberOfVertices << ' ' << numberOfVertexIndices << '\n';
528 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
529 {
530 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
531 auto nn = static_cast<unsigned int>(buffer[index++]);
532 if (cellType == CellGeometryEnum::VERTEX_CELL)
533 {
534 outputFile << nn;
535 for (unsigned int jj = 0; jj < nn; ++jj)
536 {
537 outputFile << ' ' << buffer[index++];
538 }
539 outputFile << '\n';
540 }
541 else
542 {
543 index += nn;
544 }
545 }
546 }
547
549 index = 0;
550 ExposeMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
551 if (numberOfLines)
552 {
553 numberOfLineIndices = 0;
554 SizeValueType numberOfPolylines = 0;
556 PointIdVector pointIds;
557 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
558 {
559 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
560 auto nn = static_cast<unsigned int>(buffer[index++]);
561
562 pointIds.clear();
563 if (cellType == CellGeometryEnum::LINE_CELL)
564 {
565 pointIds.push_back(static_cast<SizeValueType>(buffer[index]));
566 pointIds.push_back(static_cast<SizeValueType>(buffer[index + 1]));
567 }
568 else if (cellType == CellGeometryEnum::POLYLINE_CELL)
569 {
570 for (unsigned int jj = 0; jj < nn; ++jj)
571 {
572 pointIds.push_back(static_cast<SizeValueType>(buffer[index + jj]));
573 }
574 }
575
576 polylines->InsertElement(numberOfPolylines++, pointIds);
577 numberOfLineIndices += pointIds.size();
578 index += nn;
579 }
580
581 numberOfLines = polylines->Size();
582 numberOfLineIndices += numberOfLines;
583 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
584 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLineIndices", numberOfLineIndices);
585 outputFile << "LINES " << numberOfLines << ' ' << numberOfLineIndices << '\n';
586 for (SizeValueType ii = 0; ii < polylines->Size(); ++ii)
587 {
588 auto nn = static_cast<unsigned int>(polylines->ElementAt(ii).size());
589 outputFile << nn;
590 for (unsigned int jj = 0; jj < nn; ++jj)
591 {
592 outputFile << ' ' << polylines->ElementAt(ii)[jj];
593 }
594 outputFile << '\n';
595 }
596 }
597
599 index = 0;
600 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygons", numberOfPolygons);
601 if (numberOfPolygons)
602 {
603 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
604 outputFile << "POLYGONS " << numberOfPolygons << ' ' << numberOfPolygonIndices << '\n';
605 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
606 {
607 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
608 auto nn = static_cast<unsigned int>(buffer[index++]);
609 if (cellType == CellGeometryEnum::POLYGON_CELL || cellType == CellGeometryEnum::TRIANGLE_CELL ||
610 cellType == CellGeometryEnum::QUADRILATERAL_CELL)
611 {
612 outputFile << nn;
613 for (unsigned int jj = 0; jj < nn; ++jj)
614 {
615 outputFile << ' ' << buffer[index++];
616 }
617 outputFile << '\n';
618 }
619 else
620 {
621 index += nn;
622 }
623 }
624 }
625 }
626
627 template <typename T>
628 void
629 WriteCellsBufferAsBINARY(std::ofstream & outputFile, T * buffer)
630 {
631 MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
632 unsigned int numberOfVertices = 0;
633 unsigned int numberOfVertexIndices = 0;
634 unsigned int numberOfLines = 0;
635 unsigned int numberOfLineIndices = 0;
636 unsigned int numberOfPolygons = 0;
637 unsigned int numberOfPolygonIndices = 0;
638
640 SizeValueType index = 0;
641
642 ExposeMetaData<unsigned int>(metaDic, "numberOfVertices", numberOfVertices);
643 if (numberOfVertices)
644 {
645 ExposeMetaData<unsigned int>(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
646 outputFile << "VERTICES " << numberOfVertices << ' ' << numberOfVertexIndices << '\n';
647 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfVertexIndices);
648 ReadCellsBuffer(buffer, data.get());
650 data.get(), numberOfVertexIndices, &outputFile);
651 outputFile << '\n';
652 }
653
655 index = 0;
656 ExposeMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
657 if (numberOfLines)
658 {
659 numberOfLineIndices = 0;
660 SizeValueType numberOfPolylines = 0;
662 PointIdVector pointIds;
663 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
664 {
665 auto cellType = static_cast<CellGeometryEnum>(static_cast<int>(buffer[index++]));
666 auto nn = static_cast<unsigned int>(buffer[index++]);
667 pointIds.clear();
668
669 if (cellType == CellGeometryEnum::LINE_CELL)
670 {
671 pointIds.push_back(static_cast<SizeValueType>(buffer[index]));
672 pointIds.push_back(static_cast<SizeValueType>(buffer[index + 1]));
673 }
674 else if (cellType == CellGeometryEnum::POLYLINE_CELL)
675 {
676 for (unsigned int jj = 0; jj < nn; ++jj)
677 {
678 pointIds.push_back(static_cast<SizeValueType>(buffer[index + jj]));
679 }
680 }
681 polylines->InsertElement(numberOfPolylines++, pointIds);
682 numberOfLineIndices += pointIds.size();
683 index += nn;
684 }
685
686 numberOfLines = polylines->Size();
687 numberOfLineIndices += numberOfLines;
688 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLines", numberOfLines);
689 EncapsulateMetaData<unsigned int>(metaDic, "numberOfLineIndices", numberOfLineIndices);
690
691 outputFile << "LINES " << numberOfLines << ' ' << numberOfLineIndices << '\n';
692 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfLineIndices);
693 unsigned long outputIndex = 0;
694 for (SizeValueType ii = 0; ii < polylines->Size(); ++ii)
695 {
696 auto nn = static_cast<unsigned int>(polylines->ElementAt(ii).size());
697 data[outputIndex++] = nn;
698 for (unsigned int jj = 0; jj < nn; ++jj)
699 {
700 data[outputIndex++] = polylines->ElementAt(ii)[jj];
701 }
702 }
703
704 itk::ByteSwapper<unsigned int>::SwapWriteRangeFromSystemToBigEndian(data.get(), numberOfLineIndices, &outputFile);
705 outputFile << '\n';
706 }
707
709 index = 0;
710 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygons", numberOfPolygons);
711 if (numberOfPolygons)
712 {
713 ExposeMetaData<unsigned int>(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
714 outputFile << "POLYGONS " << numberOfPolygons << ' ' << numberOfPolygonIndices << '\n';
715 const auto data = make_unique_for_overwrite<unsigned int[]>(numberOfPolygonIndices);
716 ReadCellsBuffer(buffer, data.get());
718 data.get(), numberOfPolygonIndices, &outputFile);
719 outputFile << '\n';
720 }
721 }
722
723 template <typename T>
724 void
725 WritePointDataBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & pointPixelComponentName)
726 {
727 const MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
728 StringType dataName;
729
730 outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << '\n';
731 switch (this->m_PointPixelType)
732 {
733 case IOPixelEnum::SCALAR:
734 {
735 outputFile << "SCALARS ";
736 ExposeMetaData<StringType>(metaDic, "pointScalarDataName", dataName);
737 outputFile << dataName << " ";
738 break;
739 }
740 case IOPixelEnum::OFFSET:
741 case IOPixelEnum::POINT:
742 case IOPixelEnum::COVARIANTVECTOR:
743 case IOPixelEnum::VECTOR:
744 {
745 outputFile << "VECTORS ";
746 ExposeMetaData<StringType>(metaDic, "pointVectorDataName", dataName);
747 outputFile << dataName << " ";
748 break;
749 }
750 case IOPixelEnum::SYMMETRICSECONDRANKTENSOR:
751 case IOPixelEnum::DIFFUSIONTENSOR3D:
752 {
753 outputFile << "TENSORS ";
754 ExposeMetaData<StringType>(metaDic, "pointTensorDataName", dataName);
755 outputFile << dataName << " ";
756 break;
757 }
758 case IOPixelEnum::ARRAY:
759 case IOPixelEnum::VARIABLELENGTHVECTOR:
760 {
761 outputFile << "COLOR_SCALARS ";
762 ExposeMetaData<StringType>(metaDic, "pointColorScalarDataName", dataName);
763 outputFile << dataName << " ";
765 outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
766 return;
767 }
768 default:
769 {
770 itkExceptionStringMacro("Unknown point pixel type");
771 }
772 }
773
774 outputFile << pointPixelComponentName << '\n';
775
776 if (this->m_PointPixelType == IOPixelEnum::SCALAR)
777 {
778 outputFile << "LOOKUP_TABLE default" << '\n';
779 }
780
781 const Indent indent(2);
782 if (this->m_PointPixelType == IOPixelEnum::SYMMETRICSECONDRANKTENSOR)
783 {
784 T * ptr = buffer;
785 SizeValueType i = 0;
786 const SizeValueType num = this->m_NumberOfPointPixelComponents * this->m_NumberOfPointPixels;
787 // Note that only the 3D tensors are supported in the VTK File Format
788 // documentation.
789 if (this->m_NumberOfPointPixelComponents == 3)
790 {
791 T zero(T{});
792 T e12;
793 while (i < num)
794 {
795 // row 1
796 outputFile << ConvertNumberToString(*ptr++) << indent;
797 e12 = *ptr++;
798 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(zero) << '\n';
799 // row 2
800 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent
801 << ConvertNumberToString(zero) << '\n';
802 // row 3
803 outputFile << ConvertNumberToString(zero) << indent << ConvertNumberToString(zero) << indent
804 << ConvertNumberToString(zero) << "\n\n";
805 i += 3;
806 }
807 }
808 else if (this->m_NumberOfPointPixelComponents == 6)
809 {
810 T e12;
811 T e13;
812 T e23;
813 while (i < num)
814 {
815 // row 1
816 outputFile << ConvertNumberToString(*ptr++) << indent;
817 e12 = *ptr++;
818 outputFile << ConvertNumberToString(e12) << indent;
819 e13 = *ptr++;
820 outputFile << ConvertNumberToString(e13) << '\n';
821 // row 2
822 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent;
823 e23 = *ptr++;
824 outputFile << ConvertNumberToString(e23) << '\n';
825 // row 3
826 outputFile << ConvertNumberToString(e13) << indent << ConvertNumberToString(e23) << indent
827 << ConvertNumberToString(*ptr++) << "\n\n";
828 i += 6;
829 }
830 }
831 else
832 {
834 __FILE__, __LINE__, "itk::ERROR: VTKImageIO2: Unsupported number of components in tensor.", ITK_LOCATION);
835 throw e_;
836 }
837 }
838 else // not tensor
839 {
840 for (SizeValueType ii = 0; ii < this->m_NumberOfPointPixels; ++ii)
841 {
842 unsigned int jj = 0;
843 for (; jj < this->m_NumberOfPointPixelComponents - 1; ++jj)
844 {
845 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfPointPixelComponents + jj]) << indent;
846 }
847 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfPointPixelComponents + jj]) << '\n';
848 }
849 }
850 }
851
852 template <typename T>
853 void
854 WritePointDataBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & pointPixelComponentName)
855 {
856 const MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
857 StringType dataName;
858
859 outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << '\n';
860 switch (this->m_PointPixelType)
861 {
862 case IOPixelEnum::SCALAR:
863 {
864 outputFile << "SCALARS ";
865 ExposeMetaData<StringType>(metaDic, "pointScalarDataName", dataName);
866 outputFile << dataName << " ";
867 break;
868 }
869 case IOPixelEnum::OFFSET:
870 case IOPixelEnum::POINT:
871 case IOPixelEnum::COVARIANTVECTOR:
872 case IOPixelEnum::VECTOR:
873 {
874 outputFile << "VECTORS ";
875 ExposeMetaData<StringType>(metaDic, "pointVectorDataName", dataName);
876 outputFile << dataName << " ";
877 break;
878 }
879 case IOPixelEnum::SYMMETRICSECONDRANKTENSOR:
880 case IOPixelEnum::DIFFUSIONTENSOR3D:
881 {
882 outputFile << "TENSORS ";
883 ExposeMetaData<StringType>(metaDic, "pointTensorDataName", dataName);
884 outputFile << dataName << " ";
885 break;
886 }
887 case IOPixelEnum::ARRAY:
888 case IOPixelEnum::VARIABLELENGTHVECTOR:
889 {
890 outputFile << "COLOR_SCALARS ";
891 ExposeMetaData<StringType>(metaDic, "pointColorScalarDataName", dataName);
892 outputFile << dataName << " ";
894 outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
895 return;
896 }
897 default:
898 {
899 itkExceptionStringMacro("Unknown point pixel type");
900 }
901 }
902
903 outputFile << pointPixelComponentName << '\n';
904 if (this->m_PointPixelType == IOPixelEnum::SCALAR)
905 {
906 outputFile << "LOOKUP_TABLE default\n";
907 }
908
910 buffer, this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents, &outputFile);
911 outputFile << '\n';
912 }
913
914 template <typename T>
915 void
916 WriteCellDataBufferAsASCII(std::ofstream & outputFile, T * buffer, const StringType & cellPixelComponentName)
917 {
918 const MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
919 StringType dataName;
920
921 outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << '\n';
922 switch (this->m_CellPixelType)
923 {
924 case IOPixelEnum::SCALAR:
925 {
926 outputFile << "SCALARS ";
927 ExposeMetaData<StringType>(metaDic, "cellScalarDataName", dataName);
928 outputFile << dataName << " ";
929 break;
930 }
931 case IOPixelEnum::OFFSET:
932 case IOPixelEnum::POINT:
933 case IOPixelEnum::COVARIANTVECTOR:
934 case IOPixelEnum::VECTOR:
935 {
936 outputFile << "VECTORS ";
937 ExposeMetaData<StringType>(metaDic, "cellVectorDataName", dataName);
938 outputFile << dataName << " ";
939 break;
940 }
941 case IOPixelEnum::SYMMETRICSECONDRANKTENSOR:
942 case IOPixelEnum::DIFFUSIONTENSOR3D:
943 {
944 outputFile << "TENSORS ";
945 ExposeMetaData<StringType>(metaDic, "cellTensorDataName", dataName);
946 outputFile << dataName << " ";
947 break;
948 }
949 case IOPixelEnum::ARRAY:
950 case IOPixelEnum::VARIABLELENGTHVECTOR:
951 {
952 outputFile << "COLOR_SCALARS ";
953 ExposeMetaData<StringType>(metaDic, "cellColorScalarDataName", dataName);
954 outputFile << dataName << " ";
956 outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
957 return;
958 }
959 default:
960 {
961 itkExceptionStringMacro("Unknown cell pixel type");
962 }
963 }
964
965 outputFile << cellPixelComponentName << '\n';
966 if (this->m_CellPixelType == IOPixelEnum::SCALAR)
967 {
968 outputFile << "LOOKUP_TABLE default" << '\n';
969 }
970
971 const Indent indent(2);
972 if (this->m_CellPixelType == IOPixelEnum::SYMMETRICSECONDRANKTENSOR)
973 {
974 T * ptr = buffer;
975 SizeValueType i = 0;
976 const SizeValueType num = this->m_NumberOfCellPixelComponents * this->m_NumberOfCellPixels;
977 if (this->m_NumberOfCellPixelComponents == 2)
978 {
979 T zero(T{});
980 T e12;
981 while (i < num)
982 {
983 // row 1
984 outputFile << ConvertNumberToString(*ptr++) << indent;
985 e12 = *ptr++;
986 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(zero) << '\n';
987 // row 2
988 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent
989 << ConvertNumberToString(zero) << '\n';
990 // row 3
991 outputFile << ConvertNumberToString(zero) << indent << ConvertNumberToString(zero) << indent
992 << ConvertNumberToString(zero) << "\n\n";
993 i += 3;
994 }
995 }
996 else if (this->m_NumberOfCellPixelComponents == 3)
997 {
998 T e12;
999 T e13;
1000 T e23;
1001 while (i < num)
1002 {
1003 // row 1
1004 outputFile << ConvertNumberToString(*ptr++) << indent;
1005 e12 = *ptr++;
1006 outputFile << ConvertNumberToString(e12) << indent;
1007 e13 = *ptr++;
1008 outputFile << ConvertNumberToString(e13) << '\n';
1009 // row 2
1010 outputFile << ConvertNumberToString(e12) << indent << ConvertNumberToString(*ptr++) << indent;
1011 e23 = *ptr++;
1012 outputFile << ConvertNumberToString(e23) << '\n';
1013 // row 3
1014 outputFile << ConvertNumberToString(e13) << indent << ConvertNumberToString(e23) << indent
1015 << ConvertNumberToString(*ptr++) << "\n\n";
1016 i += 6;
1017 }
1018 }
1019 else
1020 {
1021 ExceptionObject e_(__FILE__,
1022 __LINE__,
1023 "itk::ERROR: VTKPolyDataMeshIO: Unsupported number of components in tensor.",
1024 ITK_LOCATION);
1025 throw e_;
1026 }
1027 }
1028 else // not tensor
1029 {
1030 for (SizeValueType ii = 0; ii < this->m_NumberOfCellPixels; ++ii)
1031 {
1032 unsigned int jj = 0;
1033 for (; jj < this->m_NumberOfCellPixelComponents - 1; ++jj)
1034 {
1035 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfCellPixelComponents + jj]) << indent;
1036 }
1037 outputFile << ConvertNumberToString(buffer[ii * this->m_NumberOfCellPixelComponents + jj]) << '\n';
1038 }
1039 }
1040 }
1041
1042 template <typename T>
1043 void
1044 WriteCellDataBufferAsBINARY(std::ofstream & outputFile, T * buffer, const StringType & cellPixelComponentName)
1045 {
1046 const MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
1047 StringType dataName;
1048
1049 outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << '\n';
1050 switch (this->m_CellPixelType)
1051 {
1052 case IOPixelEnum::SCALAR:
1053 {
1054 outputFile << "SCALARS ";
1055 ExposeMetaData<StringType>(metaDic, "cellScalarDataName", dataName);
1056 outputFile << dataName << " ";
1057 break;
1058 }
1059 case IOPixelEnum::OFFSET:
1060 case IOPixelEnum::POINT:
1061 case IOPixelEnum::COVARIANTVECTOR:
1062 case IOPixelEnum::VECTOR:
1063 {
1064 outputFile << "VECTORS ";
1065 ExposeMetaData<StringType>(metaDic, "cellVectorDataName", dataName);
1066 outputFile << dataName << " ";
1067 break;
1068 }
1069 case IOPixelEnum::SYMMETRICSECONDRANKTENSOR:
1070 case IOPixelEnum::DIFFUSIONTENSOR3D:
1071 {
1072 outputFile << "TENSORS ";
1073 ExposeMetaData<StringType>(metaDic, "cellTensorDataName", dataName);
1074 outputFile << dataName << " ";
1075 break;
1076 }
1077 case IOPixelEnum::ARRAY:
1078 case IOPixelEnum::VARIABLELENGTHVECTOR:
1079 {
1080 outputFile << "COLOR_SCALARS ";
1081 ExposeMetaData<StringType>(metaDic, "cellColorScalarDataName", dataName);
1082 outputFile << dataName << " ";
1084 outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
1085 return;
1086 }
1087 default:
1088 {
1089 itkExceptionStringMacro("Unknown cell pixel type");
1090 }
1091 }
1092
1093 outputFile << cellPixelComponentName << '\n';
1094 if (this->m_CellPixelType == IOPixelEnum::SCALAR)
1095 {
1096 outputFile << "LOOKUP_TABLE default\n";
1097 }
1098
1100 buffer, this->m_NumberOfCells * this->m_NumberOfCellPixelComponents, &outputFile);
1101 outputFile << '\n';
1102 }
1103
1104 template <typename T>
1105 void
1106 WriteColorScalarBufferAsASCII(std::ofstream & outputFile,
1107 T * buffer,
1108 unsigned int numberOfPixelComponents,
1109 SizeValueType numberOfPixels)
1110 {
1111 outputFile << numberOfPixelComponents << '\n';
1112 const Indent indent(2);
1113 for (SizeValueType ii = 0; ii < numberOfPixels; ++ii)
1114 {
1115 for (unsigned int jj = 0; jj < numberOfPixelComponents; ++jj)
1116 {
1117 outputFile << ConvertNumberToString(buffer[ii * numberOfPixelComponents + jj]) << indent;
1118 }
1119
1120 outputFile << '\n';
1121 }
1122 }
1123
1124 template <typename T>
1125 void
1126 WriteColorScalarBufferAsBINARY(std::ofstream & outputFile,
1127 T * buffer,
1128 unsigned int numberOfPixelComponents,
1129 SizeValueType numberOfPixels)
1130 {
1131 outputFile << numberOfPixelComponents << '\n';
1132 const SizeValueType numberOfElements = numberOfPixelComponents * numberOfPixels;
1133 const auto data = make_unique_for_overwrite<unsigned char[]>(numberOfElements);
1134 for (SizeValueType ii = 0; ii < numberOfElements; ++ii)
1135 {
1136 data[ii] = static_cast<unsigned char>(buffer[ii]);
1137 }
1138
1139 outputFile.write(reinterpret_cast<char *>(data.get()), numberOfElements);
1140 outputFile << '\n';
1141 }
1142
1145 template <typename TInput, typename TOutput>
1146 void
1147 ReadCellsBuffer(TInput * input, TOutput * output)
1148 {
1149 SizeValueType inputIndex = 0;
1150 SizeValueType outputIndex = 0;
1151
1152 if (input && output)
1153 {
1154 for (SizeValueType ii = 0; ii < this->m_NumberOfCells; ++ii)
1155 {
1156 ++inputIndex;
1157 auto nn = static_cast<unsigned int>(input[inputIndex++]);
1158 output[outputIndex++] = nn;
1159 for (unsigned int jj = 0; jj < nn; ++jj)
1160 {
1161 output[outputIndex++] = static_cast<TOutput>(input[inputIndex++]);
1162 }
1163 }
1164 }
1165 }
1166
1169 GetComponentTypeFromString(const std::string & pointType);
1170
1171private:
1176 template <typename T>
1177 static void
1178 ReadComponentsAsASCII(std::ifstream & inputFile, T * const buffer, const SizeValueType numberOfComponents)
1179 {
1180 for (SizeValueType i = 0; i < numberOfComponents; ++i)
1181 {
1182 if (!(inputFile >> buffer[i]))
1183 {
1184 itkGenericExceptionMacro("Failed to read a component from the specified ASCII input file!");
1185 }
1186 }
1187 }
1188
1189 static void
1190 ReadComponentsAsASCII(std::ifstream & inputFile, float * const buffer, const SizeValueType numberOfComponents);
1191
1192 static void
1193 ReadComponentsAsASCII(std::ifstream & inputFile, double * const buffer, const SizeValueType numberOfComponents);
1194
1195 template <typename TOffset>
1196 void
1197 ReadCellsBufferAsBINARYOffsetType(std::ifstream & inputFile, void * buffer);
1198
1199 template <typename TOffset, typename TConnectivity>
1200 void
1201 ReadCellsBufferAsBINARYConnectivityType(std::ifstream & inputFile, void * buffer);
1202
1204};
1205} // end namespace itk
1206
1207#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)
Standard exception handling object.
Control indentation during Print() invocation.
Definition itkIndent.h:51
IOPixelEnum m_CellPixelType
unsigned int m_NumberOfPointPixelComponents
SizeValueType m_NumberOfPoints
IdentifierType SizeValueType
unsigned int m_PointDimension
IOPixelEnum m_PointPixelType
SizeValueType m_NumberOfPointPixels
SizeValueType m_NumberOfCellPixels
unsigned int m_NumberOfCellPixelComponents
SizeValueType m_NumberOfCells
Provides a mechanism for storing a collection of arbitrary data types.
MetaDataDictionary & GetMetaDataDictionary()
Implements transparent reference counting.
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
PolylinesContainerType::Pointer PolylinesContainerPointer
std::vector< SizeValueType > PointIdVector
SmartPointer< Self > Pointer
bool CanWriteFile(const char *fileName) override
void ReadPointData(void *buffer) override
void WriteMeshInformation() override
SmartPointer< const Self > ConstPointer
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)
VectorContainer< PointIdVector > PolylinesContainerType
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)
Superclass::SizeValueType SizeValueType
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)
The "itk" namespace contains all Insight Segmentation and Registration Toolkit (ITK) classes....
void EncapsulateMetaData(MetaDataDictionary &Dictionary, const std::string &key, const T &invalue)
CommonEnums::IOComponent IOComponentEnum
detail::VectorContainer< std::conditional_t< std::is_void_v< T2 >, SizeValueType, T1 >, std::conditional_t< std::is_void_v< T2 >, T1, T2 > > VectorContainer
std::string ConvertNumberToString(const TValue val)
bool ExposeMetaData(const MetaDataDictionary &Dictionary, const std::string key, T &outval)
CommonEnums::CellGeometry CellGeometryEnum
auto make_unique_for_overwrite(const vcl_size_t numberOfElements)