ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvColorFromScalarDlg.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 
9 
10 // local
11 #include "ecvConsole.h"
12 #include "ecvHistogramWindow.h"
13 
14 // CV_DB_LIB
15 #include <ecvColorScale.h>
16 #include <ecvHObjectCaster.h>
17 #include <ecvPointCloud.h>
18 
19 // Qt
20 #include <QPushButton>
21 
22 // ui
23 #include <ui_colorFromScalarDlg.h>
24 
25 // system
26 #include <cassert>
27 #include <cstring>
28 
30  ccPointCloud* pointCloud)
31  : QDialog(parent, Qt::Tool),
32  m_cloud(pointCloud),
33  m_systemInvalid(false),
34  m_ui(new Ui::ColorFromScalarDialog) {
35  m_ui->setupUi(this);
36 
37  // populate boxes
38  m_boxes_min[0] = m_ui->minInputSpinBoxR;
39  m_boxes_max[0] = m_ui->maxInputSpinBoxR;
40  m_boxes_min[1] = m_ui->minInputSpinBoxG;
41  m_boxes_max[1] = m_ui->maxInputSpinBoxG;
42  m_boxes_min[2] = m_ui->minInputSpinBoxB;
43  m_boxes_max[2] = m_ui->maxInputSpinBoxB;
44  m_boxes_min[3] = m_ui->minInputSpinBoxA;
45  m_boxes_max[3] = m_ui->maxInputSpinBoxA;
46 
47  // populate combo boxes
48  m_combos[0] = m_ui->channelComboR;
49  m_combos[1] = m_ui->channelComboG;
50  m_combos[2] = m_ui->channelComboB;
51  m_combos[3] = m_ui->channelComboA;
52 
53  // populate labels
54  m_labels_min[0] = m_ui->MinLabelR;
55  m_labels_min[1] = m_ui->MinLabelG;
56  m_labels_min[2] = m_ui->MinLabelB;
57  m_labels_min[3] = m_ui->MinLabelA;
58  m_labels_max[0] = m_ui->MaxLabelR;
59  m_labels_max[1] = m_ui->MaxLabelG;
60  m_labels_max[2] = m_ui->MaxLabelB;
61  m_labels_max[3] = m_ui->MaxLabelA;
62  m_reverse[0] = m_ui->reverseR;
63  m_reverse[1] = m_ui->reverseG;
64  m_reverse[2] = m_ui->reverseB;
65  m_reverse[3] = m_ui->reverseA;
66 
67  m_ui->fixA->setChecked(true); // set alpha fixed to checked
68 
69  // create histograms
70  QFrame* histoFrame[c_channelCount] = {m_ui->histoFrameR, m_ui->histoFrameG,
71  m_ui->histoFrameB, m_ui->histoFrameA};
72  for (unsigned i = 0; i < c_channelCount; i++) {
73  m_histograms[i] = new ccHistogramWindow(this);
75  auto layout = new QHBoxLayout;
76 
77  layout->setContentsMargins(0, 0, 0, 0);
78  layout->addWidget(m_histograms[i]);
79 
80  histoFrame[i]->setLayout(layout);
81  }
82 
83  // initialise colour scales
84  for (unsigned i = 0; i < c_channelCount; i++) {
86  new ccColorScale(QString::asprintf("%d", i)));
87  }
88  if (m_cloud->getNumberOfScalarFields() > 0) {
91  }
92  ccScalarField* sf = static_cast<ccScalarField*>(
94  if (!sf) // I had this happen 1 time during testing but could never
95  // replicate
96  {
97  assert(false);
99  "[ccColorFromScalarDlg] Get current scalar field failed!");
100  m_systemInvalid = true;
102  } else {
106 
107  for (unsigned i = 0; i < c_channelCount; i++) {
108  m_scalars[i] = nullptr;
109  m_prevFixed[i] = true;
110  m_combos[i]->clear();
111  for (unsigned int s = 0; s < m_cloud->getNumberOfScalarFields();
112  s++) {
113  m_combos[i]->addItem(m_cloud->getScalarFieldName(s));
114  }
115  m_combos[i]->setCurrentIndex(
117  }
118 
119  updateColormaps();
120 
121  // initialise histograms
122  m_prevFixed[c_channelCount - 1] = false;
123  updateChannel(0); // init first histogram
124  for (unsigned i = 1; i < c_channelCount;
125  i++) // copy data from this histogram into the next ones
126  {
127  m_scalars[i] = sf;
129  m_histograms[i]->fromBinArray(m_histograms[0]->histoValues(),
130  m_histograms[0]->minVal(),
131  m_histograms[0]->maxVal());
132  updateHistogram(i);
133  }
134 
135  sf->setColorScale(
137  1]); // set grey colour ramp to start with
139  }
140  } else {
141  CVLog::Error(
142  "[ccColorFromScalarDlg] Current cloud has no scalar fields!");
143  m_systemInvalid = true;
145  }
146 
147  // connect GUI elements
148  connect(m_ui->channelComboR,
149  static_cast<void (QComboBox::*)(int)>(
150  &QComboBox::currentIndexChanged),
152  connect(m_ui->channelComboG,
153  static_cast<void (QComboBox::*)(int)>(
154  &QComboBox::currentIndexChanged),
156  connect(m_ui->channelComboB,
157  static_cast<void (QComboBox::*)(int)>(
158  &QComboBox::currentIndexChanged),
160  connect(m_ui->channelComboA,
161  static_cast<void (QComboBox::*)(int)>(
162  &QComboBox::currentIndexChanged),
164 
165  connect(m_ui->buttonBox->button(QDialogButtonBox::Apply),
166  &QPushButton::clicked, this, &ccColorFromScalarDlg::onApply);
167  connect(m_ui->minInputSpinBoxR,
168  static_cast<void (QDoubleSpinBox::*)(double)>(
169  &QDoubleSpinBox::valueChanged),
171  connect(m_ui->maxInputSpinBoxR,
172  static_cast<void (QDoubleSpinBox::*)(double)>(
173  &QDoubleSpinBox::valueChanged),
175  connect(m_ui->minInputSpinBoxG,
176  static_cast<void (QDoubleSpinBox::*)(double)>(
177  &QDoubleSpinBox::valueChanged),
179  connect(m_ui->maxInputSpinBoxG,
180  static_cast<void (QDoubleSpinBox::*)(double)>(
181  &QDoubleSpinBox::valueChanged),
183  connect(m_ui->minInputSpinBoxB,
184  static_cast<void (QDoubleSpinBox::*)(double)>(
185  &QDoubleSpinBox::valueChanged),
187  connect(m_ui->maxInputSpinBoxB,
188  static_cast<void (QDoubleSpinBox::*)(double)>(
189  &QDoubleSpinBox::valueChanged),
191  connect(m_ui->minInputSpinBoxA,
192  static_cast<void (QDoubleSpinBox::*)(double)>(
193  &QDoubleSpinBox::valueChanged),
195  connect(m_ui->maxInputSpinBoxA,
196  static_cast<void (QDoubleSpinBox::*)(double)>(
197  &QDoubleSpinBox::valueChanged),
199 
200  connect(m_ui->reverseR, &QCheckBox::stateChanged, this,
202  connect(m_ui->reverseG, &QCheckBox::stateChanged, this,
204  connect(m_ui->reverseB, &QCheckBox::stateChanged, this,
206  connect(m_ui->reverseA, &QCheckBox::stateChanged, this,
208  connect(m_ui->toggleHSV, &QRadioButton::toggled, this,
210  connect(m_ui->toggleRGB, &QRadioButton::toggled, this,
212 
213  connect(m_ui->fixR, &QCheckBox::stateChanged, this,
215  connect(m_ui->fixG, &QCheckBox::stateChanged, this,
217  connect(m_ui->fixB, &QCheckBox::stateChanged, this,
219  connect(m_ui->fixA, &QCheckBox::stateChanged, this,
221 
222  // connect histogram events
239 
240  for (int i = 1; i < c_channelCount; ++i) {
241  updateChannel(i);
242  }
243 }
244 
246  if (!m_systemInvalid) {
247  ccScalarField* sf = static_cast<ccScalarField*>(
255  }
256  delete m_ui;
257 }
258 
260  if (!m_systemInvalid) {
261  // check for reversed
262  bool reversed[c_channelCount] = {
263  m_ui->reverseR->isChecked(), m_ui->reverseG->isChecked(),
264  m_ui->reverseB->isChecked(), m_ui->reverseA->isChecked()};
265 
266  // create colourmaps for RGB
267  if (m_ui->toggleRGB->isChecked()) {
268  // update labels
269  m_ui->mRedLabel->setText(QStringLiteral("Red"));
270  m_ui->mGreenLabel->setText(QStringLiteral("Green"));
271  m_ui->mBlueLabel->setText(QStringLiteral("Blue"));
272  m_ui->mAlphaLabel->setText(QStringLiteral("Alpha"));
273 
274  // populate colour ramps
275  Qt::GlobalColor start_colors[c_channelCount] = {
277  Qt::GlobalColor end_colors[c_channelCount] = {Qt::red, Qt::green,
279 
280  for (unsigned i = 0; i < c_channelCount; i++) {
281  m_colors[i]->clear();
282  if (reversed[i]) // flip
283  {
284  m_colors[i]->insert(
285  ccColorScaleElement(0.0, end_colors[i]));
286  m_colors[i]->insert(
287  ccColorScaleElement(1.0, start_colors[i]));
288  } else {
289  m_colors[i]->insert(
290  ccColorScaleElement(0.0, start_colors[i]));
291  m_colors[i]->insert(
292  ccColorScaleElement(1.0, end_colors[i]));
293  }
294 
295  m_colors[i]->update();
296  }
297  } else // create colourmaps for HSV
298  {
299  // update labels
300  m_ui->mRedLabel->setText(QStringLiteral("Hue"));
301  m_ui->mGreenLabel->setText(QStringLiteral("Sat"));
302  m_ui->mBlueLabel->setText(QStringLiteral("Value"));
303  m_ui->mAlphaLabel->setText(QStringLiteral("Alpha"));
304 
305  // populate colour ramps
306  Qt::GlobalColor start_colors[c_channelCount] = {
307  Qt::black, Qt::gray, Qt::black, Qt::black};
308  Qt::GlobalColor end_colors[c_channelCount] = {Qt::red, Qt::green,
310 
311  for (unsigned i = 0; i < c_channelCount; i++) {
312  m_colors[i]->clear();
313  if (reversed[i]) // flip
314  {
315  m_colors[i]->insert(
316  ccColorScaleElement(0.0, end_colors[i]));
317  m_colors[i]->insert(
318  ccColorScaleElement(1.0, start_colors[i]));
319  } else {
320  m_colors[i]->insert(
321  ccColorScaleElement(0.0, start_colors[i]));
322  m_colors[i]->insert(
323  ccColorScaleElement(1.0, end_colors[i]));
324  }
325 
326  m_colors[i]->update();
327  }
328 
329  // overwrite first colourmap with hue rainbow
330  int hue;
331  m_colors[0]->clear();
332 
333  ecvColor::Rgb col = ecvColor::Convert::hsv2rgb(360.0f, 1.0f, 1.0f);
334  m_colors[0]->insert(
335  ccColorScaleElement(1.0, QColor(col.r, col.g, col.b, 255)));
336  for (unsigned i = 0; i < 360; i += 2) {
337  // calculate hue value
338  if (reversed[0]) {
339  hue = 360 - i;
340  } else {
341  hue = i;
342  }
343 
344  // calculate colour
345  col = ecvColor::Convert::hsv2rgb(hue, 1.0f, 1.0f);
346 
347  // add stop
348  m_colors[0]->insert(
349  ccColorScaleElement(static_cast<double>(i) / 360.0,
350  QColor(col.r, col.g, col.b, 255)));
351  }
352  m_colors[0]->update();
353  }
354  }
355 }
356 
358  if (!m_systemInvalid) {
359  // update colourmaps
360  updateColormaps();
361 
362  // refresh histograms
363  refreshDisplay();
364  }
365 }
366 
368  if (!m_systemInvalid) {
369  // update colourmaps
370  updateColormaps();
371  refreshDisplay();
372  }
373 }
374 
375 // update/redraw histograms but don't reset postion of UI elements/sliders etc.
377  if (!m_systemInvalid) {
378  // refresh histograms
379  for (int i = 0; i < c_channelCount; i++) {
380  updateHistogram(i);
381  }
382  }
383 }
384 
386  if (!m_systemInvalid) {
387  if (n >= c_channelCount || n < 0) {
388  CVLog::Error(
389  "[ccColorFromScalarDlg] updateHistogram called with an "
390  "invalid channel index");
391  return;
392  }
393  // first check if fixed or not and enable disable ui features based on
394  // this
395  bool fixed[c_channelCount] = {
396  m_ui->fixR->isChecked(), m_ui->fixG->isChecked(),
397  m_ui->fixB->isChecked(), m_ui->fixA->isChecked()};
398  m_histograms[n]->setEnabled(!fixed[n]);
399  m_combos[n]->setEnabled(!fixed[n]);
400  m_boxes_max[n]->setEnabled(!fixed[n]);
401  m_labels_max[n]->setEnabled(!fixed[n]);
402  m_reverse[n]->setEnabled(!fixed[n]);
403  if (fixed[n]) // this channel is/has been fixed
404  {
405  if (fixed[n] != m_prevFixed[n]) {
406  m_labels_min[n]->setText(" Value:");
407  m_boxes_min[n]->setMaximum(255.0);
408  m_boxes_min[n]->setMinimum(0.0);
409  m_boxes_max[n]->setMaximum(255.0);
410  m_boxes_max[n]->setMinimum(0.0);
411  m_boxes_max[n]->setValue(200.0);
412  m_boxes_min[n]->setValue(200.0);
413  m_boxes_min[n]->setSingleStep(1.0);
414  m_boxes_max[n]->setSingleStep(1.0);
415 
416  // edge case for HSV values (0 - 360)
417  if (n == 0 && m_ui->toggleHSV->isChecked()) {
418  m_boxes_min[n]->setMaximum(360);
419  }
420  }
421 
422  // and make histogram grey
423  m_histograms[n]->clear();
426  None); // disable interactivity
427  m_histograms[n]->setAxisLabels("", "");
430  None); // only display XAxis
431  m_histograms[n]->refresh();
432  m_histograms[n]->replot();
433  } else {
434  if (fixed[n] != m_prevFixed[n]) {
435  setDefaultSatValuePerChannel(n); // update slider positions
436  m_labels_min[n]->setText(
437  "Minimum:"); // ensure label text is correct
438  }
439 
440  // set scalar field
442  m_scalars[n]->setSaturationStart(m_boxes_min[n]->value());
443  m_scalars[n]->setSaturationStop(m_boxes_max[n]->value());
446  SaturationRange); // disable interactivity
447  m_histograms[n]->setAxisLabels("", "");
450  XAxis); // only display XAxis
451  m_histograms[n]->refresh();
452  }
453  m_prevFixed[n] = fixed[n];
454  }
455 }
456 
458  if (!m_systemInvalid) {
459  if (n >= c_channelCount || n < 0) {
460  CVLog::Error(
461  "[ccColorFromScalarDlg] updateSpinBoxLimits called with an "
462  "invalid channel index");
463  return;
464  }
465  bool fixed[c_channelCount] = {
466  m_ui->fixR->isChecked(), m_ui->fixG->isChecked(),
467  m_ui->fixB->isChecked(), m_ui->fixA->isChecked()};
468  if (fixed[n]) {
469  return;
470  }
471  ccScalarField* sf = static_cast<ccScalarField*>(
472  m_cloud->getScalarField(m_combos[n]->currentIndex()));
473  if (sf) {
474  m_minSat[n] = sf->getMin();
475  m_maxSat[n] = sf->getMax();
476  double singleStepSize = (m_maxSat[n] - m_minSat[n]) / 100.0;
477  if (singleStepSize < 0.01) {
478  singleStepSize = 0.01;
479  }
480  m_boxes_min[n]->setMinimum(m_minSat[n]);
481  m_boxes_min[n]->setMaximum(m_maxSat[n]);
482  m_boxes_min[n]->setSingleStep(singleStepSize);
483  m_boxes_max[n]->setMinimum(m_minSat[n]);
484  m_boxes_max[n]->setMaximum(m_maxSat[n]);
485  m_boxes_max[n]->setSingleStep(singleStepSize);
486  m_boxes_max[n]->setCorrectionMode(
487  QAbstractSpinBox::CorrectionMode::CorrectToNearestValue);
488  }
489  }
490 }
491 
493  if (!m_systemInvalid) {
494  if (n >= c_channelCount || n < 0) {
495  CVLog::Error(
496  "[ccColorFromScalarDlg] updateChannel called with an "
497  "invalid channel index");
498  return;
499  }
500 
501  ccScalarField* sf = static_cast<ccScalarField*>(
502  m_cloud->getScalarField(m_combos[n]->currentIndex()));
503  if (sf) {
504  m_scalars[n] = sf;
506  m_histograms[n]->clear(); // clear last histogram
507  m_histograms[n]->fromSF(m_scalars[n], 255, false,
508  true); // generate new one
509  updateHistogram(n); // update plotting etc.
510  }
511  }
512 }
513 
515  if (!m_systemInvalid) {
516  if (n >= c_channelCount || n < 0) {
517  CVLog::Error(
518  "[ccColorFromScalarDlg] setDefaultSatValuePerChannel "
519  "called with an invalid channel index");
520  return;
521  }
522  // set default stretch (n.b. this is a cheap hack to avoid calculating
523  // percentiles [by assuming uniform data distribution])
525  m_minSat[n] = m_scalars[n]->getMin();
526  m_maxSat[n] = m_scalars[n]->getMax();
528  ScalarType range = m_maxSat[n] - m_minSat[n];
529  m_histograms[n]->setMinSatValue(m_minSat[n] + 0.1 * range);
530  m_boxes_min[n]->setValue(m_minSat[n] + 0.1 * range);
531  m_histograms[n]->setMaxSatValue(m_maxSat[n] - 0.1 * range);
532  m_boxes_max[n]->setValue(m_maxSat[n] - 0.1 * range);
533  }
534 }
535 
537  refreshDisplay();
538 }
539 
540 // mapping ranges changed
541 void ccColorFromScalarDlg::minChanged(int n, double val, bool slider) {
542  if (n >= c_channelCount || n < 0) {
543  CVLog::Error(
544  "[ccColorFromScalarDlg] minChanged called with an invalid "
545  "channel index");
546  return;
547  }
548  if (val <= m_maxSat[n]) // valid value?
549  {
551  m_minSat[n] = val;
552  if (slider) // change was made with the slider
553  {
554  m_boxes_min[n]->setValue(val);
555  } else // change was made with text box
556  {
557  m_histograms[n]->setMinSatValue(val);
558  }
559  } else {
560  // CVLog::Warning(QString("minChanged Channel %1 failed New min > max,
561  // val = %2, maxval = %3").arg(n).arg(val).arg(m_maxSat[n]));
562  }
563 }
564 
565 void ccColorFromScalarDlg::maxChanged(int n, double val, bool slider) {
566  if (n >= c_channelCount || n < 0) {
567  CVLog::Error(
568  "[ccColorFromScalarDlg] maxChanged called with an invalid "
569  "channel index");
570  return;
571  }
572  if (val >= m_minSat[n]) // valid value?
573  {
575  m_maxSat[n] = val;
576  if (slider) // change was made with the slider
577  {
578  m_boxes_max[n]->setValue(val);
579  } else // change was made with text box
580  {
581  m_histograms[n]->setMaxSatValue(val);
582  }
583  } else {
584  // CVLog::Warning(QString("maxChanged Channel %1 failed New max < min,
585  // val = %2, minval = %3").arg(n).arg(val).arg(m_minSat[n]));
586  }
587 }
588 
590  if (!m_systemInvalid) {
591  if (!m_cloud->hasColors()) {
592  m_cloud->resizeTheRGBTable(false);
593  }
594 
595  // which maps to flip?
596  bool reversed[c_channelCount] = {
597  m_ui->reverseR->isChecked(), m_ui->reverseG->isChecked(),
598  m_ui->reverseB->isChecked(), m_ui->reverseA->isChecked()};
599 
600  // and which are fixed?
601  bool fixed[c_channelCount] = {
602  m_ui->fixR->isChecked(), m_ui->fixG->isChecked(),
603  m_ui->fixB->isChecked(), m_ui->fixA->isChecked()};
604 
605  // map scalar values to RGB
606  if (m_ui->toggleRGB->isChecked()) {
607  int col[c_channelCount];
608  for (unsigned p = 0; p < m_cloud->size(); p++) {
609  // get col
610  for (unsigned i = 0; i < c_channelCount; i++) {
611  if (fixed[i]) // fixed value
612  {
613  col[i] = static_cast<int>(m_boxes_min[i]->value());
614  } else // map from scalar
615  {
616  col[i] = static_cast<int>(
617  255.0 *
618  (m_scalars[i]->getValue(p) - m_minSat[i]) /
619  (m_maxSat[i] - m_minSat[i]));
620  }
621 
622  // trim to range 0 - 255
623  col[i] = std::max(col[i], 0);
624  col[i] = std::min(col[i], 255);
625 
626  // flip?
627  if (reversed[i] && !fixed[i]) {
628  col[i] = 255 - col[i];
629  }
630  }
633  QColor(col[0], col[1], col[2], col[3])));
634  }
635  } else // map scalar values to HSV (and then to RGB)
636  {
637  float col[c_channelCount];
638  for (unsigned p = 0; p < m_cloud->size(); p++) {
639  // get col
640  for (unsigned i = 0; i < c_channelCount; i++) {
641  if (fixed[i]) // fixed value
642  {
643  col[i] =
644  m_boxes_min[i]->value() /
645  m_boxes_min[i]
646  ->maximum(); // n.b. most 'fixed' boxes
647  // between 0 - 255, but
648  // hue between 0 and 360.
649  } else // map from scalar
650  {
651  col[i] = (m_scalars[i]->getValue(p) - m_minSat[i]) /
652  (m_maxSat[i] - m_minSat[i]);
653  }
654 
655  // trim to range 0 - 1
656  col[i] = std::max(col[i], 0.0f);
657  col[i] = std::min(col[i], 1.0f);
658 
659  // flip?
660  if (reversed[i] && !fixed[i]) {
661  col[i] = 1.0f - col[i];
662  }
663  }
664 
665  // calculate and set colour
666  ecvColor::Rgb rgb = ecvColor::Convert::hsv2rgb(col[0] * 360.0f,
667  col[1], col[2]);
669  p,
671  rgb, static_cast<int>(col[3] * ecvColor::MAX)));
672  }
673  }
675  m_cloud->showSF(false);
676  m_cloud->showColors(true);
678  }
679 }
680 
682  for (unsigned n = 0; n < c_channelCount; n++) {
683  m_histograms[n]->setEnabled(false);
684  m_combos[n]->setEnabled(false);
685  m_boxes_min[n]->setEnabled(false);
686  m_boxes_max[n]->setEnabled(false);
687  m_labels_min[n]->setEnabled(false);
688  m_labels_max[n]->setEnabled(false);
689  m_reverse[n]->setEnabled(false);
690  }
691  m_ui->toggleHSV->setEnabled(false);
692  m_ui->toggleRGB->setEnabled(false);
693  m_ui->fixR->setEnabled(false);
694  m_ui->fixG->setEnabled(false);
695  m_ui->fixB->setEnabled(false);
696  m_ui->fixA->setEnabled(false);
697  m_ui->buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false);
698 }
MouseEvent event
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
QDoubleSpinBox * m_boxes_min[c_channelCount]
ccColorScale::Shared m_storedOrigColorScale
Associated point cloud scalar field original scale (to restore on exit)
QLabel * m_labels_max[c_channelCount]
void minSpinChangedG(double val)
void minChanged(int n, double val, bool slider)
void maxSpinChangedA(double val)
void minChangedR(double val)
void minSpinChangedA(double val)
void maxSpinChangedG(double val)
void maxChangedB(double val)
void minChangedB(double val)
void toggleColorMode(bool state)
void maxChangedG(double val)
void maxChanged(int n, double val, bool slider)
void maxSpinChangedB(double val)
ccHistogramWindow * m_histograms[c_channelCount]
Associated histogram view.
double m_maxSat[c_channelCount]
void minSpinChangedR(double val)
ccColorScale::Shared m_colors[c_channelCount]
Associated colour scales.
QCheckBox * m_reverse[c_channelCount]
QLabel * m_labels_min[c_channelCount]
void maxChangedR(double val)
ccScalarField * m_scalars[c_channelCount]
static constexpr int c_channelCount
ccScalarField::Range m_storedOrigSatRange
void minSpinChangedB(double val)
void maxChangedA(double val)
void minChangedG(double val)
void minChangedA(double val)
bool m_prevFixed[c_channelCount]
QDoubleSpinBox * m_boxes_max[c_channelCount]
QComboBox * m_combos[c_channelCount]
ccScalarField::Range m_storedOrigDisplayRange
void resizeEvent(QResizeEvent *event)
ccColorFromScalarDlg(QWidget *parent, ccPointCloud *pointCloud)
Default constructor.
ccPointCloud * m_cloud
Associated point cloud (color source)
double m_minSat[c_channelCount]
void maxSpinChangedR(double val)
Color scale element: one value + one color.
Definition: ecvColorScale.h:22
Color scale.
Definition: ecvColorScale.h:71
QSharedPointer< ccColorScale > Shared
Shared pointer type.
Definition: ecvColorScale.h:74
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual void redrawDisplay(bool forceRedraw=true, bool only2D=false)
Redraws associated display.
Histogram widget.
void sfMaxSatValChanged(double)
void sfMinSatValChanged(double)
void refresh()
Updates the display.
void fromSF(ccScalarField *sf, unsigned initialNumberOfClasses=0, bool numberOfClassesCanBeChanged=true, bool showNaNValuesInGrey=true)
Computes histogram from a scalar field.
void fromBinArray(const std::vector< unsigned > &histoValues, double minVal, double maxVal)
void setAxisDisplayOption(AxisDisplayOptions axisOptions)
void setRefreshAfterResize(bool refreshAfterResize)
void setSFInteractionMode(SFInteractionModes modes)
Enables SF interaction mode.
void clear()
Clears the display.
void setAxisLabels(const QString &xLabel, const QString &yLabel)
Sets axis labels.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
bool resizeTheRGBTable(bool fillWithWhite=false)
Resizes the RGB colors array.
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
bool hasColors() const override
Returns whether colors are enabled or not.
void setPointColor(size_t pointIndex, const ecvColor::Rgb &col)
Sets a particular point color.
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
void colorsHaveChanged()
ScalarType min() const
ScalarType max() const
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
void setSaturationStop(ScalarType val)
Sets the value at which to stop color gradient.
void setMinDisplayed(ScalarType val)
Sets the minimum displayed value.
void setColorScale(ccColorScale::Shared scale)
Sets associated color scale.
const Range & saturationRange() const
Access to the range of saturation values.
const Range & displayRange() const
Access to the range of displayed values.
void setSaturationStart(ScalarType val)
Sets the value at which to start color gradient.
void setMaxDisplayed(ScalarType val)
Sets the maximum displayed value.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
unsigned size() const override
Definition: PointCloudTpl.h:38
const char * getScalarFieldName(int index) const
Returns the name of a specific scalar field.
ScalarType getMin() const
Returns the minimum value.
Definition: ScalarField.h:72
ScalarType & getValue(std::size_t index)
Definition: ScalarField.h:92
ScalarType getMax() const
Returns the maximum value.
Definition: ScalarField.h:74
static Rgb hsv2rgb(float H, float S, float V)
Converts a HSV color to RGB color space.
RGB color structure.
Definition: ecvColorTypes.h:49
RGBA color structure.
int min(int a, int b)
Definition: cutil_math.h:53
int max(int a, int b)
Definition: cutil_math.h:48
constexpr utility::nullopt_t None
Definition: TensorKey.h:20
constexpr Rgb black(0, 0, 0)
constexpr Rgb white(MAX, MAX, MAX)
constexpr ColorCompType MAX
Max value of a single color component (default type)
Definition: ecvColorTypes.h:34
Rgba FromQColora(QColor qColor)
Conversion from QColor'a'.
constexpr Rgb red(MAX, 0, 0)
constexpr Rgb blue(0, 0, MAX)
constexpr Rgb green(0, MAX, 0)