123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.08.13
- #pragma once
- #include <Mathematics/MinHeap.h>
- #include <limits>
- // The topic of fast marching methods are discussed in the book
- // Level Set Methods and Fast Marching Methods:
- // Evolving Interfaces in Computational Geometry, Fluid Mechanics,
- // Computer Vision, and Materials Science
- // J.A. Sethian,
- // Cambridge University Press, 1999
- namespace WwiseGTE
- {
- template <typename Real>
- class FastMarch
- {
- // Abstract base class.
- public:
- virtual ~FastMarch()
- {
- }
- protected:
- // The seed points have a crossing time of 0. As the iterations
- // occur, some of the non-seed points are visited by the moving
- // front. Define maxReal to be std::numeric_limits<Real>::max().
- // The valid crossing times are 0 <= t < maxReal. A value of
- // maxReal indicates the pixel has not yet been reached by the
- // moving front. If the speed value at a pixel is 0, the pixel
- // is marked with a time of -maxReal. Such pixels can never be
- // visited; the minus sign distinguishes these from pixels not yet
- // reached during iteration.
- //
- // Trial pixels are identified by having min-heap records
- // associated with them. Known or far pixels have no associated
- // record.
- //
- // The speeds must be nonnegative and are inverted because the
- // reciprocals are all that are needed in the numerical method.
- FastMarch(size_t quantity, std::vector<size_t> const& seeds, std::vector<Real> const& speeds)
- :
- mQuantity(quantity),
- mTimes(quantity, std::numeric_limits<Real>::max()),
- mInvSpeeds(quantity),
- mHeap(static_cast<int>(quantity)),
- mTrials(quantity, nullptr)
- {
- for (auto seed : seeds)
- {
- mTimes[seed] = (Real)0;
- }
- for (size_t i = 0; i < mQuantity; ++i)
- {
- if (speeds[i] > (Real)0)
- {
- mInvSpeeds[i] = (Real)1 / speeds[i];
- }
- else
- {
- mInvSpeeds[i] = std::numeric_limits<Real>::max();
- mTimes[i] = -std::numeric_limits<Real>::max();
- }
- }
- }
- FastMarch(size_t quantity, std::vector<size_t> const& seeds, Real speed)
- :
- mQuantity(quantity),
- mTimes(quantity, std::numeric_limits<Real>::max()),
- mInvSpeeds(quantity, (Real)1 / speed),
- mHeap(static_cast<int>(quantity)),
- mTrials(quantity, nullptr)
- {
- for (auto seed : seeds)
- {
- mTimes[seed] = (Real)0;
- }
- }
- public:
- // Member access.
- inline size_t GetQuantity() const
- {
- return mQuantity;
- }
- inline void SetTime(size_t i, Real time)
- {
- mTimes[i] = time;
- }
- inline Real GetTime(size_t i) const
- {
- return mTimes[i];
- }
- void GetTimeExtremes(Real& minValue, Real& maxValue) const
- {
- minValue = std::numeric_limits<Real>::max();
- maxValue = -std::numeric_limits<Real>::max();
- size_t i;
- for (i = 0; i < mQuantity; ++i)
- {
- if (IsValid(i))
- {
- minValue = mTimes[i];
- maxValue = minValue;
- break;
- }
- }
- // Assert: At least one time must be valid, in which case
- // i < mQuantity at this point. If all times are invalid,
- // minValue = +maxReal and maxValue = -maxReal on exit.
- for (/**/; i < mQuantity; ++i)
- {
- if (IsValid(i))
- {
- if (mTimes[i] < minValue)
- {
- minValue = mTimes[i];
- }
- else if (mTimes[i] > maxValue)
- {
- maxValue = mTimes[i];
- }
- }
- }
- }
- // Image element classification.
- inline bool IsValid(size_t i) const
- {
- return (Real)0 <= mTimes[i] && mTimes[i] < std::numeric_limits<Real>::max();
- }
- inline bool IsTrial(size_t i) const
- {
- return mTrials[i] != nullptr;
- }
- inline bool IsFar(size_t i) const
- {
- return mTimes[i] == std::numeric_limits<Real>::max();
- }
- inline bool IsZeroSpeed(size_t i) const
- {
- return mTimes[i] == -std::numeric_limits<Real>::max();
- }
- inline bool IsInterior(size_t i) const
- {
- return IsValid(i) && !IsTrial(i);
- }
- void GetInterior(std::vector<size_t>& interior) const
- {
- interior.clear();
- for (size_t i = 0; i < mQuantity; ++i)
- {
- if (IsValid(i) && !IsTrial(i))
- {
- interior.push_back(i);
- }
- }
- }
- virtual void GetBoundary(std::vector<size_t>& boundary) const = 0;
- virtual bool IsBoundary(size_t i) const = 0;
- // Run one step of the fast marching algorithm.
- virtual void Iterate() = 0;
- protected:
- size_t mQuantity;
- std::vector<Real> mTimes;
- std::vector<Real> mInvSpeeds;
- MinHeap<size_t, Real> mHeap;
- std::vector<typename MinHeap<size_t, Real>::Record*> mTrials;
- };
- }
|