ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ccCloudLayersHelper.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 "../include/ccCloudLayersHelper.h"
9 
10 #include "../include/ccMouseCircle.h"
11 
12 // CC
13 #include <ecvMainAppInterface.h>
14 #include <ecvPointCloud.h>
15 #include <ecvScalarField.h>
16 
17 // QT
18 #include <QStringList>
19 
20 // System
21 #include <thread>
22 
24  ccPointCloud* cloud)
25  : m_app(app),
26  m_cloud(cloud),
27  m_formerCloudColors(nullptr),
28  m_formerCloudColorsWereShown(false),
29  m_formerCloudSFWasShown(false),
30  m_scalarFieldIndex(0),
31  m_modified(false),
32  m_parameters{} {
33  m_projectedPoints.resize(m_cloud->size());
34  m_pointInFrustum.resize(m_cloud->size());
35 
36  if (m_cloud) {
37  m_formerCloudColorsWereShown = m_cloud->colorsShown();
38  m_formerCloudSFWasShown = m_cloud->sfShown();
39 
40  if (m_cloud->hasColors()) {
41  // store the original colors
42  m_formerCloudColors = m_cloud->rgbColors()->clone();
43  if (!m_formerCloudColors) {
44  CVLog::Error("Not enough memory to backup previous colors");
45  }
46  } else {
47  // check memory for rgb colors
48  if (!m_cloud->resizeTheRGBTable()) {
49  CVLog::Error("Not enough memory to show colors");
50  }
51  }
52 
53  cloud->showColors(true);
54  cloud->showSF(false);
55  }
56 }
57 
59  if (m_cloud) {
60  if (m_formerCloudColors) {
61  if (m_cloud->rgbColors()) {
62  // restore original colors
63  m_formerCloudColors->copy(*m_cloud->rgbColors());
64  }
65 
66  delete m_formerCloudColors;
67  m_formerCloudColors = nullptr;
68  } else {
69  m_cloud->unallocateColors();
70  }
71 
72  m_cloud->showColors(m_formerCloudColorsWereShown);
73  m_cloud->showSF(m_formerCloudSFWasShown);
74  m_cloud->redrawDisplay();
75  }
76  m_cloud = nullptr;
77 }
78 
80  unsigned sfCount = m_cloud->getNumberOfScalarFields();
81  QStringList scalarFields;
82  if (m_cloud->hasScalarFields()) {
83  for (unsigned i = 0; i < sfCount; ++i) {
84  scalarFields.append(QString(m_cloud->getScalarFieldName(i)));
85  }
86  }
87  return scalarFields;
88 }
89 
91  m_scalarFieldIndex = index;
92 }
93 
95  m_formerCloudSFWasShown = true;
96  m_cloud->setCurrentDisplayedScalarField(m_scalarFieldIndex);
97 }
98 
100  unsigned pointCount = m_cloud->size();
101  for (unsigned i = 0; i < pointCount; ++i) {
102  ecvColor::Rgb color = m_cloud->getPointColor(i);
103  m_cloud->setPointColor(i, color);
104  }
105  m_cloud->setVisible(value);
106  m_cloud->redrawDisplay();
107 }
108 
109 void ccCloudLayersHelper::apply(QList<ccAsprsModel::AsprsItem>& items) {
110  if (m_scalarFieldIndex >= m_cloud->getNumberOfScalarFields()) return;
111 
112  m_cloud->setRGBColor(ecvColor::black);
113 
114  for (int i = 0; i < items.size(); ++i) {
115  items[i].count = apply(items[i]);
116  }
117 
118  m_cloud->redrawDisplay();
119 }
120 
122  bool redrawDisplay) {
124  ecvColor.a = item.visible ? ecvColor::MAX : 0;
125  cloudViewer::ScalarField* sf = m_cloud->getScalarField(m_scalarFieldIndex);
126  if (!sf) return 0;
127 
128  ScalarType code = static_cast<ScalarType>(item.code);
129  int affected = 0;
130  int counter = 0;
131  for (auto it = sf->begin(); it != sf->end(); ++it, ++counter) {
132  if ((*it) == code) {
133  m_cloud->setPointColor(counter, ecvColor);
134  ++affected;
135  }
136  }
137 
138  if (redrawDisplay) m_cloud->redrawDisplay();
139 
140  return affected;
141 }
142 
144  ScalarType oldCode) {
145  cloudViewer::ScalarField* sf = m_cloud->getScalarField(m_scalarFieldIndex);
146  if (!sf) return;
147 
148  ScalarType code = static_cast<ScalarType>(item.code);
149  int counter = 0;
150  for (auto it = sf->begin(); it != sf->end(); ++it, ++counter) {
151  if ((*it) == oldCode) {
152  sf->setValue(counter, code);
153  }
154  }
155 }
156 
158  const ccAsprsModel::AsprsItem* to,
159  bool redrawDisplay) {
160  cloudViewer::ScalarField* sf = m_cloud->getScalarField(m_scalarFieldIndex);
161  if (!sf) return 0;
162 
163  ScalarType code = static_cast<ScalarType>(from.code);
164  ScalarType emptyCode = to != nullptr ? static_cast<ScalarType>(to->code)
165  : static_cast<ScalarType>(0);
166  const ecvColor::Rgb color =
167  to != nullptr ? ecvColor::FromQColor(to->color) : ecvColor::black;
168 
169  int affected = 0;
170  int counter = 0;
171  for (auto it = sf->begin(); it != sf->end(); ++it, ++counter) {
172  if ((*it) == code) {
173  sf->setValue(counter, emptyCode);
174  m_cloud->setPointColor(counter, color);
175  ++affected;
176  }
177  }
178 
179  if (redrawDisplay) m_cloud->redrawDisplay();
180 
181  return affected;
182 }
183 
185  cloudViewer::ScalarField* sf = m_cloud->getScalarField(m_scalarFieldIndex);
186  if (!sf) return;
187 
188  unsigned cloudSize = m_cloud->size();
189  m_cloudState.resize(cloudSize);
190  for (unsigned i = 0; i < cloudSize; ++i) {
191  m_cloudState[i].update(sf->getValue(i), m_cloud->getPointColor(i));
192  }
193 }
194 
197  (m_cloud ? m_cloud->getScalarField(m_scalarFieldIndex) : nullptr);
198  if (!sf) {
199  assert(false);
200  return;
201  }
202 
203  unsigned cloudSize = m_cloud->size();
204  if (m_cloudState.size() != cloudSize) {
205  assert(false);
206  return;
207  }
208 
209  for (unsigned i = 0; i < cloudSize; ++i) {
210  const CloudState& state = m_cloudState[i];
211  sf->setValue(i, state.code);
212  m_cloud->setPointColor(i, state.color);
213  }
214 }
215 
216 void ccCloudLayersHelper::project(ccGLCameraParameters camera,
217  unsigned start,
218  unsigned end) {
219  const double half_w = camera.viewport[2] / 2.0;
220  const double half_h = camera.viewport[3] / 2.0;
221 
222  CCVector3d Q2D;
223  bool pointInFrustum = false;
224  for (unsigned i = start; i < end; ++i) {
225  const CCVector3* P3D = m_cloud->getPoint(i);
226  camera.project(*P3D, Q2D, &pointInFrustum);
227  m_projectedPoints[i] =
228  CCVector2(static_cast<PointCoordinateType>(Q2D.x - half_w),
229  static_cast<PointCoordinateType>(Q2D.y - half_h));
230  m_pointInFrustum[i] = pointInFrustum;
231  }
232 }
233 
234 PointCoordinateType ccCloudLayersHelper::ComputeSquaredEuclideanDistance(
235  const CCVector2& a, const CCVector2& b) {
236  return (b - a).norm2();
237 }
238 
240  float squareDist,
241  std::map<ScalarType, int>& affected) {
242  if (m_parameters.output == nullptr ||
243  ((!m_parameters.anyPoints && !m_parameters.visiblePoints) &&
244  m_parameters.input == nullptr)) {
245  return;
246  }
247 
248  cloudViewer::ScalarField* sf = m_cloud->getScalarField(m_scalarFieldIndex);
249  if (!sf) return;
250 
251  ScalarType inputCode =
252  m_parameters.input != nullptr
253  ? static_cast<ScalarType>(m_parameters.input->code)
254  : 0;
255  ScalarType outputCode = static_cast<ScalarType>(m_parameters.output->code);
256 
257  unsigned char alpha = m_parameters.output->visible ? ecvColor::MAX : 0;
258  ecvColor::Rgba outputColor = ecvColor::Rgba(
259  ecvColor::FromQColor(m_parameters.output->color), alpha);
260 
261  unsigned cloudSize = m_cloud->size();
262  for (unsigned i = 0; i < cloudSize; ++i) {
263  // skip camera outside point
264  if (!m_pointInFrustum[i]) continue;
265 
266  const auto& color = m_cloud->getPointColor(i);
267 
268  // skip invisible points
269  if (m_parameters.visiblePoints && !m_cloud->isVisible()) continue;
270 
271  ScalarType code = sf->getValue(i);
272 
273  // skip other codes
274  if (m_parameters.input && code != inputCode) continue;
275 
276  // skip circle outside point
277  if (ComputeSquaredEuclideanDistance(center, m_projectedPoints[i]) >
278  squareDist)
279  continue;
280 
281  if (code != outputCode) {
282  sf->setValue(i, outputCode);
283  m_cloud->setPointColor(i, outputColor);
284 
285  --affected[code];
286  ++affected[outputCode];
287  }
288 
289  m_modified = true;
290  }
291 
292  m_cloud->redrawDisplay();
293 }
294 
296  // check camera parameters changes
297  bool hasChanges = false;
298  auto a = m_cameraParameters.modelViewMat.data();
299  auto b = camera.modelViewMat.data();
300  for (int i = 0; i < OPENGL_MATRIX_SIZE; ++i) {
301  if (std::abs(a[i] - b[i]) > 1e-6) {
302  hasChanges = true;
303  break;
304  }
305  }
306 
307  if (!hasChanges) return;
308 
309  m_cameraParameters = camera;
310  unsigned cloudSize = m_cloud->size();
311 
312  unsigned processorCount = std::thread::hardware_concurrency();
313  if (processorCount == 0) processorCount = 1;
314 
315  const size_t part_size = cloudSize / processorCount;
316  std::vector<std::thread*> threads;
317  threads.resize(processorCount, nullptr);
318  for (unsigned i = 0; i < processorCount; ++i) {
319  size_t start = i * part_size;
320  size_t end = start + part_size;
321 
322  if (i == processorCount - 1) end = cloudSize;
323 
324  threads[i] = new std::thread(&ccCloudLayersHelper::project, this,
325  camera, start, end);
326  }
327 
328  for (auto it = threads.begin(); it != threads.end(); ++it) (*it)->join();
329 
330  for (auto it = threads.begin(); it != threads.end(); ++it) delete (*it);
331 }
332 
334  return m_parameters;
335 }
Vector2Tpl< PointCoordinateType > CCVector2
Default 2D Vector.
Definition: CVGeom.h:780
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
math::float4 color
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
ColorsTableType * clone() override
Duplicates array (overloaded from ccArray::clone)
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
bool copy(Base &dest) const
Copies the content of this array in another one.
Definition: ecvArray.h:43
void projectCloud(const ccGLCameraParameters &camera)
void apply(QList< ccAsprsModel::AsprsItem > &items)
int moveItem(const ccAsprsModel::AsprsItem &from, const ccAsprsModel::AsprsItem *to, bool redrawDisplay=false)
void mouseMove(const CCVector2 &center, float squareDist, std::map< ScalarType, int > &affected)
void changeCode(const ccAsprsModel::AsprsItem &item, ScalarType oldCode)
void setScalarFieldIndex(int index)
ccCloudLayersHelper(ecvMainAppInterface *app, ccPointCloud *cloud)
void setVisible(bool value)
ccPointCloud * cloud()
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual bool isVisible() const
Returns whether entity is visible or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
T * data()
Returns a pointer to internal data.
virtual void redrawDisplay(bool forceRedraw=true, bool only2D=false)
Redraws associated display.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
ColorsTableType * rgbColors() const
Returns pointer on RGB colors table.
void unallocateColors()
Erases the cloud colors.
bool resizeTheRGBTable(bool fillWithWhite=false)
Resizes the RGB colors array.
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.
const ecvColor::Rgb & getPointColor(unsigned pointIndex) const override
Returns color corresponding to a given point.
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
bool hasScalarFields() const override
Returns whether one or more scalar fields are instantiated.
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.
const CCVector3 * getPoint(unsigned index) const override
A simple scalar field (to be associated to a point cloud)
Definition: ScalarField.h:25
ScalarType & getValue(std::size_t index)
Definition: ScalarField.h:92
void setValue(std::size_t index, ScalarType value)
Definition: ScalarField.h:96
RGB color structure.
Definition: ecvColorTypes.h:49
RGBA color structure.
Main application interface (for plugins)
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
static const unsigned OPENGL_MATRIX_SIZE
Model view matrix size (OpenGL)
Colors namespace.
Definition: ecvColorTypes.h:32
constexpr Rgb black(0, 0, 0)
constexpr ColorCompType MAX
Max value of a single color component (default type)
Definition: ecvColorTypes.h:34
Rgb FromQColor(QColor qColor)
Conversion from QColor.
Rgba FromQColora(QColor qColor)
Conversion from QColor'a'.
RgbaTpl< ColorCompType > Rgba
4 components, default type
ccAsprsModel::AsprsItem * output
ccAsprsModel::AsprsItem * input
OpenGL camera parameters.
ccGLMatrixd modelViewMat
Model view matrix (GL_MODELVIEW)
bool project(const CCVector3d &input3D, CCVector3d &output2D, bool *inFrustum=nullptr) const
Projects a 3D point in 2D (+ normalized 'z' coordinate)
int viewport[4]
Viewport (GL_VIEWPORT)