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