ITK  5.0.0
Insight Segmentation and Registration Toolkit
itkVTKPolyDataMeshIO.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
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  * http://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"
27 
28 #include <fstream>
29 #include <vector>
30 
31 namespace itk
32 {
40 class ITKIOMeshVTK_EXPORT VTKPolyDataMeshIO:public MeshIOBase
41 {
42 public:
43  ITK_DISALLOW_COPY_AND_ASSIGN(VTKPolyDataMeshIO);
44 
50 
52 
53  using StringType = std::string;
54  using StringVectorType = std::vector< StringType >;
55  using StringStreamType = std::stringstream;
56  using PointIdVector = std::vector< SizeValueType >;
59 
61  itkNewMacro(Self);
62 
64  itkTypeMacro(VTKPolyDataMeshIO, MeshIOBase);
65 
73  bool CanReadFile(const char *FileNameToRead) override;
74 
76  void ReadMeshInformation() override;
77 
79  void ReadPoints(void *buffer) override;
80 
81  void ReadCells(void *buffer) override;
82 
83  void ReadPointData(void *buffer) override;
84 
85  void ReadCellData(void *buffer) override;
86 
87  /*-------- This part of the interfaces deals with writing data. ----- */
93  bool CanWriteFile(const char *FileNameToWrite) override;
94 
96  void WriteMeshInformation() override;
97 
100  void WritePoints(void *buffer) override;
101 
102  void WriteCells(void *buffer) override;
103 
104  void WritePointData(void *buffer) override;
105 
106  void WriteCellData(void *buffer) override;
107 
108  void Write() override;
109 
110 protected:
112  ~VTKPolyDataMeshIO() override;
113 
114  void PrintSelf(std::ostream & os, Indent indent) const override;
115 
116  // Internal function to get next line from a given file (*.vtk)
117  int GetNextLine(std::ifstream& ifs, std::string& line, bool lowerCase = true, SizeValueType count= 0);
118 
119  template< typename T >
120  void UpdateCellInformation(T *buffer)
121  {
122  unsigned int numberOfVertices = 0;
123  unsigned int numberOfVertexIndices = 0;
124  unsigned int numberOfLines = 0;
125  SizeValueType numberOfLineIndices = 0;
126  unsigned int numberOfPolygons = 0;
127  unsigned int numberOfPolygonIndices = 0;
128 
129  SizeValueType index = 0;
130 
131  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
132  {
133  auto cellType = static_cast< MeshIOBase::CellGeometryType >( static_cast< int >( buffer[index++] ) );
134  auto nn = static_cast< unsigned int >( buffer[index++] );
135  switch ( cellType )
136  {
137  case VERTEX_CELL:
138  numberOfVertices++;
139  numberOfVertexIndices += nn + 1;
140  break;
141  case LINE_CELL:
142  numberOfLines++;
143  numberOfLineIndices += nn + 1;
144  break;
145  case TRIANGLE_CELL:
146  numberOfPolygons++;
147  numberOfPolygonIndices += nn + 1;
148  break;
149  case POLYGON_CELL:
150  numberOfPolygons++;
151  numberOfPolygonIndices += nn + 1;
152  break;
153  case QUADRILATERAL_CELL:
154  numberOfPolygons++;
155  numberOfPolygonIndices += nn + 1;
156  break;
157  default:
158  itkExceptionMacro(<< "Currently we dont support this cell type");
159  }
160 
161  index += nn;
162  }
163 
164  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
165  EncapsulateMetaData< unsigned int >(metaDic, "numberOfVertices", numberOfVertices);
166  EncapsulateMetaData< unsigned int >(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
167  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLines", numberOfLines);
168  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLineIndices", numberOfLineIndices);
169  EncapsulateMetaData< unsigned int >(metaDic, "numberOfPolygons", numberOfPolygons);
170  EncapsulateMetaData< unsigned int >(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
171  return;
172  }
173 
174  template< typename T >
175  void ReadPointsBufferAsASCII(std::ifstream & inputFile, T *buffer)
176  {
177  std::string line;
178 
179  while ( !inputFile.eof() )
180  {
181  std::getline(inputFile, line, '\n');
182 
183  if ( line.find("POINTS") != std::string::npos )
184  {
186  SizeValueType numberOfComponents = this->m_NumberOfPoints * this->m_PointDimension;
187  for ( SizeValueType ii = 0; ii < numberOfComponents; ii++ )
188  {
189  inputFile >> buffer[ii];
190  }
191  }
192  }
193  }
194 
195  template< typename T >
196  void ReadPointsBufferAsBINARY(std::ifstream & inputFile, T *buffer)
197  {
198  std::string line;
199 
200  while ( !inputFile.eof() )
201  {
202  std::getline(inputFile, line, '\n');
203 
204  if ( line.find("POINTS") != std::string::npos )
205  {
207  SizeValueType numberOfComponents = this->m_NumberOfPoints * this->m_PointDimension;
208  inputFile.read( reinterpret_cast< char * >( buffer ), numberOfComponents * sizeof( T ) );
210  {
211  itk::ByteSwapper< T >::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
212  }
213  }
214  }
215  }
217 
218  void ReadCellsBufferAsASCII(std::ifstream & inputFile, void *buffer);
219 
220  void ReadCellsBufferAsBINARY(std::ifstream & inputFile, void *buffer);
221 
222  template< typename T >
223  void ReadPointDataBufferAsASCII(std::ifstream & inputFile, T *buffer)
224  {
225  StringType line;
226 
227  while ( !inputFile.eof() )
228  {
229  std::getline(inputFile, line, '\n');
230  if ( line.find("POINT_DATA") != std::string::npos )
231  {
232  if ( !inputFile.eof() )
233  {
234  std::getline(inputFile, line, '\n');
235  }
236  else
237  {
238  itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
239  }
240 
242  if ( line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos )
243  {
244  if ( !inputFile.eof() )
245  {
246  std::getline(inputFile, line, '\n');
247  if ( line.find("LOOKUP_TABLE") == std::string::npos )
248  {
249  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
250  }
251  }
252  else
253  {
254  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
255  }
256  }
258 
260  SizeValueType numberOfComponents = this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents;
261  for ( SizeValueType ii = 0; ii < numberOfComponents; ii++ )
262  {
263  inputFile >> buffer[ii];
264  }
265  }
266  }
267  }
268 
269  template< typename T >
270  void ReadPointDataBufferAsBINARY(std::ifstream & inputFile, T *buffer)
271  {
272  StringType line;
273 
274  while ( !inputFile.eof() )
275  {
276  std::getline(inputFile, line, '\n');
277  if ( line.find("POINT_DATA") != std::string::npos )
278  {
279  if ( !inputFile.eof() )
280  {
281  std::getline(inputFile, line, '\n');
282  }
283  else
284  {
285  itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
286  }
287 
289  if ( line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos )
290  {
291  if ( !inputFile.eof() )
292  {
293  std::getline(inputFile, line, '\n');
294  if ( line.find("LOOKUP_TABLE") == std::string::npos )
295  {
296  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
297  }
298  }
299  else
300  {
301  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
302  }
303  }
305 
307  SizeValueType numberOfComponents = this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents;
308  inputFile.read( reinterpret_cast< char * >( buffer ), numberOfComponents * sizeof( T ) );
310  {
311  itk::ByteSwapper< T >::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
312  }
313  }
314  }
315  }
317 
318  template< typename T >
319  void ReadCellDataBufferAsASCII(std::ifstream & inputFile, T *buffer)
320  {
321  StringType line;
322 
323  while ( !inputFile.eof() )
324  {
325  std::getline(inputFile, line, '\n');
326  if ( line.find("CELL_DATA") != std::string::npos )
327  {
328  if ( !inputFile.eof() )
329  {
330  std::getline(inputFile, line, '\n');
331  }
332  else
333  {
334  itkExceptionMacro("UnExpected end of line while trying to read CELL_DATA");
335  }
336 
338  if ( line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos )
339  {
340  if ( !inputFile.eof() )
341  {
342  std::getline(inputFile, line, '\n');
343  if ( line.find("LOOKUP_TABLE") == std::string::npos )
344  {
345  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
346  }
347  }
348  else
349  {
350  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
351  }
352  }
354 
356  SizeValueType numberOfComponents = this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents;
357  for ( SizeValueType ii = 0; ii < numberOfComponents; ii++ )
358  {
359  inputFile >> buffer[ii];
360  }
361  }
362  }
363  }
364 
365  template< typename T >
366  void ReadCellDataBufferAsBINARY(std::ifstream & inputFile, T *buffer)
367  {
368  StringType line;
369 
370  while ( !inputFile.eof() )
371  {
372  std::getline(inputFile, line, '\n');
373  if ( line.find("POINT_DATA") != std::string::npos )
374  {
375  if ( !inputFile.eof() )
376  {
377  std::getline(inputFile, line, '\n');
378  }
379  else
380  {
381  itkExceptionMacro("UnExpected end of line while trying to read POINT_DATA");
382  }
383 
385  if ( line.find("SCALARS") != std::string::npos && line.find("COLOR_SCALARS") == std::string::npos )
386  {
387  if ( !inputFile.eof() )
388  {
389  std::getline(inputFile, line, '\n');
390  if ( line.find("LOOKUP_TABLE") == std::string::npos )
391  {
392  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
393  }
394  }
395  else
396  {
397  itkExceptionMacro("UnExpected end of line while trying to read LOOKUP_TABLE");
398  }
399  }
400 
402  SizeValueType numberOfComponents = this->m_NumberOfCellPixels * this->m_NumberOfCellPixelComponents;
403  inputFile.read( reinterpret_cast< char * >( buffer ), numberOfComponents * sizeof( T ) );
405  {
406  itk::ByteSwapper< T >::SwapRangeFromSystemToBigEndian(buffer, numberOfComponents);
407  }
408  }
409  }
410  }
412 
413  template< typename T >
414  void WritePointsBufferAsASCII(std::ofstream & outputFile, T *buffer, const StringType & pointComponentType)
415  {
416  NumberToString<T> convert;
418  outputFile << "POINTS " << this->m_NumberOfPoints;
419 
420  outputFile << pointComponentType << '\n';
421  for ( SizeValueType ii = 0; ii < this->m_NumberOfPoints; ii++ )
422  {
423  for ( unsigned int jj = 0; jj < this->m_PointDimension - 1; jj++ )
424  {
425  outputFile << convert(buffer[ii * this->m_PointDimension + jj]) << " ";
426  }
427 
428  outputFile << convert(buffer[ii * this->m_PointDimension + this->m_PointDimension - 1]) << '\n';
429  }
430 
431  return;
432  }
433 
434  template< typename T >
435  void WritePointsBufferAsBINARY(std::ofstream & outputFile, T *buffer, const StringType & pointComponentType)
436  {
438  outputFile << "POINTS " << this->m_NumberOfPoints;
439  outputFile << pointComponentType << "\n";
440  itk::ByteSwapper< T >::SwapWriteRangeFromSystemToBigEndian(buffer, this->m_NumberOfPoints * this->m_PointDimension, &outputFile);
441  outputFile << "\n";
442 
443  return;
444  }
445 
446  template< typename T >
447  void WriteCellsBufferAsASCII(std::ofstream & outputFile, T *buffer)
448  {
449  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
450  unsigned int numberOfVertices = 0;
451  unsigned int numberOfVertexIndices = 0;
452  unsigned int numberOfLines = 0;
453  unsigned int numberOfLineIndices = 0;
454  unsigned int numberOfPolygons = 0;
455  unsigned int numberOfPolygonIndices = 0;
456 
458  SizeValueType index = 0;
459 
460  ExposeMetaData< unsigned int >(metaDic, "numberOfVertices", numberOfVertices);
461  if ( numberOfVertices )
462  {
463  ExposeMetaData< unsigned int >(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
464  outputFile << "VERTICES " << numberOfVertices << " " << numberOfVertexIndices << '\n';
465  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
466  {
467  auto cellType = static_cast< MeshIOBase::CellGeometryType >( static_cast< int >( buffer[index++] ) );
468  auto nn = static_cast< unsigned int >( buffer[index++] );
469  if ( cellType == VERTEX_CELL )
470  {
471  outputFile << nn;
472  for ( unsigned int jj = 0; jj < nn; jj++ )
473  {
474  outputFile << " " << buffer[index++];
475  }
476  outputFile << '\n';
477  }
478  else
479  {
480  index += nn;
481  }
482  }
483  }
484 
486  index = 0;
487  ExposeMetaData< unsigned int >(metaDic, "numberOfLines", numberOfLines);
488  if ( numberOfLines )
489  {
490  numberOfLineIndices = 0;
491  SizeValueType numberOfPolylines = 0;
492  PolylinesContainerPointer polylines = PolylinesContainerType::New();
493  PointIdVector pointIds;
494  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
495  {
496  auto cellType = static_cast< MeshIOBase::CellGeometryType >( static_cast< int >( buffer[index++] ) );
497  auto nn = static_cast< unsigned int >( buffer[index++] );
498  if ( cellType == LINE_CELL )
499  {
500  if ( pointIds.size() >= nn )
501  {
502  SizeValueType id = pointIds.back();
503  if ( id == static_cast< SizeValueType >( buffer[index] ) )
504  {
505  pointIds.push_back( static_cast< SizeValueType >( buffer[index + 1] ) );
506  }
507  else if ( id == static_cast< SizeValueType >( buffer[index + 1] ) )
508  {
509  pointIds.push_back( static_cast< SizeValueType >( buffer[index] ) );
510  }
511  else
512  {
513  polylines->InsertElement(numberOfPolylines++, pointIds);
514  numberOfLineIndices += pointIds.size();
515  pointIds.clear();
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  else
525  {
526  for ( unsigned int jj = 0; jj < nn; jj++ )
527  {
528  pointIds.push_back( static_cast< SizeValueType >( buffer[index + jj] ) );
529  }
530  }
531  }
532 
533  index += nn;
534  }
535  polylines->InsertElement(numberOfPolylines++, pointIds);
536  numberOfLineIndices += pointIds.size();
537  pointIds.clear();
538 
539  numberOfLines = polylines->Size();
540  numberOfLineIndices += numberOfLines;
541  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLines", numberOfLines);
542  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLineIndices", numberOfLineIndices);
543  outputFile << "LINES " << numberOfLines << " " << numberOfLineIndices << '\n';
544  for ( SizeValueType ii = 0; ii < polylines->Size(); ++ii )
545  {
546  auto nn = static_cast<unsigned int>( polylines->ElementAt(ii).size() );
547  outputFile << nn;
548  for ( unsigned int jj = 0; jj < nn; ++jj )
549  {
550  outputFile << " " << polylines->ElementAt(ii)[jj];
551  }
552  outputFile << '\n';
553  }
554  }
555 
557  index = 0;
558  ExposeMetaData< unsigned int >(metaDic, "numberOfPolygons", numberOfPolygons);
559  if ( numberOfPolygons )
560  {
561  ExposeMetaData< unsigned int >(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
562  outputFile << "POLYGONS " << numberOfPolygons << " " << numberOfPolygonIndices << '\n';
563  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
564  {
565  auto cellType = static_cast< MeshIOBase::CellGeometryType >( static_cast< int >( buffer[index++] ) );
566  auto nn = static_cast< unsigned int >( buffer[index++] );
567  if ( cellType == POLYGON_CELL ||
568  cellType == TRIANGLE_CELL ||
569  cellType == QUADRILATERAL_CELL )
570  {
571  outputFile << nn;
572  for ( unsigned int jj = 0; jj < nn; jj++ )
573  {
574  outputFile << " " << buffer[index++];
575  }
576  outputFile << '\n';
577  }
578  else
579  {
580  index += nn;
581  }
582  }
583  }
584  }
586 
587  template< typename T >
588  void WriteCellsBufferAsBINARY(std::ofstream & outputFile, T *buffer)
589  {
590  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
591  unsigned int numberOfVertices = 0;
592  unsigned int numberOfVertexIndices = 0;
593  unsigned int numberOfLines = 0;
594  unsigned int numberOfLineIndices = 0;
595  unsigned int numberOfPolygons = 0;
596  unsigned int numberOfPolygonIndices = 0;
597 
599  SizeValueType index = 0;
600 
601  ExposeMetaData< unsigned int >(metaDic, "numberOfVertices", numberOfVertices);
602  if ( numberOfVertices )
603  {
604  ExposeMetaData< unsigned int >(metaDic, "numberOfVertexIndices", numberOfVertexIndices);
605  outputFile << "VERTICES " << numberOfVertices << " " << numberOfVertexIndices << '\n';
606  auto * data = new unsigned int[numberOfVertexIndices];
607  ReadCellsBuffer(buffer, data);
608  itk::ByteSwapper< unsigned int >::SwapWriteRangeFromSystemToBigEndian(data, numberOfVertexIndices, &outputFile);
609  outputFile << "\n";
610  delete[] data;
611  }
612 
614  index = 0;
615  ExposeMetaData< unsigned int >(metaDic, "numberOfLines", numberOfLines);
616  if ( numberOfLines )
617  {
618  numberOfLineIndices = 0;
619  SizeValueType numberOfPolylines = 0;
620  PolylinesContainerPointer polylines = PolylinesContainerType::New();
621  PointIdVector pointIds;
622  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
623  {
624  auto cellType = static_cast< MeshIOBase::CellGeometryType >( static_cast< int >( buffer[index++] ) );
625  auto nn = static_cast< unsigned int >( buffer[index++] );
626  if ( cellType == LINE_CELL )
627  {
628  if ( pointIds.size() >= nn )
629  {
630  SizeValueType id = pointIds.back();
631  if ( id == static_cast< SizeValueType >( buffer[index] ) )
632  {
633  pointIds.push_back( static_cast< SizeValueType >( buffer[index + 1] ) );
634  }
635  else if ( id == static_cast< SizeValueType >( buffer[index + 1] ) )
636  {
637  pointIds.push_back( static_cast< SizeValueType >( buffer[index] ) );
638  }
639  else
640  {
641  polylines->InsertElement(numberOfPolylines++, pointIds);
642  numberOfLineIndices += pointIds.size();
643  pointIds.clear();
645 
646  for ( unsigned int jj = 0; jj < nn; jj++ )
647  {
648  pointIds.push_back( static_cast< SizeValueType >( buffer[index + jj] ) );
649  }
650  }
651  }
652  else
653  {
654  for ( unsigned int jj = 0; jj < nn; jj++ )
655  {
656  pointIds.push_back( static_cast< SizeValueType >( buffer[index + jj] ) );
657  }
658  }
659  }
660 
661  index += nn;
662  }
663  polylines->InsertElement(numberOfPolylines++, pointIds);
664  numberOfLineIndices += pointIds.size();
665  pointIds.clear();
666 
667  numberOfLines = polylines->Size();
668  numberOfLineIndices += numberOfLines;
669  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLines", numberOfLines);
670  EncapsulateMetaData< unsigned int >(metaDic, "numberOfLineIndices", numberOfLineIndices);
671 
672  outputFile << "LINES " << numberOfLines << " " << numberOfLineIndices << '\n';
673  auto * data = new unsigned int[numberOfLineIndices];
674  unsigned long outputIndex = 0;
675  for ( SizeValueType ii = 0; ii < polylines->Size(); ++ii )
676  {
677  auto nn = static_cast<unsigned int>( polylines->ElementAt(ii).size() );
678  data[outputIndex++] = nn;
679  for ( unsigned int jj = 0; jj < nn; ++jj )
680  {
681  data[outputIndex++] = polylines->ElementAt(ii)[jj];
682  }
683  }
684 
685  itk::ByteSwapper< unsigned int >::SwapWriteRangeFromSystemToBigEndian(data, numberOfLineIndices, &outputFile);
686  outputFile << "\n";
687  delete[] data;
688  }
689 
691  index = 0;
692  ExposeMetaData< unsigned int >(metaDic, "numberOfPolygons", numberOfPolygons);
693  if ( numberOfPolygons )
694  {
695  ExposeMetaData< unsigned int >(metaDic, "numberOfPolygonIndices", numberOfPolygonIndices);
696  outputFile << "POLYGONS " << numberOfPolygons << " " << numberOfPolygonIndices << '\n';
697  auto * data = new unsigned int[numberOfPolygonIndices];
698  ReadCellsBuffer(buffer, data);
699  itk::ByteSwapper< unsigned int >::SwapWriteRangeFromSystemToBigEndian(data, numberOfPolygonIndices, &outputFile);
700  outputFile << "\n";
701  delete[] data;
702  }
703  }
705 
706  template< typename T >
707  void WritePointDataBufferAsASCII(std::ofstream & outputFile, T *buffer, const StringType & pointPixelComponentName)
708  {
709  NumberToString<T> convert;
710  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
711  StringType dataName;
712 
713  outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << '\n';
714  switch ( this->m_PointPixelType )
715  {
716  case SCALAR:
717  {
718  outputFile << "SCALARS ";
719  ExposeMetaData< StringType >(metaDic, "pointScalarDataName", dataName);
720  outputFile << dataName << " ";
721  break;
722  }
723  case OFFSET:
724  case POINT:
725  case COVARIANTVECTOR:
726  case VECTOR:
727  {
728  outputFile << "VECTORS ";
729  ExposeMetaData< StringType >(metaDic, "pointVectorDataName", dataName);
730  outputFile << dataName << " ";
731  break;
732  }
733  case SYMMETRICSECONDRANKTENSOR:
734  case DIFFUSIONTENSOR3D:
735  {
736  outputFile << "TENSORS ";
737  ExposeMetaData< StringType >(metaDic, "pointTensorDataName", dataName);
738  outputFile << dataName << " ";
739  break;
740  }
741  case ARRAY:
742  case VARIABLELENGTHVECTOR:
743  {
744  outputFile << "COLOR_SCALARS ";
745  ExposeMetaData< StringType >(metaDic, "pointColorScalarDataName", dataName);
746  outputFile << dataName << " ";
747  WriteColorScalarBufferAsASCII(outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
748  return;
749  }
750  default:
751  {
752  itkExceptionMacro(<< "Unknown point pixel type");
753  }
754  }
755 
756  outputFile << pointPixelComponentName << '\n';
757 
758  if ( this->m_PointPixelType == SCALAR )
759  {
760  outputFile << "LOOKUP_TABLE default" << '\n';
761  }
762 
763  Indent indent(2);
764  if ( this->m_PointPixelType == SYMMETRICSECONDRANKTENSOR )
765  {
766  T *ptr = buffer;
767  SizeValueType i = 0;
768  const SizeValueType num = this->m_NumberOfPointPixelComponents * this->m_NumberOfPointPixels;
769  // Note that only the 3D tensors are supported in the VTK File Format
770  // documentation.
771  if( this->m_NumberOfPointPixelComponents == 3 )
772  {
773  T zero( itk::NumericTraits<T>::ZeroValue() );
774  T e12;
775  while( i < num )
776  {
777  // row 1
778  outputFile << convert(*ptr++) << indent;
779  e12 = *ptr++;
780  outputFile << convert(e12) << indent;
781  outputFile << convert(zero) << '\n';
782  // row 2
783  outputFile << convert(e12) << indent;
784  outputFile << convert(*ptr++) << indent;
785  outputFile << convert(zero) << '\n';
786  // row 3
787  outputFile << convert(zero) << indent << convert(zero) << indent << convert(zero) << "\n\n";
788  i += 3;
789  }
790  }
791  else if( this->m_NumberOfPointPixelComponents == 6 )
792  {
793  T e12;
794  T e13;
795  T e23;
796  while( i < num )
797  {
798  // row 1
799  outputFile << convert(*ptr++) << indent;
800  e12 = *ptr++;
801  outputFile << convert(e12) << indent;
802  e13 = *ptr++;
803  outputFile << convert(e13) << '\n';
804  // row 2
805  outputFile << convert(e12) << indent;
806  outputFile << convert(*ptr++) << indent;
807  e23 = *ptr++;
808  outputFile << convert(e23) << '\n';
809  // row 3
810  outputFile << convert(e13) << indent;
811  outputFile << convert(e23) << indent;
812  outputFile << convert(*ptr++) << "\n\n";
813  i += 6;
814  }
815  }
816  else
817  {
818  ::itk::ExceptionObject e_(__FILE__, __LINE__,
819  "itk::ERROR: VTKImageIO2: Unsupported number of components in tensor.",
820  ITK_LOCATION);
821  throw e_;
822  }
823  }
824  else // not tensor
825  {
826  unsigned int jj;
827  for ( SizeValueType ii = 0; ii < this->m_NumberOfPointPixels; ii++ )
828  {
829  for ( jj = 0; jj < this->m_NumberOfPointPixelComponents - 1; jj++ )
830  {
831  outputFile << convert(buffer[ii * this->m_NumberOfPointPixelComponents + jj]) << indent;
832  }
833  outputFile << convert(buffer[ii * this->m_NumberOfPointPixelComponents + jj]);
834  outputFile << '\n';
835  }
836  }
837 
838  return;
839  }
840 
841  template< typename T >
842  void WritePointDataBufferAsBINARY(std::ofstream & outputFile, T *buffer, const StringType & pointPixelComponentName)
843  {
844  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
845  StringType dataName;
846 
847  outputFile << "POINT_DATA " << this->m_NumberOfPointPixels << "\n";
848  switch ( this->m_PointPixelType )
849  {
850  case SCALAR:
851  {
852  outputFile << "SCALARS ";
853  ExposeMetaData< StringType >(metaDic, "pointScalarDataName", dataName);
854  outputFile << dataName << " ";
855  break;
856  }
857  case OFFSET:
858  case POINT:
859  case COVARIANTVECTOR:
860  case VECTOR:
861  {
862  outputFile << "VECTORS ";
863  ExposeMetaData< StringType >(metaDic, "pointVectorDataName", dataName);
864  outputFile << dataName << " ";
865  break;
866  }
867  case SYMMETRICSECONDRANKTENSOR:
868  case DIFFUSIONTENSOR3D:
869  {
870  outputFile << "TENSORS ";
871  ExposeMetaData< StringType >(metaDic, "pointTensorDataName", dataName);
872  outputFile << dataName << " ";
873  break;
874  }
875  case ARRAY:
876  case VARIABLELENGTHVECTOR:
877  {
878  outputFile << "COLOR_SCALARS ";
879  ExposeMetaData< StringType >(metaDic, "pointColorScalarDataName", dataName);
880  outputFile << dataName << " ";
881  WriteColorScalarBufferAsBINARY(outputFile, buffer, this->m_NumberOfPointPixelComponents, this->m_NumberOfPointPixels);
882  return;
883  }
884  default:
885  {
886  itkExceptionMacro(<< "Unknown point pixel type");
887  }
888  }
889 
890  outputFile << pointPixelComponentName << "\n";
891  if ( this->m_PointPixelType == SCALAR )
892  {
893  outputFile << "LOOKUP_TABLE default\n";
894  }
895 
897  this->m_NumberOfPointPixels * this->m_NumberOfPointPixelComponents,
898  &outputFile);
899  outputFile << "\n";
900  return;
901  }
902 
903  template< typename T >
904  void WriteCellDataBufferAsASCII(std::ofstream & outputFile, T *buffer, const StringType & cellPixelComponentName)
905  {
906  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
907  StringType dataName;
908 
909  outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << '\n';
910  switch ( this->m_CellPixelType )
911  {
912  case SCALAR:
913  {
914  outputFile << "SCALARS ";
915  ExposeMetaData< StringType >(metaDic, "cellScalarDataName", dataName);
916  outputFile << dataName << " ";
917  break;
918  }
919  case OFFSET:
920  case POINT:
921  case COVARIANTVECTOR:
922  case VECTOR:
923  {
924  outputFile << "VECTORS ";
925  ExposeMetaData< StringType >(metaDic, "cellVectorDataName", dataName);
926  outputFile << dataName << " ";
927  break;
928  }
929  case SYMMETRICSECONDRANKTENSOR:
930  case DIFFUSIONTENSOR3D:
931  {
932  outputFile << "TENSORS ";
933  ExposeMetaData< StringType >(metaDic, "cellTensorDataName", dataName);
934  outputFile << dataName << " ";
935  break;
936  }
937  case ARRAY:
938  case VARIABLELENGTHVECTOR:
939  {
940  outputFile << "COLOR_SCALARS ";
941  ExposeMetaData< StringType >(metaDic, "cellColorScalarDataName", dataName);
942  outputFile << dataName << " ";
943  WriteColorScalarBufferAsASCII(outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
944  return;
945  }
946  default:
947  {
948  itkExceptionMacro(<< "Unknown cell pixel type");
949  }
950  }
951 
952  outputFile << cellPixelComponentName << '\n';
953  if ( this->m_CellPixelType == SCALAR )
954  {
955  outputFile << "LOOKUP_TABLE default" << '\n';
956  }
957 
958  Indent indent(2);
959  if ( this->m_CellPixelType == SYMMETRICSECONDRANKTENSOR )
960  {
961  T *ptr = buffer;
962  SizeValueType i = 0;
963  const SizeValueType num = this->m_NumberOfCellPixelComponents * this->m_NumberOfCellPixels;
964  if( this->m_NumberOfCellPixelComponents == 2 )
965  {
966  T zero( itk::NumericTraits<T>::ZeroValue() );
967  T e12;
968  while( i < num )
969  {
970  // row 1
971  outputFile << *ptr++ << indent;
972  e12 = *ptr++;
973  outputFile << e12 << indent;
974  outputFile << zero << '\n';
975  // row 2
976  outputFile << e12 << indent;
977  outputFile << *ptr++ << indent;
978  outputFile << zero << '\n';
979  // row 3
980  outputFile << zero << indent << zero << indent << zero << "\n\n";
981  i += 3;
982  }
983  }
984  else if( this->m_NumberOfCellPixelComponents == 3 )
985  {
986  T e12;
987  T e13;
988  T e23;
989  while( i < num )
990  {
991  // row 1
992  outputFile << *ptr++ << indent;
993  e12 = *ptr++;
994  outputFile << e12 << indent;
995  e13 = *ptr++;
996  outputFile << e13 << '\n';
997  // row 2
998  outputFile << e12 << indent;
999  outputFile << *ptr++ << indent;
1000  e23 = *ptr++;
1001  outputFile << e23 << '\n';
1002  // row 3
1003  outputFile << e13 << indent;
1004  outputFile << e23 << indent;
1005  outputFile << *ptr++ << "\n\n";
1006  i += 6;
1007  }
1008  }
1009  else
1010  {
1011  ExceptionObject e_(__FILE__, __LINE__,
1012  "itk::ERROR: VTKPolyDataMeshIO: Unsupported number of components in tensor.",
1013  ITK_LOCATION);
1014  throw e_;
1015  }
1016  }
1017  else // not tensor
1018  {
1019  unsigned int jj;
1020  for ( SizeValueType ii = 0; ii < this->m_NumberOfCellPixels; ii++ )
1021  {
1022  for ( jj = 0; jj < this->m_NumberOfCellPixelComponents - 1; jj++ )
1023  {
1024  outputFile << buffer[ii * this->m_NumberOfCellPixelComponents + jj] << indent;
1025  }
1026  outputFile << buffer[ii * this->m_NumberOfCellPixelComponents + jj];
1027  outputFile << '\n';
1028  }
1029  }
1030 
1031  return;
1032  }
1033 
1034  template< typename T >
1035  void WriteCellDataBufferAsBINARY(std::ofstream & outputFile, T *buffer, const StringType & cellPixelComponentName)
1036  {
1037  MetaDataDictionary & metaDic = this->GetMetaDataDictionary();
1038  StringType dataName;
1039 
1040  outputFile << "CELL_DATA " << this->m_NumberOfCellPixels << "\n";
1041  switch ( this->m_CellPixelType )
1042  {
1043  case SCALAR:
1044  {
1045  outputFile << "SCALARS ";
1046  ExposeMetaData< StringType >(metaDic, "cellScalarDataName", dataName);
1047  outputFile << dataName << " ";
1048  break;
1049  }
1050  case OFFSET:
1051  case POINT:
1052  case COVARIANTVECTOR:
1053  case VECTOR:
1054  {
1055  outputFile << "VECTORS ";
1056  ExposeMetaData< StringType >(metaDic, "cellVectorDataName", dataName);
1057  outputFile << dataName << " ";
1058  break;
1059  }
1060  case SYMMETRICSECONDRANKTENSOR:
1061  case DIFFUSIONTENSOR3D:
1062  {
1063  outputFile << "TENSORS ";
1064  ExposeMetaData< StringType >(metaDic, "cellTensorDataName", dataName);
1065  outputFile << dataName << " ";
1066  break;
1067  }
1068  case ARRAY:
1069  case VARIABLELENGTHVECTOR:
1070  {
1071  outputFile << "COLOR_SCALARS ";
1072  ExposeMetaData< StringType >(metaDic, "cellColorScalarDataName", dataName);
1073  outputFile << dataName << " ";
1074  WriteColorScalarBufferAsBINARY(outputFile, buffer, this->m_NumberOfCellPixelComponents, this->m_NumberOfCellPixels);
1075  return;
1076  }
1077  default:
1078  {
1079  itkExceptionMacro(<< "Unknown cell pixel type");
1080  }
1081  }
1082 
1083  outputFile << cellPixelComponentName << "\n";
1084  if ( this->m_CellPixelType == SCALAR )
1085  {
1086  outputFile << "LOOKUP_TABLE default\n";
1087  }
1088 
1090  this->m_NumberOfCells * this->m_NumberOfCellPixelComponents,
1091  &outputFile);
1092  outputFile << "\n";
1093  return;
1094  }
1095 
1096  template< typename T >
1097  void WriteColorScalarBufferAsASCII(std::ofstream & outputFile,
1098  T *buffer,
1099  unsigned int numberOfPixelComponents,
1100  SizeValueType numberOfPixels)
1101  {
1102  NumberToString<float> convert;
1103  outputFile << numberOfPixelComponents << "\n";
1104  Indent indent(2);
1105  for ( SizeValueType ii = 0; ii < numberOfPixels; ++ii )
1106  {
1107  for ( unsigned int jj = 0; jj < numberOfPixelComponents; ++jj )
1108  {
1109  outputFile << convert(static_cast< float >( buffer[ii * numberOfPixelComponents + jj])) << indent;
1110  }
1111 
1112  outputFile << "\n";
1113  }
1114 
1115  return;
1116  }
1117 
1118  template< typename T >
1119  void WriteColorScalarBufferAsBINARY(std::ofstream & outputFile,
1120  T *buffer,
1121  unsigned int numberOfPixelComponents,
1122  SizeValueType numberOfPixels)
1123  {
1124  outputFile << numberOfPixelComponents << "\n";
1125  SizeValueType numberOfElements = numberOfPixelComponents * numberOfPixels;
1126  auto * data = new unsigned char[numberOfElements];
1127  for ( SizeValueType ii = 0; ii < numberOfElements; ++ii )
1128  {
1129  data[ii] = static_cast< unsigned char >( buffer[ii] );
1130  }
1131 
1132  outputFile.write(reinterpret_cast< char * >( data ), numberOfElements);
1133 
1134  delete[] data;
1135  outputFile << "\n";
1136  return;
1137  }
1138 
1141  template< typename TInput, typename TOutput >
1142  void ReadCellsBuffer(TInput *input, TOutput *output)
1143  {
1144  SizeValueType inputIndex = 0;
1145  SizeValueType outputIndex = 0;
1146 
1147  if ( input && output )
1148  {
1149  for ( SizeValueType ii = 0; ii < this->m_NumberOfCells; ii++ )
1150  {
1151  inputIndex++;
1152  auto nn = static_cast< unsigned int >( input[inputIndex++] );
1153  output[outputIndex++] = nn;
1154  for ( unsigned int jj = 0; jj < nn; jj++ )
1155  {
1156  output[outputIndex++] = static_cast< TOutput >( input[inputIndex++] );
1157  }
1158  }
1159  }
1160  }
1161 
1163  IOComponentType GetComponentTypeFromString(const std::string & pixelType);
1164 };
1165 } // end namespace itk
1166 
1167 #endif // itkVTKPolyDataMeshIO_h
Light weight base class for most itk classes.
IdentifierType SizeValueType
Definition: itkMeshIOBase.h:86
unsigned long SizeValueType
Definition: itkIntTypes.h:83
void WritePointsBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &pointComponentType)
This class defines how to read and write vtk legacy file format.
void ReadPointsBufferAsASCII(std::ifstream &inputFile, T *buffer)
void ReadCellDataBufferAsASCII(std::ifstream &inputFile, T *buffer)
std::vector< SizeValueType > PointIdVector
std::stringstream StringStreamType
void WritePointsBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &pointComponentType)
void WriteColorScalarBufferAsBINARY(std::ofstream &outputFile, T *buffer, unsigned int numberOfPixelComponents, SizeValueType numberOfPixels)
void ReadCellsBuffer(TInput *input, TOutput *output)
static void SwapRangeFromSystemToBigEndian(T *p, BufferSizeType num)
void WriteCellsBufferAsBINARY(std::ofstream &outputFile, T *buffer)
Provides a mechanism for storing a collection of arbitrary data types.
Convert floating and fixed point numbers to strings.
void ReadCellDataBufferAsBINARY(std::ifstream &inputFile, T *buffer)
Standard exception handling object.
void WriteCellDataBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &cellPixelComponentName)
void WriteCellDataBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &cellPixelComponentName)
void ReadPointsBufferAsBINARY(std::ifstream &inputFile, T *buffer)
void WritePointDataBufferAsBINARY(std::ofstream &outputFile, T *buffer, const StringType &pointPixelComponentName)
void ReadPointDataBufferAsBINARY(std::ifstream &inputFile, T *buffer)
Define a front-end to the STL &quot;vector&quot; container that conforms to the IndexedContainerInterface.
std::vector< StringType > StringVectorType
void WriteCellsBufferAsASCII(std::ofstream &outputFile, T *buffer)
Control indentation during Print() invocation.
Definition: itkIndent.h:49
static void SwapWriteRangeFromSystemToBigEndian(T *p, int num, OStreamType *fp)
Abstract superclass defines mesh IO interface.
Definition: itkMeshIOBase.h:69
void WritePointDataBufferAsASCII(std::ofstream &outputFile, T *buffer, const StringType &pointPixelComponentName)
void WriteColorScalarBufferAsASCII(std::ofstream &outputFile, T *buffer, unsigned int numberOfPixelComponents, SizeValueType numberOfPixels)
Base class for most ITK classes.
Definition: itkObject.h:60
Perform machine dependent byte swapping.
void ReadPointDataBufferAsASCII(std::ifstream &inputFile, T *buffer)
void UpdateCellInformation(T *buffer)