ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
FastMarchingForPropagation.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 // local
11 #include "DgmOctree.h"
12 #include "ReferenceCloud.h"
13 #include "ScalarFieldTools.h"
14 
15 using namespace cloudViewer;
16 
18  : FastMarching(),
19  m_jumpCoef(0) // resistance a l'avancement du front, en fonction de
20  // Cell->f (ici, pas de resistance)
21  ,
22  m_detectionThreshold(
23  Cell::T_INF()) // saut relatif de la valeur d'arrivee qui arrete
24  // la propagation (ici, "desactive")
25 {}
26 
28  DgmOctree* theOctree,
29  unsigned char level,
30  bool constantAcceleration /*=false*/) {
31  assert(theCloud && theOctree);
32 
33  int result = initGridWithOctree(theOctree, level);
34  if (result < 0) return result;
35 
36  // on remplit la grille
38  theOctree->getCellCodes(level, cellCodes, true);
39 
40  ReferenceCloud Yk(theOctree->associatedCloud());
41 
42  while (!cellCodes.empty()) {
43  if (!theOctree->getPointsInCell(cellCodes.back(), level, &Yk, true)) {
44  // not enough memory?
45  return -1;
46  }
47 
48  // on transforme le code de cellule en position
49  Tuple3i cellPos;
50  theOctree->getCellPos(cellCodes.back(), level, cellPos, true);
51 
52  // on renseigne la grille
53  unsigned gridPos = pos2index(cellPos);
54 
55  PropagationCell* aCell = new PropagationCell;
56  aCell->cellCode = cellCodes.back();
57  aCell->f = (constantAcceleration
58  ? 1.0f
59  : static_cast<float>(
61  &Yk)));
62 
63  m_theGrid[gridPos] = aCell;
64 
65  cellCodes.pop_back();
66  }
67 
68  m_initialized = true;
69 
70  return 0;
71 }
72 
74  if (!m_initialized) return -1;
75 
76  unsigned minTCellIndex = getNearestTrialCell();
77  if (minTCellIndex == 0) {
78  // fl_alert("No more trial cells !");
79  return 0;
80  }
81 
82  Cell* minTCell = m_theGrid[minTCellIndex];
83  assert(minTCell != nullptr);
84 
85  // last arrival time
86  float lastT =
87  (m_activeCells.empty() ? 0 : m_theGrid[m_activeCells.back()]->T);
88 
89  if (minTCell->T - lastT > m_detectionThreshold * m_cellSize) {
90  // reset();
91  return 0;
92  }
93 
94  assert(minTCell->state != Cell::ACTIVE_CELL);
95 
96  if (minTCell->T < Cell::T_INF()) {
97  // we add this cell to the "ACTIVE" set
98  addActiveCell(minTCellIndex);
99 
100  assert(minTCell->T >= lastT);
101 
102  // add its neighbors to the TRIAL set
103  Cell* nCell;
104  for (unsigned i = 0; i < m_numberOfNeighbours; ++i) {
105  // get neighbor cell
106  unsigned nIndex = minTCellIndex + m_neighboursIndexShift[i];
107  nCell = m_theGrid[nIndex];
108  if (nCell) {
109  // if it' not yet a TRIAL cell
110  if (nCell->state == Cell::FAR_CELL) {
111  nCell->T = computeT(nIndex);
112  addTrialCell(nIndex);
113  } else if (nCell->state == Cell::TRIAL_CELL)
114  // otherwise we must update it's arrival time
115  {
116  float t_old = nCell->T;
117  float t_new = computeT(nIndex);
118 
119  if (t_new < t_old) nCell->T = t_new;
120  }
121  }
122  }
123  } else {
124  addIgnoredCell(minTCellIndex);
125  }
126 
127  return 1;
128 }
129 
131  initTrialCells();
132 
133  int result = 1;
134  while (result > 0) {
135  result = step();
136  }
137 
138  return result;
139 }
140 
143  if (!m_initialized || !m_octree ||
145  return false;
146 
147  points->clear();
148 
149  for (unsigned i = 0; i < m_activeCells.size(); ++i) {
150  PropagationCell* aCell =
151  static_cast<PropagationCell*>(m_theGrid[m_activeCells[i]]);
153  true, false))
154  return false;
155  }
156 
157  // raz de la norme du gradient du point, pour qu'il ne soit plus pris en
158  // compte par la suite !
159  points->placeIteratorAtBeginning();
160  for (unsigned k = 0; k < points->size(); ++k) {
161  points->setCurrentPointScalarValue(NAN_VALUE);
162  points->forwardIterator();
163  }
164 
165  return true;
166 }
167 
169  if (!m_initialized || !m_octree ||
171  return false;
172 
174 
175  for (unsigned i = 0; i < m_activeCells.size(); ++i) {
176  PropagationCell* aCell =
177  static_cast<PropagationCell*>(m_theGrid[m_activeCells[i]]);
178 
179  if (!m_octree->getPointsInCell(aCell->cellCode, m_gridLevel, &Yk,
180  true)) {
181  // not enough memory?
182  return false;
183  }
184 
186  for (unsigned k = 0; k < Yk.size(); ++k) {
187  Yk.setCurrentPointScalarValue(aCell->T);
188  Yk.forwardIterator();
189  }
190  // Yk.clear(); //useless
191  }
192 
193  return true;
194 }
195 
196 #ifdef _MSC_VER
197 // Visual 2012 (and previous versions) don't know expm1
198 #if _MSC_VER <= 1700
199 
200 // Compute exp(x) - 1 without loss of precision for small values of x.
201 template <typename T>
202 T expm1(T x) {
203  if (std::abs(x) < 1e-5)
204  return x + (x * x) / 2;
205  else
206  return exp(x) - 1;
207 }
208 
209 #endif
210 #endif
211 
213  Cell* currentCell, Cell* neighbourCell) const {
214  PropagationCell* cCell = static_cast<PropagationCell*>(currentCell);
215  PropagationCell* nCell = static_cast<PropagationCell*>(neighbourCell);
216  return expm1(m_jumpCoef * (cCell->f - nCell->f));
217 }
218 
220  if (!m_initialized) return;
221 
222  // on fait bien attention a ne pas initialiser les cellules sur les bords
223  for (unsigned k = 0; k < m_dz; ++k) {
224  int pos[3] = {0, 0, static_cast<int>(k)};
225 
226  for (unsigned j = 0; j < m_dy; ++j) {
227  pos[1] = static_cast<int>(j);
228 
229  for (unsigned i = 0; i < m_dx; ++i) {
230  pos[0] = static_cast<int>(i);
231 
232  unsigned index =
233  static_cast<unsigned>(pos[0] + 1) +
234  static_cast<unsigned>(pos[1] + 1) * m_rowSize +
235  static_cast<unsigned>(pos[2] + 1) * m_sliceSize;
236 
237  PropagationCell* theCell =
238  reinterpret_cast<PropagationCell*>(m_theGrid[index]);
239 
240  if (theCell) {
241  bool isMin = true;
242  bool isMax = true;
243 
244  // theCell->state = ACTIVE_CELL;
245 
246  for (unsigned n = 0; n < CC_FM_MAX_NUMBER_OF_NEIGHBOURS;
247  ++n) {
248  const PropagationCell* nCell =
249  reinterpret_cast<const PropagationCell*>(
250  m_theGrid[index +
252  if (nCell) {
253  if (nCell->f > theCell->f)
254  isMax = false;
255  else if (nCell->f < theCell->f)
256  isMin = false;
257  }
258  }
259 
260  if (isMin != isMax) {
261  // if (isMin)
262  // theCell->T = 1.0;
263  // else
264  // theCell->T = 2.0;
265 
266  if (isMax) {
267  theCell->T = 0;
268  addActiveCell(index);
269  }
270  }
271  // else theCell->T = 0;
272  }
273  }
274  }
275  }
276 }
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
Definition: CVConst.h:76
#define CC_FM_MAX_NUMBER_OF_NEIGHBOURS
Definition: FastMarching.h:26
int points
core::Tensor result
Definition: VtkUtils.cpp:76
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
std::vector< CellCode > cellCodesContainer
Octree cell codes container.
Definition: DgmOctree.h:92
bool getCellCodes(unsigned char level, cellCodesContainer &vec, bool truncatedCodes=false) const
Definition: DgmOctree.cpp:2822
A Fast Marching grid cell for surfacical propagation.
DgmOctree::CellCode cellCode
Equivalent cell code in the octree.
float m_jumpCoef
Accceleration exageration factor.
float computeTCoefApprox(Cell *currentCell, Cell *neighbourCell) const override
Computes the front acceleration between two cells.
int propagate() override
Propagates the front.
int init(GenericCloud *theCloud, DgmOctree *theOctree, unsigned char gridLevel, bool constantAcceleration=false)
Initializes the grid with a point cloud (and ist corresponding octree)
int step() override
Propagates the front (one step)
bool setPropagationTimingsAsDistances()
Sets the propagation timings as distances for each point.
void findPeaks()
Find peaks of local acceleration values.
float m_detectionThreshold
Threshold for propagation stop.
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
Fast Marching algorithm (front propagation)
Definition: FastMarching.h:41
virtual void addActiveCell(unsigned index)
Add a cell to the ACTIVE cells list.
float m_cellSize
Octree cell size at equivalent subdivision level.
Definition: FastMarching.h:242
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.
unsigned m_dx
Grid size along the X dimension.
Definition: FastMarching.h:221
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.
unsigned m_dz
Grid size along the Z dimension.
Definition: FastMarching.h:225
unsigned m_rowSize
Shift for cell access acceleration (Y dimension)
Definition: FastMarching.h:227
virtual int initGridWithOctree(DgmOctree *octree, unsigned char gridLevel)
virtual void initTrialCells()
Initializes the TRIAL cells list.
unsigned m_sliceSize
Shift for cell access acceleration (Z dimension)
Definition: FastMarching.h:229
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
unsigned m_dy
Grid size along the Y dimension.
Definition: FastMarching.h:223
A very simple point cloud (no point duplication)
void placeIteratorAtBeginning() override
Sets the cloud iterator at the beginning.
unsigned size() const override
Returns the number of points.
virtual void setCurrentPointScalarValue(ScalarType value)
Sets the current point associated scalar value.
virtual void forwardIterator()
Forwards the local element iterator.
static ScalarType computeMeanScalarValue(GenericCloud *theCloud)
Computes the mean value of a scalar field associated to a cloud.
__host__ __device__ int2 abs(int2 v)
Definition: cutil_math.h:1267
Generic file read and write utility for python interface.