CustusX  2023.01.05-dev+develop.0da12
An IGT application
cxMetricNamesRep.cpp
Go to the documentation of this file.
1 /*=========================================================================
2 This file is part of CustusX, an Image Guided Therapy Application.
3 
4 Copyright (c) SINTEF Department of Medical Technology.
5 All rights reserved.
6 
7 CustusX is released under a BSD 3-Clause license.
8 
9 See Lisence.txt (https://github.com/SINTEFMedtek/CustusX/blob/master/License.txt) for details.
10 =========================================================================*/
11 #include "cxMetricNamesRep.h"
12 
13 #include <vtkRenderer.h>
14 #include <vtkActor2D.h>
15 #include <vtkTextProperty.h>
16 #include <vtkTextMapper.h>
17 #include <QTimer>
18 
19 #include "cxView.h"
20 #include "cxVtkHelperClasses.h"
21 #include "cxTypeConversions.h"
22 #include "cxDataMetric.h"
23 #include "cxLogger.h"
24 
25 
26 namespace cx
27 {
28 
30  RepImpl()
31 {
32  mFontSize = 20;
33 }
34 
36 {
37 }
38 
40 {
41  return wrap_new(new MetricNamesRep(), uid);
42 }
43 
45 {
46  for(unsigned i =0; i<mDisplayText.size(); ++i)
47  {
48  mDisplayText[i]->setRenderer(view->getRenderer());
49  }
50 }
51 
53 {
54  for(unsigned i =0; i<mDisplayText.size(); ++i)
55  {
56  mDisplayText[i]->setRenderer(NULL);
57  }
58 }
59 
60 void MetricNamesRep::setData(std::vector<DataPtr> data)
61 {
62  std::vector<DataMetricPtr> metrics = this->convertToMetrics(data);
63 
64  if (this->equal(metrics, mMetrics))
65  return;
66 
67  for (unsigned i=0; i<mMetrics.size(); ++i)
68  {
69  disconnect(mMetrics[i].get(), SIGNAL(transformChanged()), this, SLOT(setModified()));
70  disconnect(mMetrics[i].get(), SIGNAL(propertiesChanged()), this, SLOT(setModified()));
71  }
72 
73  mMetrics = metrics;
74 
75  for (unsigned i=0; i<mMetrics.size(); ++i)
76  {
77  connect(mMetrics[i].get(), SIGNAL(transformChanged()), this, SLOT(setModified()));
78  connect(mMetrics[i].get(), SIGNAL(propertiesChanged()), this, SLOT(setModified()));
79  }
80 
81  this->callSetColoredTextListSlot();
82  // Call again with a small delay, as the view might not be ready yet. I.e. the bounding box of the corner text is not properly initialized.
83  // Need the second call to avoid some assertion.
84  QTimer::singleShot(500, this, &MetricNamesRep::callSetColoredTextListSlot);
85 }
86 
87 void MetricNamesRep::callSetColoredTextListSlot()
88 {
89  this->setColoredTextList(this->getAllMetricTexts(), Eigen::Array2d(0.98, 0.98));
90 }
91 
92 std::vector<DataMetricPtr> MetricNamesRep::convertToMetrics(std::vector<DataPtr> data)
93 {
94  std::vector<DataMetricPtr> metrics;
95  for (unsigned i=0; i<data.size(); ++i)
96  {
97  DataMetricPtr metric = boost::dynamic_pointer_cast<DataMetric>(data[i]);
98  if (metric)
99  metrics.push_back(metric);
100  }
101  return metrics;
102 }
103 
104 bool MetricNamesRep::equal(std::vector<DataMetricPtr> a, std::vector<DataMetricPtr> b) const
105 {
106  if (a.size()!=b.size())
107  return false;
108  for (unsigned i=0; i<a.size(); ++i)
109  if (a[i] != b[i])
110  return false;
111  return true;
112 }
113 
115 {
116  std::vector<std::pair<QColor, QString> > text;
117  text = this->getAllMetricTexts();
118  CX_ASSERT(text.size()==mDisplayText.size());
119 
120  for (unsigned i=0; i<mDisplayText.size(); ++i)
121  {
122  mDisplayText[i]->updateText(text[i].second);
123  mDisplayText[i]->setColor(text[i].first);
124  }
125 
126 }
127 
128 void MetricNamesRep::setColoredTextList(std::vector<std::pair<QColor, QString> > text, Eigen::Array2d pos, vtkViewport *vp)
129 {
130  mDisplayText.clear();
131 
132  if (vp==0)
133  {
134  vp = this->getRenderer();
135  }
136 // if (vp==0)
137 // {
138 // return;
139 // }
140 
142  bb = this->findNormalizedBoundingBoxAroundText(text, pos, vp);
143  double meanHeight = bb.range()[1]/text.size();
144 
145  for (unsigned i=0; i<text.size(); ++i)
146  {
147  TextDisplayPtr rep;
148  rep.reset( new TextDisplay( text[i].second, text[i].first, mFontSize) );
149  rep->textProperty()->SetJustificationToLeft();
150  rep->getActor()->GetPositionCoordinate()->SetCoordinateSystemToNormalizedViewport();
151 
152  Vector3D currentPos = bb.bottomLeft() + (meanHeight*i)*Eigen::Vector3d::UnitY();
153  rep->setPosition(currentPos);
154  rep->setRenderer(this->getRenderer());
155 
156  mDisplayText.push_back(rep);
157  }
158 }
159 
160 DoubleBoundingBox3D MetricNamesRep::findNormalizedBoundingBoxAroundText(std::vector<std::pair<QColor, QString> > text, Eigen::Array2d pos, vtkViewport *vp)
161 {
162  QStringList fullText;
163  for (unsigned i=0; i<text.size(); ++i)
164  fullText << text[i].second;
165  TextDisplay test(fullText.join("\n"), QColor(Qt::red), mFontSize);
166  test.textProperty()->SetJustificationToLeft();
167  double width_p = test.getMapper()->GetWidth(vp);
168  double height_p = test.getMapper()->GetHeight(vp);
169  height_p *= 1.1; // increase spacing
170 
171  Eigen::Array2i size_vp(vp->GetSize());
172  Eigen::Array2d normsize_box(width_p/size_vp[0], height_p/size_vp[1]);
173 
174  // move box into viewport:
175  double border = 0.02;
176  DoubleBoundingBox3D bb_vp(border, 1.0-border, border, 1.0-border, 0, 0);
177  DoubleBoundingBox3D bb_box(pos[0], pos[0]+normsize_box[0], pos[1], pos[1]+normsize_box[1], 0, 0);
178  bb_box = this->moveBoxIntoAnother(bb_box, bb_vp);
179 
180  return bb_box;
181 }
182 
184 {
185  // move negative direction
186  for (unsigned i=0; i<2; ++i)
187  {
188  double shift = another[2*i+1] - box[2*i+1];
189  if (shift < 0)
190  {
191  box[2*i] += shift;
192  box[2*i+1] += shift;
193  }
194  }
195 
196  // move positive direction
197  for (unsigned i=0; i<3; ++i)
198  {
199  double shift = another[2*i] - box[2*i];
200  if (shift > 0)
201  {
202  box[2*i] -= shift;
203  box[2*i+1] -= shift;
204  }
205  }
206 
207  return box;
208 }
209 
211 {
212  mFontSize = size;
213 }
214 
215 QString MetricNamesRep::getText(DataMetricPtr metric, bool showLabel) const
216 {
217  QStringList text;
218  if (showLabel)
219  text << metric->getName();
220  if (metric->showValueInGraphics())
221  text << metric->getValueAsString();
222  return text.join(" = ");
223 }
224 
225 std::vector<std::pair<QColor, QString> > MetricNamesRep::getAllMetricTexts() const
226 {
227  std::vector<std::pair<QColor, QString> > retval;
228 
229  for (unsigned i = 0; i < mMetrics.size(); ++i)
230  {
231  DataMetricPtr metric = mMetrics[i];
232  QString line = metric->getName();
233 
234  if (!metric->showValueInGraphics())
235  continue;
236 
237  QString text = this->getText(metric, true);
238  retval.push_back(std::make_pair(metric->getColor(), text));
239  }
240  std::reverse(retval.begin(), retval.end());
241  return retval;
242 }
243 
244 
245 } // namespace cx
246 
vtkTextProperty * textProperty()
vtkRendererPtr getRenderer()
Definition: cxRepImpl.cpp:88
#define CX_ASSERT(statement)
Definition: cxLogger.h:116
boost::shared_ptr< DataMetric > DataMetricPtr
Definition: cxDataMetric.h:73
std::vector< DataMetricPtr > convertToMetrics(std::vector< DataPtr > data)
void setFontSize(int size)
must be set before setting data
Vector3D bottomLeft() const
static boost::shared_ptr< REP > wrap_new(REP *object, QString uid)
Definition: cxRepImpl.h:62
boost::shared_ptr< class View > ViewPtr
void setColoredTextList(std::vector< std::pair< QColor, QString > > text, Eigen::Array2d pos, vtkViewport *vp=0)
boost::shared_ptr< class MetricNamesRep > MetricNamesRepPtr
static MetricNamesRepPtr New(const QString &uid="")
void setData(std::vector< DataPtr > data)
virtual void addRepActorsToViewRenderer(ViewPtr view)
Helper for drawing text in 2D.
boost::shared_ptr< class TextDisplay > TextDisplayPtr
Default implementation of Rep.
Definition: cxRepImpl.h:42
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
virtual void onModifiedStartRender()
DoubleBoundingBox3D moveBoxIntoAnother(DoubleBoundingBox3D box, DoubleBoundingBox3D another)
std::vector< std::pair< QColor, QString > > getAllMetricTexts() const
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
Definition: cxVector3D.h:42
std::vector< TextDisplayPtr > mDisplayText
QString getText(DataMetricPtr metric, bool showLabel) const
virtual void removeRepActorsFromViewRenderer(ViewPtr view)
Base class for all Data Metrics.
Definition: cxDataMetric.h:43
bool equal(std::vector< DataMetricPtr > a, std::vector< DataMetricPtr > b) const
void setModified()
Definition: cxRepImpl.cpp:112
DoubleBoundingBox3D findNormalizedBoundingBoxAroundText(std::vector< std::pair< QColor, QString > > text, Eigen::Array2d pos, vtkViewport *vp)
std::vector< DataMetricPtr > mMetrics
Namespace for all CustusX production code.