Medical Imaging Interaction Toolkit  2018.4.99-08619e4f
Medical Imaging Interaction Toolkit
mitkBoundingShapeVtkMapper3D.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 
14 #include "../DataManagement/mitkBoundingShapeUtil.h"
15 #include <mitkBaseProperty.h>
16 #include <vtkAppendPolyData.h>
17 #include <vtkCamera.h>
18 #include <vtkCubeSource.h>
19 #include <vtkDataSetMapper.h>
20 #include <vtkMath.h>
21 #include <vtkPolyData.h>
22 #include <vtkPolyDataMapper.h>
23 #include <vtkSphereSource.h>
24 #include <vtkTransformFilter.h>
25 
26 namespace mitk
27 {
28  class BoundingShapeVtkMapper3D::Impl
29  {
30  class LocalStorage : public Mapper::BaseLocalStorage
31  {
32  public:
33  LocalStorage();
34  ~LocalStorage() override;
35 
36  LocalStorage(const LocalStorage &) = delete;
37  LocalStorage &operator=(const LocalStorage &) = delete;
38 
39  std::vector<vtkSmartPointer<vtkSphereSource>> Handles;
40  vtkSmartPointer<vtkActor> Actor;
41  vtkSmartPointer<vtkActor> HandleActor;
42  vtkSmartPointer<vtkActor> SelectedHandleActor;
43  vtkSmartPointer<vtkPropAssembly> PropAssembly;
44  };
45 
46  public:
47  Impl() : DistanceFromCam(1.0)
48  {
49  Point3D initialPoint;
50  initialPoint.Fill(0);
51 
52  for (int i = 0; i < 6; ++i)
53  HandlePropertyList.push_back(Handle(initialPoint, i, GetHandleIndices(i)));
54  }
55 
56  double DistanceFromCam;
57  std::vector<Handle> HandlePropertyList;
58  mitk::LocalStorageHandler<LocalStorage> LocalStorageHandler;
59  };
60 }
61 
62 mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::LocalStorage()
63  : Actor(vtkSmartPointer<vtkActor>::New()),
64  HandleActor(vtkSmartPointer<vtkActor>::New()),
65  SelectedHandleActor(vtkSmartPointer<vtkActor>::New()),
66  PropAssembly(vtkSmartPointer<vtkPropAssembly>::New())
67 {
68  for (int i = 0; i < 6; i++)
69  Handles.push_back(vtkSmartPointer<vtkSphereSource>::New());
70 }
71 
72 mitk::BoundingShapeVtkMapper3D::Impl::LocalStorage::~LocalStorage()
73 {
74 }
75 
77 {
78  Superclass::SetDefaultProperties(node, renderer, overwrite);
79 }
80 
81 mitk::BoundingShapeVtkMapper3D::BoundingShapeVtkMapper3D() : m_Impl(new Impl)
82 {
83 }
84 
85 mitk::BoundingShapeVtkMapper3D::~BoundingShapeVtkMapper3D()
86 {
87  delete m_Impl;
88 }
89 
91 {
92  //Superclass::ApplyColorAndOpacityProperties(renderer, actor);
93 }
94 
96 {
97  if (actor == nullptr)
98  return;
99 
100  auto dataNode = this->GetDataNode();
101 
102  if (dataNode == nullptr)
103  return;
104 
105  bool isVisible = false;
106  dataNode->GetBoolProperty("Bounding Shape.3D Rendering", isVisible, renderer);
107 
108  actor->SetVisibility(isVisible);
109 
110  float lineWidth = 1.0f;
111  dataNode->GetFloatProperty("Bounding Shape.Line.Width", lineWidth, renderer);
112 
113  auto property = actor->GetProperty();
114  property->SetLineWidth(lineWidth);
115 }
116 
118 {
119  auto dataNode = this->GetDataNode();
120 
121  if (dataNode == nullptr)
122  return;
123 
124  vtkCamera *camera = renderer->GetVtkRenderer()->GetActiveCamera();
125 
126  auto localStorage = m_Impl->LocalStorageHandler.GetLocalStorage(renderer);
127  bool needGenerateData = localStorage->GetLastGenerateDataTime() < dataNode->GetMTime();
128  double distance = camera->GetDistance();
129 
130  if (std::abs(distance - m_Impl->DistanceFromCam) > mitk::eps)
131  {
132  m_Impl->DistanceFromCam = distance;
133  needGenerateData = true;
134  }
135 
136  if (needGenerateData)
137  {
138  bool isVisible = true;
139  dataNode->GetVisibility(isVisible, renderer);
140 
141  if (!isVisible)
142  {
143  localStorage->Actor->VisibilityOff();
144  return;
145  }
146 
147  // set the input-object at time t for the mapper
148  auto *geometryData = dynamic_cast<GeometryData *>(dataNode->GetData());
149  if (geometryData == nullptr)
150  return;
151 
152  mitk::BaseGeometry::Pointer geometry = geometryData->GetGeometry();
153  mitk::Vector3D spacing = geometry->GetSpacing();
154 
155  // calculate cornerpoints from geometry
156  std::vector<Point3D> cornerPoints = GetCornerPoints(geometry, true);
157 
158  Point3D p0 = cornerPoints[0];
159  Point3D p1 = cornerPoints[1];
160  Point3D p2 = cornerPoints[2];
161  Point3D p4 = cornerPoints[4];
162 
163  Point3D extent;
164  extent[0] =
165  sqrt((p0[0] - p4[0]) * (p0[0] - p4[0]) + (p0[1] - p4[1]) * (p0[1] - p4[1]) + (p0[2] - p4[2]) * (p0[2] - p4[2]));
166  extent[1] =
167  sqrt((p0[0] - p2[0]) * (p0[0] - p2[0]) + (p0[1] - p2[1]) * (p0[1] - p2[1]) + (p0[2] - p2[2]) * (p0[2] - p2[2]));
168  extent[2] =
169  sqrt((p0[0] - p1[0]) * (p0[0] - p1[0]) + (p0[1] - p1[1]) * (p0[1] - p1[1]) + (p0[2] - p1[2]) * (p0[2] - p1[2]));
170 
171  // calculate center based on half way of the distance between two opposing cornerpoints
172  mitk::Point3D center = CalcAvgPoint(cornerPoints[7], cornerPoints[0]);
173 
174  if (m_Impl->HandlePropertyList.size() == 6)
175  {
176  // set handle positions
177  Point3D pointLeft = CalcAvgPoint(cornerPoints[5], cornerPoints[6]);
178  Point3D pointRight = CalcAvgPoint(cornerPoints[1], cornerPoints[2]);
179  Point3D pointTop = CalcAvgPoint(cornerPoints[0], cornerPoints[6]);
180  Point3D pointBottom = CalcAvgPoint(cornerPoints[7], cornerPoints[1]);
181  Point3D pointFront = CalcAvgPoint(cornerPoints[2], cornerPoints[7]);
182  Point3D pointBack = CalcAvgPoint(cornerPoints[4], cornerPoints[1]);
183 
184  m_Impl->HandlePropertyList[0].SetPosition(pointLeft);
185  m_Impl->HandlePropertyList[1].SetPosition(pointRight);
186  m_Impl->HandlePropertyList[2].SetPosition(pointTop);
187  m_Impl->HandlePropertyList[3].SetPosition(pointBottom);
188  m_Impl->HandlePropertyList[4].SetPosition(pointFront);
189  m_Impl->HandlePropertyList[5].SetPosition(pointBack);
190  }
191 
192  auto cube = vtkCubeSource::New();
193  cube->SetXLength(extent[0] / spacing[0]);
194  cube->SetYLength(extent[1] / spacing[1]);
195  cube->SetZLength(extent[2] / spacing[2]);
196 
197  // calculates translation based on offset+extent not on the transformation matrix
198  vtkSmartPointer<vtkMatrix4x4> imageTransform = geometry->GetVtkTransform()->GetMatrix();
199  auto translation = vtkSmartPointer<vtkTransform>::New();
200  translation->Translate(center[0] - imageTransform->GetElement(0, 3),
201  center[1] - imageTransform->GetElement(1, 3),
202  center[2] - imageTransform->GetElement(2, 3));
203 
204  auto transform = vtkSmartPointer<vtkTransform>::New();
205  transform->SetMatrix(imageTransform);
206  transform->PostMultiply();
207  transform->Concatenate(translation);
208  transform->Update();
209  cube->Update();
210 
211  auto transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
212  transformFilter->SetInputData(cube->GetOutput());
213  transformFilter->SetTransform(transform);
214  transformFilter->Update();
215  cube->Delete();
216 
217  vtkSmartPointer<vtkPolyData> polydata = transformFilter->GetPolyDataOutput();
218  if (polydata == nullptr)
219  {
220  localStorage->Actor->VisibilityOff();
221  return;
222  }
223 
224  mitk::DoubleProperty::Pointer handleSizeProperty =
225  dynamic_cast<mitk::DoubleProperty *>(this->GetDataNode()->GetProperty("Bounding Shape.Handle Size Factor"));
226 
227  ScalarType initialHandleSize;
228  if (handleSizeProperty != nullptr)
229  initialHandleSize = handleSizeProperty->GetValue();
230  else
231  initialHandleSize = 1.0 / 40.0;
232 
233  double handlesize =
234  ((camera->GetDistance() * std::tan(vtkMath::RadiansFromDegrees(camera->GetViewAngle()))) / 2.0) *
235  initialHandleSize;
236 
237  if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->HandleActor))
238  localStorage->PropAssembly->RemovePart(localStorage->HandleActor);
239  if (localStorage->PropAssembly->GetParts()->IsItemPresent(localStorage->Actor))
240  localStorage->PropAssembly->RemovePart(localStorage->Actor);
241 
242  auto selectedhandlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
243  auto appendPoly = vtkSmartPointer<vtkAppendPolyData>::New();
244 
245  mitk::IntProperty::Pointer activeHandleId =
246  dynamic_cast<mitk::IntProperty *>(dataNode->GetProperty("Bounding Shape.Active Handle ID"));
247 
248  int i = 0;
249  for (auto &handle : localStorage->Handles)
250  {
251  Point3D handlecenter = m_Impl->HandlePropertyList[i].GetPosition();
252  handle->SetCenter(handlecenter[0], handlecenter[1], handlecenter[2]);
253  handle->SetRadius(handlesize);
254  handle->Update();
255  if (activeHandleId == nullptr)
256  {
257  appendPoly->AddInputConnection(handle->GetOutputPort());
258  }
259  else
260  {
261  if (activeHandleId->GetValue() != m_Impl->HandlePropertyList[i].GetIndex())
262  {
263  appendPoly->AddInputConnection(handle->GetOutputPort());
264  }
265  else
266  {
267  selectedhandlemapper->SetInputData(handle->GetOutput());
268  localStorage->SelectedHandleActor->SetMapper(selectedhandlemapper);
269  localStorage->SelectedHandleActor->GetProperty()->SetColor(0, 1, 0);
270  localStorage->SelectedHandleActor->GetMapper()->SetInputDataObject(handle->GetOutput());
271  localStorage->PropAssembly->AddPart(localStorage->SelectedHandleActor);
272  }
273  }
274  i++;
275  }
276  appendPoly->Update();
277 
278  auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
279  mapper->SetInputData(polydata);
280 
281  auto handlemapper = vtkSmartPointer<vtkPolyDataMapper>::New();
282  handlemapper->SetInputData(appendPoly->GetOutput());
283 
284  localStorage->Actor->SetMapper(mapper);
285  localStorage->Actor->GetMapper()->SetInputDataObject(polydata);
286  localStorage->Actor->GetProperty()->SetOpacity(0.3);
287 
288  mitk::ColorProperty::Pointer selectedColor = dynamic_cast<mitk::ColorProperty *>(dataNode->GetProperty("color"));
289  if (selectedColor != nullptr)
290  {
291  mitk::Color color = selectedColor->GetColor();
292  localStorage->Actor->GetProperty()->SetColor(color[0], color[1], color[2]);
293  }
294 
295  localStorage->HandleActor->SetMapper(handlemapper);
296  if (activeHandleId == nullptr)
297  {
298  localStorage->HandleActor->GetProperty()->SetColor(1, 1, 1);
299  }
300  else
301  {
302  localStorage->HandleActor->GetProperty()->SetColor(1, 0, 0);
303  }
304 
305  localStorage->HandleActor->GetMapper()->SetInputDataObject(appendPoly->GetOutput());
306 
307  this->ApplyColorAndOpacityProperties(renderer, localStorage->Actor);
308  this->ApplyBoundingShapeProperties(renderer, localStorage->Actor);
309 
310  this->ApplyColorAndOpacityProperties(renderer, localStorage->HandleActor);
311  this->ApplyBoundingShapeProperties(renderer, localStorage->HandleActor);
312 
313  this->ApplyColorAndOpacityProperties(renderer, localStorage->SelectedHandleActor);
314  this->ApplyBoundingShapeProperties(renderer, localStorage->SelectedHandleActor);
315 
316  // apply properties read from the PropertyList
317  // this->ApplyProperties(localStorage->m_Actor, renderer);
318  // this->ApplyProperties(localStorage->m_HandleActor, renderer);
319  // this->ApplyProperties(localStorage->m_SelectedHandleActor, renderer);
320 
321  localStorage->Actor->VisibilityOn();
322  localStorage->HandleActor->VisibilityOn();
323  localStorage->SelectedHandleActor->VisibilityOn();
324 
325  localStorage->PropAssembly->AddPart(localStorage->Actor);
326  localStorage->PropAssembly->AddPart(localStorage->HandleActor);
327  localStorage->PropAssembly->VisibilityOn();
328 
329  localStorage->UpdateGenerateDataTime();
330  }
331 }
333 {
334  return m_Impl->LocalStorageHandler.GetLocalStorage(renderer)->PropAssembly;
335 }
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr, bool fallBackOnDataProperties=true) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
void ApplyColorAndOpacityProperties(BaseRenderer *, vtkActor *) override
Apply specific color and opacity properties read from the PropertyList. Reimplemented in GLmapper (do...
vtkRenderer * GetVtkRenderer() const
void ApplyColorAndOpacityProperties(BaseRenderer *, vtkActor *) override
Apply specific color and opacity properties read from the PropertyList. Reimplemented in GLmapper (do...
virtual DataNode * GetDataNode() const
Get the DataNode containing the data to map. Method only returns valid DataNode Pointer if the mapper...
Definition: mitkMapper.cpp:31
double ScalarType
vtkProp * GetVtkProp(BaseRenderer *renderer) override
Organizes the rendering process.
DataCollection - Class to facilitate loading/accessing structured data.
std::vector< mitk::Point3D > GetCornerPoints(mitk::BaseGeometry::Pointer geometry, bool visualizationOffset)
helper function for calculating corner points of the bounding object from a given geometry ...
BaseLocalStorage & operator=(const BaseLocalStorage &)=delete
std::vector< int > GetHandleIndices(int index)
The ColorProperty class RGB color property.
void ApplyBoundingShapeProperties(BaseRenderer *renderer, vtkActor *)
Data class only having a BaseGeometry but not containing any specific data.
Point< ScalarType, 3 > Point3D
Definition: mitkPoint.h:95
itk::RGBPixel< float > Color
Color Standard RGB color typedef (float)
void GenerateDataForRenderer(BaseRenderer *renderer) override
Generate the data needed for rendering into renderer.
const float selectedColor[]
MITKCORE_EXPORT const ScalarType eps
static void SetDefaultProperties(DataNode *node, BaseRenderer *renderer=nullptr, bool overwrite=false)
mitk::Point3D CalcAvgPoint(mitk::Point3D a, mitk::Point3D b)
helper function for calculating the average of two points
Class for nodes of the DataTree.
Definition: mitkDataNode.h:57