FastMarch.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/MinHeap.h>
  9. #include <limits>
  10. // The topic of fast marching methods are discussed in the book
  11. // Level Set Methods and Fast Marching Methods:
  12. // Evolving Interfaces in Computational Geometry, Fluid Mechanics,
  13. // Computer Vision, and Materials Science
  14. // J.A. Sethian,
  15. // Cambridge University Press, 1999
  16. namespace WwiseGTE
  17. {
  18. template <typename Real>
  19. class FastMarch
  20. {
  21. // Abstract base class.
  22. public:
  23. virtual ~FastMarch()
  24. {
  25. }
  26. protected:
  27. // The seed points have a crossing time of 0. As the iterations
  28. // occur, some of the non-seed points are visited by the moving
  29. // front. Define maxReal to be std::numeric_limits<Real>::max().
  30. // The valid crossing times are 0 <= t < maxReal. A value of
  31. // maxReal indicates the pixel has not yet been reached by the
  32. // moving front. If the speed value at a pixel is 0, the pixel
  33. // is marked with a time of -maxReal. Such pixels can never be
  34. // visited; the minus sign distinguishes these from pixels not yet
  35. // reached during iteration.
  36. //
  37. // Trial pixels are identified by having min-heap records
  38. // associated with them. Known or far pixels have no associated
  39. // record.
  40. //
  41. // The speeds must be nonnegative and are inverted because the
  42. // reciprocals are all that are needed in the numerical method.
  43. FastMarch(size_t quantity, std::vector<size_t> const& seeds, std::vector<Real> const& speeds)
  44. :
  45. mQuantity(quantity),
  46. mTimes(quantity, std::numeric_limits<Real>::max()),
  47. mInvSpeeds(quantity),
  48. mHeap(static_cast<int>(quantity)),
  49. mTrials(quantity, nullptr)
  50. {
  51. for (auto seed : seeds)
  52. {
  53. mTimes[seed] = (Real)0;
  54. }
  55. for (size_t i = 0; i < mQuantity; ++i)
  56. {
  57. if (speeds[i] > (Real)0)
  58. {
  59. mInvSpeeds[i] = (Real)1 / speeds[i];
  60. }
  61. else
  62. {
  63. mInvSpeeds[i] = std::numeric_limits<Real>::max();
  64. mTimes[i] = -std::numeric_limits<Real>::max();
  65. }
  66. }
  67. }
  68. FastMarch(size_t quantity, std::vector<size_t> const& seeds, Real speed)
  69. :
  70. mQuantity(quantity),
  71. mTimes(quantity, std::numeric_limits<Real>::max()),
  72. mInvSpeeds(quantity, (Real)1 / speed),
  73. mHeap(static_cast<int>(quantity)),
  74. mTrials(quantity, nullptr)
  75. {
  76. for (auto seed : seeds)
  77. {
  78. mTimes[seed] = (Real)0;
  79. }
  80. }
  81. public:
  82. // Member access.
  83. inline size_t GetQuantity() const
  84. {
  85. return mQuantity;
  86. }
  87. inline void SetTime(size_t i, Real time)
  88. {
  89. mTimes[i] = time;
  90. }
  91. inline Real GetTime(size_t i) const
  92. {
  93. return mTimes[i];
  94. }
  95. void GetTimeExtremes(Real& minValue, Real& maxValue) const
  96. {
  97. minValue = std::numeric_limits<Real>::max();
  98. maxValue = -std::numeric_limits<Real>::max();
  99. size_t i;
  100. for (i = 0; i < mQuantity; ++i)
  101. {
  102. if (IsValid(i))
  103. {
  104. minValue = mTimes[i];
  105. maxValue = minValue;
  106. break;
  107. }
  108. }
  109. // Assert: At least one time must be valid, in which case
  110. // i < mQuantity at this point. If all times are invalid,
  111. // minValue = +maxReal and maxValue = -maxReal on exit.
  112. for (/**/; i < mQuantity; ++i)
  113. {
  114. if (IsValid(i))
  115. {
  116. if (mTimes[i] < minValue)
  117. {
  118. minValue = mTimes[i];
  119. }
  120. else if (mTimes[i] > maxValue)
  121. {
  122. maxValue = mTimes[i];
  123. }
  124. }
  125. }
  126. }
  127. // Image element classification.
  128. inline bool IsValid(size_t i) const
  129. {
  130. return (Real)0 <= mTimes[i] && mTimes[i] < std::numeric_limits<Real>::max();
  131. }
  132. inline bool IsTrial(size_t i) const
  133. {
  134. return mTrials[i] != nullptr;
  135. }
  136. inline bool IsFar(size_t i) const
  137. {
  138. return mTimes[i] == std::numeric_limits<Real>::max();
  139. }
  140. inline bool IsZeroSpeed(size_t i) const
  141. {
  142. return mTimes[i] == -std::numeric_limits<Real>::max();
  143. }
  144. inline bool IsInterior(size_t i) const
  145. {
  146. return IsValid(i) && !IsTrial(i);
  147. }
  148. void GetInterior(std::vector<size_t>& interior) const
  149. {
  150. interior.clear();
  151. for (size_t i = 0; i < mQuantity; ++i)
  152. {
  153. if (IsValid(i) && !IsTrial(i))
  154. {
  155. interior.push_back(i);
  156. }
  157. }
  158. }
  159. virtual void GetBoundary(std::vector<size_t>& boundary) const = 0;
  160. virtual bool IsBoundary(size_t i) const = 0;
  161. // Run one step of the fast marching algorithm.
  162. virtual void Iterate() = 0;
  163. protected:
  164. size_t mQuantity;
  165. std::vector<Real> mTimes;
  166. std::vector<Real> mInvSpeeds;
  167. MinHeap<size_t, Real> mHeap;
  168. std::vector<typename MinHeap<size_t, Real>::Record*> mTrials;
  169. };
  170. }