ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvOctree.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 "ecvOctree.h"
9 
10 #include "ecvBox.h"
11 #include "ecvCameraSensor.h"
12 #include "ecvDisplayTools.h"
13 #include "ecvNormalVectors.h"
14 #include "ecvPointCloud.h"
15 #include "ecvProgressDialog.h"
16 #include "ecvScalarField.h"
17 
18 // CV_CORE_LIB
19 #include <Neighbourhood.h>
20 #include <RayAndBox.h>
21 #include <ScalarFieldTools.h>
22 
24  : cloudViewer::DgmOctree(aCloud),
25  m_theAssociatedCloudAsGPC(aCloud),
26  m_displayedLevel(1),
27  m_displayMode(WIRE),
28  m_visible(true),
29  m_frustumIntersector(nullptr) {}
30 
33  delete m_frustumIntersector;
34  m_frustumIntersector = nullptr;
35  }
36 }
37 
39  std::vector<unsigned>& inCameraFrustum) {
40  if (!sensor) return false;
41 
42  // initialization
43  float globalPlaneCoefficients[6][4];
44  CCVector3 globalCorners[8];
45  CCVector3 globalEdges[6];
46  CCVector3 globalCenter;
48  globalPlaneCoefficients, globalCorners, globalEdges, globalCenter);
49 
50  if (!m_frustumIntersector) {
52  if (!m_frustumIntersector->build(this)) {
54  "[ccOctree::intersectWithFrustum] Not enough memory!");
55  return false;
56  }
57  }
58 
59  // get points of cells in frustum
60  std::vector<std::pair<unsigned, CCVector3>> pointsToTest;
62  pointsToTest, inCameraFrustum, globalPlaneCoefficients,
63  globalCorners, globalEdges, globalCenter);
64 
65  // project points
66  for (size_t i = 0; i < pointsToTest.size(); i++) {
67  if (sensor->isGlobalCoordInFrustum(pointsToTest[i].second /*, false*/))
68  inCameraFrustum.push_back(pointsToTest[i].first);
69  }
70 
71  return true;
72 }
73 
74 void ccOctree::setDisplayedLevel(int level) {
75  if (level != m_displayedLevel) {
76  m_displayedLevel = level;
77  // m_glListIsDeprecated = true;
78  }
79 }
80 
82  if (m_displayMode != mode) {
83  m_displayMode = mode;
84  // m_glListIsDeprecated = true;
85  }
86 }
87 
89  // warn the others that the octree organization is going to change
90  emit updated();
91 
92  DgmOctree::clear();
93 }
94 
96 
99 }
100 
102  m_dimMin *= multFactor;
103  m_dimMax *= multFactor;
104  m_pointsMin *= multFactor;
105  m_pointsMax *= multFactor;
106 
107  for (int i = 0; i <= MAX_OCTREE_LEVEL; ++i) m_cellSize[i] *= multFactor;
108 }
109 
111  m_dimMin += T;
112  m_dimMax += T;
113  m_pointsMin += T;
114  m_pointsMax += T;
115 }
116 
117 /*** RENDERING METHODS ***/
118 
121  return;
122  }
123 
124  if (!ecvDisplayTools::GetCurrentScreen()) return;
125 
126  if (m_displayMode == WIRE) {
127  // this display mode is too heavy to be stored as a GL list
128  //(therefore we always render it dynamically)
129 
130  void* additionalParameters[] = {
131  reinterpret_cast<void*>(m_frustumIntersector),
132  reinterpret_cast<void*>(&m_visible)};
134  additionalParameters);
135  } else {
136  glDrawParams glParams;
138  }
139 }
140 
143  void** additionalParameters,
146  static_cast<ccOctreeFrustumIntersector*>(additionalParameters[0]);
147  bool visible = *(static_cast<bool*>(additionalParameters[1]));
148  CCVector3 bbMin, bbMax;
149  cell.parentOctree->computeCellLimits(cell.truncatedCode, cell.level, bbMin,
150  bbMax, true);
151 
154  if (ofi) vis = ofi->positionFromFrustum(cell.truncatedCode, cell.level);
155 
157  context.viewID = QString("Octree-") + QString::number(cell.truncatedCode);
158 
159  if (visible) {
160  // outside
162  context.bbDefaultCol = ecvColor::green;
163  } else {
164  context.defaultLineWidth = 2;
165  // inside
167  context.bbDefaultCol = ecvColor::magenta;
168  // intersecting
169  else
170  context.bbDefaultCol = ecvColor::blue;
171  }
172 
174  ccBBox cellBox(bbMin, bbMax);
176  } else {
177  context.removeEntityType = ENTITY_TYPE::ECV_SHAPE;
178  context.removeViewID = context.viewID;
180  }
181 
182  return true;
183 }
184 
187  void** additionalParameters,
189  // variables additionnelles
190  glDrawParams* glParams =
191  reinterpret_cast<glDrawParams*>(additionalParameters[0]);
192  ccGenericPointCloud* cloud =
193  reinterpret_cast<ccGenericPointCloud*>(additionalParameters[1]);
194  // QOpenGLFunctions_2_1* glFunc =
195  // static_cast<QOpenGLFunctions_2_1*>(additionalParameters[2]);
196  // assert(glFunc != nullptr);
197 
198  if (glParams->showSF) {
200  cell.points);
201  const ecvColor::Rgb* col = cloud->getScalarValueColor(dist);
202  // glFunc->glColor3ubv(col ? col->rgb : ecvColor::lightGrey.rgb);
203  } else if (glParams->showColors) {
204  ColorCompType col[3];
205  ComputeAverageColor(cell.points, cloud, col);
206  // glFunc->glColor3ubv(col);
207  }
208 
209  if (glParams->showNorms) {
210  CCVector3 N = ComputeAverageNorm(cell.points, cloud);
211  // ccGL::Normal3v(glFunc, N.u);
212  }
213 
214  const CCVector3* gravityCenter =
216  // ccGL::Vertex3v(glFunc, gravityCenter->u);
217 
218  return true;
219 }
220 
223  void** additionalParameters,
225  // variables additionnelles
226  glDrawParams* glParams =
227  reinterpret_cast<glDrawParams*>(additionalParameters[0]);
228  ccGenericPointCloud* cloud =
229  reinterpret_cast<ccGenericPointCloud*>(additionalParameters[1]);
230  ccGenericPrimitive* primitive =
231  reinterpret_cast<ccGenericPrimitive*>(additionalParameters[2]);
233  reinterpret_cast<CC_DRAW_CONTEXT*>(additionalParameters[3]);
234 
235  // get the set of OpenGL functions (version 2.1)
236  // QOpenGLFunctions_2_1* glFunc =
237  // context->glFunctions<QOpenGLFunctions_2_1>(); assert(glFunc != nullptr);
238 
239  // if (glFunc == nullptr)
240  // return false;
241 
242  CCVector3 cellCenter;
244  cellCenter, true);
245 
246  if (glParams->showSF) {
248  cell.points);
249  const ecvColor::Rgb* rgb = cloud->getScalarValueColor(dist);
250  if (rgb) primitive->setColor(*rgb);
251  } else if (glParams->showColors) {
252  ecvColor::Rgb col;
253  ComputeAverageColor(cell.points, cloud, col.rgb);
254  primitive->setColor(col);
255  }
256 
257  if (glParams->showNorms) {
258  CCVector3 N = ComputeAverageNorm(cell.points, cloud);
259  if (primitive->getTriNormsTable()) {
260  // only one normal!
261  primitive->getTriNormsTable()->setValue(
263  }
264  }
265 
266  // glFunc->glPushMatrix();
267  // ccGL::Translate(glFunc, cellCenter.x, cellCenter.y, cellCenter.z);
268  primitive->draw(*context);
269  // glFunc->glPopMatrix();
270 
271  return true;
272 }
273 
276  ColorCompType meanCol[]) {
277  if (!subset || subset->size() == 0 || !sourceCloud) return;
278 
279  assert(sourceCloud->hasColors());
280  assert(subset->getAssociatedCloud() ==
282 
283  Tuple3Tpl<double> sum(0, 0, 0);
284 
285  unsigned n = subset->size();
286  for (unsigned i = 0; i < n; ++i) {
287  const ecvColor::Rgb& _theColor =
289  sum.x += _theColor.r;
290  sum.y += _theColor.g;
291  sum.z += _theColor.b;
292  }
293 
294  meanCol[0] = static_cast<ColorCompType>(sum.x / n);
295  meanCol[1] = static_cast<ColorCompType>(sum.y / n);
296  meanCol[2] = static_cast<ColorCompType>(sum.z / n);
297 }
298 
301  CCVector3 N(0, 0, 0);
302 
303  if (!subset || subset->size() == 0 || !sourceCloud) return N;
304 
305  assert(sourceCloud->hasNormals());
306  assert(subset->getAssociatedCloud() ==
308 
309  unsigned n = subset->size();
310  for (unsigned i = 0; i < n; ++i) {
311  const CCVector3& Ni =
313  N += Ni;
314  }
315 
316  N.normalize();
317  return N;
318 }
319 
320 bool ccOctree::pointPicking(const CCVector2d& clickPos,
321  const ccGLCameraParameters& camera,
322  PointDescriptor& output,
323  double pickWidth_pix /*=3.0*/) const {
324  output.point = 0;
325  output.squareDistd = -1.0;
326 
328  assert(false);
329  return false;
330  }
331 
332  if (m_thePointsAndTheirCellCodes.empty()) {
333  // nothing to do
334  return false;
335  }
336 
337  CCVector3d clickPosd(clickPos.x, clickPos.y, 0.0);
338  CCVector3d X(0, 0, 0);
339  if (!camera.unproject(clickPosd, X)) {
340  return false;
341  }
342 
343  ccGLMatrix trans;
344  bool hasGLTrans =
346 
347  // compute 3D picking 'ray'
348  CCVector3 rayAxis, rayOrigin;
349  {
350  CCVector3d clickPosd2(clickPos.x, clickPos.y, 1.0);
351  CCVector3d Y(0, 0, 0);
352  if (!camera.unproject(clickPosd2, Y)) {
353  return false;
354  }
355 
356  rayAxis = CCVector3::fromArray((Y - X).u);
357  rayOrigin = CCVector3::fromArray(X.u);
358 
359  if (hasGLTrans) {
360  ccGLMatrix iTrans = trans.inverse();
361  iTrans.applyRotation(rayAxis);
362  iTrans.apply(rayOrigin);
363  }
364 
365  rayAxis.normalize(); // normalize afterwards as the local
366  // transformation may have a scale != 1
367  }
368 
369  CCVector3 margin(0, 0, 0);
370  double maxFOV_rad = 0;
371  if (camera.perspective) {
372  maxFOV_rad = 0.002 * pickWidth_pix; // empirical conversion from pixels
373  // to FOV angle (in radians)
374  } else {
375  double maxRadius = pickWidth_pix * camera.pixelSize / 2;
376  margin = CCVector3(1, 1, 1) *
377  static_cast<PointCoordinateType>(maxRadius);
378  }
379 
380  // first test with the total bounding box
381  Ray<PointCoordinateType> ray(rayAxis, rayOrigin);
382  if (!AABB<PointCoordinateType>(m_dimMin - margin, m_dimMax + margin)
383  .intersects(ray)) {
384  // no intersection
385  return true; // DGM: false would mean that an error occurred!
386  // (output.point == 0 means that nothing has been found)
387  }
388 
389  // no need to go too deep
390  const unsigned char maxLevel = findBestLevelForAGivenPopulationPerCell(10);
391 
392  // starting level of subdivision
393  unsigned char level = 1;
394  // binary shift for cell code truncation at current level
395  unsigned char currentBitDec = GET_BIT_SHIFT(level);
396  // current cell code
397  CellCode currentCellCode = INVALID_CELL_CODE;
398  CellCode currentCellTruncatedCode = INVALID_CELL_CODE;
399  // whether the current cell should be skipped or not
400  bool skipThisCell = false;
401 
402 #ifdef DEBUG_PICKING_MECHANISM
404 #endif
405 
406  // ray with origin expressed in the local coordinate system!
407  Ray<PointCoordinateType> rayLocal(rayAxis, rayOrigin - m_dimMin);
408 
409  // visibility table (if any)
413  : 0;
414 
415  // scalar field with hidden values (if any)
416  ccScalarField* activeSF = 0;
419  !visTable // if the visibility table is instantiated, we always display
420  // ALL points
421  ) {
422  ccPointCloud* pc =
425  if (sf && sf->mayHaveHiddenValues() && sf->getColorScale()) {
426  // we must take this SF display parameters into account as some
427  // points may be hidden!
428  activeSF = sf;
429  }
430  }
431 
432  // let's sweep through the octree
433  for (cellsContainer::const_iterator it =
435  it != m_thePointsAndTheirCellCodes.end(); ++it) {
436  CellCode truncatedCode = (it->theCode >> currentBitDec);
437 
438  // new cell?
439  if (truncatedCode != currentCellTruncatedCode) {
440  // look for the biggest 'parent' cell that englobes this cell and
441  // the previous one (if any)
442  while (level > 1) {
443  unsigned char bitDec = GET_BIT_SHIFT(level - 1);
444  if ((it->theCode >> bitDec) == (currentCellCode >> bitDec)) {
445  // same parent cell, we can stop here
446  break;
447  }
448  --level;
449  }
450 
451  currentCellCode = it->theCode;
452 
453  // now try to go deeper with the new cell
454  while (level < maxLevel) {
455  Tuple3i cellPos;
456  getCellPos(it->theCode, level, cellPos, false);
457 
458  // first test with the total bounding box
459  PointCoordinateType halfCellSize = getCellSize(level) / 2;
460  CCVector3 cellCenter((2 * cellPos.x + 1) * halfCellSize,
461  (2 * cellPos.y + 1) * halfCellSize,
462  (2 * cellPos.z + 1) * halfCellSize);
463 
464  CCVector3 halfCell =
465  CCVector3(halfCellSize, halfCellSize, halfCellSize);
466 
467  if (camera.perspective) {
468  double radialSqDist, sqDistToOrigin;
469  rayLocal.squareDistances(cellCenter, radialSqDist,
470  sqDistToOrigin);
471 
472  double dx = sqrt(sqDistToOrigin);
473  double dy = std::max<double>(
474  0, sqrt(radialSqDist) - SQRT_3 * halfCellSize);
475  double fov_rad = atan2(dy, dx);
476 
477  skipThisCell = (fov_rad > maxFOV_rad);
478  } else {
479  skipThisCell = !AABB<PointCoordinateType>(
480  cellCenter - halfCell - margin,
481  cellCenter + halfCell + margin)
482  .intersects(rayLocal);
483  }
484 
485  if (skipThisCell)
486  break;
487  else
488  ++level;
489  }
490 
491  currentBitDec = GET_BIT_SHIFT(level);
492  currentCellTruncatedCode = (currentCellCode >> currentBitDec);
493  }
494 
495 #ifdef DEBUG_PICKING_MECHANISM
496  m_theAssociatedCloud->setPointScalarValue(it->theIndex, level);
497 #endif
498 
499  if (!skipThisCell) {
500  // we shouldn't test points that are actually hidden!
501  if ((!visTable || visTable->at(it->theIndex) == POINT_VISIBLE) &&
502  (!activeSF ||
503  activeSF->getColor(activeSF->getValue(it->theIndex)))) {
504  // test the point
505  const CCVector3* P =
506  m_theAssociatedCloud->getPoint(it->theIndex);
507  CCVector3 Q = *P;
508  if (hasGLTrans) {
509  trans.apply(Q);
510  }
511 
512  CCVector3d Q2D;
513  camera.project(Q, Q2D);
514 
515  if (fabs(Q2D.x - clickPos.x) <= pickWidth_pix &&
516  fabs(Q2D.y - clickPos.y) <= pickWidth_pix) {
517  double squareDist =
518  CCVector3d(X.x - Q.x, X.y - Q.y, X.z - Q.z)
519  .norm2d();
520  if (!output.point || squareDist < output.squareDistd) {
521  output.point = P;
522  output.pointIndex = it->theIndex;
523  output.squareDistd = squareDist;
524  }
525  }
526  }
527  }
528  }
529 
530  return true;
531 }
532 
534  if (!cloud) {
535  assert(false);
536  return 0;
537  }
538 
539  PointCoordinateType largestDim = cloud->getOwnBB().getMaxBoxDim();
540 
541  return largestDim /
542  std::min<unsigned>(100, std::max<unsigned>(1, cloud->size() / 100));
543 }
544 
546  ccGenericPointCloud* cloud,
547  const BestRadiusParams& params,
548  QWidget* parentWidget /*=nullptr*/) {
549  if (!cloud) {
550  assert(false);
551  return 0;
552  }
553 
554  if (!cloud->getOctree()) {
555  ecvProgressDialog pDlg(true, parentWidget);
556  if (!cloud->computeOctree(&pDlg)) {
557  CVLog::Error(tr("Could not compute octree for cloud '%1'")
558  .arg(cloud->getName()));
559  return 0;
560  }
561  }
562 
563  return ccOctree::GuessBestRadius(cloud, params, cloud->getOctree().data());
564 }
565 
567  ccGenericPointCloud* cloud,
568  const BestRadiusParams& params,
569  cloudViewer::DgmOctree* inputOctree /*=nullptr*/,
570  cloudViewer::GenericProgressCallback* progressCb /*=nullptr*/) {
571  if (!cloud) {
572  assert(false);
573  return 0;
574  }
575 
576  cloudViewer::DgmOctree* octree = inputOctree;
577  if (!octree) {
578  octree = new cloudViewer::DgmOctree(cloud);
579  if (octree->build(progressCb) <= 0) {
580  delete octree;
582  "[GuessBestRadius] Failed to compute the cloud octree");
583  return 0;
584  }
585  }
586 
587  PointCoordinateType bestRadius = GuessNaiveRadius(cloud);
588  if (bestRadius == 0) {
589  CVLog::Warning("[GuessBestRadius] The cloud has invalid dimensions");
590  return 0;
591  }
592 
593  if (cloud->size() < 100) {
594  // no need to do anything else for very small clouds!
595  return bestRadius;
596  }
597 
598  // we are now going to sample the cloud so as to compute statistics on the
599  // density
600  {
601  const unsigned sampleCount =
602  std::min<unsigned>(200, cloud->size() / 10);
603 
604  double aimedPop = params.aimedPopulationPerCell;
605  PointCoordinateType radius = bestRadius;
606  PointCoordinateType lastRadius = radius;
607  double lastMeanPop = 0;
608 
609  std::random_device rd; // non-deterministic generator
610  std::mt19937 gen(rd()); // to seed mersenne twister.
611  std::uniform_int_distribution<unsigned> dist(0, cloud->size() - 1);
612 
613  // we may have to do this several times
614  for (size_t attempt = 0; attempt < 10; ++attempt) {
615  int totalCount = 0;
616  int totalSquareCount = 0;
617  int minPop = 0;
618  int maxPop = 0;
619  int aboveMinPopCount = 0;
620 
621  unsigned char octreeLevel =
623  radius);
624 
625  for (size_t i = 0; i < sampleCount; ++i) {
626  unsigned randomIndex = dist(gen);
627  assert(randomIndex < cloud->size());
628 
629  const CCVector3* P = cloud->getPoint(randomIndex);
632  *P, radius, Yk, octreeLevel);
633  assert(n >= 1);
634 
635  totalCount += n;
636  totalSquareCount += n * n;
637  if (i == 0) {
638  minPop = maxPop = n;
639  } else {
640  if (n < minPop)
641  minPop = n;
642  else if (n > maxPop)
643  maxPop = n;
644  }
645 
646  if (n >= params.minCellPopulation) {
647  ++aboveMinPopCount;
648  }
649  }
650 
651  double meanPop = static_cast<double>(totalCount) / sampleCount;
652  double stdDevPop = sqrt(std::abs(
653  static_cast<double>(totalSquareCount) / sampleCount -
654  meanPop * meanPop));
655  double aboveMinPopRatio =
656  static_cast<double>(aboveMinPopCount) / sampleCount;
657 
658  CVLog::Print(QString("[GuessBestRadius] Radius = %1 -> samples "
659  "population in [%2 ; %3] (mean %4 / std. dev. "
660  "%5 / %6% above minimum)")
661  .arg(radius)
662  .arg(minPop)
663  .arg(maxPop)
664  .arg(meanPop)
665  .arg(stdDevPop)
666  .arg(aboveMinPopRatio * 100));
667 
668  if (std::abs(meanPop - aimedPop) < params.aimedPopulationRange) {
669  // we have found a correct radius
670  bestRadius = radius;
671 
672  if (aboveMinPopRatio < params.minAboveMinRatio) {
673  // CVLog::Warning("[GuessBestRadius] The cloud density is
674  // very inhomogeneous! You may have to increase the radius
675  // to get valid normals everywhere... but the result will be
676  // smoother");
677  aimedPop = params.aimedPopulationPerCell +
678  (2.0 * stdDevPop) /* * (1.0-aboveMinPopRatio)*/;
679  assert(aimedPop >= params.aimedPopulationPerCell);
680  } else {
681  break;
682  }
683  }
684 
685  // otherwise we have to find a better estimate for the radius
686  PointCoordinateType newRadius = radius;
687  //(warning: we consider below that the number of points is
688  // proportional to the SURFACE of the neighborhood)
689  assert(meanPop >= 1.0);
690  if (attempt == 0) {
691  // this is our best (only) guess for the moment
692  bestRadius = radius;
693 
694  newRadius = radius * sqrt(aimedPop / meanPop);
695  } else {
696  // keep track of our best guess nevertheless
697  if (std::abs(meanPop - aimedPop) <
698  std::abs(bestRadius - aimedPop)) {
699  bestRadius = radius;
700  }
701 
702  double slope = (radius * radius - lastRadius * lastRadius) /
703  (meanPop - lastMeanPop);
704  PointCoordinateType newSquareRadius =
705  lastRadius * lastRadius +
706  (aimedPop - lastMeanPop) * slope;
707  if (newSquareRadius > 0) {
708  newRadius = sqrt(newSquareRadius);
709  } else {
710  // can't do any better!
711  break;
712  }
713  }
714 
715  lastRadius = radius;
716  lastMeanPop = meanPop;
717 
718  radius = newRadius;
719  }
720  }
721 
722  if (octree && !inputOctree) {
723  delete octree;
724  octree = nullptr;
725  }
726 
727  return bestRadius;
728 }
constexpr unsigned char POINT_VISIBLE
Definition: CVConst.h:92
constexpr double SQRT_3
Square root of 3.
Definition: CVConst.h:29
Vector3Tpl< double > CCVector3d
Double 3D Vector.
Definition: CVGeom.h:804
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
Definition: CVGeom.h:798
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
int size
void * X
Definition: SmallVector.cpp:45
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Print(const char *format,...)
Prints out a formatted message in console.
Definition: CVLog.cpp:113
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
3-Tuple structure (templated version)
Definition: CVGeom.h:132
Type y
Definition: CVGeom.h:137
Type u[3]
Definition: CVGeom.h:139
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:36
Type y
Definition: CVGeom.h:36
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
double norm2d() const
Returns vector square norm (forces double precision output)
Definition: CVGeom.h:419
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
Definition: CVGeom.h:268
void setValue(size_t index, const Type &value)
Definition: ecvArray.h:102
Bounding box structure.
Definition: ecvBBox.h:25
Camera (projective) sensor.
bool computeGlobalPlaneCoefficients(float planeCoefficients[6][4], CCVector3 ptsFrustum[8], CCVector3 edges[6], CCVector3 &center)
bool isGlobalCoordInFrustum(const CCVector3 &globalCoord) const
Tests if a 3D point is in the field of view of the camera.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual void getDrawingParameters(glDrawParams &params) const
Returns main OpenGL parameters for this entity.
void applyRotation(Vector3Tpl< float > &vec) const
Applies rotation only to a 3D vector (in place) - float version.
ccGLMatrixTpl< T > inverse() const
Returns inverse transformation.
void apply(float vec[3]) const
Applies transformation to a 3D vector (in place) - float version.
Float version of ccGLMatrixTpl.
Definition: ecvGLMatrix.h:19
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual const CCVector3 & getPointNormal(unsigned pointIndex) const =0
Returns normal corresponding to a given point.
virtual const ecvColor::Rgb * getScalarValueColor(ScalarType d) const =0
Returns color corresponding to a given scalar value.
virtual ccOctree::Shared computeOctree(cloudViewer::GenericProgressCallback *progressCb=nullptr, bool autoAddChild=true)
Computes the cloud octree.
virtual bool isVisibilityTableInstantiated() const
Returns whether the visibility array is allocated or not.
virtual const ecvColor::Rgb & getPointColor(unsigned pointIndex) const =0
Returns color corresponding to a given point.
virtual ccOctree::Shared getOctree() const
Returns the associated octree (if any)
virtual VisibilityTableType & getTheVisibilityArray()
Returns associated visibility array.
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
std::vector< unsigned char > VisibilityTableType
Array of "visibility" information for each point.
Generic primitive interface.
virtual void setColor(const ecvColor::Rgb &col)
Sets primitive color (shortcut)
void draw(CC_DRAW_CONTEXT &context) override
Draws entity and its children.
bool getAbsoluteGLTransformation(ccGLMatrix &trans) const
Definition: ecvHObject.cpp:740
NormsIndexesTableType * getTriNormsTable() const override
Returns per-triangle normals shared array.
Definition: ecvMesh.h:344
static CompressedNormType GetNormIndex(const PointCoordinateType N[])
Returns the compressed index corresponding to a normal vector.
virtual QString getName() const
Returns object name.
Definition: ecvObject.h:72
bool isA(CV_CLASS_ENUM type) const
Definition: ecvObject.h:131
void computeFrustumIntersectionWithOctree(std::vector< std::pair< unsigned, CCVector3 >> &pointsToTest, std::vector< unsigned > &inCameraFrustum, const float planesCoefficients[6][4], const CCVector3 ptsFrustum[8], const CCVector3 edges[6], const CCVector3 &center)
OctreeCellVisibility
Definition of the state of a cell compared to a frustum.
bool build(cloudViewer::DgmOctree *octree)
Prepares structure for frustum filtering.
OctreeCellVisibility positionFromFrustum(cloudViewer::DgmOctree::CellCode truncatedCode, unsigned char level) const
Returns the cell visibility.
int m_displayedLevel
Displayed level.
Definition: ecvOctree.h:183
static CCVector3 ComputeAverageNorm(cloudViewer::ReferenceCloud *subset, ccGenericPointCloud *sourceCloud)
Computes the average normal of a set of points.
Definition: ecvOctree.cpp:299
void setDisplayedLevel(int level)
Sets the currently displayed octree level.
Definition: ecvOctree.cpp:74
virtual ~ccOctree()
Destructor.
Definition: ecvOctree.cpp:31
static bool DrawCellAsAPrimitive(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=0)
Definition: ecvOctree.cpp:221
static void ComputeAverageColor(cloudViewer::ReferenceCloud *subset, ccGenericPointCloud *sourceCloud, ColorCompType meanCol[])
Computes the average color of a set of points.
Definition: ecvOctree.cpp:274
static bool DrawCellAsAPoint(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=0)
Definition: ecvOctree.cpp:185
ccBBox getSquareBB() const
Returns the octree (square) bounding-box.
Definition: ecvOctree.cpp:95
ccOctree(ccGenericPointCloud *cloud)
Default constructor.
Definition: ecvOctree.cpp:23
static PointCoordinateType GuessBestRadiusAutoComputeOctree(ccGenericPointCloud *cloud, const BestRadiusParams &params, QWidget *parentWidget=nullptr)
Definition: ecvOctree.cpp:545
void setDisplayMode(DisplayMode mode)
Sets the currently display mode.
Definition: ecvOctree.cpp:81
bool intersectWithFrustum(ccCameraSensor *sensor, std::vector< unsigned > &inCameraFrustum)
Intersects octree with a camera sensor.
Definition: ecvOctree.cpp:38
static bool DrawCellAsABox(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=0)
Definition: ecvOctree.cpp:141
void multiplyBoundingBox(const PointCoordinateType multFactor)
Multiplies the bounding-box of the octree.
Definition: ecvOctree.cpp:101
ccGenericPointCloud * m_theAssociatedCloudAsGPC
Associated cloud (as a ccGenericPointCloud)
Definition: ecvOctree.h:180
void updated()
Signal sent when the octree organization is modified (cleared, etc.)
DisplayMode
Octree displaying methods.
Definition: ecvOctree.h:77
ccBBox getPointsBB() const
Returns the points bounding-box.
Definition: ecvOctree.cpp:97
bool pointPicking(const CCVector2d &clickPos, const ccGLCameraParameters &camera, PointDescriptor &output, double pickWidth_pix=3.0) const
Octree-driven point picking algorithm.
Definition: ecvOctree.cpp:320
ccOctreeFrustumIntersector * m_frustumIntersector
For frustum intersection.
Definition: ecvOctree.h:189
virtual void clear() override
Clears the octree.
Definition: ecvOctree.cpp:88
DisplayMode m_displayMode
Display mode.
Definition: ecvOctree.h:186
static PointCoordinateType GuessBestRadius(ccGenericPointCloud *cloud, const BestRadiusParams &params, cloudViewer::DgmOctree *cloudOctree=nullptr, cloudViewer::GenericProgressCallback *progressCb=nullptr)
Tries to guess the best 'local radius' for octree-based computation.
Definition: ecvOctree.cpp:566
void draw(CC_DRAW_CONTEXT &context)
Draws the octree.
Definition: ecvOctree.cpp:119
static PointCoordinateType GuessNaiveRadius(ccGenericPointCloud *cloud)
Tries to guess a very naive 'local radius' for octree-based computation.
Definition: ecvOctree.cpp:533
bool m_visible
For Octree Display.
Definition: ecvOctree.h:192
void translateBoundingBox(const CCVector3 &T)
Translates the bounding-box of the octree.
Definition: ecvOctree.cpp:110
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
const ecvColor::Rgb * getColor(ScalarType value) const
bool mayHaveHiddenValues() const
T getMaxBoxDim() const
Returns maximal box dimension.
Definition: BoundingBox.h:185
The octree structure used throughout the library.
Definition: DgmOctree.h:39
static const CellCode INVALID_CELL_CODE
Invalid cell code.
Definition: DgmOctree.h:89
unsigned CellCode
Type of the code of an octree cell.
Definition: DgmOctree.h:78
GenericIndexedCloudPersist * m_theAssociatedCloud
Associated cloud.
Definition: DgmOctree.h:1233
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
Definition: DgmOctree.cpp:498
static const int MAX_OCTREE_LEVEL
Max octree subdivision level.
Definition: DgmOctree.h:67
CCVector3 m_dimMax
Max coordinates of the octree bounding-box.
Definition: DgmOctree.h:1245
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
Definition: DgmOctree.cpp:2664
PointCoordinateType m_cellSize[MAX_OCTREE_LEVEL+2]
Cell dimensions for all subdivision levels.
Definition: DgmOctree.h:1255
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
Definition: DgmOctree.h:494
int getPointsInSphericalNeighbourhood(const CCVector3 &sphereCenter, PointCoordinateType radius, NeighboursSet &neighbours, unsigned char level) const
Returns the points falling inside a sphere.
Definition: DgmOctree.cpp:1846
void computeCellCenter(CellCode code, unsigned char level, CCVector3 &center, bool isCodeTruncated=false) const
Definition: DgmOctree.h:862
unsigned executeFunctionForAllCellsAtLevel(unsigned char level, octreeCellFunc func, void **additionalParameters, bool multiThread=false, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
Definition: DgmOctree.cpp:3573
void computeCellLimits(CellCode code, unsigned char level, CCVector3 &cellMin, CCVector3 &cellMax, bool isCodeTruncated=false) const
Returns the spatial limits of a given cell.
Definition: DgmOctree.cpp:520
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
Definition: DgmOctree.cpp:196
CCVector3 m_dimMin
Min coordinates of the octree bounding-box.
Definition: DgmOctree.h:1243
cellsContainer m_thePointsAndTheirCellCodes
The coded octree structure.
Definition: DgmOctree.h:1230
static unsigned char GET_BIT_SHIFT(unsigned char level)
Returns the binary shift for a given level of subdivision.
Definition: DgmOctree.cpp:113
std::vector< PointDescriptor > NeighboursSet
A set of neighbours.
Definition: DgmOctree.h:133
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
Definition: DgmOctree.cpp:2737
virtual bool enableScalarField()=0
Enables the scalar field associated to the cloud.
virtual unsigned size() const =0
Returns the number of points.
virtual void setPointScalarValue(unsigned pointIndex, ScalarType value)=0
Sets the ith point associated scalar value.
A generic 3D point cloud with index-based point access.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
const CCVector3 * getGravityCenter()
Returns gravity center.
A very simple point cloud (no point duplication)
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
static ScalarType computeMeanScalarValue(GenericCloud *theCloud)
Computes the mean value of a scalar field associated to a cloud.
ScalarType & getValue(std::size_t index)
Definition: ScalarField.h:92
RGB color structure.
Definition: ecvColorTypes.h:49
static void RemoveEntities(const ccHObject *obj)
static void DrawBBox(const CC_DRAW_CONTEXT &context, const ccBBox *bbox)
static QWidget * GetCurrentScreen()
Graphical progress indicator (thread-safe)
unsigned char ColorCompType
Default color components type (R,G and B)
Definition: ecvColorTypes.h:29
@ ECV_WIREFRAME_MODE
@ ECV_SHAPE
ImGuiContext * context
Definition: Window.cpp:76
normal_z rgb
@ POINT_CLOUD
Definition: CVTypes.h:104
Generic file read and write utility for python interface.
constexpr Rgb magenta(MAX, 0, MAX)
constexpr Rgb blue(0, 0, MAX)
constexpr Rgb green(0, MAX, 0)
cloudViewer::NormalizedProgress * nProgress
cloudViewer::DgmOctree * octree
unsigned char octreeLevel
ccGenericPointCloud * sourceCloud
Simple axis aligned box structure.
Definition: RayAndBox.h:50
bool intersects(const Ray< T > &r, T *t0=0, T *t1=0) const
Definition: RayAndBox.h:69
Simple Ray structure.
Definition: RayAndBox.h:14
void squareDistances(const Vector3Tpl< T > &P, double &radial, double &toOrigin) const
Definition: RayAndBox.h:35
OpenGL camera parameters.
bool unproject(const CCVector3d &input2D, CCVector3d &output3D) const
Unprojects a 2D point (+ normalized 'z' coordinate) in 3D.
float pixelSize
Pixel size (i.e. zoom) - non perspective mode only.
bool perspective
Perspective mode.
bool project(const CCVector3d &input3D, CCVector3d &output2D, bool *inFrustum=nullptr) const
Projects a 3D point in 2D (+ normalized 'z' coordinate)
Display context.
Parameters for the GuessBestRadius method.
Definition: ecvOctree.h:122
int minCellPopulation
Minimum cell poulation.
Definition: ecvOctree.h:126
int aimedPopulationPerCell
Aimed poulation per octree cell.
Definition: ecvOctree.h:123
int aimedPopulationRange
Aimed poulation range per octree cell.
Definition: ecvOctree.h:124
Structure used during nearest neighbour search.
Definition: DgmOctree.h:101
const CCVector3 * point
Point.
Definition: DgmOctree.h:103
double squareDistd
Point associated distance value.
Definition: DgmOctree.h:107
Octree cell descriptor.
Definition: DgmOctree.h:354
ReferenceCloud * points
Set of points lying inside this cell.
Definition: DgmOctree.h:365
const DgmOctree * parentOctree
Octree to which the cell belongs.
Definition: DgmOctree.h:359
unsigned char level
Cell level of subdivision.
Definition: DgmOctree.h:367
CellCode truncatedCode
Truncated cell code.
Definition: DgmOctree.h:361
Display parameters of a 3D entity.
bool showColors
Display colors.
bool showNorms
Display normals.
bool showSF
Display scalar field (prioritary on colors)