ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvRenderingTools.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 "ecvRenderingTools.h"
9 
10 // CV_DB_LIB
11 #include "ecvColorScalesManager.h"
12 #include "ecvDisplayTools.h"
13 #include "ecvGBLSensor.h"
14 #include "ecvGenericPointCloud.h"
15 #include "ecvScalarField.h"
16 
17 // Qt
18 #include <QDialog>
19 #include <QLabel>
20 #include <QVBoxLayout>
21 
22 // STL
23 #include <limits>
24 
26  QWidget* parent /*=0*/,
27  unsigned maxDim /*=1024*/) {
28  if (!sensor) return;
29 
30  const ccDepthBuffer& depthBuffer = sensor->getDepthBuffer();
31  if (depthBuffer.zBuff.empty()) {
32  return;
33  }
34 
35  // determine min and max depths
36  PointCoordinateType minDist = 0.0f;
37  PointCoordinateType maxDist = 0.0f;
38  {
39  const PointCoordinateType* _zBuff = depthBuffer.zBuff.data();
40  double sumDist = 0.0;
41  double sumDist2 = 0.0;
42  unsigned count = 0;
43  for (unsigned x = 0; x < depthBuffer.height * depthBuffer.width;
44  ++x, ++_zBuff) {
45  if (x == 0) {
46  maxDist = minDist = *_zBuff;
47  } else if (*_zBuff > 0) {
48  maxDist = std::max(maxDist, *_zBuff);
49  minDist = std::min(minDist, *_zBuff);
50  }
51 
52  if (*_zBuff > 0) {
53  sumDist += *_zBuff;
54  sumDist2 += static_cast<double>(*_zBuff) * *_zBuff;
55  ++count;
56  }
57  }
58 
59  if (count) {
60  double avg = sumDist / count;
61  double stdDev = sqrt(std::abs(sumDist2 / count - avg * avg));
62  // for better dynamics
63  maxDist = std::min(maxDist, static_cast<PointCoordinateType>(
64  avg + 1.0 * stdDev));
65  }
66  }
67 
68  QImage bufferImage(depthBuffer.width, depthBuffer.height,
69  QImage::Format_RGB32);
70  {
71  ccColorScale::Shared colorScale =
73  assert(colorScale);
74  ScalarType coef =
75  cloudViewer::LessThanEpsilon(maxDist - minDist)
76  ? 0
77  : static_cast<ScalarType>(ccColorScale::MAX_STEPS - 1) /
78  (maxDist - minDist);
79 
80  const PointCoordinateType* _zBuff = depthBuffer.zBuff.data();
81  for (unsigned y = 0; y < depthBuffer.height; ++y) {
82  for (unsigned x = 0; x < depthBuffer.width; ++x, ++_zBuff) {
83  const ecvColor::Rgb& col =
84  (*_zBuff >= minDist
85  ? colorScale->getColorByIndex(
86  static_cast<unsigned>(
87  (std::min(maxDist, *_zBuff) -
88  minDist) *
89  coef))
90  : ecvColor::black);
91  bufferImage.setPixel(x, depthBuffer.height - 1 - y,
92  qRgb(col.r, col.g, col.b));
93  }
94  }
95  }
96 
97  QDialog* dlg = new QDialog(parent);
98  dlg->setWindowTitle(QString("%0 depth buffer [%1 x %2]")
99  .arg(sensor->getParent()->getName())
100  .arg(depthBuffer.width)
101  .arg(depthBuffer.height));
102 
103  unsigned maxDBDim =
104  std::max<unsigned>(depthBuffer.width, depthBuffer.height);
105  unsigned scale = 1;
106  while (maxDBDim > maxDim) {
107  maxDBDim >>= 1;
108  scale <<= 1;
109  }
110  dlg->setFixedSize(bufferImage.size() / scale);
111 
112  QVBoxLayout* vboxLayout = new QVBoxLayout(dlg);
113  vboxLayout->setContentsMargins(0, 0, 0, 0);
114  QLabel* label = new QLabel(dlg);
115  label->setScaledContents(true);
116  vboxLayout->addWidget(label);
117 
118  label->setPixmap(QPixmap::fromImage(bufferImage));
119  dlg->show();
120 }
121 
123 struct ScaleElement {
125  double value;
129  bool condensed;
130 
132  ScaleElement(double val, bool dispText = true, bool isCondensed = false)
133  : value(val), textDisplayed(dispText), condensed(isCondensed) {}
134 };
135 
136 // structure for recursive display of labels
137 struct vlabel {
138  int yPos;
139  int yMin;
140  int yMax;
141  double val;
143  // default constructor
144  vlabel(int y, int y1, int y2, double v)
145  : yPos(y), yMin(y1), yMax(y2), val(v) {
146  assert(y2 >= y1);
147  }
148 };
149 
151 using vlabelSet = std::list<vlabel>;
152 
153 // helper: returns the neighbouring labels at a given position
154 //(first: above label, second: below label)
155 // Warning: set must be already sorted!
156 using vlabelPair = std::pair<vlabelSet::iterator, vlabelSet::iterator>;
157 
159  if (set.empty()) {
160  return vlabelPair(set.end(), set.end());
161  } else {
162  vlabelSet::iterator it1 = set.begin();
163  if (y < it1->yPos) {
164  return vlabelPair(set.end(), it1);
165  }
166  vlabelSet::iterator it2 = it1;
167  ++it2;
168  for (; it2 != set.end(); ++it2, ++it1) {
169  if (y <= it2->yPos) // '<=' to make sure the last label stays at
170  // the top!
171  return vlabelPair(it1, it2);
172  }
173  return vlabelPair(it1, set.end());
174  }
175 }
176 
177 // For log scale inversion
178 const double c_log10 = log(10.0);
179 
180 // Convert standard range to log scale
181 void ConvertToLogScale(ScalarType& dispMin, ScalarType& dispMax) {
182  ScalarType absDispMin = (dispMax < 0 ? std::min(-dispMax, -dispMin)
183  : std::max<ScalarType>(dispMin, 0));
184  ScalarType absDispMax = std::max(std::abs(dispMin), std::abs(dispMax));
185  dispMin = std::log10(
186  std::max(absDispMin, std::numeric_limits<ScalarType>::epsilon()));
187  dispMax = std::log10(
188  std::max(absDispMax, std::numeric_limits<ScalarType>::epsilon()));
189 }
190 
192  const ccScalarField* sf = context.sfColorScaleToDisplay;
193  QWidget* display =
194  static_cast<QWidget*>(ecvDisplayTools::GetCurrentScreen());
195 
196  DrawColorRamp(context, sf, display, context.glW, context.glH,
197  context.renderZoom);
198 }
199 
201  const ccScalarField* sf,
202  QWidget* win,
203  int glW,
204  int glH,
205  float renderZoom /*=1.0f*/) {
206  WIDGETS_PARAMETER params(WIDGETS_TYPE::WIDGET_SCALAR_BAR, "vtkBlockColors");
207  params.context = context;
208  params.context.viewID = "vtkBlockColors";
209 
210  if (!sf || !sf->getColorScale() || !win) {
212  return;
213  }
214 
216 }
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
int count
QSharedPointer< ccColorScale > Shared
Shared pointer type.
Definition: ecvColorScale.h:74
static const unsigned MAX_STEPS
Maximum number of steps (internal representation)
static ccColorScale::Shared GetDefaultScale(DEFAULT_SCALES scale=BGYR)
Returns a pre-defined color scale (static shortcut)
Sensor "depth map".
unsigned height
Buffer height.
std::vector< PointCoordinateType > zBuff
Z-Buffer grid.
unsigned width
Buffer width.
Ground-based Laser sensor.
Definition: ecvGBLSensor.h:26
const ccDepthBuffer & getDepthBuffer() const
Returns the associated depth buffer.
Definition: ecvGBLSensor.h:225
ccHObject * getParent() const
Returns parent object.
Definition: ecvHObject.h:245
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
static void DrawColorRamp(const CC_DRAW_CONTEXT &context)
static void ShowDepthBuffer(ccGBLSensor *lidar, QWidget *parent=nullptr, unsigned maxDim=1024)
Displays a depth buffer as an image.
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
RGB color structure.
Definition: ecvColorTypes.h:49
static void RemoveWidgets(const WIDGETS_PARAMETER &param, bool update=false)
static QWidget * GetCurrentScreen()
static void DrawWidgets(const WIDGETS_PARAMETER &param, bool update=false)
@ WIDGET_SCALAR_BAR
std::pair< vlabelSet::iterator, vlabelSet::iterator > vlabelPair
void ConvertToLogScale(ScalarType &dispMin, ScalarType &dispMax)
std::list< vlabel > vlabelSet
A set of 'vlabel' structures.
static vlabelPair GetVLabelsAround(int y, vlabelSet &set)
const double c_log10
ImGuiContext * context
Definition: Window.cpp:76
normal_z y
normal_z x
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
Definition: CVMath.h:23
constexpr Rgb black(0, 0, 0)
Graphical scale atomical element.
double value
Starting value.
ScaleElement(double val, bool dispText=true, bool isCondensed=false)
Default constructor.
bool condensed
Specifies whether the cube is condensed or not.
bool textDisplayed
Specifies whether the value should be displayed.
CC_DRAW_CONTEXT context
Display context.
vlabel(int y, int y1, int y2, double v)