Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkSurfaceStlIO.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkSurfaceStlIO.h"
14 
15 #include "mitkIOMimeTypes.h"
16 #include "mitkLocaleSwitch.h"
17 #include "mitkSurface.h"
18 
19 #include <vtkCleanPolyData.h>
20 #include <vtkErrorCode.h>
21 #include <vtkPolyDataNormals.h>
22 #include <vtkSTLReader.h>
23 #include <vtkSTLWriter.h>
24 #include <vtkSmartPointer.h>
25 #include <vtkTriangleFilter.h>
26 
27 namespace mitk
28 {
29  std::string SurfaceStlIO::OPTION_MERGE_POINTS()
30  {
31  static std::string s = "Merge points";
32  return s;
33  }
34 
35  std::string SurfaceStlIO::OPTION_TAG_SOLIDS()
36  {
37  static std::string s = "Tag solids";
38  return s;
39  }
40 
41  std::string SurfaceStlIO::OPTION_CLEAN()
42  {
43  static std::string s = "Clean poly data";
44  return s;
45  }
46 
48  : SurfaceVtkIO(Surface::GetStaticNameOfClass(), IOMimeTypes::STEREOLITHOGRAPHY_MIMETYPE(), "Stereolithography")
49  {
50  Options defaultOptions;
51 
52  defaultOptions[OPTION_MERGE_POINTS()] = us::Any(true);
53  defaultOptions[OPTION_TAG_SOLIDS()] = us::Any(false);
54  defaultOptions[OPTION_CLEAN()] = us::Any(true);
55 
56  this->SetDefaultReaderOptions(defaultOptions);
57 
58  this->RegisterService();
59  }
60 
61  std::vector<itk::SmartPointer<BaseData>> SurfaceStlIO::Read()
62  {
63  LocaleSwitch localeSwitch("C");
64 
65  Options options = this->GetReaderOptions();
66 
68 
69  vtkSmartPointer<vtkSTLReader> stlReader = vtkSmartPointer<vtkSTLReader>::New();
70  stlReader->SetFileName(this->GetLocalFileName().c_str());
71 
72  bool mergePoints = true;
73  bool tagSolids = false;
74  bool cleanData = true;
75 
76  try
77  {
78  mergePoints = us::any_cast<bool>(options[OPTION_MERGE_POINTS()]);
79  tagSolids = us::any_cast<bool>(options[OPTION_TAG_SOLIDS()]);
80  cleanData = us::any_cast<bool>(options[OPTION_CLEAN()]);
81  }
82  catch (const us::BadAnyCastException &e)
83  {
84  MITK_WARN << "Unexpected error: " << e.what();
85  }
86 
87  stlReader->SetMerging(mergePoints);
88  stlReader->SetScalarTags(tagSolids);
89 
90  vtkSmartPointer<vtkPolyDataNormals> normalsGenerator = vtkSmartPointer<vtkPolyDataNormals>::New();
91  normalsGenerator->SetInputConnection(stlReader->GetOutputPort());
92 
93  vtkSmartPointer<vtkPolyDataAlgorithm> algo = normalsGenerator;
94  if (cleanData)
95  {
96  vtkSmartPointer<vtkCleanPolyData> cleanPolyDataFilter = vtkSmartPointer<vtkCleanPolyData>::New();
97  cleanPolyDataFilter->SetInputConnection(normalsGenerator->GetOutputPort());
98  cleanPolyDataFilter->PieceInvariantOff();
99  cleanPolyDataFilter->ConvertLinesToPointsOff();
100  cleanPolyDataFilter->ConvertPolysToLinesOff();
101  cleanPolyDataFilter->ConvertStripsToPolysOff();
102  if (mergePoints)
103  {
104  cleanPolyDataFilter->PointMergingOn();
105  }
106  algo = cleanPolyDataFilter;
107  }
108  algo->Update();
109 
110  if (algo->GetOutput() != nullptr)
111  {
112  vtkSmartPointer<vtkPolyData> surfaceWithNormals = algo->GetOutput();
113  output->SetVtkPolyData(surfaceWithNormals);
114  }
115 
116  std::vector<BaseData::Pointer> result;
117  result.push_back(output.GetPointer());
118  return result;
119  }
120 
122  {
123  LocaleSwitch localeSwitch("C");
124 
126  const auto *input = dynamic_cast<const Surface *>(this->GetInput());
127 
128  const unsigned int timesteps = input->GetTimeGeometry()->CountTimeSteps();
129  for (unsigned int t = 0; t < timesteps; ++t)
130  {
131  std::string fileName;
132  vtkSmartPointer<vtkPolyData> polyData = this->GetPolyData(t, fileName);
133  vtkSmartPointer<vtkTriangleFilter> triangleFilter = vtkSmartPointer<vtkTriangleFilter>::New();
134  triangleFilter->SetInputData(polyData);
135  vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();
136  writer->SetInputConnection(triangleFilter->GetOutputPort());
137 
138  // The vtk stl writer cannot write to streams
139  LocalFile localFile(this);
140  writer->SetFileName(localFile.GetFileName().c_str());
141 
142  if (writer->Write() == 0 || writer->GetErrorCode() != 0)
143  {
144  mitkThrow() << "Error during surface writing"
145  << (writer->GetErrorCode() ?
146  std::string(": ") + vtkErrorCode::GetStringFromErrorCode(writer->GetErrorCode()) :
147  std::string());
148  }
149 
150  if (this->GetOutputStream() && input->GetTimeGeometry()->CountTimeSteps() > 1)
151  {
152  MITK_WARN << "Writing multiple time-steps to output streams is not supported. "
153  << "Only the first time-step will be written";
154  break;
155  }
156  }
157  }
158 
159  SurfaceStlIO *SurfaceStlIO::IOClone() const { return new SurfaceStlIO(*this); }
160 }
Class for storing surfaces (vtkPolyData).
Definition: mitkSurface.h:28
virtual TimeStepType CountTimeSteps() const =0
Returns the number of time steps.
The IOMimeTypes class.
DataCollection - Class to facilitate loading/accessing structured data.
ValueType * any_cast(Any *operand)
Definition: usAny.h:377
void SetDefaultReaderOptions(const Options &defaultOptions)
vtkSmartPointer< vtkPolyData > GetPolyData(unsigned int t, std::string &fileName)
std::map< std::string, us::Any > Options
Options for reading or writing data.
Definition: mitkIFileIO.h:69
void Write() override
Write the base data to the specified location or output stream.
const char * what() const override
Definition: usAny.h:352
std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
std::string GetLocalFileName() const
Get a local file name for reading.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:61
#define MITK_WARN
Definition: mitkLogMacros.h:19
Convenience class to temporarily change the current locale.
std::pair< us::ServiceRegistration< IFileReader >, us::ServiceRegistration< IFileWriter > > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define mitkThrow()
const BaseData * GetInput() const override
Get the input data set via SetInput().
Definition: usAny.h:163
A local file representation for streams.
std::ostream * GetOutputStream() const override
Get the output stream.
Options GetReaderOptions() const
static Pointer New()