fw4spl
SHistogram.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "scene2D/adaptor/SHistogram.hpp"
8 
9 #include <fwData/Histogram.hpp>
10 #include <fwData/Point.hpp>
11 
12 #include <fwRenderQt/data/InitQtPen.hpp>
13 #include <fwRenderQt/Scene2DGraphicsView.hpp>
14 
15 #include <fwServices/macros.hpp>
16 
17 #include <QGraphicsRectItem>
18 #include <QGraphicsView>
19 
20 fwServicesRegisterMacro( ::fwRenderQt::IAdaptor, ::scene2D::adaptor::SHistogram);
21 
22 namespace scene2D
23 {
24 
25 namespace adaptor
26 {
27 static const ::fwServices::IService::KeyType s_POINT_INOUT = "point";
28 static const ::fwServices::IService::KeyType s_HISTOGRAM_INPUT = "histogram";
29 
30 const float SHistogram::SCALE = 1.1f; // vertical scaling factor applied at each mouse scroll
31 
32 //---------------------------------------------------------------------------------------------------------
33 
34 SHistogram::SHistogram() noexcept :
35  m_opacity( 0.80f ),
36  m_scale(1.0f),
37  m_layer(nullptr),
38  m_color(Qt::green)
39 {
40 }
41 
42 //---------------------------------------------------------------------------------------------------------
43 
44 SHistogram::~SHistogram() noexcept
45 {
46 }
47 
48 //---------------------------------------------------------------------------------------------------------
49 
51 {
52  this->configureParams(); // Looks for 'xAxis', 'yAxis' and 'zValue'
53 
54  const ConfigType config = this->getConfigTree().get_child("config.<xmlattr>");
55 
56  m_scale = m_yAxis->getScale();
57 
58  if (config.count("color"))
59  {
60  ::fwRenderQt::data::InitQtPen::setPenColor(m_color, config.get<std::string>("color"));
61  }
62 
63  if (config.count("opacity"))
64  {
65  m_opacity = config.get<float>("opacity");
66  }
67 }
68 
69 //---------------------------------------------------------------------------------------------------------
70 
72 {
73  updating();
74 }
75 
76 //---------------------------------------------------------------------------------------------------------
77 
79 {
80  this->stopping();
81 
82  ::fwData::Histogram::csptr histogram = this->getInput< ::fwData::Histogram>(s_HISTOGRAM_INPUT);
83  ::fwData::Histogram::fwHistogramValues values = histogram->getValues();
84 
85  m_layer = new QGraphicsItemGroup();
86 
87  if (!values.empty())
88  {
89  // Update color with opacity
90  QColor color = m_color.color();
91  color.setAlphaF( m_opacity );
92  m_color.setColor( color );
93 
94  const float min = histogram->getMinValue();
95  const float binsWidth = histogram->getBinsWidth();
96 
97  // Initialize the path with a start point:
98  // The value preceding the current value that we'll use to build the arcs of the path
99  Point2DType startPoint = this->mapAdaptorToScene(Point2DType(min, values[0]), m_xAxis, m_yAxis);
100 
101  Point2DType pair;
102 
103  QBrush brush = QBrush(m_color.color());
104 
105  // Build the graphic items:
106  const int nbValues = (int)values.size();
107  for(int i = 1; i < nbValues; ++i)
108  {
109  pair = this->mapAdaptorToScene(Point2DType(min + i * binsWidth, values[i]), m_xAxis, m_yAxis);
110 
111  QPainterPath painter( QPointF(startPoint.first, 0) );
112  painter.lineTo( startPoint.first, startPoint.second );
113  painter.lineTo( pair.first, pair.second );
114  painter.lineTo( pair.first, 0 );
115 
116  QGraphicsPathItem* item = new QGraphicsPathItem( painter );
117  item->setPath( painter );
118  item->setBrush( brush );
119  item->setPen( Qt::NoPen );
120  item->setCacheMode( QGraphicsItem::DeviceCoordinateCache );
121 
122  m_layer->addToGroup( item );
123 
124  startPoint = pair;
125  }
126 
127  // Adjust the layer's position and zValue depending on the associated axis
128  m_layer->setPos(m_xAxis->getOrigin(), m_yAxis->getOrigin());
129  m_layer->setZValue(m_zValue);
130 
131  // Add to the scene the unique item which gather the whole set of rectangle graphic items:
132  this->getScene2DRender()->getScene()->addItem( m_layer );
133  }
134 }
135 
136 //---------------------------------------------------------------------------------------------------------
137 
138 void SHistogram::updateCurrentPoint(::fwRenderQt::data::Event& _event, const ::fwData::Point::sptr& point)
139 {
140  ::fwData::Histogram::csptr histogram = this->getInput< ::fwData::Histogram >(s_HISTOGRAM_INPUT);
141  ::fwData::Histogram::fwHistogramValues values = histogram->getValues();
142  const float histogramMinValue = histogram->getMinValue();
143  const float histogramBinsWidth = histogram->getBinsWidth();
144 
145  // Event coordinates in scene
146  ::fwRenderQt::data::Coord sceneCoord = this->getScene2DRender()->mapToScene( _event.getCoord() );
147 
148  const int histIndex = (int) sceneCoord.getX();
149  const int index = histIndex - histogramMinValue;
150  const int nbValues = (int)values.size() * histogramBinsWidth;
151 
152  if(index >= 0 && index < nbValues)
153  {
154  point->getCoord()[0] = sceneCoord.getX();
155  point->getCoord()[1] = values.at( index / histogramBinsWidth ) * m_scale;
156  }
157 }
158 
159 //---------------------------------------------------------------------------------------------------------
160 
162 {
163  if (m_layer)
164  {
165  this->getScene2DRender()->getScene()->removeItem(m_layer);
166  delete m_layer;
167  m_layer = nullptr;
168  }
169 }
170 
171 //---------------------------------------------------------------------------------------------------------
172 
174 {
175  bool updatePointedPos = false;
176 
177  // Vertical scaling
178  if( _event.getType() == ::fwRenderQt::data::Event::MouseWheelUp )
179  {
180  m_scale *= SCALE;
181  m_layer->setTransform(QTransform::fromScale(1, SCALE), true);
182 
183  //_event.setAccepted( true );
184  m_yAxis->setScale( m_scale );
185 
186  updatePointedPos = true;
187  }
188  else if( _event.getType() == ::fwRenderQt::data::Event::MouseWheelDown )
189  {
190  m_scale /= SCALE;
191  m_layer->setTransform(QTransform::fromScale(1, 1 / SCALE), true);
192 
193  //_event.setAccepted( true );
194  m_yAxis->setScale( m_scale );
195 
196  updatePointedPos = true;
197  }
198  else if( _event.getType() == ::fwRenderQt::data::Event::MouseMove )
199  {
200  updatePointedPos = true;
201  }
202 
203  ::fwData::Point::sptr point = this->getInOut< ::fwData::Point>(s_POINT_INOUT);
204  if( point && updatePointedPos )
205  {
206  this->updateCurrentPoint(_event, point);
207  }
208 }
209 
210 //----------------------------------------------------------------------------------------------------------
211 
213 {
214  KeyConnectionsMap connections;
215  connections.push( s_HISTOGRAM_INPUT, ::fwData::Histogram::s_MODIFIED_SIG, s_UPDATE_SLOT );
216  return connections;
217 }
218 
219 } // namespace adaptor
220 
221 } // namespace scene2D
Root class for all scene2d adaptors.
::fwRenderQt::data::Axis::sptr m_xAxis
The x Axis.
This class is a helper to define the connections of a service and its data.
Definition: IService.hpp:454
SCENE2D_API void configuring() override
Configure the service before starting. Apply the configuration to service.
Definition: SHistogram.cpp:50
FWRENDERQT_API Point2DType mapAdaptorToScene(const Point2DType &_xy, const ::fwRenderQt::data::Axis::sptr &_xAxis, const ::fwRenderQt::data::Axis::sptr &_yAxis) const
FWRENDERQT_API std::shared_ptr< ::fwRenderQt::SRender > getScene2DRender() const
Get the render that manages the IAdaptor.
SCENE2D_API void starting() override
Initialize the service activity.
Definition: SHistogram.cpp:71
std::pair< double, double > Point2DType
Point2D coordinate <X, Y>
static FWRENDERQT_API void setPenColor(QPen &_pen, std::string _color)
Set a pen a color.
Definition: InitQtPen.cpp:18
static const float SCALE
Ratio used for vertical scaling (default value: 1.1)
Definition: SHistogram.hpp:75
This bundles contains data and services used to display a 2D Qt scene.
IAdaptor implementation for histogram data.
Definition: SHistogram.hpp:50
SCENE2D_API void stopping() override
Uninitialize the service activity. The stop() method is always invoked before destroying a service...
Definition: SHistogram.cpp:161
SCENE2D_API void updating() override
Perform some computations according to object (this service is attached to) attribute values and its ...
Definition: SHistogram.cpp:78
::fwRenderQt::data::Axis::sptr m_yAxis
The y Axis.
FWRENDERQT_API void configureParams()
Parse the xml configuration for Axis, z value and opacity.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_MODIFIED_SIG
Key in m_signals map of signal m_sigModified.
SCENE2D_API void processInteraction(::fwRenderQt::data::Event &_event) override
Definition: SHistogram.cpp:173
This class manage events on the scene 2D (mouse event, keyboard event , ...).
Definition: Event.hpp:26
static FWSERVICES_APIconst::fwCom::Slots::SlotKeyType s_UPDATE_SLOT
Slot to call start method.
Definition: IService.hpp:177
SCENE2D_API::fwServices::IService::KeyConnectionsMap getAutoConnections() const override
Returns proposals to connect service slots to associated object signals, this method is used for obj/...
Definition: SHistogram.cpp:212
FWSERVICES_API ConfigType getConfigTree() const
Return the configuration, in an boost property tree.
Definition: IService.cpp:247