You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

148 lines
5.8 KiB

// David Eberly, Geometric Tools, Redmond WA 98052
// Copyright (c) 1998-2021
// 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.2020.01.11
#pragma once
#include <Mathematics/PdeFilter3.h>
#include <Mathematics/Math.h>
namespace gte
{
template <typename Real>
class GradientAnisotropic3 : public PdeFilter3<Real>
{
public:
GradientAnisotropic3(int xBound, int yBound, int zBound, Real xSpacing,
Real ySpacing, Real zSpacing, Real const* data, bool const* mask,
Real borderValue, typename PdeFilter<Real>::ScaleType scaleType, Real K)
:
PdeFilter3<Real>(xBound, yBound, zBound, xSpacing, ySpacing, zSpacing,
data, mask, borderValue, scaleType),
mK(K)
{
ComputeParameter();
}
virtual ~GradientAnisotropic3()
{
}
protected:
void ComputeParameter()
{
Real gradMagSqr = (Real)0;
for (int z = 1; z <= this->mZBound; ++z)
{
for (int y = 1; y <= this->mYBound; ++y)
{
for (int x = 1; x <= this->mXBound; ++x)
{
Real ux = this->GetUx(x, y, z);
Real uy = this->GetUy(x, y, z);
Real uz = this->GetUz(x, y, z);
gradMagSqr += ux * ux + uy * uy + uz * uz;
}
}
}
gradMagSqr /= (Real)this->mQuantity;
mParameter = (Real)1 / (mK * mK * gradMagSqr);
mMHalfParameter = (Real)-0.5 * mParameter;
}
virtual void OnPreUpdate() override
{
ComputeParameter();
}
virtual void OnUpdateSingle(int x, int y, int z) override
{
this->LookUp27(x, y, z);
// one-sided U-derivative estimates
Real uxFwd = this->mInvDx * (this->mUpzz - this->mUzzz);
Real uxBwd = this->mInvDx * (this->mUzzz - this->mUmzz);
Real uyFwd = this->mInvDy * (this->mUzpz - this->mUzzz);
Real uyBwd = this->mInvDy * (this->mUzzz - this->mUzmz);
Real uzFwd = this->mInvDz * (this->mUzzp - this->mUzzz);
Real uzBwd = this->mInvDz * (this->mUzzz - this->mUzzm);
// centered U-derivative estimates
Real duvzz = this->mHalfInvDx * (this->mUpzz - this->mUmzz);
Real duvpz = this->mHalfInvDx * (this->mUppz - this->mUmpz);
Real duvmz = this->mHalfInvDx * (this->mUpmz - this->mUmmz);
Real duvzp = this->mHalfInvDx * (this->mUpzp - this->mUmzp);
Real duvzm = this->mHalfInvDx * (this->mUpzm - this->mUmzm);
Real duzvz = this->mHalfInvDy * (this->mUzpz - this->mUzmz);
Real dupvz = this->mHalfInvDy * (this->mUppz - this->mUpmz);
Real dumvz = this->mHalfInvDy * (this->mUmpz - this->mUmmz);
Real duzvp = this->mHalfInvDy * (this->mUzpp - this->mUzmp);
Real duzvm = this->mHalfInvDy * (this->mUzpm - this->mUzmm);
Real duzzv = this->mHalfInvDz * (this->mUzzp - this->mUzzm);
Real dupzv = this->mHalfInvDz * (this->mUpzp - this->mUpzm);
Real dumzv = this->mHalfInvDz * (this->mUmzp - this->mUmzm);
Real duzpv = this->mHalfInvDz * (this->mUzpp - this->mUzpm);
Real duzmv = this->mHalfInvDz * (this->mUzmp - this->mUzmm);
Real uxCenSqr = duvzz * duvzz;
Real uyCenSqr = duzvz * duzvz;
Real uzCenSqr = duzzv * duzzv;
Real uxEst, uyEst, uzEst, gradMagSqr;
// estimate for C(x+1,y,z)
uyEst = (Real)0.5 *(duzvz + dupvz);
uzEst = (Real)0.5 *(duzzv + dupzv);
gradMagSqr = uxCenSqr + uyEst * uyEst + uzEst * uzEst;
Real cxp = std::exp(mMHalfParameter * gradMagSqr);
// estimate for C(x-1,y,z)
uyEst = (Real)0.5 *(duzvz + dumvz);
uzEst = (Real)0.5 *(duzzv + dumzv);
gradMagSqr = uxCenSqr + uyEst * uyEst + uzEst * uzEst;
Real cxm = std::exp(mMHalfParameter * gradMagSqr);
// estimate for C(x,y+1,z)
uxEst = (Real)0.5 *(duvzz + duvpz);
uzEst = (Real)0.5 *(duzzv + duzpv);
gradMagSqr = uxEst * uxEst + uyCenSqr + uzEst * uzEst;
Real cyp = std::exp(mMHalfParameter * gradMagSqr);
// estimate for C(x,y-1,z)
uxEst = (Real)0.5 *(duvzz + duvmz);
uzEst = (Real)0.5 *(duzzv + duzmv);
gradMagSqr = uxEst * uxEst + uyCenSqr + uzEst * uzEst;
Real cym = std::exp(mMHalfParameter * gradMagSqr);
// estimate for C(x,y,z+1)
uxEst = (Real)0.5 *(duvzz + duvzp);
uyEst = (Real)0.5 *(duzvz + duzvp);
gradMagSqr = uxEst * uxEst + uyEst * uyEst + uzCenSqr;
Real czp = std::exp(mMHalfParameter * gradMagSqr);
// estimate for C(x,y,z-1)
uxEst = (Real)0.5 *(duvzz + duvzm);
uyEst = (Real)0.5 *(duzvz + duzvm);
gradMagSqr = uxEst * uxEst + uyEst * uyEst + uzCenSqr;
Real czm = std::exp(mMHalfParameter * gradMagSqr);
this->mBuffer[this->mDst][z][y][x] = this->mUzzz + this->mTimeStep * (
cxp * uxFwd - cxm * uxBwd +
cyp * uyFwd - cym * uyBwd +
czp * uzFwd - czm * uzBwd);
}
// These are updated on each iteration, since they depend on the
// current average of the squared length of the gradients at the
// voxels.
Real mK; // k
Real mParameter; // 1/(k^2*average(gradMagSqr))
Real mMHalfParameter; // -0.5*mParameter
};
}