ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
AnglesCustomPlot.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "AnglesCustomPlot.h"
9 
10 #include <CVLog.h>
11 #include <ScalarField.h>
12 
13 #include "ui_AnglesCustomPlot.h"
14 
15 AnglesCustomPlot::AnglesCustomPlot(const QVector<double>& data,
16  const QString& xLabel,
17  int nbBins,
18  QWidget* parent)
19  : ui(new Ui::AnglesCustomPlot),
20  m_label(xLabel),
21  m_bars(nullptr),
22  m_nbBins(nbBins) {
23  setProperty("TypeOfCustomPlot", "AnglesCustomPlot");
24 
25  ui->setupUi(this);
26 
27  setWindowTitle(m_label);
28 
29  computeHistogram(data);
30 
31  createQCPBars(m_label + " [°]");
32 
33  m_bars->rescaleAxes();
34 }
35 
37 
39 static const unsigned MAX_HISTOGRAM_SIZE = 512;
40 
41 bool AnglesCustomPlot::computeHistogram(const QVector<double>& data) {
42  double minData = *std::min_element(data.begin(), data.end());
43  double maxData = *std::max_element(data.begin(), data.end());
44  double range = maxData - minData;
45 
46  if (range == 0 || data.size() == 0) {
47  // can't build histogram of a flat field
48  return false;
49  } else {
50  unsigned count = data.size();
51  unsigned numberOfBins;
52  if (m_nbBins == -1) // compute number of bins automatically
53  {
54  numberOfBins = static_cast<unsigned>(
55  ceil(sqrt(static_cast<double>(count))));
56  numberOfBins = std::max<unsigned>(
57  std::min<unsigned>(numberOfBins, MAX_HISTOGRAM_SIZE), 4);
58  } else // use number of bins
59  {
60  numberOfBins = m_nbBins;
61  }
62 
63  m_axis.resize(numberOfBins);
64  for (unsigned i = 0; i < numberOfBins; i++) {
65  m_axis[i] = minData + i * range / numberOfBins;
66  }
67 
68  // reserve memory
69  try {
70  m_histogram.resize(numberOfBins);
71  } catch (const std::bad_alloc&) {
72  CVLog::Warning("[computeHistogram] Failed to allocate histogram!");
73  }
74 
75  std::fill(m_histogram.begin(), m_histogram.end(), 0);
76 
77  // compute histogram
78  ScalarType step = static_cast<ScalarType>(numberOfBins) / range;
79  for (unsigned i = 0; i < count; ++i) {
80  const ScalarType& val = data[i];
81 
83  unsigned bin = static_cast<unsigned>((val - minData) * step);
84  ++m_histogram[std::min(bin, numberOfBins - 1)];
85  }
86  }
87  }
88 
89  return true;
90 }
91 
92 void AnglesCustomPlot::createQCPBars(const QString& xLabel) {
93  // clear previous display
94  if (m_bars) {
95  this->removePlottable(m_bars);
96  m_bars = nullptr;
97  }
98 
99  m_bars = new QCPBars(xAxis, yAxis);
100  m_bars->setAntialiased(
101  false); // gives more crisp, pixel aligned bar borders
102  m_bars->setPen(QPen(QColor(0, 168, 140).lighter(130)));
103  m_bars->setBrush(QColor(0, 168, 140));
104  m_bars->setWidth(m_axis[1] - m_axis[0]);
105  m_bars->setData(m_axis, m_histogram);
106  xAxis->setLabel(xLabel);
107  yAxis->setLabel("Counts");
108  setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);
109 }
110 
112  // set ranges appropriate to show data
113  if (m_bars) {
114  m_bars->rescaleAxes();
115  replot();
116  }
117 }
118 
120  if (event->button() == Qt::LeftButton) {
121  rescale();
122  }
123  QCustomPlot::mouseDoubleClickEvent(event);
124 }
125 
127  if (event->button() == Qt::RightButton) {
128  QMenu* menu = new QMenu(this);
129  QAction* action = new QAction("Close tab");
130  menu->addAction(action);
131  connect(action, &QAction::triggered, this,
133  menu->popup(event->globalPos());
134  }
135  QCustomPlot::mousePressEvent(event);
136 }
static const unsigned MAX_HISTOGRAM_SIZE
Default number of classes for associated histogram.
MouseEvent event
int count
void mousePressEvent(QMouseEvent *event) override
bool computeHistogram(const QVector< double > &data)
AnglesCustomPlot(const QVector< double > &data, const QString &xLabel, int nbBins, QWidget *parent=nullptr)
void mouseDoubleClickEvent(QMouseEvent *event) override
void createQCPBars(const QString &xLabel)
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
Definition: ScalarField.h:61
int min(int a, int b)
Definition: cutil_math.h:53
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Definition: MiniVec.h:89
constexpr Rgbaf lighter(0.83f, 0.83f, 0.83f, 1.00f)