Medical Imaging Interaction Toolkit  2018.4.99-389bf124
Medical Imaging Interaction Toolkit
mitkLayoutAnnotationRenderer.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
14 #include "mitkBaseRenderer.h"
15 
16 #include "mitkAnnotationUtils.h"
18 #include <mitkVtkLayerController.h>
19 
20 namespace mitk
21 {
22  const std::string LayoutAnnotationRenderer::ANNOTATIONRENDERER_ID = "LayoutAnnotationRenderer";
23 
24  const std::string LayoutAnnotationRenderer::PROP_LAYOUT = "Layout";
25  const std::string LayoutAnnotationRenderer::PROP_LAYOUT_PRIORITY = PROP_LAYOUT + ".priority";
26  const std::string LayoutAnnotationRenderer::PROP_LAYOUT_ALIGNMENT = PROP_LAYOUT + ".alignment";
27  const std::string LayoutAnnotationRenderer::PROP_LAYOUT_MARGIN = PROP_LAYOUT + ".margin";
28 
29  void LayoutAnnotationRenderer::SetMargin2D(Annotation *Annotation, const Point2D &OffsetVector)
30  {
31  mitk::Point2dProperty::Pointer OffsetVectorProperty = mitk::Point2dProperty::New(OffsetVector);
32  Annotation->SetProperty(PROP_LAYOUT_MARGIN, OffsetVectorProperty.GetPointer());
33  }
34 
35  Point2D LayoutAnnotationRenderer::GetMargin2D(Annotation *Annotation)
36  {
37  mitk::Point2D OffsetVector;
38  OffsetVector.Fill(0);
39  Annotation->GetPropertyValue<mitk::Point2D>(PROP_LAYOUT_MARGIN, OffsetVector);
40  return OffsetVector;
41  }
42 
43  LayoutAnnotationRenderer::LayoutAnnotationRenderer(const std::string &rendererId)
44  : AbstractAnnotationRenderer(rendererId, LayoutAnnotationRenderer::ANNOTATIONRENDERER_ID)
45  {
46  }
47 
48  void LayoutAnnotationRenderer::AddAlignmentProperty(Annotation *Annotation,
49  Alignment activeAlignment,
50  Point2D margin,
51  int priority)
52  {
54  alignmentProperty->AddEnum("TopLeft", TopLeft);
55  alignmentProperty->AddEnum("Top", Top);
56  alignmentProperty->AddEnum("TopRight", TopRight);
57  alignmentProperty->AddEnum("BottomLeft ", BottomLeft);
58  alignmentProperty->AddEnum("Bottom", Bottom);
59  alignmentProperty->AddEnum("BottomRight", BottomRight);
60  alignmentProperty->AddEnum("Left", Left);
61  alignmentProperty->AddEnum("Right", Right);
62  alignmentProperty->SetValue(activeAlignment);
63  Annotation->AddProperty(PROP_LAYOUT_ALIGNMENT, alignmentProperty.GetPointer());
64  Annotation->SetIntProperty(PROP_LAYOUT_PRIORITY, priority);
65  SetMargin2D(Annotation, margin);
66  }
67 
68  void LayoutAnnotationRenderer::OnAnnotationRenderersChanged()
69  {
70  if (!this->GetCurrentBaseRenderer())
71  return;
72  m_AnnotationContainerMap.clear();
73  for (Annotation *annotation : this->GetServices())
74  {
75  if (!annotation)
76  continue;
77  BaseProperty *prop = annotation->GetProperty(PROP_LAYOUT_ALIGNMENT);
78  auto *enumProb = dynamic_cast<EnumerationProperty *>(prop);
79  Alignment currentAlignment = TopLeft;
80  Point2D margin;
81  margin.Fill(5);
82  int priority = -1;
83  annotation->GetIntProperty(PROP_LAYOUT_PRIORITY, priority);
84  if (!enumProb)
85  {
86  AddAlignmentProperty(annotation, currentAlignment, margin, priority);
87  }
88  else
89  { // TODO19786 insert
90  currentAlignment = static_cast<Alignment>(enumProb->GetValueAsId());
91  }
92  AnnotationRankedMap &AnnotationVec = m_AnnotationContainerMap[currentAlignment];
93  if (!AnnotationVec.empty() && priority < 0)
94  {
95  int max = AnnotationVec.rbegin()->first;
96  if (max < 100)
97  priority = 100;
98  else
99  priority = max + 1;
100  }
101  AnnotationVec.insert(std::pair<int, Annotation *>(priority, annotation));
102  }
103  this->PrepareLayout();
104  }
105 
107  const std::string LayoutAnnotationRenderer::GetID() const { return ANNOTATIONRENDERER_ID; }
109  {
110  LayoutAnnotationRenderer *result = nullptr;
111  AbstractAnnotationRenderer *registeredService =
112  AnnotationUtils::GetAnnotationRenderer(ANNOTATIONRENDERER_ID, rendererID);
113  if (registeredService)
114  result = dynamic_cast<LayoutAnnotationRenderer *>(registeredService);
115  if (!result)
116  {
117  result = new LayoutAnnotationRenderer(rendererID);
119  }
120  return result;
121  }
122 
124  void LayoutAnnotationRenderer::AddAnnotation(Annotation *Annotation,
125  const std::string &rendererID,
126  Alignment alignment,
127  double marginX,
128  double marginY,
129  int priority)
130  {
131  GetAnnotationRenderer(rendererID);
132  us::ServiceProperties props;
133  props[Annotation::US_PROPKEY_AR_ID] = ANNOTATIONRENDERER_ID;
134  props[Annotation::US_PROPKEY_RENDERER_ID] = rendererID;
135  Annotation->RegisterAsMicroservice(props);
136  Point2D margin;
137  margin[0] = marginX;
138  margin[1] = marginY;
139  AddAlignmentProperty(Annotation, alignment, margin, priority);
140  }
141 
143  Annotation *Annotation, BaseRenderer *renderer, Alignment alignment, double marginX, double marginY, int priority)
144  {
145  AddAnnotation(Annotation, renderer->GetName(), alignment, marginX, marginY, priority);
146  }
147 
149  {
150  if (!this->GetCurrentBaseRenderer())
151  return;
152  int *size = this->GetCurrentBaseRenderer()->GetVtkRenderer()->GetSize();
153  PrepareTopLeftLayout(size);
154  PrepareTopLayout(size);
155  PrepareTopRightLayout(size);
156  PrepareBottomLeftLayout(size);
157  PrepareBottomLayout(size);
158  PrepareBottomRightLayout(size);
159  PrepareLeftLayout(size);
160  PrepareRightLayout(size);
161  }
162  void LayoutAnnotationRenderer::PrepareTopLeftLayout(int *displaySize)
163  {
164  double posX, posY;
165  Point2D margin;
166  posX = 0;
167  posY = displaySize[1];
169  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[TopLeft];
170  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
171  {
172  Annotation *Annotation = it->second;
173  margin = GetMargin2D(Annotation);
174  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
175 
176  posY -= bounds.Size[1] + margin[1];
177  bounds.Position[0] = posX + margin[0];
178  bounds.Position[1] = posY;
179  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
180  }
181  }
182  void LayoutAnnotationRenderer::PrepareTopLayout(int *displaySize)
183  {
184  double posX, posY;
185  Point2D margin;
186  posX = 0;
187  posY = displaySize[1];
189  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[Top];
190  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
191  {
192  Annotation *Annotation = it->second;
193  margin = GetMargin2D(Annotation);
194  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
195 
196  posX = displaySize[0] / 2 - bounds.Size[0] / 2;
197  posY -= bounds.Size[1] + margin[1];
198  bounds.Position[0] = posX;
199  bounds.Position[1] = posY;
200  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
201  }
202  }
203  void LayoutAnnotationRenderer::PrepareTopRightLayout(int *displaySize)
204  {
205  double posX, posY;
206  Point2D margin;
207  posX = 0;
208  posY = displaySize[1];
210  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[TopRight];
211  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
212  {
213  Annotation *Annotation = it->second;
214  margin = GetMargin2D(Annotation);
215  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
216 
217  posX = displaySize[0] - (bounds.Size[0] + margin[0]);
218  posY -= bounds.Size[1] + margin[1];
219  bounds.Position[0] = posX;
220  bounds.Position[1] = posY;
221  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
222  }
223  }
224 
225  void LayoutAnnotationRenderer::PrepareRightLayout(int *displaySize)
226  {
227  double posY;
228  Point2D margin;
229  double height = GetHeight(m_AnnotationContainerMap[Right], GetCurrentBaseRenderer());
230  posY = (height / 2.0 + displaySize[1]) / 2.0;
232  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[Right];
233  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
234  {
235  Annotation *Annotation = it->second;
236  margin = GetMargin2D(Annotation);
237  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
238 
239  posY -= bounds.Size[1] + margin[1];
240  bounds.Position[0] = displaySize[0] - (bounds.Size[0] + margin[0]);
241  bounds.Position[1] = posY + margin[1];
242  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
243  }
244  }
245 
246  void LayoutAnnotationRenderer::PrepareLeftLayout(int *displaySize)
247  {
248  double posY;
249  Point2D margin;
250  double height = GetHeight(m_AnnotationContainerMap[Left], GetCurrentBaseRenderer());
251  posY = (height / 2.0 + displaySize[1]) / 2.0;
253  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[Left];
254  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
255  {
256  Annotation *Annotation = it->second;
257  margin = GetMargin2D(Annotation);
258  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
259 
260  posY -= bounds.Size[1] + margin[1];
261  bounds.Position[0] = margin[0];
262  bounds.Position[1] = posY;
263  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
264  }
265  }
266 
267  void LayoutAnnotationRenderer::PrepareBottomLeftLayout(int * /*displaySize*/)
268  {
269  double posX, posY;
270  Point2D margin;
271  posX = 0;
272  posY = 0;
274  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[BottomLeft];
275  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
276  {
277  Annotation *Annotation = it->second;
278  margin = GetMargin2D(Annotation);
279  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
280 
281  bounds.Position[0] = posX + margin[0];
282  bounds.Position[1] = posY + margin[1];
283  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
284  posY += bounds.Size[1] + margin[1];
285  }
286  }
287  void LayoutAnnotationRenderer::PrepareBottomLayout(int *displaySize)
288  {
289  double posX, posY;
290  Point2D margin;
291  posX = 0;
292  posY = 0;
294  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[Bottom];
295  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
296  {
297  Annotation *Annotation = it->second;
298  margin = GetMargin2D(Annotation);
299  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
300 
301  posX = displaySize[0] / 2 - bounds.Size[0] / 2;
302  bounds.Position[0] = posX;
303  bounds.Position[1] = posY + margin[1];
304  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
305  posY += bounds.Size[1] + margin[1];
306  }
307  }
308  void LayoutAnnotationRenderer::PrepareBottomRightLayout(int *displaySize)
309  {
310  double posX, posY;
311  Point2D margin;
312  posX = 0;
313  posY = 0;
315  AnnotationRankedMap &AnnotationMap = m_AnnotationContainerMap[BottomRight];
316  for (auto it = AnnotationMap.cbegin(); it != AnnotationMap.cend(); ++it)
317  {
318  Annotation *Annotation = it->second;
319  margin = GetMargin2D(Annotation);
320  bounds = Annotation->GetBoundsOnDisplay(this->GetCurrentBaseRenderer());
321 
322  posX = displaySize[0] - (bounds.Size[0] + margin[0]);
323  bounds.Position[0] = posX;
324  bounds.Position[1] = posY + margin[1];
325  Annotation->SetBoundsOnDisplay(this->GetCurrentBaseRenderer(), bounds);
326  posY += bounds.Size[1] + margin[1];
327  }
328  }
329 
330  double LayoutAnnotationRenderer::GetHeight(AnnotationRankedMap &annotations, BaseRenderer *renderer)
331  {
332  double height = 0;
333  for (auto it = annotations.cbegin(); it != annotations.cend(); ++it)
334  {
335  Annotation *annotation = it->second;
336  Annotation::Bounds bounds = annotation->GetBoundsOnDisplay(renderer);
337  height += bounds.Size[0];
338  height += GetMargin2D(annotation)[0];
339  }
340  return height;
341  }
342 }
Point< ScalarType, 2 > Point2D
Definition: mitkPoint.h:94
The LayoutAnnotationRenderer is used for the layouted placement of mitk::Annotation Objects...
Container for position and size on the display.
virtual void RegisterAsMicroservice(us::ServiceProperties props)
Registers this object as a Microservice, making it available to every module and/or plugin...
itk::Point< double, 2 > Size
Organizes the rendering process.
DataCollection - Class to facilitate loading/accessing structured data.
static void RegisterAnnotationRenderer(AbstractAnnotationRenderer *annotationRenderer)
RegisterAnnotationRenderer registers an AnnotationRenderer as a microservice and saves a reference to...
static void AddAnnotation(Annotation *annotation, const std::string &rendererID, Alignment alignment=TopLeft, double marginX=5, double marginY=5, int priority=-1)
static Pointer New()
static AbstractAnnotationRenderer * GetAnnotationRenderer(const std::string &arTypeID, const std::string &rendererID)
GetAnnotationRenderer returns a registered AnnotationRenderer of a specific type and for a BaseRender...
virtual Bounds GetBoundsOnDisplay(BaseRenderer *renderer) const
Returns position and size of the Annotation on the display.
AbstractAnnotationRenderer(const std::string &rendererID, const std::string &arID)
itk::Point< double, 2 > Position
itk::SmartPointer< Self > Pointer
~LayoutAnnotationRenderer() override
virtual destructor in order to derive from this class
Baseclass of Annotation layouters An AbstractAnnotationRenderer can be implemented to control a set o...
static T max(T x, T y)
Definition: svm.cpp:56
US_UNORDERED_MAP_TYPE< std::string, Any > ServiceProperties
static Pointer New()
std::multimap< int, mitk::Annotation * > AnnotationRankedMap
static const std::string PROP_LAYOUT_ALIGNMENT
static const std::string US_PROPKEY_RENDERER_ID
static const std::string PROP_LAYOUT_PRIORITY
static const std::string US_PROPKEY_AR_ID
static LayoutAnnotationRenderer * GetAnnotationRenderer(const std::string &rendererID)
virtual void SetBoundsOnDisplay(BaseRenderer *renderer, const Bounds &)
Sets position and size of the Annotation on the display.
const char * GetName() const
get the name of the Renderer