GradientAnisotropic3.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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.2020.01.11
  7. #pragma once
  8. #include <Mathematics/PdeFilter3.h>
  9. #include <Mathematics/Math.h>
  10. namespace WwiseGTE
  11. {
  12. template <typename Real>
  13. class GradientAnisotropic3 : public PdeFilter3<Real>
  14. {
  15. public:
  16. GradientAnisotropic3(int xBound, int yBound, int zBound, Real xSpacing,
  17. Real ySpacing, Real zSpacing, Real const* data, bool const* mask,
  18. Real borderValue, typename PdeFilter<Real>::ScaleType scaleType, Real K)
  19. :
  20. PdeFilter3<Real>(xBound, yBound, zBound, xSpacing, ySpacing, zSpacing,
  21. data, mask, borderValue, scaleType),
  22. mK(K)
  23. {
  24. ComputeParameter();
  25. }
  26. virtual ~GradientAnisotropic3()
  27. {
  28. }
  29. protected:
  30. void ComputeParameter()
  31. {
  32. Real gradMagSqr = (Real)0;
  33. for (int z = 1; z <= this->mZBound; ++z)
  34. {
  35. for (int y = 1; y <= this->mYBound; ++y)
  36. {
  37. for (int x = 1; x <= this->mXBound; ++x)
  38. {
  39. Real ux = this->GetUx(x, y, z);
  40. Real uy = this->GetUy(x, y, z);
  41. Real uz = this->GetUz(x, y, z);
  42. gradMagSqr += ux * ux + uy * uy + uz * uz;
  43. }
  44. }
  45. }
  46. gradMagSqr /= (Real)this->mQuantity;
  47. mParameter = (Real)1 / (mK * mK * gradMagSqr);
  48. mMHalfParameter = (Real)-0.5 * mParameter;
  49. }
  50. virtual void OnPreUpdate() override
  51. {
  52. ComputeParameter();
  53. }
  54. virtual void OnUpdateSingle(int x, int y, int z) override
  55. {
  56. this->LookUp27(x, y, z);
  57. // one-sided U-derivative estimates
  58. Real uxFwd = this->mInvDx * (this->mUpzz - this->mUzzz);
  59. Real uxBwd = this->mInvDx * (this->mUzzz - this->mUmzz);
  60. Real uyFwd = this->mInvDy * (this->mUzpz - this->mUzzz);
  61. Real uyBwd = this->mInvDy * (this->mUzzz - this->mUzmz);
  62. Real uzFwd = this->mInvDz * (this->mUzzp - this->mUzzz);
  63. Real uzBwd = this->mInvDz * (this->mUzzz - this->mUzzm);
  64. // centered U-derivative estimates
  65. Real duvzz = this->mHalfInvDx * (this->mUpzz - this->mUmzz);
  66. Real duvpz = this->mHalfInvDx * (this->mUppz - this->mUmpz);
  67. Real duvmz = this->mHalfInvDx * (this->mUpmz - this->mUmmz);
  68. Real duvzp = this->mHalfInvDx * (this->mUpzp - this->mUmzp);
  69. Real duvzm = this->mHalfInvDx * (this->mUpzm - this->mUmzm);
  70. Real duzvz = this->mHalfInvDy * (this->mUzpz - this->mUzmz);
  71. Real dupvz = this->mHalfInvDy * (this->mUppz - this->mUpmz);
  72. Real dumvz = this->mHalfInvDy * (this->mUmpz - this->mUmmz);
  73. Real duzvp = this->mHalfInvDy * (this->mUzpp - this->mUzmp);
  74. Real duzvm = this->mHalfInvDy * (this->mUzpm - this->mUzmm);
  75. Real duzzv = this->mHalfInvDz * (this->mUzzp - this->mUzzm);
  76. Real dupzv = this->mHalfInvDz * (this->mUpzp - this->mUpzm);
  77. Real dumzv = this->mHalfInvDz * (this->mUmzp - this->mUmzm);
  78. Real duzpv = this->mHalfInvDz * (this->mUzpp - this->mUzpm);
  79. Real duzmv = this->mHalfInvDz * (this->mUzmp - this->mUzmm);
  80. Real uxCenSqr = duvzz * duvzz;
  81. Real uyCenSqr = duzvz * duzvz;
  82. Real uzCenSqr = duzzv * duzzv;
  83. Real uxEst, uyEst, uzEst, gradMagSqr;
  84. // estimate for C(x+1,y,z)
  85. uyEst = (Real)0.5 *(duzvz + dupvz);
  86. uzEst = (Real)0.5 *(duzzv + dupzv);
  87. gradMagSqr = uxCenSqr + uyEst * uyEst + uzEst * uzEst;
  88. Real cxp = std::exp(mMHalfParameter * gradMagSqr);
  89. // estimate for C(x-1,y,z)
  90. uyEst = (Real)0.5 *(duzvz + dumvz);
  91. uzEst = (Real)0.5 *(duzzv + dumzv);
  92. gradMagSqr = uxCenSqr + uyEst * uyEst + uzEst * uzEst;
  93. Real cxm = std::exp(mMHalfParameter * gradMagSqr);
  94. // estimate for C(x,y+1,z)
  95. uxEst = (Real)0.5 *(duvzz + duvpz);
  96. uzEst = (Real)0.5 *(duzzv + duzpv);
  97. gradMagSqr = uxEst * uxEst + uyCenSqr + uzEst * uzEst;
  98. Real cyp = std::exp(mMHalfParameter * gradMagSqr);
  99. // estimate for C(x,y-1,z)
  100. uxEst = (Real)0.5 *(duvzz + duvmz);
  101. uzEst = (Real)0.5 *(duzzv + duzmv);
  102. gradMagSqr = uxEst * uxEst + uyCenSqr + uzEst * uzEst;
  103. Real cym = std::exp(mMHalfParameter * gradMagSqr);
  104. // estimate for C(x,y,z+1)
  105. uxEst = (Real)0.5 *(duvzz + duvzp);
  106. uyEst = (Real)0.5 *(duzvz + duzvp);
  107. gradMagSqr = uxEst * uxEst + uyEst * uyEst + uzCenSqr;
  108. Real czp = std::exp(mMHalfParameter * gradMagSqr);
  109. // estimate for C(x,y,z-1)
  110. uxEst = (Real)0.5 *(duvzz + duvzm);
  111. uyEst = (Real)0.5 *(duzvz + duzvm);
  112. gradMagSqr = uxEst * uxEst + uyEst * uyEst + uzCenSqr;
  113. Real czm = std::exp(mMHalfParameter * gradMagSqr);
  114. this->mBuffer[this->mDst][z][y][x] = this->mUzzz + this->mTimeStep * (
  115. cxp * uxFwd - cxm * uxBwd +
  116. cyp * uyFwd - cym * uyBwd +
  117. czp * uzFwd - czm * uzBwd);
  118. }
  119. // These are updated on each iteration, since they depend on the
  120. // current average of the squared length of the gradients at the
  121. // voxels.
  122. Real mK; // k
  123. Real mParameter; // 1/(k^2*average(gradMagSqr))
  124. Real mMHalfParameter; // -0.5*mParameter
  125. };
  126. }