source: flair-src/trunk/tools/FlairGCS/src/RangeFinderPlot.cpp @ 437

Last change on this file since 437 was 437, checked in by Sanahuja Guillaume, 4 months ago

prepare for graphs buffering

File size: 7.2 KB
Line 
1// %flair:license{
2// This file is part of the Flair framework distributed under the
3// CECILL-C License, Version 1.0.
4// %flair:license}
5#include "RangeFinderPlot.h"
6#include "Layout.h"
7#include <stdlib.h>
8#include <qwt_plot_grid.h>
9#include <qwt_plot_magnifier.h>
10#include <qwt_scale_widget.h>
11#include <qwt_plot_panner.h>
12#include <qwt_plot_rescaler.h>
13#include <qwt_plot_shapeitem.h>
14#include <QMouseEvent>
15#include <QMenu>
16#include <QInputDialog>
17#include <qendian.h>
18#include <qmath.h>
19
20RangeFinderPlot::RangeFinderPlot(Layout *parent, int row, int col, QString name,
21                                 QString x_name, QString y_name, float xmin,
22                                 float xmax, float ymin, float ymax,
23                                 float start_angle, float end_angle,
24                                 uint32_t nb_samples, QString data_type,
25                                 bool invert_axis, bool enabled, uint16_t period)
26    : DataRemote(name, "RangeFinderPlot", parent, enabled, period) {
27  invert_axis = true;
28  this->start_angle = start_angle;
29  this->end_angle = end_angle;
30  this->nb_samples = nb_samples;
31  this->data_type = data_type;
32  this->invert_axis = invert_axis;
33
34  if (data_type == "float") {
35    receivesize = nb_samples * sizeof(float);
36  } else if (data_type == "int8_t") {
37    receivesize = nb_samples * sizeof(int8_t);
38  } else if (data_type == "int16_t") {
39    receivesize = nb_samples * sizeof(int16_t);
40  } else {
41    fprintf(stderr,"RangeFinderPlot::RangeFinderPlot unknown type %s\n",
42           data_type.toLocal8Bit().constData());
43  }
44
45  plot = new QwtPlot(NULL);
46  plot->setEnabled(enabled);
47  // plot->setAutoReplot( false );
48
49  parent->addWidget(plot, row, col);
50  visible_widget = plot;
51
52  plot->setTitle(name);
53
54  // grid
55  QwtPlotGrid *grid = new QwtPlotGrid;
56  grid->setPen(QPen(Qt::black, 0, Qt::DotLine));
57  grid->attach(plot);
58
59  plot->updateAxes();
60
61  // zoomer
62  QwtPlotMagnifier *zoomer = new QwtPlotMagnifier(plot->canvas());
63  zoomer->setMouseButton(Qt::RightButton, Qt::ControlModifier);
64
65  // scroller
66  QwtPlotPanner *scroller = new QwtPlotPanner(plot->canvas());
67
68  // Axis
69  if (!invert_axis) {
70    plot->setAxisTitle(QwtPlot::xBottom, x_name);
71    setXAxisScale(xmin, xmax);
72
73    plot->setAxisTitle(QwtPlot::yLeft, y_name);
74    setYAxisScale(ymin, ymax);
75  } else {
76    plot->setAxisTitle(QwtPlot::xBottom, y_name);
77    setXAxisScale(ymin, ymax);
78
79    plot->setAxisTitle(QwtPlot::yLeft, x_name);
80    setYAxisScale(xmin, xmax);
81  }
82
83  QwtPlotRescaler *rescaler = new QwtPlotRescaler(plot->canvas());
84  rescaler->setRescalePolicy(QwtPlotRescaler::Fixed);
85
86  //( void ) new QwtPlotMagnifier( plot->canvas() );
87
88  plot->canvas()->installEventFilter(this);
89
90  for (uint32_t i = 0; i < nb_samples; i++) {
91    addTriangle(start_angle + i * (end_angle - start_angle + 1) / nb_samples,
92                start_angle +
93                    (i + 1) * (end_angle - start_angle + 1) / nb_samples);
94  }
95}
96
97RangeFinderPlot::~RangeFinderPlot() { delete plot; }
98
99void RangeFinderPlot::XmlEvent(QDomElement *dom) { XmlSetup(dom); }
100
101bool RangeFinderPlot::eventFilter(QObject *o, QEvent *e) {
102  if (o == plot->canvas()) {
103    switch (e->type()) {
104    case QEvent::MouseButtonPress: {
105      mousePressEvent((QMouseEvent *)e);
106      break;
107    }
108
109    default:
110      break;
111    }
112  }
113  return plot->eventFilter(o, e);
114}
115
116//
117//  Set a plain canvas frame and align the scales to it
118//
119void RangeFinderPlot::alignScales(void) {
120  // The code below shows how to align the scales to
121  // the canvas frame, but is also a good example demonstrating
122  // why the spreaded API needs polishing.
123  /*
124      plot->canvas()->setFrameStyle(QFrame::Box | QFrame::Plain );
125      plot->canvas()->setLineWidth(1);
126  */
127  for (int i = 0; i < QwtPlot::axisCnt; i++) {
128    QwtScaleWidget *scaleWidget = (QwtScaleWidget *)plot->axisWidget(i);
129    if (scaleWidget)
130      scaleWidget->setMargin(0);
131
132    QwtScaleDraw *scaleDraw = (QwtScaleDraw *)plot->axisScaleDraw(i);
133    if (scaleDraw)
134      scaleDraw->enableComponent(QwtAbstractScaleDraw::Backbone, false);
135  }
136}
137
138void RangeFinderPlot::setXAxisScale(float xmin, float xmax) {
139  xmin_orig = xmin;
140  xmax_orig = xmax;
141  plot->setAxisScale(QwtPlot::xBottom, xmin_orig, xmax_orig);
142}
143
144void RangeFinderPlot::setYAxisScale(float ymin, float ymax) {
145  ymin_orig = ymin;
146  ymax_orig = ymax;
147  plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
148}
149
150void RangeFinderPlot::BufEvent(char **buf, int *buf_size, uint16_t period,
151                               bool big_endian) {
152  plot->setEnabled(IsEnabled());
153  if (IsEnabled() == false || RefreshRate_ms() != period)
154    return;
155
156  for (uint32_t i = 0; i < nb_samples; i++) {
157    if (data_type == "float") {
158      uint32_t data_raw;
159      float *data = (float *)&data_raw;
160
161      memcpy((void *)&data_raw, *buf, sizeof(uint32_t));
162      *buf += sizeof(uint32_t);
163      if (big_endian == true)
164        data_raw = qFromBigEndian(data_raw);
165      SetTriangle(i, *data);
166    } else if (data_type == "int8_t") {
167      int8_t data;
168      memcpy((void *)&data, *buf, sizeof(data));
169      *buf += sizeof(data);
170      SetTriangle(i, data);
171    } else if (data_type == "int16_t") {
172      int16_t data;
173      memcpy((void *)&data, *buf, sizeof(data));
174      *buf += sizeof(data);
175      if (big_endian == true)
176        data = qFromBigEndian(data);
177      SetTriangle(i, data);
178    } else {
179      fprintf(stderr,"RangeFinderPlot::BufEvent unknown type %s\n",
180             data_type.toLocal8Bit().constData());
181    }
182  }
183
184  plot->replot();
185}
186
187void RangeFinderPlot::addTriangle(float angle_min, float angle_max) {
188  QwtPlotShapeItem *item = new QwtPlotShapeItem();
189
190  item->setRenderHint(QwtPlotItem::RenderAntialiased, true);
191  item->attach(plot);
192  triangles.append(item);
193}
194
195void RangeFinderPlot::SetTriangle(uint32_t id, float length) {
196  QPainterPath path;
197  QPolygonF triangle;
198  float angle_min =
199      start_angle + id * (end_angle - start_angle + 1) / nb_samples;
200  float angle_max =
201      start_angle + (id + 1) * (end_angle - start_angle + 1) / nb_samples;
202
203  if (invert_axis) {
204    angle_min = 90 - angle_min;
205    angle_max = 90 - angle_max;
206  }
207
208  triangle += QPointF(0, 0);
209  triangle += QPointF(length * cos(angle_min * M_PI / 180.),
210                      length * sin(angle_min * M_PI / 180.));
211  triangle += QPointF(length * cos(angle_max * M_PI / 180.),
212                      length * sin(angle_max * M_PI / 180.));
213
214  path.addPolygon(triangle);
215
216  path.closeSubpath();
217  triangles.at(id)->setShape(path);
218
219  QColor fillColor = "SandyBrown";
220  fillColor.setAlpha(200);
221
222  QPen pen(QColor("SandyBrown"), 1);
223  pen.setJoinStyle(Qt::MiterJoin);
224  triangles.at(id)->setPen(pen);
225  triangles.at(id)->setBrush(fillColor);
226}
227
228// context menu
229void RangeFinderPlot::mousePressEvent(QMouseEvent *event) {
230  if (event->button() == Qt::RightButton) {
231    QMenu *menu = new QMenu("nom", plot);
232    // ajout des actions
233    QAction *a, *z;
234
235    a = menu->addAction("reset y zoom");
236
237    appendmenu(menu);
238    z = execmenu(plot, menu, event->globalPos());
239    delete menu;
240
241    if (z == a) {
242      // zoom to original size
243      if (!invert_axis) {
244        plot->setAxisScale(QwtPlot::yLeft, ymin_orig, ymax_orig);
245      } else {
246        plot->setAxisScale(QwtPlot::yLeft, xmin_orig, xmax_orig);
247      }
248      plot->replot();
249    }
250  }
251}
Note: See TracBrowser for help on using the repository browser.