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