Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.