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