SimCenterCommon
Common functionality used within different SimCenter projects
simfigure.cpp
Go to the documentation of this file.
1 #include "simfigure.h"
2 #include "ui_simfigure.h"
3 
4 #include <QVBoxLayout>
5 #include <QBrush>
6 #include <QFont>
7 #include <QVector>
8 #include <QPoint>
9 #include <QPolygon>
10 #include <QPointF>
11 #include <QPolygonF>
12 #include <QMap>
13 #include <QMapIterator>
14 #include <QFileDialog>
15 #include <QSize>
16 #include <QSizeF>
17 
18 #include <qwt_plot.h>
19 #include <qwt_plot_grid.h>
20 #include <qwt_scale_engine.h>
21 #include <qwt_plot_curve.h>
22 #include <qwt_symbol.h>
23 #include <qwt_legend.h>
24 #include <qwt_plot_legenditem.h>
25 #include <qwt_plot_renderer.h>
26 
27 #include "qwt_picker.h"
28 #include "qwt_plot_picker.h"
29 #include "qwt_plot_zoomer.h"
30 #include "qwt_plot_item.h"
31 #include "qwt_plot_shapeitem.h"
32 #include "qwt_picker_machine.h"
33 
34 #include <QDebug>
35 
36 #include <algorithm>
37 
38 #define MIN(vec) *std::min_element(vec.constBegin(), vec.constEnd())
39 #define MAX(vec) *std::max_element(vec.constBegin(), vec.constEnd())
40 
41 SimFigure::SimFigure(QWidget *parent) :
42  QFrame(parent),
43  ui(new Ui::SimFigure)
55 {
56  ui->setupUi(this);
57 
58  m_grid = nullptr;
59  m_legend = nullptr;
60  m_curves.clear();
61 
62  m_plot = new QwtPlot(this);
63  QVBoxLayout *lyt = new QVBoxLayout(ui->pltWidgetSpace);
64  lyt->addWidget(m_plot);
65  m_plot->setCanvasBackground(QBrush(Qt::white));
66 
67  ui->btn_standard->setChecked(true);
68 
69  m_axisType = AxisType::Default;
70  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine(10));
71  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine(10));
72 
73  m_plot->setAxisScale(QwtPlot::yLeft, 1, 100);
74  m_plot->setAxisScale(QwtPlot::xBottom, 1, 100);
75 
76  grid(true, true);
77 
78  m_picker = new QwtPlotPicker(m_plot->canvas());
79  m_picker->setStateMachine(new QwtPickerClickPointMachine);
80  //m_picker->setTrackerMode(QwtPicker::AlwaysOff);
81  m_picker->setTrackerMode(QwtPicker::AlwaysOn);
82  m_picker->setRubberBand(QwtPicker::RectRubberBand);
83 
84  m_zoomer = new QwtPlotZoomer(m_plot->canvas());
85 
86  connect(m_picker, SIGNAL(activated(bool)), this, SLOT(on_picker_activated(bool)));
87  connect(m_picker, SIGNAL(selected(const QPolygon &)), this, SLOT(on_picker_selected(const QPolygon &)));
88  connect(m_picker, SIGNAL(appended(const QPoint &)), this, SLOT(on_picker_appended(const QPoint &)));
89  connect(m_picker, SIGNAL(moved(const QPoint &)), this, SLOT(on_picker_moved(const QPoint &)));
90  connect(m_picker, SIGNAL(removed(const QPoint &)), this, SLOT(on_picker_removed(const QPoint &)));
91  connect(m_picker, SIGNAL(changed(const QPolygon &)), this, SLOT(on_picker_changed(const QPolygon &)));
92 }
93 
96 {
97  delete ui;
98 }
99 
104 void SimFigure::axisTypeChanged(void)
105 {
106  if (ui->btn_standard->isChecked())
107  {
108  if (m_axisType != AxisType::Default)
109  {
110  m_axisType = AxisType::Default;
111  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine(10));
112  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine(10));
113 
114  rescale();
115 
116  m_plot->replot();
117  }
118  }
119  else if (ui->btn_logX->isChecked())
120  {
121  if (m_axisType != AxisType::LogX)
122  {
123  m_axisType = AxisType::LogX;
124  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine(10));
125  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine(10));
126 
127  rescale();
128 
129  m_plot->replot();
130  }
131  }
132  else if (ui->btn_logY->isChecked())
133  {
134  if (m_axisType != AxisType::LogY)
135  {
136  m_axisType = AxisType::LogY;
137  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine(10));
138  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine(10));
139 
140  rescale();
141 
142  m_plot->replot();
143  }
144  }
145  else if (ui->btn_loglog->isChecked())
146  {
147  if (m_axisType != AxisType::LogLog)
148  {
149  m_axisType = AxisType::LogLog;
150 
151  m_plot->setAxisMaxMajor( QwtPlot::yLeft, 6 );
152  m_plot->setAxisMaxMinor( QwtPlot::yLeft, 9 );
153 
154  m_plot->setAxisMaxMajor( QwtPlot::xBottom, 6 );
155  m_plot->setAxisMaxMinor( QwtPlot::xBottom, 9 );
156 
157  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine(10));
158  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine(10));
159 
160  rescale();
161 
162  m_plot->replot();
163  }
164  }
165 
166  grid(true, true);
167 
168  m_plot->repaint();
169 
170  //qDebug() << "signal axisTypeChanged received " << int(m_axisType);
171 }
172 
173 void SimFigure::grid(bool major, bool minor)
180 {
181  m_showMajorGrid = major;
182  m_showMinorGrid = minor;
183 
184  refreshGrid();
185 }
186 
189 {
190  return m_axisType;
191 }
192 
195 {
196  m_axisType = type;
197  switch (m_axisType) {
198  case AxisType::LogX :
199  ui->btn_logX->setChecked(true);
200  break;
201  case AxisType::LogY :
202  ui->btn_logY->setChecked(true);
203  break;
204  case AxisType::LogLog :
205  ui->btn_loglog->setChecked(true);
206  break;
207  case AxisType::Default :
208  ui->btn_standard->setChecked(true);
209  break;
210  }
211  this->axisTypeChanged();
212 }
213 
228 int SimFigure::plot(QVector<double> &x, QVector<double> &y, LineType lt, QColor color, Marker mk)
229 {
230  if (x.length() <= 0 || y.length() <= 0) return -1;
231 
232  // update min and max values
233 
234  if (MAX(x) > m_data_xmax) m_data_xmax=MAX(x);
235  if (MIN(x) < m_data_xmin) m_data_xmin=MIN(x);
236  if (MAX(y) > m_data_ymax) m_data_ymax=MAX(y);
237  if (MIN(y) < m_data_ymin) m_data_ymin=MIN(y);
238 
239  // now add that curve
240 
241  QwtPlotCurve *curve = new QwtPlotCurve("default");
242  curve->setSamples(x,y);
243 
244  setLineStyle(curve, lt);
245  setMarker(curve, mk, 10);
246  setLineColor(curve, color);
247 
248  curve->attach(m_plot);
249 
250  m_curves.append(curve);
251 
252  //grid(true,true);
253  fit_data();
254  m_plot->replot();
255 
256  int idx = m_curves.length();
257  m_plotInvMap.insert(curve, idx);
258 
259  return idx;
260 }
261 
275 int SimFigure::scatter(QVector<double> &x, QVector<double> &y, QColor color, Marker mk)
276 {
277  return plot(x, y, SimFigure::LineType::None, color, mk);
278 }
283 QString SimFigure::xLabel(void)
284 {
285  return m_plot->axisTitle(QwtPlot::xBottom).text();
286 }
287 
292 QString SimFigure::yLabel(void)
293 {
294  return m_plot->axisTitle(QwtPlot::yLeft).text();
295 }
296 
301 {
302  int size = m_plot->axisTitle(QwtPlot::xBottom).font().pointSize();
303  return size;
304 }
305 
310 {
311  int size = m_plot->title().font().pointSize();
312  return size;
313 }
314 
319 {
320  if (sz>0)
321  {
322  QwtText text = m_plot->axisTitle(QwtPlot::xBottom);
323  QFont font = text.font();
324  font.setPointSize(sz);
325  text.setFont(font);
326  m_plot->setAxisTitle(QwtPlot::xBottom, text);
327 
328  text = m_plot->axisTitle(QwtPlot::yLeft);
329  text.setFont(font);
330  m_plot->setAxisTitle(QwtPlot::yLeft, text);
331  }
332 }
333 
338 {
339  if (sz>0)
340  {
341  QwtText text = m_plot->title();
342  QFont font = text.font();
343  font.setPointSize(sz);
344  text.setFont(font);
345  m_plot->setTitle(text);
346  }
347 }
348 
353 QString SimFigure::title(void)
354 {
355  return m_plot->title().text();
356 }
357 
361 void SimFigure::setXLabel(QString label)
362 {
363  m_plot->setAxisTitle(QwtPlot::xBottom, label);
364 }
365 
369 void SimFigure::setYLabel(QString label)
370 {
371  m_plot->setAxisTitle(QwtPlot::yLeft, label);
372 }
373 
378 {
379  m_plot->setTitle(title);
380 }
381 
384 {
385  if (m_curves.length() > 0)
386  {
387  m_plot->setAxisScale(QwtPlot::yLeft, m_ymin, m_ymax);
388  m_plot->setAxisScale(QwtPlot::xBottom, m_xmin, m_xmax);
389  }
390  else
391  {
392  m_plot->setAxisScale(QwtPlot::yLeft, 1, 100);
393  m_plot->setAxisScale(QwtPlot::xBottom, 1, 100);
394  }
395  m_plot->replot();
396  m_plot->repaint();
397 
398 }
399 
404 void SimFigure::setXLim(double xmin, double xmax)
405 {
406  if (xmin<xmax) {
407  m_xmax = xmax;
408  m_xmin = xmin;
409  this->rescale();
410  }
411 }
412 
417 void SimFigure::setYLim(double ymin, double ymax)
418 {
419  if (ymin<ymax) {
420  m_ymax = ymax;
421  m_ymin = ymin;
422  this->rescale();
423  }
424 }
425 
428 {
429 
430  if (m_grid != nullptr)
431  {
432  m_grid->detach();
433  delete m_grid;
434  m_grid = nullptr;
435  }
436  // Create Background Grid for Plot
437  if (m_showMajorGrid)
438  {
439  m_grid = new QwtPlotGrid();
440  m_grid->attach( m_plot );
441  m_grid->setAxes(QwtPlot::xBottom, QwtPlot::yLeft);
442 
443  //m_plot->enableAxis(QwtPlot::xBottom);
444 
445  m_grid->setMajorPen(QPen(Qt::darkGray, 0.8));
446  m_grid->setMinorPen(QPen(Qt::lightGray, 0.5));
447  m_grid->setZ(1);
448  m_grid->enableX(true);
449  m_grid->enableY(true);
450 
451  if (m_showMinorGrid)
452  {
453  m_grid->enableXMin(true);
454  m_grid->enableYMin(true);
455  }
456  else {
457  m_grid->enableXMin(false);
458  m_grid->enableYMin(false);
459  }
460 
461  switch (m_axisType) {
462  case AxisType::Default:
463  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
464  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
465  break;
466  case AxisType::LogX:
467  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine);
468  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLinearScaleEngine);
469  break;
470  case AxisType::LogY:
471  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLinearScaleEngine);
472  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine);
473  break;
474  case AxisType::LogLog:
475  m_plot->setAxisScaleEngine(QwtPlot::xBottom, new QwtLogScaleEngine);
476  m_plot->setAxisScaleEngine(QwtPlot::yLeft, new QwtLogScaleEngine);
477  break;
478  }
479  }
480 
481  m_plot->replot();
482 }
483 
489 {
490  cla();
491 }
492 
494 void SimFigure::cla(void)
495 {
496  foreach (QwtPlotCurve *curve, m_curves)
497  {
498  curve->detach();
499  delete curve;
500 
501  m_plotInvMap.clear();
502  }
503  m_curves.clear();
504 
505  // reset label and title fonts
506  setTitleFontSize(14);
507  setLabelFontSize(12);
508 
509  lastSelection.object = nullptr;
510  lastSelection.plotID = -1;
511 
512  m_data_xmin = 1.e20;
513  m_data_xmax = 1.e-20;
514  m_data_ymin = 1.e20;
515  m_data_ymax = 1.e-20;
516 
517  m_xmin = 1.e20;
518  m_xmax = 1.e-20;
519  m_ymin = 1.e20;
520  m_ymax = 1.e-20;
521 
522  m_plot->replot();
523 
524  emit curve_selected(-1);
525 }
526 
531 void SimFigure::legend(QList<QString> labels, Location loc)
532 {
533  moveLegend(loc);
534 
535  if (labels.length()>0)
536  {
537  showLegend();
538  }
539 }
540 
544 {
545  if (m_legend == nullptr)
546  {
547  m_legend = new QwtPlotLegendItem();
548  m_legend->attach(m_plot);
549  }
550  m_legend->setMaxColumns(1);
551 
552  uint alignment = 0;
553 
554  if (m_legend) {
555 
556  switch (loc) {
557  case Location::Top:
558  case Location::North:
559  alignment = Qt::AlignTop|Qt::AlignHCenter;
560  break;
561  case Location::Bottom:
562  case Location::South:
563  alignment = Qt::AlignBottom|Qt::AlignHCenter;
564  break;
565  case Location::Left:
566  case Location::West:
567  alignment = Qt::AlignLeft|Qt::AlignVCenter;
568  break;
569  case Location::Right:
570  case Location::East:
571  alignment = Qt::AlignRight|Qt::AlignVCenter;
572  break;
573  case Location::TopLeft:
574  case Location::NorthWest:
575  alignment = Qt::AlignTop|Qt::AlignLeft;
576  break;
578  case Location::SouthWest:
579  alignment = Qt::AlignBottom|Qt::AlignLeft;
580  break;
581  case Location::TopRight:
582  case Location::NorthEast:
583  alignment = Qt::AlignRight|Qt::AlignTop;
584  break;
586  case Location::SouthEast:
587  alignment = Qt::AlignRight|Qt::AlignBottom; break;
588  }
589 
590  m_legend->setAlignment(Qt::Alignment(alignment));
591  m_plot->replot();
592  m_plot->repaint();
593  }
594 }
595 
598 {
599  if (m_legend == nullptr)
600  {
601  m_legend = new QwtPlotLegendItem();
602  m_legend->attach(m_plot);
603  }
604  m_legend->setMaxColumns(1);
605 
606  if (on)
607  {
608  m_legend->show();
609  }
610  else {
611  m_legend->hide();
612  }
613 
614  m_plot->replot();
615  m_plot->repaint();
616 }
617 
620 {
621  return (m_legend!=nullptr && m_legend->isVisible());
622 }
623 
626 {
627  //qWarning() << "picker activated " << on;
628 }
629 
631 void SimFigure::on_picker_selected(const QPolygon &polygon)
632 {
633  //qWarning() << "picker selected " << polygon;
634 }
635 
637 void SimFigure::on_picker_appended (const QPoint &pos)
638 {
639  //qWarning() << "picker appended " << pos;
640 
641  double coords[ QwtPlot::axisCnt ];
642  coords[ QwtPlot::xBottom ] = m_plot->canvasMap( QwtPlot::xBottom ).invTransform( pos.x() );
643  coords[ QwtPlot::xTop ] = m_plot->canvasMap( QwtPlot::xTop ).invTransform( pos.x() );
644  coords[ QwtPlot::yLeft ] = m_plot->canvasMap( QwtPlot::yLeft ).invTransform( pos.y() );
645  coords[ QwtPlot::yRight ] = m_plot->canvasMap( QwtPlot::yRight ).invTransform( pos.y() );
646 
647  QwtPlotItem *item = itemAt(pos);
648 
649  if ( item )
650  {
651  if ( item->rtti() == QwtPlotItem::Rtti_PlotShape )
652  {
653  QwtPlotShapeItem *theShape = static_cast<QwtPlotShapeItem *>(item);
654  theShape->setPen(Qt::cyan, 4);
655  QBrush brush = theShape->brush();
656  QColor color = brush.color();
657  color.setAlpha(64);
658  brush.setColor(color);
659  theShape->setBrush(brush);
660  }
661 
662  if ( item->rtti() == QwtPlotItem::Rtti_PlotCurve )
663  {
664  QwtPlotCurve *theCurve = static_cast<QwtPlotCurve *>(item);
665 
666  if (lastSelection.object != item)
667  {
668  if (lastSelection.object != nullptr) clearSelection();
669  select(item);
670  }
671 
672  // we need a way to revert to original color schema when a different curve is selected.
673 
674  }
675 
676  m_plot->replot();
677  }
678  else
679  {
680  qWarning() << "no item itentified at" << coords[QwtPlot::xBottom] << coords[QwtPlot::yLeft];
681  }
682 }
683 
685 void SimFigure::on_picker_moved (const QPoint &pos)
686 {
687  //qWarning() << "picker moved " << pos;
688 }
689 
691 void SimFigure::on_picker_removed (const QPoint &pos)
692 {
693  //qWarning() << "picker removed " << pos;
694 }
695 
697 void SimFigure::on_picker_changed (const QPolygon &selection)
698 {
699  //qWarning() << "picker changed " << selection;
700 }
701 
702 
704 {
705  this->ui->axisControls->setVisible(show);
706 }
707 
708 
710 {
711  m_xmax = m_data_xmax;
712  m_xmin = m_data_xmin;
713  m_ymax = m_data_ymax;
714  m_ymin = m_data_ymin;
715  rescale();
716 
717  //m_zoomer->zoom(QRectF(m_xmin,m_ymax,m_xmax-m_xmin,m_ymax-m_ymin));
718 }
719 
721 QwtPlotItem* SimFigure::itemAt( const QPoint& pos ) const
722 {
723  if ( m_plot == nullptr )
724  return nullptr;
725 
726  // translate pos into the plot coordinates
727  double coords[ QwtPlot::axisCnt ];
728  coords[ QwtPlot::xBottom ] = m_plot->canvasMap( QwtPlot::xBottom ).invTransform( pos.x() );
729  coords[ QwtPlot::xTop ] = m_plot->canvasMap( QwtPlot::xTop ).invTransform( pos.x() );
730  coords[ QwtPlot::yLeft ] = m_plot->canvasMap( QwtPlot::yLeft ).invTransform( pos.y() );
731  coords[ QwtPlot::yRight ] = m_plot->canvasMap( QwtPlot::yRight ).invTransform( pos.y() );
732 
733  QwtPlotItemList items = m_plot->itemList();
734  for ( int i = items.size() - 1; i >= 0; i-- )
735  {
736  QwtPlotItem *item = items[ i ];
737  if ( item->isVisible() && item->rtti() == QwtPlotItem::Rtti_PlotCurve )
738  {
739  double dist;
740 
741  QwtPlotCurve *curveItem = static_cast<QwtPlotCurve *>( item );
742  const QPointF p( coords[ item->xAxis() ], coords[ item->yAxis() ] );
743 
744  if ( curveItem->boundingRect().contains( p ) || true )
745  {
746  // trace curves ...
747  dist = 1000.;
748  for (size_t line=0; line < curveItem->dataSize() - 1; line++)
749  {
750  QPointF pnt;
751  double x, y;
752 
753  pnt = curveItem->sample(line);
754  x = m_plot->canvasMap( QwtPlot::xBottom ).transform( pnt.x() );
755  y = m_plot->canvasMap( QwtPlot::yLeft ).transform( pnt.y() );
756  QPointF x0(x,y);
757 
758  pnt = curveItem->sample(line+1);
759  x = m_plot->canvasMap( QwtPlot::xBottom ).transform( pnt.x() );
760  y = m_plot->canvasMap( QwtPlot::yLeft ).transform( pnt.y() );
761  QPointF x1(x,y);
762 
763  QPointF r = pos - x0;
764  QPointF s = x1 - x0;
765  double s2 = QPointF::dotProduct(s,s);
766 
767  if (s2 > 1e-6)
768  {
769  double xi = QPointF::dotProduct(r,s) / s2;
770 
771  if ( 0.0 <= xi && xi <= 1.0 )
772  {
773  QPointF t(-s.y()/sqrt(s2), s.x()/sqrt(s2));
774  double d1 = QPointF::dotProduct(r,t);
775  if ( d1 < 0.0 ) { d1 = -d1; }
776  if ( d1 < dist ) { dist = d1;}
777  }
778  }
779  else
780  {
781  dist = sqrt(QPointF::dotProduct(r,r));
782  QPointF r2 = pos - x1;
783  double d2 = sqrt(QPointF::dotProduct(r2,r2)); // review
784  if ( d2 < dist ) { dist = d2; }
785  }
786  }
787 
788  //qWarning() << "curve dist =" << dist;
789 
790  if ( dist <= 5 ) return static_cast<QwtPlotItem *>(curveItem);
791  }
792  }
793  if ( item->isVisible() && item->rtti() == QwtPlotItem::Rtti_PlotShape )
794  {
795  QwtPlotShapeItem *shapeItem = static_cast<QwtPlotShapeItem *>( item );
796  const QPointF p( coords[ item->xAxis() ], coords[ item->yAxis() ] );
797 
798  if ( shapeItem->boundingRect().contains( p ) && shapeItem->shape().contains( p ) )
799  {
800  return static_cast<QwtPlotItem *>(shapeItem);
801  }
802  }
803  }
804 
805  return nullptr;
806 }
807 
808 
812 void SimFigure::select(int ID)
813 {
814  QwtPlotItem *theItem = nullptr;
815 
816  if (ID > 0 && m_curves.length() >= ID && m_curves.value(ID-1) != nullptr)
817  theItem = m_curves.value(ID-1);
818 
819  if (theItem) select(theItem);
820 }
821 
824 void SimFigure::select(QwtPlotItem *item)
825 {
826  clearSelection();
827 
828  if (item != nullptr)
829  {
830  QwtPlotCurve *theCurve = static_cast<QwtPlotCurve *>(item);
831 
832  // save settings
833  lastSelection.object = item; // we need to use the generic pointer
834  lastSelection.plotID = m_plotInvMap.value(theCurve, -1);
835  lastSelection.pen = theCurve->pen();
836  lastSelection.brush = theCurve->brush();
837 
838  // visually ID selected
839  theCurve->setPen(Qt::cyan, 4);
840 
841  // let code now that selection changed
842  int ID = m_plotInvMap.value(theCurve, -1);
843  m_plot->replot();
844 
845  emit curve_selected(ID);
846  }
847 }
848 
851 {
852  if (lastSelection.object != nullptr)
853  {
854  // restore old settings
855  QwtPlotCurve *lastCurve = static_cast<QwtPlotCurve *>(lastSelection.object);
856  lastCurve->setPen(lastSelection.pen);
857  lastCurve->setBrush(lastSelection.brush);
858  lastSelection.object = nullptr; // we need to use the generic pointer
859  lastSelection.plotID = -1;
860 
861  m_plot->replot();
862  }
863 
864  emit curve_selected(-1);
865 }
866 
869 {
870  int w = 0;
871 
872  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
873  {
874  QPen pen = m_curves.value(ID-1)->pen();
875  w = pen.width();
876  }
877  return w;
878 }
879 
881 double SimFigure::lineWidthF(int ID)
882 {
883  double w = 0;
884 
885  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
886  {
887  QPen pen = m_curves.value(ID-1)->pen();
888  w = pen.widthF();
889  }
890  return w;
891 }
892 
894 void SimFigure::setLineWidth(int ID, int wd)
895 {
896  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
897  {
898  QPen pen = m_curves.value(ID-1)->pen();
899  pen.setWidth(wd);
900  m_curves.value(ID-1)->setPen(pen);
901  }
902 }
903 
905 void SimFigure::setLineWidthF(int ID, double wd)
906 {
907  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
908  {
909  QPen pen = m_curves.value(ID-1)->pen();
910  pen.setWidthF(wd);
911  m_curves.value(ID-1)->setPen(pen);
912  }
913 }
914 
917 {
918  return LineType::Solid; // for now
919 }
920 
923 {
924  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
925  {
926  setLineStyle(m_curves.value(ID-1), lt);
927  setMarker(m_curves.value(ID-1), mk, 10);
928  }
929 }
930 
932 void SimFigure::setLineStyle(QwtPlotCurve *curve, LineType lt)
933 {
934  QPen pen = curve->pen();
935  pen.setWidth(2);
936 
937  switch (lt)
938  {
939  case LineType::None :
940  pen.setStyle(Qt::NoPen);
941  break;
942  case LineType::Solid :
943  pen.setStyle(Qt::SolidLine);
944  break;
945  case LineType::Dashed :
946  pen.setStyle(Qt::DashLine);
947  break;
948  case LineType::Dotted :
949  pen.setStyle(Qt::DotLine);
950  break;
951  case LineType::DashDotted :
952  pen.setStyle(Qt::DashDotLine);
953  break;
954  }
955 
956  curve->setPen(pen);
957 }
958 
965 {
966  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
967  {
968  const QwtSymbol *sym = m_curves.value(ID-1)->symbol();
969  int mk = sym->style();
970  switch (mk) {
971  case QwtSymbol::NoSymbol:
972  return Marker::None;
973  case QwtSymbol::XCross:
974  return Marker::Ex;
975  case QwtSymbol::Rect:
976  return Marker::Box;
977  case QwtSymbol::Cross:
978  return Marker::Plus;
979  case QwtSymbol::Ellipse:
980  return Marker::Circle;
981  case QwtSymbol::Star1:
982  return Marker::Asterisk;
983  case QwtSymbol::Triangle:
984  return Marker::Triangle;
985  case QwtSymbol::DTriangle:
986  return Marker::DownTriangle;
987  case QwtSymbol::LTriangle:
988  return Marker::LeftTriangle;
989  case QwtSymbol::RTriangle:
990  return Marker::RightTriangle;
991  }
992  }
993  else {
994  return Marker::None;
995  }
996 }
997 
1004 {
1005  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
1006  {
1007  const QwtSymbol *sym = m_curves.value(ID-1)->symbol();
1008  int size = sym->size().width();
1009  return size;
1010  }
1011  else {
1012  return -1;
1013  }
1014 }
1015 
1019 void SimFigure::setMarker(int ID, Marker mk, int size)
1020 {
1021  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
1022  {
1023  setMarker(m_curves.value(ID-1), mk, size);
1024  }
1025 }
1026 
1028 void SimFigure::setMarker(QwtPlotCurve *curve, Marker mk, int size)
1029 {
1030  QColor color;
1031  QColor brush;
1032 
1033  if (curve) {
1034 
1035  /* these colors return Qt::black even though th ecurve has color. May be bug in Qwt (?) */
1036  color = curve->pen().color();
1037  brush = curve->brush().color();
1038 
1039  //qDebug() << "Color / brush: " << color << " / " << brush;
1040 
1041  QwtSymbol *newSymbol = nullptr;
1042 
1043  if (size>0) {
1044 
1045  switch (mk)
1046  {
1047  case Marker::None :
1048  newSymbol = new QwtSymbol(QwtSymbol::NoSymbol);
1049  break;
1050  case Marker::Ex :
1051  newSymbol = new QwtSymbol(QwtSymbol::XCross);
1052  break;
1053  case Marker::Box :
1054  newSymbol = new QwtSymbol(QwtSymbol::Rect);
1055  break;
1056  case Marker::Plus :
1057  newSymbol = new QwtSymbol(QwtSymbol::Cross);
1058  break;
1059  case Marker::Circle :
1060  newSymbol = new QwtSymbol(QwtSymbol::Ellipse);
1061  break;
1062  case Marker::Asterisk :
1063  newSymbol = new QwtSymbol(QwtSymbol::Star1);
1064  break;
1065  case Marker::Triangle :
1066  newSymbol = new QwtSymbol(QwtSymbol::Triangle);
1067  break;
1068  case Marker::DownTriangle :
1069  newSymbol = new QwtSymbol(QwtSymbol::DTriangle);
1070  break;
1071  case Marker::LeftTriangle :
1072  newSymbol = new QwtSymbol(QwtSymbol::LTriangle);
1073  break;
1074  case Marker::RightTriangle :
1075  newSymbol = new QwtSymbol(QwtSymbol::RTriangle);
1076  break;
1077  }
1078  }
1079  else {
1080  newSymbol = new QwtSymbol(QwtSymbol::NoSymbol);
1081  }
1082 
1083  newSymbol->setSize(size);
1084 
1085  newSymbol->setPen(color, 0.5);
1086  newSymbol->setColor(Qt::lightGray);
1087 
1088  curve->setSymbol(newSymbol);
1089  }
1090 }
1091 
1093 QColor SimFigure::lineColor(int ID)
1094 {
1095  QColor color;
1096  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
1097  {
1098  color = m_curves.value(ID-1)->pen().color();
1099  }
1100  else {
1101  color = Qt::red;
1102  }
1103  return color;
1104 }
1105 
1107 void SimFigure::setLineColor(int ID, QColor color)
1108 {
1109  if (ID > 0 && m_curves.length() <= ID && m_curves.value(ID-1) != nullptr)
1110  {
1111  setLineColor(m_curves.value(ID-1), color);
1112  }
1113 }
1114 
1116 void SimFigure::setLineColor(QwtPlotCurve *curve, QColor color)
1117 {
1118  QPen pen = curve->pen();
1119  pen.setColor(color);
1120  curve->setPen(pen);
1121 }
1122 
1136 void SimFigure::saveToFile(QString filename, SimFigure::FileType type, QSizeF size, int res)
1137 {
1138  if (res<50) res=50;
1139 
1140  QFileInfo *file = new QFileInfo(filename);
1141  QString base = file->completeBaseName();
1142  QString ext = (file->suffix()).toLower();
1143 
1144  // check for valid type
1145  if (ext == "ps" || ext == "pdf" || ext == "png" || ext == "svg" || ext == "bmp")
1146  {
1147  // use extension from provided file type
1148  }
1149  else {
1150  // fallback to user specified type
1151 
1152  switch (type)
1153  {
1154  case SimFigure::FileType::PS : ext = "ps"; break;
1155  case SimFigure::FileType::PDF : ext = "pdf"; break;
1156  case SimFigure::FileType::PNG : ext = "png"; break;
1157  case SimFigure::FileType::SVG : ext = "svg"; break;
1158  case SimFigure::FileType::BMP : ext = "bmp"; break;
1159  }
1160  }
1161 
1162  QString newFilename = base + "." + ext;
1163 
1164  QwtPlotRenderer *renderer = new QwtPlotRenderer(this);
1165  renderer->renderDocument(m_plot, newFilename, ext, size, res);
1166 }
1167 
1181 void SimFigure::exportToFile(QString filename, SimFigure::FileType type, QSizeF size, int res)
1182 {
1183  if (res<50) res=50;
1184 
1185  QFileInfo *file = new QFileInfo(filename);
1186  QString base = file->completeBaseName();
1187  QString ext = (file->suffix()).toLower();
1188 
1189  // check for valid type
1190  if (ext == "ps" || ext == "pdf" || ext == "png" || ext == "svg" || ext == "bmp")
1191  {
1192  // use extension from provided file type
1193  }
1194  else {
1195  // fallback to user specified type
1196 
1197  switch (type)
1198  {
1199  case SimFigure::FileType::PS : ext = "ps"; break;
1200  case SimFigure::FileType::PDF : ext = "pdf"; break;
1201  case SimFigure::FileType::PNG : ext = "png"; break;
1202  case SimFigure::FileType::SVG : ext = "svg"; break;
1203  case SimFigure::FileType::BMP : ext = "bmp"; break;
1204  }
1205  }
1206 
1207  QString newFilename = base + "." + ext;
1208 
1209  QwtPlotRenderer *renderer = new QwtPlotRenderer(this);
1210  renderer->exportTo(m_plot, newFilename, size, res);
1211 }
scaleable vector graphic file
void setYLim(double ymin, double ymax)
Sets y-axis limits to given values. ymax must be larger than ymin.
Definition: simfigure.cpp:417
void setMarker(int ID, Marker mk, int size=10)
Definition: simfigure.cpp:1019
centered vertically on the left
portable document format
Location
The Location enum.
Definition: simfigure.h:79
upside-down triangle
PostScript file.
SimFigure::AxisType axisType(void)
Definition: simfigure.cpp:187
int scatter(QVector< double > &, QVector< double > &, QColor col=Qt::blue, Marker mk=Marker::Circle)
Definition: simfigure.cpp:275
centered horizontally at the bottom
int markerSize(int ID)
SimFigure::markerSize.
Definition: simfigure.cpp:1003
void cla(void)
Definition: simfigure.cpp:494
bool legendVisible(void)
Definition: simfigure.cpp:619
Definition: dialogabout.h:6
centered vertically on the right
equivalent to Bottom
void grid(bool mayor=true, bool minor=true)
Definition: simfigure.cpp:173
const char * filename
Definition: ioapi.h:38
void on_picker_changed(const QPolygon &selection)
Definition: simfigure.cpp:697
a dashed line is drawn
void setLineWidthF(int ID, double wd)
Definition: simfigure.cpp:905
void rescale(void)
Definition: simfigure.cpp:383
void setLineStyle(int ID, LineType lt=LineType::Solid, Marker mk=Marker::None)
Definition: simfigure.cpp:922
voidpf void uLong size
Definition: ioapi.h:39
linear scale for x, log scale for y
portable network graphic file
#define MIN(vec)
Definition: simfigure.cpp:38
SimFigure::LineType lineStyle(int ID)
Definition: simfigure.cpp:916
void on_picker_removed(const QPoint &pos)
Definition: simfigure.cpp:691
void setLineColor(int ID, QColor color)
Definition: simfigure.cpp:1107
SimFigure::Marker marker(int ID)
SimFigure::marker.
Definition: simfigure.cpp:964
void clearSelection(void)
Definition: simfigure.cpp:850
void setAxisType(AxisType type)
Definition: simfigure.cpp:194
void on_picker_activated(bool on)
Definition: simfigure.cpp:625
void on_picker_selected(const QPolygon &polygon)
Definition: simfigure.cpp:631
void on_picker_appended(const QPoint &pos)
Definition: simfigure.cpp:637
void curve_selected(int ID)
void showAxisControls(bool show)
Definition: simfigure.cpp:703
a dash-dotted line is drawn
void setTitleFontSize(int)
sets the current font size used for title() to sz
Definition: simfigure.cpp:337
log scales for x and y
centered horizontally at the top
MicroSOft bitmap file.
QString title()
SimFigure::title()
Definition: simfigure.cpp:353
QColor lineColor(int ID)
Definition: simfigure.cpp:1093
#define MAX(vec)
Definition: simfigure.cpp:39
no marker (line only)
equivalent to TopRight
equivalent to BottomLeft
equivalent to BottomRight
void on_picker_moved(const QPoint &pos)
Definition: simfigure.cpp:685
QString xLabel()
SimFigure::xLabel()
Definition: simfigure.cpp:283
LineType
The LineType enum.
Definition: simfigure.h:50
point to the left triangle
equivalent to TopLeft
int labelFontSize()
returns the current font size used for xLabel() and yLabel()
Definition: simfigure.cpp:300
Marker
The Marker enum.
Definition: simfigure.h:62
void setLabelFontSize(int)
sets the current font size used for xLabel() and yLabel() to sz
Definition: simfigure.cpp:318
equivalent to Top
void setXLabel(QString lbl)
Definition: simfigure.cpp:361
void setLineWidth(int ID, int wd)
Definition: simfigure.cpp:894
linear scales for x and y
log scale for x, linear scale for y
FileType
The FileType enum.
Definition: simfigure.h:102
equivalent to Left
void setTitle(QString title)
Definition: simfigure.cpp:377
void setYLabel(QString lbl)
Definition: simfigure.cpp:369
void showLegend(bool=true)
Definition: simfigure.cpp:597
equivalent to Right
void select(int)
Definition: simfigure.cpp:812
void setXLim(double xmin, double xmax)
Sets x-axis limits to given values. xmax must be larger than xmin.
Definition: simfigure.cpp:404
a solid line is drawn
void legend(QList< QString > labels, Location loc=Location::South)
Definition: simfigure.cpp:531
a dotted line is drawn
double lineWidthF(int ID)
Definition: simfigure.cpp:881
void clear(void)
Definition: simfigure.cpp:488
no line is drawn (only markers)
SimFigure(QWidget *parent=nullptr)
Definition: simfigure.cpp:41
int plot(QVector< double > &, QVector< double > &, LineType lt=LineType::Solid, QColor col=Qt::red, Marker mk=Marker::None)
Definition: simfigure.cpp:228
void exportToFile(QString filename, SimFigure::FileType type=SimFigure::FileType::PNG, QSizeF size=QSizeF(300, 200), int res=85)
save image to file
Definition: simfigure.cpp:1181
QwtPlotItem * itemAt(const QPoint &pos) const
Definition: simfigure.cpp:721
int titleFontSize()
returns the current font size used for title()
Definition: simfigure.cpp:309
void refreshGrid(void)
Definition: simfigure.cpp:427
QString yLabel()
SimFigure::yLabel()
Definition: simfigure.cpp:292
point to the right triangle
void saveToFile(QString filename, SimFigure::FileType type=SimFigure::FileType::PNG, QSizeF size=QSizeF(300, 200), int res=85)
save image to file
Definition: simfigure.cpp:1136
AxisType
The AxisType enum.
Definition: simfigure.h:39
void fit_data()
Definition: simfigure.cpp:709
int lineWidth(int ID)
Definition: simfigure.cpp:868
void moveLegend(Location loc)
Definition: simfigure.cpp:543