Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkPlaneGeometryDataMapper2D.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 
19 // mitk includes
20 #include "mitkVtkPropRenderer.h"
22 #include <mitkDataNode.h>
23 #include <mitkLine.h>
24 #include <mitkPlaneGeometry.h>
26 #include <mitkPointSet.h>
27 #include <mitkProperties.h>
29 #include <mitkSlicedGeometry3D.h>
30 
31 // vtk includes
32 #include <mitkIPropertyAliases.h>
33 #include <vtkActor2D.h>
34 #include <vtkCellArray.h>
35 #include <vtkCellData.h>
36 #include <vtkLine.h>
37 #include <vtkPoints.h>
38 #include <vtkPolyData.h>
39 #include <vtkPolyDataMapper2D.h>
40 #include <vtkProperty2D.h>
41 #include <vtkTriangle.h>
42 
44 #include <algorithm>
45 #include <array>
46 #include <cassert>
47 #include <set>
48 
49 namespace
50 {
52  template <typename T>
53  class SimpleInterval
54  {
55  public:
56  SimpleInterval(T start = T(), T end = T())
57  : m_LowerBoundary(std::min(start, end)), m_UpperBoundary(std::max(start, end))
58  {
59  }
60 
61  T GetLowerBoundary() const { return m_LowerBoundary; }
62  T GetUpperBoundary() const { return m_UpperBoundary; }
63  bool empty() const { return m_LowerBoundary == m_UpperBoundary; }
64  bool operator<(const SimpleInterval &otherInterval) const
65  {
66  return this->m_UpperBoundary < otherInterval.GetLowerBoundary();
67  }
68 
69  private:
70  T m_LowerBoundary;
71  T m_UpperBoundary;
72  };
73 
74  template <typename T>
75  class IntervalSet
76  {
77  public:
78  typedef SimpleInterval<T> IntervalType;
79 
80  IntervalSet(IntervalType startingInterval) { m_IntervalsContainer.insert(std::move(startingInterval)); }
81  void operator-=(const IntervalType &interval)
82  {
83  // equal_range will find all the intervals in the interval set which intersect with the input interval
84  // due to the nature of operator< of SimpleInterval
85  auto range = m_IntervalsContainer.equal_range(interval);
86 
87  for (auto iter = range.first; iter != range.second;)
88  {
89  auto subtractionResult = SubtractIntervals(*iter, interval);
90 
91  // Remove the old interval from the set
92  iter = m_IntervalsContainer.erase(iter);
93  for (auto &&interval : subtractionResult)
94  {
95  if (!interval.empty())
96  {
97  // Add the new interval to the set
98  // emplace_hint adds the element at the closest valid place before the hint iterator,
99  // which is exactly where the new interval should be
100  iter = m_IntervalsContainer.insert(iter, std::move(interval));
101  ++iter;
102  }
103  }
104  }
105  }
106 
107  IntervalSet operator-(const IntervalType &interval)
108  {
109  IntervalSet result = *this;
110  result -= interval;
111  return result;
112  }
113 
114  typedef std::set<IntervalType> IntervalsContainer;
115 
116  const IntervalsContainer &getIntervals() const { return m_IntervalsContainer; }
117  private:
118  IntervalsContainer m_IntervalsContainer;
119 
120  std::array<IntervalType, 2> SubtractIntervals(const IntervalType &firstInterval, const IntervalType &secondInterval)
121  {
122  assert(secondInterval.GetUpperBoundary() >= firstInterval.GetLowerBoundary() &&
123  firstInterval.GetUpperBoundary() >=
124  secondInterval.GetLowerBoundary()); // Non-intersecting intervals should never reach here
125 
126  if (secondInterval.GetLowerBoundary() < firstInterval.GetLowerBoundary())
127  {
128  if (firstInterval.GetUpperBoundary() < secondInterval.GetUpperBoundary())
129  {
130  std::array<IntervalType, 2> result = {{IntervalType(), IntervalType()}};
131  return result; // firstInterval completely enclosed
132  }
133  std::array<IntervalType, 2> result = {
134  {IntervalType(firstInterval.GetUpperBoundary(), secondInterval.GetUpperBoundary()), IntervalType()}};
135  return result; // secondInterval removes the beginning of firstInterval
136  }
137 
138  if (firstInterval.GetUpperBoundary() < secondInterval.GetUpperBoundary())
139  {
140  std::array<IntervalType, 2> result = {
141  {IntervalType(firstInterval.GetLowerBoundary(), secondInterval.GetLowerBoundary()), IntervalType()}};
142  return result; // secondInterval removes the end of firstInterval
143  }
144  std::array<IntervalType, 2> result = {
145  {IntervalType(firstInterval.GetLowerBoundary(), secondInterval.GetLowerBoundary()),
146  IntervalType(secondInterval.GetUpperBoundary(), firstInterval.GetUpperBoundary())}};
147  return result; // secondInterval is completely enclosed in firstInterval and removes the middle
148  }
149  };
150 }
151 
153 
154 // input for this mapper ( = PlaneGeometryData)
156 {
157  return static_cast<PlaneGeometryData *>(GetDataNode()->GetData());
158 }
159 
161  : m_RenderOrientationArrows(false), m_ArrowOrientationPositive(true), m_DepthValue(1.0f)
162 {
163  s_AllInstances.insert(this);
164 }
165 
167 {
168  s_AllInstances.erase(this);
169 }
170 
172 {
173  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
174  return ls->m_CrosshairAssembly;
175 }
176 
178 {
179  BaseLocalStorage *ls = m_LSH.GetLocalStorage(renderer);
180 
181  // The PlaneGeometryDataMapper2D mapper is special in that the rendering of
182  // OTHER PlaneGeometryDatas affects how we render THIS PlaneGeometryData
183  // (for the gap at the point where they intersect). A change in any of the
184  // other PlaneGeometryData nodes could mean that we render ourself
185  // differently, so we check for that here.
186  for (AllInstancesContainer::iterator it = s_AllInstances.begin(); it != s_AllInstances.end(); ++it)
187  {
188  bool generateDataRequired = ls->IsGenerateDataRequired(renderer, this, (*it)->GetDataNode());
189  if (generateDataRequired)
190  break;
191  }
192 
194 
195  // Collect all other PlaneGeometryDatas that are being mapped by this mapper
196  m_OtherPlaneGeometries.clear();
197 
198  for (AllInstancesContainer::iterator it = s_AllInstances.begin(); it != s_AllInstances.end(); ++it)
199  {
200  Self *otherInstance = *it;
201 
202  // Skip ourself
203  if (otherInstance == this)
204  continue;
205 
206  mitk::DataNode *otherNode = otherInstance->GetDataNode();
207  if (!otherNode)
208  continue;
209 
210  // Skip other PlaneGeometryData nodes that are not visible on this renderer
211  if (!otherNode->IsVisible(renderer))
212  continue;
213 
214  PlaneGeometryData *otherData = dynamic_cast<PlaneGeometryData *>(otherNode->GetData());
215  if (!otherData)
216  continue;
217 
218  PlaneGeometry *otherGeometry = dynamic_cast<PlaneGeometry *>(otherData->GetPlaneGeometry());
219  if (otherGeometry && !dynamic_cast<AbstractTransformGeometry *>(otherData->GetPlaneGeometry()))
220  {
221  m_OtherPlaneGeometries.push_back(otherNode);
222  }
223  }
224 
225  CreateVtkCrosshair(renderer);
226 
227  ApplyAllProperties(renderer);
228 }
229 
231 {
232  bool visible = true;
233  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
234  ls->m_CrosshairActor->SetVisibility(0);
235  ls->m_ArrowActor->SetVisibility(0);
236  ls->m_CrosshairHelperLineActor->SetVisibility(0);
237 
238  GetDataNode()->GetVisibility(visible, renderer, "visible");
239 
240  if (!visible)
241  {
242  return;
243  }
244 
245  PlaneGeometryData::Pointer input = const_cast<PlaneGeometryData *>(this->GetInput());
246  mitk::DataNode *geometryDataNode = renderer->GetCurrentWorldPlaneGeometryNode();
247  const PlaneGeometryData *rendererWorldPlaneGeometryData =
248  dynamic_cast<PlaneGeometryData *>(geometryDataNode->GetData());
249 
250  // intersecting with ourself?
251  if (input.IsNull() || input.GetPointer() == rendererWorldPlaneGeometryData)
252  {
253  return; // nothing to do in this case
254  }
255 
256  const PlaneGeometry *inputPlaneGeometry = dynamic_cast<const PlaneGeometry *>(input->GetPlaneGeometry());
257 
258  const PlaneGeometry *worldPlaneGeometry =
259  dynamic_cast<const PlaneGeometry *>(rendererWorldPlaneGeometryData->GetPlaneGeometry());
260 
261  if (worldPlaneGeometry && dynamic_cast<const AbstractTransformGeometry *>(worldPlaneGeometry) == NULL &&
262  inputPlaneGeometry && dynamic_cast<const AbstractTransformGeometry *>(input->GetPlaneGeometry()) == NULL)
263  {
264  const BaseGeometry *referenceGeometry = inputPlaneGeometry->GetReferenceGeometry();
265 
266  // calculate intersection of the plane data with the border of the
267  // world geometry rectangle
268  Point3D point1, point2;
269 
270  Line3D crossLine;
271 
272  // Calculate the intersection line of the input plane with the world plane
273  if (worldPlaneGeometry->IntersectionLine(inputPlaneGeometry, crossLine))
274  {
275  bool hasIntersection = referenceGeometry ? CutCrossLineWithReferenceGeometry(referenceGeometry, crossLine) :
276  CutCrossLineWithPlaneGeometry(inputPlaneGeometry, crossLine);
277 
278  if (!hasIntersection)
279  {
280  return;
281  }
282 
283  point1 = crossLine.GetPoint1();
284  point2 = crossLine.GetPoint2();
285 
286  vtkSmartPointer<vtkCellArray> lines = vtkSmartPointer<vtkCellArray>::New();
287  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
288  vtkSmartPointer<vtkPolyData> linesPolyData = vtkSmartPointer<vtkPolyData>::New();
289 
290  // Now iterate through all other lines displayed in this window and
291  // calculate the positions of intersection with the line to be
292  // rendered; these positions will be stored in lineParams to form a
293  // gap afterwards.
294  NodesVectorType::iterator otherPlanesIt = m_OtherPlaneGeometries.begin();
295  NodesVectorType::iterator otherPlanesEnd = m_OtherPlaneGeometries.end();
296 
297  int gapSize = 32;
298  this->GetDataNode()->GetPropertyValue("Crosshair.Gap Size", gapSize, NULL);
299 
300  auto intervals = IntervalSet<double>(SimpleInterval<double>(0, 1));
301 
302  ScalarType lineLength = point1.EuclideanDistanceTo(point2);
303  ScalarType gapInMM = gapSize * renderer->GetScaleFactorMMPerDisplayUnit();
304  float gapSizeParam = gapInMM / lineLength;
305 
306  if (gapSize != 0)
307  {
308  while (otherPlanesIt != otherPlanesEnd)
309  {
310  bool ignorePlane = false;
311  (*otherPlanesIt)->GetPropertyValue("Crosshair.Ignore", ignorePlane);
312  if (ignorePlane)
313  {
314  ++otherPlanesIt;
315  continue;
316  }
317 
318  PlaneGeometry *otherPlaneGeometry = static_cast<PlaneGeometry *>(
319  static_cast<PlaneGeometryData *>((*otherPlanesIt)->GetData())->GetPlaneGeometry());
320 
321  if (otherPlaneGeometry != inputPlaneGeometry && otherPlaneGeometry != worldPlaneGeometry)
322  {
323  double intersectionParam;
324  if (otherPlaneGeometry->IntersectionPointParam(crossLine, intersectionParam) && intersectionParam > 0 &&
325  intersectionParam < 1)
326  {
327  Point3D point = crossLine.GetPoint() + intersectionParam * crossLine.GetDirection();
328 
329  bool intersectionPointInsideOtherPlane =
330  otherPlaneGeometry->HasReferenceGeometry() ?
331  TestPointInReferenceGeometry(otherPlaneGeometry->GetReferenceGeometry(), point) :
332  TestPointInPlaneGeometry(otherPlaneGeometry, point);
333 
334  if (intersectionPointInsideOtherPlane)
335  {
336  intervals -= SimpleInterval<double>(intersectionParam - gapSizeParam, intersectionParam + gapSizeParam);
337  }
338  }
339  }
340  ++otherPlanesIt;
341  }
342  }
343 
344  for (const auto &interval : intervals.getIntervals())
345  {
346  this->DrawLine(crossLine.GetPoint(interval.GetLowerBoundary()),
347  crossLine.GetPoint(interval.GetUpperBoundary()),
348  lines,
349  points);
350  }
351 
352  // Add the points to the dataset
353  linesPolyData->SetPoints(points);
354  // Add the lines to the dataset
355  linesPolyData->SetLines(lines);
356 
357  Vector3D orthogonalVector;
358  orthogonalVector = inputPlaneGeometry->GetNormal();
359  worldPlaneGeometry->Project(orthogonalVector, orthogonalVector);
360  orthogonalVector.Normalize();
361 
362  // Visualize
363  ls->m_Mapper->SetInputData(linesPolyData);
364  ls->m_CrosshairActor->SetMapper(ls->m_Mapper);
365 
366  // Determine if we should draw the area covered by the thick slicing, default is false.
367  // This will also show the area of slices that do not have thick slice mode enabled
368  bool showAreaOfThickSlicing = false;
369  GetDataNode()->GetBoolProperty("reslice.thickslices.showarea", showAreaOfThickSlicing);
370 
371  // determine the pixelSpacing in that direction
372  double thickSliceDistance = SlicedGeometry3D::CalculateSpacing(
373  referenceGeometry ? referenceGeometry->GetSpacing() : inputPlaneGeometry->GetSpacing(), orthogonalVector);
374 
375  IntProperty *intProperty = 0;
376  if (GetDataNode()->GetProperty(intProperty, "reslice.thickslices.num") && intProperty)
377  thickSliceDistance *= intProperty->GetValue() + 0.5;
378  else
379  showAreaOfThickSlicing = false;
380 
381  // not the nicest place to do it, but we have the width of the visible bloc in MM here
382  // so we store it in this fancy property
383  GetDataNode()->SetFloatProperty("reslice.thickslices.sizeinmm", thickSliceDistance * 2);
384 
385  ls->m_CrosshairActor->SetVisibility(1);
386 
387  vtkSmartPointer<vtkPolyData> arrowPolyData = vtkSmartPointer<vtkPolyData>::New();
388  ls->m_Arrowmapper->SetInputData(arrowPolyData);
389  if (this->m_RenderOrientationArrows)
390  {
391  ScalarType triangleSizeMM = 7.0 * renderer->GetScaleFactorMMPerDisplayUnit();
392 
393  vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
394  vtkSmartPointer<vtkPoints> triPoints = vtkSmartPointer<vtkPoints>::New();
395 
396  DrawOrientationArrow(triangles, triPoints, triangleSizeMM, orthogonalVector, point1, point2);
397  DrawOrientationArrow(triangles, triPoints, triangleSizeMM, orthogonalVector, point2, point1);
398  arrowPolyData->SetPoints(triPoints);
399  arrowPolyData->SetPolys(triangles);
400  ls->m_ArrowActor->SetVisibility(1);
401  }
402 
403  // Visualize
404  vtkSmartPointer<vtkPolyData> helperlinesPolyData = vtkSmartPointer<vtkPolyData>::New();
405  ls->m_HelperLinesmapper->SetInputData(helperlinesPolyData);
406  if (showAreaOfThickSlicing)
407  {
408  vtkSmartPointer<vtkCellArray> helperlines = vtkSmartPointer<vtkCellArray>::New();
409  // vectorToHelperLine defines how to reach the helperLine from the mainLine
410  // got the right direction, so we multiply the width
411  Vector3D vecToHelperLine = orthogonalVector * thickSliceDistance;
412 
413  this->DrawLine(point1 - vecToHelperLine, point2 - vecToHelperLine, helperlines, points);
414  this->DrawLine(point1 + vecToHelperLine, point2 + vecToHelperLine, helperlines, points);
415 
416  // Add the points to the dataset
417  helperlinesPolyData->SetPoints(points);
418 
419  // Add the lines to the dataset
420  helperlinesPolyData->SetLines(helperlines);
421 
422  ls->m_CrosshairActor->GetProperty()->SetLineStipplePattern(0xf0f0);
423  ls->m_CrosshairActor->GetProperty()->SetLineStippleRepeatFactor(1);
424  ls->m_CrosshairHelperLineActor->SetVisibility(1);
425  }
426  }
427  }
428 }
429 
431 {
432  Point2D mappedPoint;
433  planeGeometry->Map(point, mappedPoint);
434  planeGeometry->WorldToIndex(mappedPoint, mappedPoint);
435 
436  return (planeGeometry->GetBounds()[0] < mappedPoint[0] && mappedPoint[0] < planeGeometry->GetBounds()[1] &&
437  planeGeometry->GetBounds()[2] < mappedPoint[1] && mappedPoint[1] < planeGeometry->GetBounds()[3]);
438 }
439 
441  const Point3D &point)
442 {
443  return referenceGeometry->IsInside(point);
444 }
445 
447  Line3D &crossLine)
448 {
449  Point2D indexLinePoint;
450  Vector2D indexLineDirection;
451 
452  planeGeometry->Map(crossLine.GetPoint(), indexLinePoint);
453  planeGeometry->Map(crossLine.GetPoint(), crossLine.GetDirection(), indexLineDirection);
454 
455  planeGeometry->WorldToIndex(indexLinePoint, indexLinePoint);
456  planeGeometry->WorldToIndex(indexLineDirection, indexLineDirection);
457 
458  mitk::Point2D intersectionPoints[2];
459 
460  // Then, clip this line with the (transformed) bounding box of the
461  // reference geometry.
462  int nIntersections = Line3D::RectangleLineIntersection(planeGeometry->GetBounds()[0],
463  planeGeometry->GetBounds()[2],
464  planeGeometry->GetBounds()[1],
465  planeGeometry->GetBounds()[3],
466  indexLinePoint,
467  indexLineDirection,
468  intersectionPoints[0],
469  intersectionPoints[1]);
470 
471  if (nIntersections < 2)
472  {
473  return false;
474  }
475 
476  planeGeometry->IndexToWorld(intersectionPoints[0], intersectionPoints[0]);
477  planeGeometry->IndexToWorld(intersectionPoints[1], intersectionPoints[1]);
478 
479  Point3D point1, point2;
480 
481  planeGeometry->Map(intersectionPoints[0], point1);
482  planeGeometry->Map(intersectionPoints[1], point2);
483  crossLine.SetPoints(point1, point2);
484 
485  return true;
486 }
487 
489  Line3D &crossLine)
490 {
491  Point3D boundingBoxMin, boundingBoxMax;
492  boundingBoxMin = referenceGeometry->GetCornerPoint(0);
493  boundingBoxMax = referenceGeometry->GetCornerPoint(7);
494 
495  Point3D indexLinePoint;
496  Vector3D indexLineDirection;
497 
498  referenceGeometry->WorldToIndex(crossLine.GetPoint(), indexLinePoint);
499  referenceGeometry->WorldToIndex(crossLine.GetDirection(), indexLineDirection);
500 
501  referenceGeometry->WorldToIndex(boundingBoxMin, boundingBoxMin);
502  referenceGeometry->WorldToIndex(boundingBoxMax, boundingBoxMax);
503 
504  Point3D point1, point2;
505 
506  // Then, clip this line with the (transformed) bounding box of the
507  // reference geometry.
508  int nIntersections = Line3D::BoxLineIntersection(boundingBoxMin[0],
509  boundingBoxMin[1],
510  boundingBoxMin[2],
511  boundingBoxMax[0],
512  boundingBoxMax[1],
513  boundingBoxMax[2],
514  indexLinePoint,
515  indexLineDirection,
516  point1,
517  point2);
518 
519  if (nIntersections < 2)
520  {
521  return false;
522  }
523 
524  referenceGeometry->IndexToWorld(point1, point1);
525  referenceGeometry->IndexToWorld(point2, point2);
526  crossLine.SetPoints(point1, point2);
527 
528  return true;
529 }
530 
532  mitk::Point3D p1,
533  vtkCellArray *lines,
534  vtkPoints *points)
535 {
536  vtkIdType pidStart = points->InsertNextPoint(p0[0], p0[1], p0[2]);
537  vtkIdType pidEnd = points->InsertNextPoint(p1[0], p1[1], p1[2]);
538 
539  vtkSmartPointer<vtkLine> lineVtk = vtkSmartPointer<vtkLine>::New();
540  lineVtk->GetPointIds()->SetId(0, pidStart);
541  lineVtk->GetPointIds()->SetId(1, pidEnd);
542 
543  lines->InsertNextCell(lineVtk);
544 }
545 
546 void mitk::PlaneGeometryDataMapper2D::DrawOrientationArrow(vtkSmartPointer<vtkCellArray> triangles,
547  vtkSmartPointer<vtkPoints> triPoints,
548  double triangleSizeMM,
549  Vector3D &orthogonalVector,
550  Point3D &point1,
551  Point3D &point2)
552 {
553  // Draw arrows to indicate plane orientation
554  // Vector along line
555  Vector3D v1 = point2 - point1;
556  v1.Normalize();
557  v1 *= triangleSizeMM;
558 
559  // Orthogonal vector
560  Vector3D v2 = orthogonalVector;
561  v2 *= triangleSizeMM;
562  if (!this->m_ArrowOrientationPositive)
563  v2 *= -1.0;
564 
565  // Initialize remaining triangle coordinates accordingly
566  Point3D p1 = point1 + v1 * 2.0;
567  Point3D p2 = point1 + v1 + v2;
568 
569  vtkIdType t0 = triPoints->InsertNextPoint(point1[0], point1[1], point1[2]); // start of the line
570  vtkIdType t1 = triPoints->InsertNextPoint(p1[0], p1[1], p1[2]); // point on line
571  vtkIdType t2 = triPoints->InsertNextPoint(p2[0], p2[1], p2[2]); // direction point
572 
573  vtkSmartPointer<vtkTriangle> triangle = vtkSmartPointer<vtkTriangle>::New();
574  triangle->GetPointIds()->SetId(0, t0);
575  triangle->GetPointIds()->SetId(1, t1);
576  triangle->GetPointIds()->SetId(2, t2);
577 
578  triangles->InsertNextCell(triangle);
579 }
580 
582 {
583  int thickSlicesMode = 0;
584  // determine the state and the extend of the thick-slice mode
585  mitk::ResliceMethodProperty *resliceMethodEnumProperty = 0;
586  if (dn->GetProperty(resliceMethodEnumProperty, "reslice.thickslices") && resliceMethodEnumProperty)
587  thickSlicesMode = resliceMethodEnumProperty->GetValueAsId();
588 
589  IntProperty *intProperty = 0;
590  if (dn->GetProperty(intProperty, "reslice.thickslices.num") && intProperty)
591  {
592  thickSlicesNum = intProperty->GetValue();
593  if (thickSlicesNum < 1)
594  thickSlicesNum = 0;
595  if (thickSlicesNum > 10)
596  thickSlicesNum = 10;
597  }
598 
599  if (thickSlicesMode == 0)
600  thickSlicesNum = 0;
601 
602  return thickSlicesMode;
603 }
604 
606 {
607  LocalStorage *ls = m_LSH.GetLocalStorage(renderer);
608  ApplyColorAndOpacityProperties2D(renderer, ls->m_CrosshairActor);
609  ApplyColorAndOpacityProperties2D(renderer, ls->m_CrosshairHelperLineActor);
610  ApplyColorAndOpacityProperties2D(renderer, ls->m_ArrowActor);
611 
612  float thickness;
613  this->GetDataNode()->GetFloatProperty("Line width", thickness, renderer);
614  ls->m_CrosshairActor->GetProperty()->SetLineWidth(thickness);
615  ls->m_CrosshairHelperLineActor->GetProperty()->SetLineWidth(thickness);
616 
617  PlaneOrientationProperty *decorationProperty;
618  this->GetDataNode()->GetProperty(decorationProperty, "decoration", renderer);
619  if (decorationProperty != NULL)
620  {
622  {
623  m_RenderOrientationArrows = true;
624  m_ArrowOrientationPositive = true;
625  }
626  else if (decorationProperty->GetPlaneDecoration() ==
628  {
629  m_RenderOrientationArrows = true;
630  m_ArrowOrientationPositive = false;
631  }
632  else
633  {
634  m_RenderOrientationArrows = false;
635  }
636  }
637 }
638 
640 {
641  float rgba[4] = {1.0f, 1.0f, 1.0f, 1.0f};
642  DataNode *node = GetDataNode();
643 
644  // check for color prop and use it for rendering if it exists
645  node->GetColor(rgba, renderer, "color");
646  // check for opacity prop and use it for rendering if it exists
647  node->GetOpacity(rgba[3], renderer, "opacity");
648 
649  double drgba[4] = {rgba[0], rgba[1], rgba[2], rgba[3]};
650  actor->GetProperty()->SetColor(drgba);
651  actor->GetProperty()->SetOpacity(drgba[3]);
652 }
653 
655  mitk::BaseRenderer *renderer,
656  bool overwrite)
657 {
659  node->AddProperty("Line width", mitk::FloatProperty::New(1), renderer, overwrite);
660  aliases->AddAlias("line width", "Crosshair.Line Width", "");
661  node->AddProperty("Crosshair.Gap Size", mitk::IntProperty::New(32), renderer, overwrite);
662  node->AddProperty("decoration",
664  renderer,
665  overwrite);
666  aliases->AddAlias("decoration", "Crosshair.Orientation Decoration", "");
667 
668  Superclass::SetDefaultProperties(node, renderer, overwrite);
669 }
670 
672 {
673 }
674 
676 {
677  m_CrosshairAssembly = vtkSmartPointer<vtkPropAssembly>::New();
678 
679  m_CrosshairActor = vtkSmartPointer<vtkActor2D>::New();
680  m_ArrowActor = vtkSmartPointer<vtkActor2D>::New();
681  m_CrosshairHelperLineActor = vtkSmartPointer<vtkActor2D>::New();
682 
683  m_HelperLinesmapper = vtkSmartPointer<vtkPolyDataMapper2D>::New();
686 
687  m_CrosshairActor->SetMapper(m_Mapper);
688  m_ArrowActor->SetMapper(m_Arrowmapper);
689  m_CrosshairHelperLineActor->SetMapper(m_HelperLinesmapper);
690 
691  m_CrosshairActor->SetVisibility(0);
692  m_ArrowActor->SetVisibility(0);
693  m_CrosshairHelperLineActor->SetVisibility(0);
694 
695  m_CrosshairAssembly->AddPart(m_CrosshairActor);
696  m_CrosshairAssembly->AddPart(m_ArrowActor);
697  m_CrosshairAssembly->AddPart(m_CrosshairHelperLineActor);
698 
699  vtkCoordinate *tcoord = vtkCoordinate::New();
700  tcoord->SetCoordinateSystemToWorld();
701  m_HelperLinesmapper->SetTransformCoordinate(tcoord);
702  m_Mapper->SetTransformCoordinate(tcoord);
703  // tcoord->SetCoordinateSystemToNormalizedDisplay();
704  m_Arrowmapper->SetTransformCoordinate(tcoord);
705  tcoord->Delete();
706 }
707 
709 {
710 }
virtual vtkProp * GetVtkProp(mitk::BaseRenderer *renderer) override
returns the a prop assembly
bool IntersectionPointParam(const Line3D &line, double &t) const
Calculate line parameter of intersection point between the plane and a line.
Interface of property aliases service.
virtual DataNode * GetCurrentWorldPlaneGeometryNode()
Get a DataNode pointing to a data object containing the current 2D-worldgeometry. ...
const itk::Point< TCoordRep, NPointDimension > & GetPoint1() const
Get start point of the line.
Definition: mitkLine.h:115
Descibes a line.
Definition: mitkLine.h:32
Base class for mapper specific rendering ressources.
Definition: mitkMapper.h:200
double GetScaleFactorMMPerDisplayUnit() const
vtkSmartPointer< vtkPolyDataMapper2D > m_Arrowmapper
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
double ScalarType
void DrawOrientationArrow(vtkSmartPointer< vtkCellArray > triangles, vtkSmartPointer< vtkPoints > triPoints, double triangleSizeMM, Vector3D &orthogonalVector, Point3D &point1, Point3D &point2)
Internal class holding the mapper, actor, etc. for each of the 3 2D render windows.
Organizes the rendering process.
STL namespace.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
virtual bool AddAlias(const std::string &propertyName, const std::string &alias, const std::string &className="")=0
Add an alias for a specific property.
BaseData * GetData() const
Get the data object (instance of BaseData, e.g., an Image) managed by this DataNode.
virtual mitk::PlaneGeometry * GetPlaneGeometry() const
Get the reference to the PlaneGeometry that is stored by the object.
static int BoxLineIntersection(TCoordRep x1, TCoordRep y1, TCoordRep z1, TCoordRep x2, TCoordRep y2, TCoordRep z2, itk::Point< TCoordRep, 3 > p, itk::Vector< TCoordRep, 3 > d, itk::Point< TCoordRep, 3 > &s1, itk::Point< TCoordRep, 3 > &s2)
Calculates the intersection points of a straight line in 3D with a box.
Definition: mitkLine.h:350
mitk::BaseProperty * GetProperty(const char *propertyKey, const mitk::BaseRenderer *renderer=nullptr) const
Get the property (instance of BaseProperty) with key propertyKey from the PropertyList of the rendere...
const itk::Vector< TCoordRep, NPointDimension > & GetDirection() const
Get the direction vector of the line.
Definition: mitkLine.h:74
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
const BoundsArrayType GetBounds() const
virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const
Base class of all mappers, Vtk as well as OpenGL mappers.
Definition: mitkMapper.h:54
Vector3D GetNormal() const
Normal of the plane.
int DetermineThickSliceMode(DataNode *dn, int &thickSlicesNum)
Returns the thick slice mode for the given datanode.
static void SetDefaultProperties(mitk::DataNode *node, mitk::BaseRenderer *renderer=NULL, bool overwrite=false)
set the default properties for this mapper
bool IsVisible(const mitk::BaseRenderer *renderer, const char *propertyKey="visible", bool defaultIsOn=true) const
Convenience access method for visibility properties (instances of BoolProperty). Return value is the ...
Definition: mitkDataNode.h:453
void ApplyColorAndOpacityProperties2D(BaseRenderer *renderer, vtkActor2D *actor)
static bool CutCrossLineWithReferenceGeometry(const BaseGeometry *referenceGeometry, Line3D &crossLine)
void AddProperty(const char *propertyKey, BaseProperty *property, const mitk::BaseRenderer *renderer=nullptr, bool overwrite=false)
Add the property (instance of BaseProperty) if it does not exist (or always ifoverwrite istrue) with ...
bool IsGenerateDataRequired(mitk::BaseRenderer *renderer, mitk::Mapper *mapper, mitk::DataNode *dataNode) const
Definition: mitkMapper.cpp:129
bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey="opacity") const
Convenience access method for opacity properties (instances of FloatProperty)
const itk::Point< TCoordRep, NPointDimension > & GetPoint() const
Get start point of the line.
Definition: mitkLine.h:53
static bool TestPointInPlaneGeometry(const PlaneGeometry *planeGeometry, const Point3D &point)
virtual const mitk::PlaneGeometryData * GetInput() const
virtual void UpdateVtkTransform(mitk::BaseRenderer *renderer) override
Set the vtkTransform of the m_Prop3D for the current time step of renderer.
void SetPoints(const itk::Point< TCoordRep, NPointDimension > &point1, const itk::Point< TCoordRep, NPointDimension > &point2)
Define line by two points.
Definition: mitkLine.h:94
Describes a geometry defined by an vtkAbstractTransform and a plane.
Data class containing PlaneGeometry objects.
static bool CutCrossLineWithPlaneGeometry(const PlaneGeometry *planeGeometry, Line3D &crossLine)
static AllInstancesContainer s_AllInstances
static T max(T x, T y)
Definition: svm.cpp:70
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
void CreateVtkCrosshair(BaseRenderer *renderer)
static Pointer New()
vtkSmartPointer< vtkPolyDataMapper2D > m_HelperLinesmapper
static T min(T x, T y)
Definition: svm.cpp:67
virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 3D point in mm (projec...
bool HasReferenceGeometry() const
static bool TestPointInReferenceGeometry(const BaseGeometry *referenceGeometry, const Point3D &point)
static Pointer New()
const BaseGeometry * GetReferenceGeometry() const
Get the geometrical frame of reference for this PlaneGeometry.
virtual void ApplyAllProperties(BaseRenderer *renderer)
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
virtual void GenerateDataForRenderer(mitk::BaseRenderer *renderer) override
Generate the data needed for rendering into renderer.
itk::Point< TCoordRep, NPointDimension > GetPoint2() const
Get end point of the line.
Definition: mitkLine.h:121
bool IntersectionLine(const PlaneGeometry *plane, Line3D &crossline) const
Calculate the intersecting line of two planes.
static double CalculateSpacing(const mitk::Vector3D &spacing, const mitk::Vector3D &d)
static int RectangleLineIntersection(TCoordRep x1, TCoordRep y1, TCoordRep x2, TCoordRep y2, itk::Point< TCoordRep, 2 > p, itk::Vector< TCoordRep, 2 > d, itk::Point< TCoordRep, 2 > &s1, itk::Point< TCoordRep, 2 > &s2)
Calculates the intersection points of a straight line in 2D with a rectangle.
Definition: mitkLine.h:264
Describes a two-dimensional, rectangular plane.
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
virtual DataNode * GetDataNode() const
Get the DataNode containing the data to map. Method only returns valid DataNode Pointer if the mapper...
Definition: mitkMapper.cpp:36
static IPropertyAliases * GetPropertyAliases(us::ModuleContext *context=us::GetModuleContext())
Get an IPropertyAliases instance.
bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="color") const
Convenience access method for color properties (instances of ColorProperty)
BaseGeometry Describes the geometry of a data object.
Class for nodes of the DataTree.
Definition: mitkDataNode.h:66
void DrawLine(Point3D p0, Point3D p1, vtkCellArray *lines, vtkPoints *points)
virtual IdType GetValueAsId() const
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
virtual T GetValue() const
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.