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