ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
fastMarchingForFacetExtraction.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 // CV_DB_LIB
11 #include <ecvGenericPointCloud.h>
12 #include <ecvOctree.h>
13 #include <ecvPointCloud.h>
14 
15 // Qt
16 #include <QApplication>
17 
19 const int c_3dNeighboursPosShift[] = {
20  -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, 0, -1, -1, 0, 0, -1,
21  0, 1, -1, 1, -1, -1, 1, 0, -1, 1, 1, 0, -1, -1, 0, -1,
22  0, 0, -1, 1, 0, 0, -1, 0, 0, 1, 0, 1, -1, 0, 1, 0,
23  0, 1, 1, 1, -1, -1, 1, -1, 0, 1, -1, 1, 1, 0, -1, 1,
24  0, 0, 1, 0, 1, 1, 1, -1, 1, 1, 0, 1, 1, 1};
25 
27  : cloudViewer::FastMarching(),
28  m_currentFacetPoints(nullptr),
29  m_currentFacetError(0),
30  m_maxError(0),
31  m_errorMeasure(cloudViewer::DistanceComputationTools::RMS),
32  m_useRetroProjectionError(false),
33  m_propagateProgressCb(nullptr),
34  m_propagateProgress(0) {}
35 
38  delete m_currentFacetPoints;
39  }
40 }
41 
42 static bool ComputeCellStats(
44  CCVector3& N,
45  CCVector3& C,
46  ScalarType& error,
48  error = 0;
49 
50  if (!subset || subset->size() == 0) return false;
51 
52  // we compute the gravity center
53  cloudViewer::Neighbourhood Yk(subset);
54  C = *Yk.getGravityCenter();
55 
56  // we compute the (least square) best fit plane
57  const PointCoordinateType* planeEquation = Yk.getLSPlane();
58  if (planeEquation) {
59  N = CCVector3(planeEquation); // normal = first 3 components
61  ComputeCloud2PlaneDistance(subset, planeEquation, errorMeasure);
62  } else {
63  // not enough points?
64  N = CCVector3(0, 0, 0);
65  }
66 
67  return true;
68 }
69 
71  ccGenericPointCloud* cloud,
72  cloudViewer::DgmOctree* theOctree,
73  unsigned char level,
74  ScalarType maxError,
76  bool useRetroProjectionError,
77  cloudViewer::GenericProgressCallback* progressCb /*=0*/) {
78  m_maxError = maxError;
79  m_errorMeasure = errorMeasure;
80  m_useRetroProjectionError = useRetroProjectionError;
81 
82  if (progressCb) {
83  if (progressCb->textCanBeEdited()) {
84  progressCb->setMethodTitle("Fast Marching grid initialization");
85  progressCb->setInfo(qPrintable(QString("Level: %1").arg(level)));
86  }
87  progressCb->update(0);
88  progressCb->start();
89  }
90 
91  int result = initGridWithOctree(theOctree, level);
92  if (result < 0) return result;
93 
94  // fill the grid with the octree
96  theOctree->getCellCodes(level, cellCodes, true);
97  size_t cellCount = cellCodes.size();
98 
100  static_cast<unsigned>(cellCount));
101  if (progressCb) {
102  progressCb->setInfo(qPrintable(
103  QString("Level: %1\nCells: %2").arg(level).arg(cellCount)));
104  }
105 
107  while (!cellCodes.empty()) {
108  if (theOctree->getPointsInCell(cellCodes.back(), level, &Yk, true)) {
109  // convert the octree cell code to grid position
110  Tuple3i cellPos;
111  theOctree->getCellPos(cellCodes.back(), level, cellPos, true);
112 
113  CCVector3 N, C;
114  ScalarType error;
115  if (ComputeCellStats(&Yk, N, C, error, m_errorMeasure)) {
116  // convert octree cell pos to FM cell pos index
117  unsigned gridPos = pos2index(cellPos);
118 
119  // create corresponding cell
120  PlanarCell* aCell = new PlanarCell;
121  aCell->cellCode = cellCodes.back();
122  aCell->N = N;
123  aCell->C = C;
124  aCell->planarError = error;
125  m_theGrid[gridPos] = aCell;
126  } else {
127  // an error occurred?!
128  return -10;
129  }
130  }
131 
132  cellCodes.pop_back();
133 
134  if (progressCb && !nProgress.oneStep()) {
135  // process cancelled by user
136  progressCb->stop();
137  return -1;
138  }
139  }
140 
141  if (progressCb) {
142  progressCb->stop();
143  }
144 
145  m_initialized = true;
146 
147  return 0;
148 }
149 
151  if (!m_initialized) return -1;
152 
153  // get 'earliest' cell
154  unsigned minTCellIndex = getNearestTrialCell();
155  if (minTCellIndex == 0) return 0;
156 
157  cloudViewer::FastMarching::Cell* minTCell = m_theGrid[minTCellIndex];
158  assert(minTCell && minTCell->state != PlanarCell::ACTIVE_CELL);
159 
160  if (minTCell->T < Cell::T_INF()) {
161  assert(m_currentFacetPoints);
162  unsigned sizeBefore = m_currentFacetPoints->size();
163 
164  // check if we can add the cell to the current "ACTIVE" set
165  ScalarType error = addCellToCurrentFacet(minTCellIndex);
166 
167  if (error >= 0) {
168  if (error > m_maxError) {
169  // resulting error would be too high
170  m_currentFacetPoints->resize(sizeBefore);
171  // we leave the cell as is (in the EMPTY state)
172  // so that we won't look at it again!
173  addIgnoredCell(minTCellIndex);
174  } else {
176 
177  // add the cell to the "ACTIVE" set
178  addActiveCell(minTCellIndex);
179 
180  // add its neighbors to the TRIAL set
181  for (unsigned i = 0; i < m_numberOfNeighbours; ++i) {
182  // get neighbor cell
183  unsigned nIndex = minTCellIndex + m_neighboursIndexShift[i];
185  if (nCell) {
186  // if it' not yet a TRIAL cell
187  if (nCell->state == PlanarCell::FAR_CELL) {
188  nCell->T = computeT(nIndex);
189  addTrialCell(nIndex);
190  }
191  // otherwise we must update it's arrival time
192  else if (nCell->state == PlanarCell::TRIAL_CELL) {
193  const float& t_old = nCell->T;
194  float t_new = computeT(nIndex);
195 
196  if (t_new < t_old) nCell->T = t_new;
197  }
198  }
199  }
200 
202  (m_currentFacetPoints->size() - sizeBefore);
203  if (m_propagateProgressCb) {
205  (100.0f * m_propagateProgress) /
207  }
208  }
209  } else {
210  // an error occurred
211  return -1;
212  }
213  } else {
214  addIgnoredCell(minTCellIndex);
215  }
216 
217  return 1;
218 }
219 
222  cloudViewer::FastMarching::Cell* destCell) const {
223  PlanarCell* oCell = static_cast<PlanarCell*>(originCell);
224  PlanarCell* dCell = static_cast<PlanarCell*>(destCell);
225 
226  // compute the 'confidence' relatively to the neighbor cell
227  // 1) it depends on the angle between the current cell's orientation
228  // and its neighbor's orientation (symmetric)
229  // 2) it depends on whether the neighbor's relative position is
230  // compatible with the current cell orientation (symmetric)
231  float orientationConfidence = 0;
232  {
233  CCVector3 AB = dCell->C - oCell->C;
234  AB.normalize();
235 
236  float psOri = fabs(
237  static_cast<float>(AB.dot(oCell->N))); // ideal: 90 degrees
238  float psDest = fabs(
239  static_cast<float>(AB.dot(dCell->N))); // ideal: 90 degrees
240  orientationConfidence =
241  (psOri + psDest) / 2; // between 0 and 1 (ideal: 0)
242  }
243 
244  // add reprojection error into balance
245  if (m_useRetroProjectionError && m_octree && oCell->N.norm2() != 0) {
246  PointCoordinateType theLSQPlaneEquation[4];
247  theLSQPlaneEquation[0] = oCell->N.x;
248  theLSQPlaneEquation[1] = oCell->N.y;
249  theLSQPlaneEquation[2] = oCell->N.z;
250  theLSQPlaneEquation[3] = oCell->C.dot(oCell->N);
251 
253  if (m_octree->getPointsInCell(oCell->cellCode, m_gridLevel, &Yk,
254  true)) {
255  ScalarType reprojError = cloudViewer::DistanceComputationTools::
256  ComputeCloud2PlaneDistance(&Yk, theLSQPlaneEquation,
258  if (reprojError >= 0)
259  return (1.0f - orientationConfidence) *
260  static_cast<float>(reprojError);
261  }
262  }
263 
264  return (1.0f - orientationConfidence) ;
265 }
266 
268  // init "TRIAL" set with seed's neighbors
269  initTrialCells();
270 
271  int result = 1;
272  while (result > 0) {
273  result = step();
274 
275  if (result > 0 && m_propagateProgressCb &&
277  return -1;
278  }
279  }
280 
281  return result;
282 }
283 
285  ccGenericPointCloud* theCloud,
286  std::vector<unsigned char>& flags,
287  unsigned facetIndex) {
288  if (!m_initialized || !m_currentFacetPoints) return 0;
289 
290  unsigned pointCount = m_currentFacetPoints->size();
291  for (unsigned k = 0; k < pointCount; ++k) {
292  unsigned index = m_currentFacetPoints->getPointGlobalIndex(k);
293  flags[index] = 1;
294 
295  theCloud->setPointScalarValue(index,
296  static_cast<ScalarType>(facetIndex));
297  }
298 
299  if (m_currentFacetPoints) {
300  m_currentFacetPoints->clear(false);
301  }
302 
303  // for (size_t i = 0; i < m_activeCells.size(); ++i)
304  //{
305  // //we remove the processed cell so as to be sure not to consider them
306  // again! cloudViewer::FastMarching::Cell* cell =
307  // m_theGrid[m_activeCells[i]]; m_theGrid[m_activeCells[i]] = 0;
308  // if (cell) delete cell;
309  // }
310 
311  // unsigned pointCount = 0;
313  for (size_t i = 0; i < m_activeCells.size(); ++i) {
314  PlanarCell* aCell =
315  static_cast<PlanarCell*>(m_theGrid[m_activeCells[i]]);
316  if (!m_octree->getPointsInCell(aCell->cellCode, m_gridLevel, &Yk, true))
317  continue;
318 
319  for (unsigned k = 0; k < Yk.size(); ++k) {
320  unsigned index = Yk.getPointGlobalIndex(k);
321  assert(flags[index] == 1);
322  // flags.setValue(index,1);
323  //++pointCount;
324  }
325 
326  m_theGrid[m_activeCells[i]] = 0;
327  delete aCell;
328  }
329 
330  return pointCount;
331 }
332 
335  return false;
336  }
337 
338  if (m_octree) {
339  if (!m_currentFacetPoints) {
342  }
343  assert(m_currentFacetPoints->size() == 0);
344 
345  unsigned index = pos2index(pos);
347  if (m_currentFacetError < 0) // invalid error?
348  return false;
349 
351  }
352 
353  return true;
354 }
355 
357  unsigned index) {
360  return -1;
361 
362  PlanarCell* cell = static_cast<PlanarCell*>(m_theGrid[index]);
363  if (!cell) return -1;
364 
366  if (!m_octree->getPointsInCell(cell->cellCode, m_gridLevel, &Yk, true))
367  return -1;
368 
369  if (!m_currentFacetPoints->add(Yk)) {
370  // not enough memory?
371  return -1;
372  }
373 
374  // update error
375  CCVector3 N, C;
376  ScalarType error;
378 
379  return error;
380 }
381 
383  // we expect at most one 'ACTIVE' cell (i.e. the current seed)
384  size_t seedCount = m_activeCells.size();
385  assert(seedCount <= 1);
386 
387  if (seedCount == 1 && m_currentFacetError <= m_maxError) {
388  unsigned index = m_activeCells.front();
389  PlanarCell* seedCell = static_cast<PlanarCell*>(m_theGrid[index]);
390 
391  assert(seedCell != nullptr);
392  assert(seedCell->T == 0);
393 
394  // add all its neighbour cells to the TRIAL set
395  for (unsigned i = 0; i < m_numberOfNeighbours; ++i) {
396  unsigned nIndex = index + m_neighboursIndexShift[i];
397  PlanarCell* nCell = (PlanarCell*)m_theGrid[nIndex];
398  // if the neighbor exists (it shouldn't be in the TRIAL or ACTIVE
399  // sets)
400  if (nCell /* && nCell->state == PlanarCell::FAR_CELL*/) {
401  assert(nCell->state == PlanarCell::FAR_CELL);
402  addTrialCell(nIndex);
403 
404  // compute its approximate arrival time
405  nCell->T = seedCell->T +
407  computeTCoefApprox(seedCell, nCell);
408  }
409  }
410  }
411 }
412 
414  ccPointCloud* theCloud,
415  unsigned char octreeLevel,
416  ScalarType maxError,
418  bool useRetroProjectionError /*=true*/,
419  cloudViewer::GenericProgressCallback* progressCb /*=0*/,
420  cloudViewer::DgmOctree* _theOctree /*=0*/) {
421  assert(theCloud);
422 
423  unsigned numberOfPoints = theCloud->size();
424  if (numberOfPoints == 0) return -1;
425 
426  if (!theCloud->getCurrentOutScalarField()) return -2;
427 
428  if (progressCb) {
429  // just spawn the dialog so that we can see the
430  // octree computation (in case the CPU charge prevents
431  // the dialog from being shown)
432  progressCb->start();
433  QApplication::processEvents();
434  }
435 
436  // we compute the octree if none is provided
437  cloudViewer::DgmOctree* theOctree = _theOctree;
438  QScopedPointer<cloudViewer::DgmOctree> tempOctree;
439  if (!theOctree) {
440  theOctree = new cloudViewer::DgmOctree(theCloud);
441  tempOctree.reset(theOctree);
442  if (theOctree->build(progressCb) < 1) {
443  return -3;
444  }
445  }
446 
447  if (progressCb) {
448  if (progressCb->textCanBeEdited()) {
449  progressCb->setMethodTitle("Fast Marching for facets extraction");
450  progressCb->setInfo("Initializing...");
451  }
452  progressCb->start();
453  QApplication::processEvents();
454  }
455  if (!theCloud->enableScalarField()) {
457  "[FastMarchingForFacetExtraction] Couldn't enable scalar "
458  "field! Not enough memory?");
459  return -4;
460  }
461 
462  // raz SF values
463  {
464  for (unsigned i = 0; i != theCloud->size(); ++i)
465  theCloud->setPointScalarValue(i, 0);
466  }
467 
468  // flags indicating if each point has been processed or not
469  std::vector<unsigned char> flags;
470  try {
471  flags.resize(numberOfPoints, 0); // defaultFlagValue = 0
472  } catch (const std::bad_alloc&) {
473  CVLog::Warning("[FastMarchingForFacetExtraction] Not enough memory!");
474  return -5;
475  }
476 
477  // Fast Marching propagation
479 
480  int result = fm.init(theCloud, theOctree, octreeLevel, maxError,
481  errorMeasure, useRetroProjectionError, progressCb);
482  if (result < 0) {
483  CVLog::Error(
484  "[FastMarchingForFacetExtraction] Something went wrong during "
485  "initialization...");
486  return -6;
487  }
488 
489  // progress notification
490  if (progressCb) {
491  progressCb->update(0);
492  if (progressCb->textCanBeEdited()) {
493  progressCb->setMethodTitle("Facets extraction");
494  progressCb->setInfo(
495  qPrintable(QString("Octree level: %1\nPoints: %2")
496  .arg(octreeLevel)
497  .arg(numberOfPoints)));
498  }
499  progressCb->start();
500  QApplication::processEvents();
501 
502  fm.setPropagateCallback(progressCb);
503  }
504 
505  const int octreeWidth = (1 << octreeLevel) - 1;
506 
507  // enable 26-connectivity mode
508  // fm.setExtendedConnectivity(true);
509 
510  // while non-processed points remain...
511  unsigned resolvedPoints = 0;
512  int lastProcessedPoint = -1;
513  unsigned facetIndex = 0;
514  while (true) {
515  // find the next non-processed point
516  do {
517  ++lastProcessedPoint;
518  } while (lastProcessedPoint < static_cast<int>(numberOfPoints) &&
519  flags[lastProcessedPoint] != 0);
520 
521  // all points have been processed? Then we can stop.
522  if (lastProcessedPoint == static_cast<int>(numberOfPoints)) {
523  break;
524  }
525 
526  // we start the propagation from this point
527  //(from its corresponding cell in fact ;)
528  const CCVector3* thePoint = theCloud->getPoint(lastProcessedPoint);
529  Tuple3i pos;
530  theOctree->getTheCellPosWhichIncludesThePoint(thePoint, pos,
531  octreeLevel);
532 
533  // clipping (in case the octree is not 'complete')
534  pos.x = std::min(octreeWidth, pos.x);
535  pos.y = std::min(octreeWidth, pos.y);
536  pos.z = std::min(octreeWidth, pos.z);
537 
538  // set corresponding FM cell as 'seed'
539  if (!fm.setSeedCell(pos)) {
540  // an error occurred?!
541  // result = -7;
542  // break;
543  continue;
544  }
545 
546  // launch propagation
547  int propagationResult = fm.propagate();
548  if (propagationResult < 0) {
549  // an error occurred or the process was cancelled by the user
550  result = -7;
551  break;
552  }
553 
554  // compute the number of points processed during this pass
555  unsigned count = fm.updateFlagsTable(theCloud, flags, ++facetIndex);
556 
557  if (count != 0) {
558  resolvedPoints += count;
559  // if (progressCb)
560  //{
561  // if (progressCb->isCancelRequested())
562  // {
563  // result = -7;
564  // break;
565  // }
566  // progressCb->update((resolvedPoints * 100.0f) / numberOfPoints);
567  // }
568  }
569 
571  }
572 
573  fm.setPropagateCallback(nullptr);
574 
575  if (progressCb) {
576  progressCb->stop();
577  }
578 
579  return result;
580 }
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 count
core::Tensor result
Definition: VtkUtils.cpp:76
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
Definition: CVLog.cpp:133
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Definition: CVLog.cpp:143
A Fast Marching grid cell for planar facets extraction.
cloudViewer::DgmOctree::CellCode cellCode
the code of the equivalent cell in the octree
Fast Marching algorithm for planar facets extraction (qFacets plugin)
unsigned m_propagateProgress
Propagation progress.
virtual float computeTCoefApprox(cloudViewer::FastMarching::Cell *currentCell, cloudViewer::FastMarching::Cell *neighbourCell) const override
Computes the front acceleration between two cells.
cloudViewer::DistanceComputationTools::ERROR_MEASURES m_errorMeasure
Error measrue.
ScalarType m_currentFacetError
Current facet error.
void setPropagateCallback(cloudViewer::GenericProgressCallback *propagateProgressCb)
Sets the propagation progress callback.
virtual int step() override
Propagates the front (one step)
unsigned updateFlagsTable(ccGenericPointCloud *theCloud, std::vector< unsigned char > &flags, unsigned facetIndex)
Updates a list of point flags, indicating the points alreay processed.
cloudViewer::GenericProgressCallback * m_propagateProgressCb
Propagation progress callback.
virtual int propagate() override
Propagates the front.
virtual void initTrialCells() override
Initializes the TRIAL cells list.
bool m_useRetroProjectionError
Whether to use retro-projection error in propagation.
cloudViewer::ReferenceCloud * m_currentFacetPoints
Current facet points.
int init(ccGenericPointCloud *cloud, cloudViewer::DgmOctree *theOctree, unsigned char gridLevel, ScalarType maxError, cloudViewer::DistanceComputationTools::ERROR_MEASURES errorMeasure, bool useRetroProjectionError, cloudViewer::GenericProgressCallback *progressCb=0)
Initializes the grid with a point cloud (and ist corresponding octree)
static int ExtractPlanarFacets(ccPointCloud *theCloud, unsigned char octreeLevel, ScalarType maxError, cloudViewer::DistanceComputationTools::ERROR_MEASURES errorMeasure, bool useRetroProjectionError=true, cloudViewer::GenericProgressCallback *progressCb=0, cloudViewer::DgmOctree *_theOctree=0)
Static entry point (helper)
virtual bool setSeedCell(const Tuple3i &pos) override
Sets a given cell as "seed".
Type y
Definition: CVGeom.h:137
Type x
Definition: CVGeom.h:137
Type z
Definition: CVGeom.h:137
void normalize()
Sets vector norm to unity.
Definition: CVGeom.h:428
Type dot(const Vector3Tpl &v) const
Dot product.
Definition: CVGeom.h:408
Type norm2() const
Returns vector square norm.
Definition: CVGeom.h:417
A 3D cloud interface with associated features (color, normals, octree, etc.)
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
The octree structure used throughout the library.
Definition: DgmOctree.h:39
GenericIndexedCloudPersist * associatedCloud() const
Returns the associated cloud.
Definition: DgmOctree.h:1191
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
bool getPointsInCell(CellCode cellCode, unsigned char level, ReferenceCloud *subset, bool isCodeTruncated=false, bool clearOutputCloud=true) const
Returns the points lying in a specific cell.
Definition: DgmOctree.cpp:537
void getTheCellPosWhichIncludesThePoint(const CCVector3 *thePoint, Tuple3i &cellPos) const
Definition: DgmOctree.h:779
std::vector< CellCode > cellCodesContainer
Octree cell codes container.
Definition: DgmOctree.h:92
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
Definition: DgmOctree.cpp:196
bool getCellCodes(unsigned char level, cellCodesContainer &vec, bool truncatedCodes=false) const
Definition: DgmOctree.cpp:2822
static ScalarType ComputeCloud2PlaneDistance(cloudViewer::GenericCloud *cloud, const PointCoordinateType *planeEquation, ERROR_MEASURES measureType)
A generic Fast Marching grid cell.
Definition: FastMarching.h:95
static float T_INF()
Returns infinite time value.
Definition: FastMarching.h:98
float T
Front arrival time.
Definition: FastMarching.h:118
virtual void addActiveCell(unsigned index)
Add a cell to the ACTIVE cells list.
unsigned pos2index(const Tuple3i &pos) const
Definition: FastMarching.h:87
Cell ** m_theGrid
Grid used to process Fast Marching.
Definition: FastMarching.h:235
virtual float computeT(unsigned index)
Computes the front arrival time at a given cell.
DgmOctree * m_octree
Associated octree.
Definition: FastMarching.h:238
std::vector< unsigned > m_activeCells
ACTIVE cells list.
Definition: FastMarching.h:212
unsigned char m_gridLevel
Equivalent octree subdivision level.
Definition: FastMarching.h:240
bool m_initialized
Specifiies whether structure is initialized or not.
Definition: FastMarching.h:219
virtual void addTrialCell(unsigned index)
Add a cell to the TRIAL cells list.
float m_neighboursDistance[26]
Neighbours distance weight.
Definition: FastMarching.h:251
virtual int initGridWithOctree(DgmOctree *octree, unsigned char gridLevel)
virtual bool setSeedCell(const Tuple3i &pos)
Sets a given cell as "seed".
unsigned m_numberOfNeighbours
Current number of neighbours (6 or 26)
Definition: FastMarching.h:247
virtual void addIgnoredCell(unsigned index)
Add a cell to the IGNORED cells list.
virtual unsigned getNearestTrialCell()
Returns the TRIAL cell with the smallest front arrival time.
int m_neighboursIndexShift[26]
Neighbours coordinates shifts in grid.
Definition: FastMarching.h:249
virtual void cleanLastPropagation()
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.
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.
virtual bool isCancelRequested()=0
Checks if the process should be canceled.
const PointCoordinateType * getLSPlane()
Returns best interpolating plane equation (Least-square)
const CCVector3 * getGravityCenter()
Returns gravity center.
bool oneStep()
Increments total progress value of a single unit.
ScalarField * getCurrentOutScalarField() const
Returns the scalar field currently associated to the cloud output.
void setPointScalarValue(unsigned pointIndex, ScalarType value) override
unsigned size() const override
Definition: PointCloudTpl.h:38
const CCVector3 * getPoint(unsigned index) const override
bool enableScalarField() override
Definition: PointCloudTpl.h:77
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
virtual bool resize(unsigned n)
Presets the size of the vector used to store point references.
virtual void clear(bool releaseMemory=false)
Clears the cloud.
bool add(const ReferenceCloud &cloud)
Add another reference cloud.
__host__ __device__ float2 fabs(float2 v)
Definition: cutil_math.h:1254
int min(int a, int b)
Definition: cutil_math.h:53
static bool ComputeCellStats(cloudViewer::ReferenceCloud *subset, CCVector3 &N, CCVector3 &C, ScalarType &error, cloudViewer::DistanceComputationTools::ERROR_MEASURES errorMeasure)
const int c_3dNeighboursPosShift[]
26-connexity neighbouring cells positions (common edges)
static void error(char *msg)
Definition: lsd.c:159
Generic file read and write utility for python interface.
cloudViewer::NormalizedProgress * nProgress
unsigned char octreeLevel