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