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
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.