Medical Imaging Interaction Toolkit  2018.4.99-12ad79a3
Medical Imaging Interaction Toolkit
mitkContourModelGLMapper2DBase.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 
15 #include "mitkColorProperty.h"
16 #include "mitkContourModelSet.h"
17 #include "mitkPlaneGeometry.h"
18 #include "mitkProperties.h"
19 #include <vtkLinearTransform.h>
20 #include "vtkPen.h"
21 #include "vtkContext2D.h"
22 #include "vtkContextDevice2D.h"
23 #include "vtkOpenGLContextDevice2D.h"
24 
26 #include "mitkBaseRenderer.h"
27 #include "mitkContourModel.h"
28 #include "mitkTextAnnotation2D.h"
29 
31 {
34 }
35 
37 {
38 }
39 
41 {
42  vtkOpenGLContextDevice2D *device = nullptr;
43  device = vtkOpenGLContextDevice2D::New();
44  if (device)
45  {
46  this->m_Context->Begin(device);
47  device->Delete();
48  this->m_Initialized = true;
49  }
50  else
51  {
52  }
53 }
54 
56 {
57  float rgba[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
58  // check for color prop and use it for rendering if it exists
59  GetDataNode()->GetColor(rgba, renderer, "color");
60  // check for opacity prop and use it for rendering if it exists
61  GetDataNode()->GetOpacity(rgba[3], renderer, "opacity");
62 
63  if (this->m_Context->GetPen() == nullptr)
64  {
65  return;
66  }
67  this->m_Context->GetPen()->SetColorF((double)rgba[0], (double)rgba[1], (double)rgba[2], (double)rgba[3]);
68 }
69 
71 {
72  if (std::find(m_RendererList.begin(), m_RendererList.end(), renderer) == m_RendererList.end())
73  {
74  m_RendererList.push_back(renderer);
75  }
76 
78  m_PointNumbersAnnotation->SetVisibility(false);
79 
81  m_ControlPointNumbersAnnotation->SetVisibility(false);
82 
83  InternalDrawContour(renderingContour, renderer);
84 }
85 
87  mitk::BaseRenderer *renderer)
88 {
89  if (!renderingContour)
90  return;
91  if (!this->m_Initialized)
92  {
93  this->Initialize(renderer);
94  }
95  vtkOpenGLContextDevice2D::SafeDownCast(
96  this->m_Context->GetDevice())->Begin(renderer->GetVtkRenderer());
97 
98  mitk::DataNode *dataNode = this->GetDataNode();
99 
100  renderingContour->UpdateOutputInformation();
101 
102  unsigned int timestep = renderer->GetTimeStep();
103 
104  if (!renderingContour->IsEmptyTimeStep(timestep))
105  {
106  // apply color and opacity read from the PropertyList
108 
109  mitk::ColorProperty::Pointer colorprop =
110  dynamic_cast<mitk::ColorProperty *>(dataNode->GetProperty("contour.color", renderer));
111  float opacity = 0.5;
112  dataNode->GetFloatProperty("opacity", opacity, renderer);
113 
114  if (colorprop)
115  {
116  // set the color of the contour
117  double red = colorprop->GetColor().GetRed();
118  double green = colorprop->GetColor().GetGreen();
119  double blue = colorprop->GetColor().GetBlue();
120  this->m_Context->GetPen()->SetColorF(red, green, blue, opacity);
121  }
122 
123  mitk::ColorProperty::Pointer selectedcolor =
124  dynamic_cast<mitk::ColorProperty *>(dataNode->GetProperty("contour.points.color", renderer));
125  if (!selectedcolor)
126  {
127  selectedcolor = mitk::ColorProperty::New(1.0, 0.0, 0.1);
128  }
129 
130  vtkLinearTransform *transform = dataNode->GetVtkTransform();
131 
132  // ContourModel::OutputType point;
133  mitk::Point3D point;
134 
135  mitk::Point3D p;
136  float vtkp[3];
137  float lineWidth = 3.0;
138 
139  bool drawit = false;
140 
141  bool isHovering = false;
142  dataNode->GetBoolProperty("contour.hovering", isHovering);
143 
144  if (isHovering)
145  dataNode->GetFloatProperty("contour.hovering.width", lineWidth);
146  else
147  dataNode->GetFloatProperty("contour.width", lineWidth);
148 
149  bool showSegments = false;
150  dataNode->GetBoolProperty("contour.segments.show", showSegments);
151 
152  bool showControlPoints = false;
153  dataNode->GetBoolProperty("contour.controlpoints.show", showControlPoints);
154 
155  bool showPoints = false;
156  dataNode->GetBoolProperty("contour.points.show", showPoints);
157 
158  bool showPointsNumbers = false;
159  dataNode->GetBoolProperty("contour.points.text", showPointsNumbers);
160 
161  bool showControlPointsNumbers = false;
162  dataNode->GetBoolProperty("contour.controlpoints.text", showControlPointsNumbers);
163 
164  bool projectmode = false;
165  dataNode->GetVisibility(projectmode, renderer, "contour.project-onto-plane");
166 
167  auto pointsIt = renderingContour->IteratorBegin(timestep);
168 
169  Point2D pt2d; // projected_p in display coordinates
170  Point2D lastPt2d;
171 
172  int index = 0;
173 
174  mitk::ScalarType maxDiff = 0.25;
175 
176  while (pointsIt != renderingContour->IteratorEnd(timestep))
177  {
178  lastPt2d = pt2d;
179 
180  point = (*pointsIt)->Coordinates;
181 
182  itk2vtk(point, vtkp);
183  transform->TransformPoint(vtkp, vtkp);
184  vtk2itk(vtkp, p);
185 
186  renderer->WorldToView(p, pt2d);
187 
188  ScalarType scalardiff = fabs(renderer->GetCurrentWorldPlaneGeometry()->SignedDistance(p));
189 
190  // project to plane
191  if (projectmode)
192  {
193  drawit = true;
194  }
195  else if (scalardiff < maxDiff) // point is close enough to be drawn
196  {
197  drawit = true;
198  }
199  else
200  {
201  drawit = false;
202  }
203 
204  // draw line
205  if (drawit)
206  {
207  if (showSegments)
208  {
209  // lastPt2d is not valid in first step
210  if (!(pointsIt == renderingContour->IteratorBegin(timestep)))
211  {
212  this->m_Context->GetPen()->SetWidth(lineWidth);
213  this->m_Context->DrawLine(pt2d[0], pt2d[1], lastPt2d[0], lastPt2d[1]);
214  this->m_Context->GetPen()->SetWidth(1);
215  }
216  }
217 
218  if (showControlPoints)
219  {
220  // draw ontrol points
221  if ((*pointsIt)->IsControlPoint)
222  {
223  float pointsize = 4;
224  Point2D tmp;
225 
226  Vector2D horz, vert;
227  horz[1] = 0;
228  vert[0] = 0;
229  horz[0] = pointsize;
230  vert[1] = pointsize;
231  this->m_Context->GetPen()->SetColorF(selectedcolor->GetColor().GetRed(),
232  selectedcolor->GetColor().GetBlue(),
233  selectedcolor->GetColor().GetGreen());
234  this->m_Context->GetPen()->SetWidth(1);
235  // a rectangle around the point with the selected color
236  auto* rectPts = new float[8];
237  tmp = pt2d - horz;
238  rectPts[0] = tmp[0];
239  rectPts[1] = tmp[1];
240  tmp = pt2d + vert;
241  rectPts[2] = tmp[0];
242  rectPts[3] = tmp[1];
243  tmp = pt2d + horz;
244  rectPts[4] = tmp[0];
245  rectPts[5] = tmp[1];
246  tmp = pt2d - vert;
247  rectPts[6] = tmp[0];
248  rectPts[7] = tmp[1];
249  this->m_Context->DrawPolygon(rectPts,4);
250  // the actual point in the specified color to see the usual color of the point
251  this->m_Context->GetPen()->SetColorF(
252  colorprop->GetColor().GetRed(), colorprop->GetColor().GetGreen(), colorprop->GetColor().GetBlue());
253  this->m_Context->DrawPoint(pt2d[0], pt2d[1]);
254  }
255  }
256 
257  if (showPoints)
258  {
259  float pointsize = 3;
260  Point2D tmp;
261 
262  Vector2D horz, vert;
263  horz[1] = 0;
264  vert[0] = 0;
265  horz[0] = pointsize;
266  vert[1] = pointsize;
267  this->m_Context->GetPen()->SetColorF(0.0, 0.0, 0.0);
268  this->m_Context->GetPen()->SetWidth(1);
269  // a rectangle around the point with the selected color
270  auto* rectPts = new float[8];
271  tmp = pt2d - horz;
272  rectPts[0] = tmp[0];
273  rectPts[1] = tmp[1];
274  tmp = pt2d + vert;
275  rectPts[2] = tmp[0];
276  rectPts[3] = tmp[1];
277  tmp = pt2d + horz;
278  rectPts[4] = tmp[0];
279  rectPts[5] = tmp[1];
280  tmp = pt2d - vert;
281  rectPts[6] = tmp[0];
282  rectPts[7] = tmp[1];
283  this->m_Context->DrawPolygon(rectPts, 4);
284  // the actual point in the specified color to see the usual color of the point
285  this->m_Context->GetPen()->SetColorF(
286  colorprop->GetColor().GetRed(), colorprop->GetColor().GetGreen(), colorprop->GetColor().GetBlue());
287  this->m_Context->DrawPoint(pt2d[0], pt2d[1]);
288  }
289 
290  if (showPointsNumbers)
291  {
292  std::string l;
293  std::stringstream ss;
294  ss << index;
295  l.append(ss.str());
296 
297  float rgb[3];
298  rgb[0] = 0.0;
299  rgb[1] = 0.0;
300  rgb[2] = 0.0;
301 
302  WriteTextWithAnnotation(m_PointNumbersAnnotation, l.c_str(), rgb, pt2d, renderer);
303  }
304 
305  if (showControlPointsNumbers && (*pointsIt)->IsControlPoint)
306  {
307  std::string l;
308  std::stringstream ss;
309  ss << index;
310  l.append(ss.str());
311 
312  float rgb[3];
313  rgb[0] = 1.0;
314  rgb[1] = 1.0;
315  rgb[2] = 0.0;
316 
317  WriteTextWithAnnotation(m_ControlPointNumbersAnnotation, l.c_str(), rgb, pt2d, renderer);
318  }
319 
320  index++;
321  }
322 
323  pointsIt++;
324  } // end while iterate over controlpoints
325 
326  // close contour if necessary
327  if (renderingContour->IsClosed(timestep) && drawit && showSegments)
328  {
329  lastPt2d = pt2d;
330  point = renderingContour->GetVertexAt(0, timestep)->Coordinates;
331  itk2vtk(point, vtkp);
332  transform->TransformPoint(vtkp, vtkp);
333  vtk2itk(vtkp, p);
334  renderer->WorldToDisplay(p, pt2d);
335 
336  this->m_Context->GetPen()->SetWidth(lineWidth);
337  this->m_Context->DrawLine(lastPt2d[0], lastPt2d[1], pt2d[0], pt2d[1]);
338  this->m_Context->GetPen()->SetWidth(1);
339  }
340 
341  // draw selected vertex if exists
342  if (renderingContour->GetSelectedVertex())
343  {
344  // transform selected vertex
345  point = renderingContour->GetSelectedVertex()->Coordinates;
346 
347  itk2vtk(point, vtkp);
348  transform->TransformPoint(vtkp, vtkp);
349  vtk2itk(vtkp, p);
350 
351  renderer->WorldToDisplay(p, pt2d);
352 
353  ScalarType scalardiff = fabs(renderer->GetCurrentWorldPlaneGeometry()->SignedDistance(p));
354  //----------------------------------
355 
356  // draw point if close to plane
357  if (scalardiff < maxDiff)
358  {
359  float pointsize = 5;
360  Point2D tmp;
361 
362  this->m_Context->GetPen()->SetColorF(0.0, 1.0, 0.0);
363  this->m_Context->GetPen()->SetWidth(1);
364  // a rectangle around the point with the selected color
365  auto* rectPts = new float[8];
366  // a diamond around the point
367  // begin from upper left corner and paint clockwise
368  rectPts[0] = pt2d[0] - pointsize;
369  rectPts[1] = pt2d[1] + pointsize;
370  rectPts[2] = pt2d[0] + pointsize;
371  rectPts[3] = pt2d[1] + pointsize;
372  rectPts[4] = pt2d[0] + pointsize;
373  rectPts[5] = pt2d[1] - pointsize;
374  rectPts[6] = pt2d[0] - pointsize;
375  rectPts[7] = pt2d[1] - pointsize;
376  this->m_Context->DrawPolygon(rectPts, 4);
377  }
378  //------------------------------------
379  }
380  }
381  this->m_Context->GetDevice()->End();
382 }
383 
385  const char *text,
386  float rgb[3],
387  Point2D /*pt2d*/,
388  mitk::BaseRenderer * /*renderer*/)
389 {
390  textAnnotation->SetText(text);
391  textAnnotation->SetColor(rgb);
392  textAnnotation->SetOpacity(1);
393  textAnnotation->SetFontSize(16);
394  textAnnotation->SetBoolProperty("drawShadow", false);
395  textAnnotation->SetVisibility(true);
396 }
virtual ScalarType SignedDistance(const Point3D &pt3d_mm) const
TextAnnotationPointerType m_PointNumbersAnnotation
ContourModel is a structure of linked vertices defining a contour in 3D space. The vertices are store...
void UpdateOutputInformation() override
Update the OutputInformation of a ContourModel object.
virtual const VertexType * GetVertexAt(int index, int timestep=0) const
Returns the vertex at the index position within the container.
mitk::Point3D Coordinates
Coordinates in 3D space.
vtkRenderer * GetVtkRenderer() const
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
static Pointer New()
virtual void InternalDrawContour(mitk::ContourModel *renderingContour, mitk::BaseRenderer *renderer)
Organizes the rendering process.
virtual const PlaneGeometry * GetCurrentWorldPlaneGeometry()
Get the current 2D-worldgeometry (m_CurrentWorldPlaneGeometry) used for 2D-rendering.
void ApplyColorAndOpacityProperties(mitk::BaseRenderer *renderer, vtkActor *actor=nullptr) override
Apply specific color and opacity properties read from the PropertyList. Reimplemented in GLmapper (do...
static Pointer New()
bool GetOpacity(float &opacity, const mitk::BaseRenderer *renderer, const char *propertyKey="opacity") const
Convenience access method for opacity properties (instances of FloatProperty)
void WorldToDisplay(const Point3D &worldIndex, Point2D &displayPoint) const
This method converts a 3D world index to the display point using the geometry of the renderWindow...
void Initialize(mitk::BaseRenderer *renderer)
The ColorProperty class RGB color property.
VertexType * GetSelectedVertex()
Get the current selected vertex.
bool GetColor(float rgb[3], const mitk::BaseRenderer *renderer=nullptr, const char *propertyKey="color") const
Convenience access method for color properties (instances of ColorProperty)
bool IsEmptyTimeStep(unsigned int t) const override
Check if there isn&#39;t something at this timestep.
void WriteTextWithAnnotation(TextAnnotationPointerType textAnnotation, const char *text, float rgb[3], Point2D pt2d, mitk::BaseRenderer *)
void DrawContour(mitk::ContourModel *contour, mitk::BaseRenderer *renderer)
virtual unsigned int GetTimeStep() const
void vtk2itk(const Tin &in, Tout &out)
VertexIterator IteratorEnd(int timestep=0) const
Returns a const VertexIterator at the end element of the contour.
bool IsClosed(int timestep=0) const
Return if the contour is closed or not.
static void AddAnnotation(Annotation *Annotation, const std::string &rendererID)
void itk2vtk(const Tin &in, Tout &out)
VertexIterator IteratorBegin(int timestep=0) const
Returns a const VertexIterator at the start element of the contour.
TextAnnotationPointerType m_ControlPointNumbersAnnotation
void WorldToView(const Point3D &worldIndex, Point2D &viewPoint) const
This method converts a 3D world index to the point on the viewport using the geometry of the renderWi...
Class for nodes of the DataTree.
Definition: mitkDataNode.h:64