ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ScalarFieldTools.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 <ScalarFieldTools.h>
9 
10 // local
12 #include <ReferenceCloud.h>
13 #include <ScalarField.h>
14 
15 // system
16 #include <cstdio>
17 
18 using namespace cloudViewer;
19 
21 
23  ScalarType& scalarValue) {
24  scalarValue = NAN_VALUE;
25 }
26 
28  ScalarType& scalarValue) {
29  scalarValue = 0;
30 }
31 
33  ScalarType& scalarValue) {
34  scalarValue = -scalarValue;
35 }
36 
39  PointCoordinateType radius,
40  bool euclideanDistances,
41  bool sameInAndOutScalarField /*=false*/,
42  GenericProgressCallback* progressCb /*=0*/,
43  DgmOctree* theCloudOctree /*=0*/) {
44  if (!theCloud) {
45  return -1;
46  }
47 
48  DgmOctree* theOctree = theCloudOctree;
49  if (!theOctree) {
50  theOctree = new DgmOctree(theCloud);
51  if (theOctree->build(progressCb) < 1) {
52  delete theOctree;
53  return -2;
54  }
55  }
56 
57  unsigned char octreeLevel = 0;
58  if (radius <= 0) {
61  radius = theOctree->getCellSize(octreeLevel);
62  } else {
63  octreeLevel =
65  radius);
66  }
67 
68  ScalarField* theGradientNorms = new ScalarField("gradient norms");
69  ScalarField* _theGradientNorms = nullptr;
70 
71  // if the IN and OUT scalar fields are the same
72  if (sameInAndOutScalarField) {
73  if (!theGradientNorms->reserveSafe(
74  theCloud->size())) // not enough memory
75  {
76  if (!theCloudOctree) delete theOctree;
77  theGradientNorms->release();
78  return -3;
79  }
80  _theGradientNorms = theGradientNorms;
81  } else // different IN and OUT scalar fields (default)
82  {
83  // we init the OUT scalar field
84  if (!theCloud->enableScalarField()) {
85  if (!theCloudOctree) delete theOctree;
86  theGradientNorms->release();
87  return -4;
88  }
89  }
90 
91  // additionnal parameters
92  void* additionalParameters[3] = {static_cast<void*>(&euclideanDistances),
93  static_cast<void*>(&radius),
94  static_cast<void*>(_theGradientNorms)};
95 
96  int result = 0;
97 
98  if (theOctree->executeFunctionForAllCellsAtLevel(
99  octreeLevel, computeMeanGradientOnPatch, additionalParameters,
100  true, progressCb, "Gradient Computation") == 0) {
101  // something went wrong
102  result = -5;
103  }
104 
105  if (!theCloudOctree) {
106  delete theOctree;
107  }
108  theGradientNorms->release();
109 
110  return result;
111 }
112 
114  const DgmOctree::octreeCell& cell,
115  void** additionalParameters,
116  NormalizedProgress* nProgress /*=0*/) {
117  // additional parameters
118  bool euclideanDistances = *reinterpret_cast<bool*>(additionalParameters[0]);
119  PointCoordinateType radius =
120  *reinterpret_cast<PointCoordinateType*>(additionalParameters[1]);
121  ScalarField* theGradientNorms =
122  reinterpret_cast<ScalarField*>(additionalParameters[2]);
123 
124  // number of points inside the current cell
125  unsigned n = cell.points->size();
126 
127  // spherical neighborhood extraction structure
129  nNSS.level = cell.level;
130  nNSS.prepare(radius, cell.parentOctree->getCellSize(nNSS.level));
131  cell.parentOctree->getCellPos(cell.truncatedCode, cell.level, nNSS.cellPos,
132  true);
133  cell.parentOctree->computeCellCenter(nNSS.cellPos, cell.level,
134  nNSS.cellCenter);
135 
136  // we already know the points inside the current cell
137  {
138  try {
139  nNSS.pointsInNeighbourhood.resize(n);
140  } catch (... /*const std::bad_alloc&*/) // out of memory
141  {
142  return false;
143  }
144  DgmOctree::NeighboursSet::iterator it =
145  nNSS.pointsInNeighbourhood.begin();
146  for (unsigned j = 0; j < n; ++j, ++it) {
147  it->point = cell.points->getPointPersistentPtr(j);
148  it->pointIndex = cell.points->getPointGlobalIndex(j);
149  }
151  }
152 
154 
155  for (unsigned i = 0; i < n; ++i) {
156  ScalarType gN = NAN_VALUE;
157  ScalarType v1 = cell.points->getPointScalarValue(i);
158 
159  if (ScalarField::ValidValue(v1)) {
160  cell.points->getPoint(i, nNSS.queryPoint);
161 
162  // we extract the point's neighbors
163  // warning: there may be more points at the end of
164  // nNSS.pointsInNeighbourhood than the actual nearest neighbors (k)!
165  unsigned k =
167  nNSS, radius, true);
168 
169  // if more than one neighbour (the query point itself)
170  if (k > 1) {
171  CCVector3d sum(0, 0, 0);
172  unsigned counter = 0;
173 
174  // j = 1 because the first point is the query point itself -->
175  // contribution = 0
176  for (unsigned j = 1; j < k; ++j) {
177  ScalarType v2 = cloud->getPointScalarValue(
178  nNSS.pointsInNeighbourhood[j].pointIndex);
179  if (ScalarField::ValidValue(v2)) {
180  CCVector3 deltaPos =
181  *nNSS.pointsInNeighbourhood[j].point -
182  nNSS.queryPoint;
183  double norm2 = deltaPos.norm2d();
184 
185  if (norm2 > ZERO_TOLERANCE_D) {
186  double deltaValue = static_cast<double>(v2 - v1);
187  if (!euclideanDistances ||
188  deltaValue * deltaValue < 1.01 * norm2) {
189  deltaValue /=
190  norm2; // we divide by 'norm' to get
191  // the normalized direction, and
192  // by 'norm' again to get the
193  // gradient (hence we use the
194  // squared norm)
195  sum.x +=
196  deltaPos.x *
197  deltaValue; // warning: here
198  // 'deltaValue'= deltaValue
199  // / squaredNorm(deltaPos)
200  // ;)
201  sum.y += deltaPos.y * deltaValue;
202  sum.z += deltaPos.z * deltaValue;
203  ++counter;
204  }
205  }
206  }
207  }
208 
209  if (counter != 0) {
210  gN = static_cast<ScalarType>(sum.norm() / counter);
211  }
212  }
213  }
214 
215  if (theGradientNorms) {
216  // if "IN" and "OUT" SFs are the same
217  theGradientNorms->setValue(cell.points->getPointGlobalIndex(i), gN);
218  } else {
219  // if "IN" and "OUT" SFs are different
220  cell.points->setPointScalarValue(i, gN);
221  }
222 
223  if (nProgress && !nProgress->oneStep()) {
224  return false;
225  }
226  }
227 
228  return true;
229 }
230 
232  PointCoordinateType sigma,
233  GenericIndexedCloudPersist* theCloud,
234  PointCoordinateType sigmaSF,
235  GenericProgressCallback* progressCb,
236  DgmOctree* theCloudOctree) {
237  if (!theCloud) return false;
238 
239  unsigned n = theCloud->size();
240  if (n == 0) return false;
241 
242  DgmOctree* theOctree = nullptr;
243  if (theCloudOctree)
244  theOctree = theCloudOctree;
245  else {
246  theOctree = new DgmOctree(theCloud);
247  if (theOctree->build(progressCb) < 1) {
248  delete theOctree;
249  return false;
250  }
251  }
252 
253  // best octree level
254  unsigned char level =
256  sigma);
257 
258  // output scalar field should be different than input one
259  theCloud->enableScalarField();
260 
261  if (progressCb) {
262  if (progressCb->textCanBeEdited()) {
263  progressCb->setMethodTitle("Gaussian filter");
264  char infos[256];
265  sprintf(infos, "Level: %i\n", level);
266  progressCb->setInfo(infos);
267  }
268  progressCb->update(0);
269  }
270 
271  void* additionalParameters[2] = {reinterpret_cast<void*>(&sigma),
272  reinterpret_cast<void*>(&sigmaSF)};
273 
274  bool success = true;
275 
276  if (theOctree->executeFunctionForAllCellsAtLevel(
277  level, computeCellGaussianFilter, additionalParameters, true,
278  progressCb, "Gaussian Filter computation") == 0) {
279  // something went wrong
280  success = false;
281  }
282 
283  return success;
284 }
285 
286 // Additional parameters:
287 // [0] -> (PointCoordinateType*) sigma: Gaussian filter sigma
288 // [1] -> (PointCoordinateType*) sigmaSF: Bilateral filter sigma (if > 0)
290  const DgmOctree::octreeCell& cell,
291  void** additionalParameters,
292  NormalizedProgress* nProgress /*=0*/) {
293  // variables additionnelles
294  PointCoordinateType sigma =
295  *(static_cast<PointCoordinateType*>(additionalParameters[0]));
296  PointCoordinateType sigmaSF =
297  *(static_cast<PointCoordinateType*>(additionalParameters[1]));
298 
299  // we use only the squared value of sigma
300  PointCoordinateType sigma2 = 2 * sigma * sigma;
301  PointCoordinateType radius = 3 * sigma; // 3*sigma > 99.7%
302 
303  // we use only the squared value of sigmaSF
304  PointCoordinateType sigmaSF2 = 2 * sigmaSF * sigmaSF;
305 
306  // number of points inside the current cell
307  unsigned n = cell.points->size();
308 
309  // structures pour la recherche de voisinages SPECIFIQUES
311  nNSS.level = cell.level;
312  cell.parentOctree->getCellPos(cell.truncatedCode, cell.level, nNSS.cellPos,
313  true);
314  cell.parentOctree->computeCellCenter(nNSS.cellPos, cell.level,
315  nNSS.cellCenter);
316 
317  // we already know the points lying in the first cell (this is the one we
318  // are treating :)
319  try {
320  nNSS.pointsInNeighbourhood.resize(n);
321  } catch (... /*const std::bad_alloc&*/) // out of memory
322  {
323  return false;
324  }
325 
326  DgmOctree::NeighboursSet::iterator it = nNSS.pointsInNeighbourhood.begin();
327  {
328  for (unsigned i = 0; i < n; ++i, ++it) {
329  it->point = cell.points->getPointPersistentPtr(i);
330  it->pointIndex = cell.points->getPointGlobalIndex(i);
331  }
332  }
334 
336 
337  bool bilateralFilter = (sigmaSF > 0);
338 
339  for (unsigned i = 0; i < n; ++i) // for each point in cell
340  {
341  ScalarType queryValue = 0;
342  if (bilateralFilter) {
343  queryValue = cell.points->getPointScalarValue(
344  i); // scalar of the query point
345 
346  // check that the query SF value is valid, otherwise no need to
347  // compute anything
348  if (!ScalarField::ValidValue(queryValue)) {
350  continue;
351  }
352  }
353 
354  // we get the points inside a spherical neighbourhood (radius:
355  // '3*sigma')
356  cell.points->getPoint(i, nNSS.queryPoint);
357  // warning: there may be more points at the end of
358  // nNSS.pointsInNeighbourhood than the actual nearest neighbors (k)!
360  nNSS, radius, false);
361 
362  // each point adds a contribution weighted by its distance to the sphere
363  // center
364  it = nNSS.pointsInNeighbourhood.begin();
365  double meanValue = 0.0;
366  double wSum = 0.0;
367  for (unsigned j = 0; j < k; ++j, ++it) {
368  double weight = exp(-(it->squareDistd) /
369  sigma2); // PDF: -exp(-(x-mu)^2/(2*sigma^2))
370 
371  ScalarType val = cloud->getPointScalarValue(it->pointIndex);
372 
373  // scalar value must be valid
374  if (!ScalarField::ValidValue(val)) {
375  continue;
376  }
377 
378  if (bilateralFilter) {
379  ScalarType dSF = queryValue - val;
380  weight *= exp(-(dSF * dSF) / sigmaSF2);
381  }
382 
383  meanValue += val * weight;
384  wSum += weight;
385  }
386 
388  i, wSum != 0.0 ? static_cast<ScalarType>(meanValue / wSum)
389  : NAN_VALUE);
390 
391  if (nProgress && !nProgress->oneStep()) {
392  return false;
393  }
394  }
395 
396  return true;
397 }
398 
400  GenericIndexedCloud* firstCloud,
401  GenericIndexedCloud* secondCloud,
402  GenericProgressCallback* progressCb) {
403  if (!firstCloud || !secondCloud) return;
404 
405  unsigned n1 = firstCloud->size();
406  if (n1 != secondCloud->size() || n1 == 0) return;
407 
408  for (unsigned i = 0; i < n1; ++i) {
409  ScalarType V1 = firstCloud->getPointScalarValue(i);
410  ScalarType V2 = secondCloud->getPointScalarValue(i);
411 
412  firstCloud->setPointScalarValue(
414  ? V1 * V2
415  : NAN_VALUE);
416  }
417 }
418 
420  ScalarType& minV,
421  ScalarType& maxV) {
422  assert(theCloud);
423 
424  minV = maxV = NAN_VALUE;
425 
426  unsigned numberOfPoints = theCloud ? theCloud->size() : 0;
427  if (numberOfPoints == 0) return;
428 
429  bool firstValidValue = true;
430 
431  for (unsigned i = 0; i < numberOfPoints; ++i) {
432  ScalarType V = theCloud->getPointScalarValue(i);
433  if (ScalarField::ValidValue(V)) {
434  if (!firstValidValue) {
435  if (V < minV)
436  minV = V;
437  else if (V > maxV)
438  maxV = V;
439  } else {
440  minV = maxV = V;
441  firstValidValue = false;
442  }
443  }
444  }
445 }
446 
448  const GenericCloud* theCloud) {
449  assert(theCloud);
450 
451  unsigned count = 0;
452 
453  if (theCloud) {
454  unsigned n = theCloud->size();
455  for (unsigned i = 0; i < n; ++i) {
456  ScalarType V = theCloud->getPointScalarValue(i);
457  if (ScalarField::ValidValue(V)) ++count;
458  }
459  }
460 
461  return count;
462 }
463 
465  unsigned numberOfClasses,
466  std::vector<int>& histo) {
467  // reset
468  histo.clear();
469 
470  // valid input?
471  if (!theCloud || numberOfClasses == 0) {
472  assert(false);
473  return;
474  }
475  unsigned pointCount = theCloud->size();
476 
477  // specific case: 1 class?!
478  if (numberOfClasses == 1) {
479  histo.push_back(static_cast<int>(pointCount));
480  return;
481  }
482 
483  try {
484  histo.resize(numberOfClasses, 0);
485  } catch (const std::bad_alloc) {
486  // out of memory
487  return;
488  }
489 
490  // compute the min and max sf values
491  ScalarType minV, maxV;
492  {
493  computeScalarFieldExtremas(theCloud, minV, maxV);
494 
495  if (!ScalarField::ValidValue(minV)) {
496  // sf is only composed of NAN values?!
497  return;
498  }
499  }
500 
501  // historgram step
502  ScalarType invStep = (maxV > minV ? numberOfClasses / (maxV - minV) : 0);
503 
504  // histogram computation
505  {
506  int iNumberOfClasses = static_cast<int>(numberOfClasses);
507  for (unsigned i = 0; i < pointCount; ++i) {
508  ScalarType V = theCloud->getPointScalarValue(i);
509  if (ScalarField::ValidValue(V)) {
510  int aimClass = static_cast<int>((V - minV) * invStep);
511  if (aimClass == iNumberOfClasses)
512  --aimClass; // sepcific case: V == maxV
513 
514  ++histo[aimClass];
515  }
516  }
517  }
518 }
519 
521  unsigned char K,
522  KMeanClass kmcc[],
523  GenericProgressCallback* progressCb) {
524  // valid parameters?
525  if (!theCloud || K == 0) {
526  assert(false);
527  return false;
528  }
529 
530  unsigned n = theCloud->size();
531  if (n == 0) return false;
532 
533  // on a besoin de memoire ici !
534  std::vector<ScalarType> theKMeans; // K clusters centers
535  std::vector<unsigned char>
536  belongings; // index of the cluster the point belongs to
537  std::vector<ScalarType>
538  minDistsToMean; // distance to the nearest cluster center
539  std::vector<ScalarType> theKSums; // sum of distances to the clusters
540  std::vector<unsigned> theKNums; // number of points per clusters
541  std::vector<unsigned>
542  theOldKNums; // number of points per clusters (prior to iteration)
543 
544  try {
545  theKMeans.resize(n);
546  belongings.resize(n);
547  minDistsToMean.resize(n);
548  theKSums.resize(K);
549  theKNums.resize(K);
550  theOldKNums.resize(K);
551  } catch (const std::bad_alloc&) {
552  // not enough memory
553  return false;
554  }
555 
556  // compute min and max SF values
557  ScalarType minV, maxV;
558  {
559  computeScalarFieldExtremas(theCloud, minV, maxV);
560 
561  if (!ScalarField::ValidValue(minV)) {
562  // sf is only composed of NAN values?!
563  return false;
564  }
565  }
566 
567  // init classes centers (regularly sampled)
568  {
569  ScalarType step = (maxV - minV) / K;
570  for (unsigned char j = 0; j < K; ++j) theKMeans[j] = minV + step * j;
571  }
572 
573  // for progress notification
574  double initialCMD = 0;
575 
576  // let's start
577  bool meansHaveMoved = false;
578  int iteration = 0;
579  do {
580  meansHaveMoved = false;
581  ++iteration;
582  {
583  for (unsigned i = 0; i < n; ++i) {
584  unsigned char minK = 0;
585 
586  ScalarType V = theCloud->getPointScalarValue(i);
587  if (ScalarField::ValidValue(V)) {
588  minDistsToMean[i] = std::abs(theKMeans[minK] - V);
589 
590  // we look for the nearest cluster center
591  for (unsigned char j = 1; j < K; ++j) {
592  ScalarType distToMean = std::abs(theKMeans[j] - V);
593  if (distToMean < minDistsToMean[i]) {
594  minDistsToMean[i] = distToMean;
595  minK = j;
596  }
597  }
598  }
599 
600  belongings[i] = minK;
601  minDistsToMean[i] = V;
602  }
603  }
604 
605  // compute the clusters centers
606  theOldKNums = theKNums;
607  std::fill(theKSums.begin(), theKSums.end(), static_cast<ScalarType>(0));
608  std::fill(theKNums.begin(), theKNums.end(), static_cast<unsigned>(0));
609  {
610  for (unsigned i = 0; i < n; ++i) {
611  if (minDistsToMean[i] >= 0) // must be a valid value!
612  {
613  theKSums[belongings[i]] += minDistsToMean[i];
614  ++theKNums[belongings[i]];
615  }
616  }
617  }
618 
619  double classMovingDist = 0.0;
620  {
621  for (unsigned char j = 0; j < K; ++j) {
622  ScalarType newMean =
623  (theKNums[j] > 0 ? theKSums[j] / theKNums[j]
624  : theKMeans[j]);
625 
626  if (theOldKNums[j] != theKNums[j]) meansHaveMoved = true;
627 
628  classMovingDist += std::abs(theKMeans[j] - newMean);
629 
630  theKMeans[j] = newMean;
631  }
632  }
633 
634  if (progressCb) {
635  if (iteration == 1) {
636  if (progressCb->textCanBeEdited()) {
637  progressCb->setMethodTitle("KMeans");
638  char buffer[256];
639  sprintf(buffer, "K=%i", K);
640  progressCb->setInfo(buffer);
641  progressCb->start();
642  }
643  progressCb->update(0);
644  initialCMD = classMovingDist;
645  } else {
646  progressCb->update(static_cast<float>(
647  (1.0 - classMovingDist / initialCMD) * 100.0));
648  }
649  }
650  } while (meansHaveMoved);
651 
652  // update distances
653  std::vector<ScalarType> mins, maxs;
654  try {
655  mins.resize(K, maxV);
656  maxs.resize(K, minV);
657  } catch (const std::bad_alloc&) {
658  // not enough memory
659  return false;
660  }
661 
662  // look for min and max values for each cluster
663  {
664  for (unsigned i = 0; i < n; ++i) {
665  ScalarType V = theCloud->getPointScalarValue(i);
666  if (ScalarField::ValidValue(V)) {
667  if (V < mins[belongings[i]])
668  mins[belongings[i]] = V;
669  else if (V > maxs[belongings[i]])
670  maxs[belongings[i]] = V;
671  }
672  }
673  }
674 
675  // last check
676  {
677  for (unsigned char j = 0; j < K; ++j)
678  if (theKNums[j] == 0) mins[j] = maxs[j] = -1.0;
679  }
680 
681  // output
682  {
683  for (unsigned char j = 0; j < K; ++j) {
684  kmcc[j].mean = theKMeans[j];
685  kmcc[j].minValue = mins[j];
686  kmcc[j].maxValue = maxs[j];
687  }
688  }
689 
690  if (progressCb) progressCb->stop();
691 
692  return true;
693 }
694 
696  // valid input?
697  if (!theCloud) {
698  assert(false);
699  return NAN_VALUE;
700  }
701 
702  double meanValue = 0.0;
703  unsigned count = 0;
704 
705  for (unsigned i = 0; i < theCloud->size(); ++i) {
706  ScalarType V = theCloud->getPointScalarValue(i);
707  if (ScalarField::ValidValue(V)) {
708  meanValue += V;
709  ++count;
710  }
711  }
712 
713  return (count ? static_cast<ScalarType>(meanValue / count) : 0);
714 }
715 
717  GenericCloud* theCloud) {
718  // valid input?
719  if (!theCloud) {
720  assert(false);
721  return NAN_VALUE;
722  }
723 
724  double meanValue = 0.0;
725  unsigned count = 0;
726 
727  for (unsigned i = 0; i < theCloud->size(); ++i) {
728  ScalarType V = theCloud->getPointScalarValue(i);
729  if (ScalarField::ValidValue(V)) {
730  double Vd = static_cast<double>(V);
731  meanValue += Vd * Vd;
732  ++count;
733  }
734  }
735 
736  return (count ? static_cast<ScalarType>(meanValue / count) : 0);
737 }
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
Definition: CVConst.h:76
constexpr double ZERO_TOLERANCE_D
Definition: CVConst.h:49
float PointCoordinateType
Type of the coordinates of a (N-D) point.
Definition: CVTypes.h:16
int count
core::Tensor result
Definition: VtkUtils.cpp:76
virtual void release()
Decrease counter and deletes object when 0.
Definition: CVShareable.cpp:35
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
double norm2d() const
Returns vector square norm (forces double precision output)
Definition: CVGeom.h:419
The octree structure used throughout the library.
Definition: DgmOctree.h:39
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
Definition: DgmOctree.cpp:498
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
Definition: DgmOctree.cpp:2664
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
Definition: DgmOctree.cpp:2479
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
Definition: DgmOctree.h:494
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
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
Definition: DgmOctree.cpp:196
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 ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
virtual void setPointScalarValue(unsigned pointIndex, ScalarType value)=0
Sets the ith point associated scalar value.
A generic 3D point cloud with index-based and presistent access to points.
A generic 3D point cloud with index-based point access.
virtual void stop()=0
Notifies the fact that the process has ended.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle)=0
Notifies the algorithm title.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
bool oneStep()
Increments total progress value of a single unit.
void setPointScalarValue(unsigned pointIndex, ScalarType value) override
Sets the ith point associated scalar value.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
ScalarType getPointScalarValue(unsigned pointIndex) const override
Returns the ith point associated scalar value.
static void multiplyScalarFields(GenericIndexedCloud *firstCloud, GenericIndexedCloud *secondCloud, GenericProgressCallback *progressCb=nullptr)
Multiplies two scalar fields of the same size.
static ScalarType computeMeanScalarValue(GenericCloud *theCloud)
Computes the mean value of a scalar field associated to a cloud.
static void SetScalarValueToNaN(const CCVector3 &P, ScalarType &scalarValue)
Sets the distance value associated to a point.
static unsigned countScalarFieldValidValues(const GenericCloud *theCloud)
Count the number of valid values in a scalar field.
static void computeScalarFieldHistogram(const GenericCloud *theCloud, unsigned numberOfClasses, std::vector< int > &histo)
Computes an histogram of the scalar field with a given number of classes.
static bool applyScalarFieldGaussianFilter(PointCoordinateType sigma, GenericIndexedCloudPersist *theCloud, PointCoordinateType sigmaSF, GenericProgressCallback *progressCb=nullptr, DgmOctree *theOctree=nullptr)
static bool computeMeanGradientOnPatch(const DgmOctree::octreeCell &cell, void **additionalParameters, NormalizedProgress *nProgress=nullptr)
static ScalarType computeMeanSquareScalarValue(GenericCloud *theCloud)
Computes the mean square value of a scalar field associated to a cloud.
static void SetScalarValueToZero(const CCVector3 &P, ScalarType &scalarValue)
Sets the distance value associated to a point to zero.
static bool computeCellGaussianFilter(const DgmOctree::octreeCell &cell, void **additionalParameters, NormalizedProgress *nProgress=nullptr)
static bool computeKmeans(const GenericCloud *theCloud, unsigned char K, KMeanClass kmcc[], GenericProgressCallback *progressCb=nullptr)
static int computeScalarFieldGradient(GenericIndexedCloudPersist *theCloud, PointCoordinateType radius, bool euclideanDistances, bool sameInAndOutScalarField=false, GenericProgressCallback *progressCb=nullptr, DgmOctree *theOctree=nullptr)
static void computeScalarFieldExtremas(const GenericCloud *theCloud, ScalarType &minV, ScalarType &maxV)
Compute the extreme values of a scalar field.
static void SetScalarValueInverted(const CCVector3 &P, ScalarType &scalarValue)
A simple scalar field (to be associated to a point cloud)
Definition: ScalarField.h:25
void setValue(std::size_t index, ScalarType value)
Definition: ScalarField.h:96
bool reserveSafe(std::size_t count)
Reserves memory (no exception thrown)
Definition: ScalarField.cpp:71
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
Definition: ScalarField.h:61
static const int AVERAGE_NUMBER_OF_POINTS_FOR_GRADIENT_COMPUTATION
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
Generic file read and write utility for python interface.
cloudViewer::NormalizedProgress * nProgress
unsigned char octreeLevel
Container of in/out parameters for nearest neighbour(s) search.
Definition: DgmOctree.h:161
unsigned char level
Level of subdivision of the octree at which to start the search.
Definition: DgmOctree.h:171
Tuple3i cellPos
Position in the octree of the cell including the query point.
Definition: DgmOctree.h:184
CCVector3 cellCenter
Coordinates of the center of the cell including the query point.
Definition: DgmOctree.h:189
void prepare(PointCoordinateType radius, PointCoordinateType cellSize)
Updates maxD2 and minD2 with search radius and cellSize.
Definition: DgmOctree.h:270
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
A K-mean class position and boundaries.
ScalarType mean
K-mean class mean value.
ScalarType minValue
K-mean class minimum value.
ScalarType maxValue
K-mean class maximum value.