Example of the Heat Laplace Operator.
#include <DGtal/helpers/StdDefs.h>
#include <DGtal/topology/DigitalSurface.h>
#include <DGtal/topology/DigitalSetBoundary.h>
#include <DGtal/topology/SetOfSurfels.h>
#include <DGtal/topology/LightImplicitDigitalSurface.h>
#include <DGtal/math/linalg/EigenSupport.h>
#include <DGtal/dec/DiscreteExteriorCalculus.h>
#include <DGtal/dec/DiscreteExteriorCalculusFactory.h>
#include <DGtal/dec/DiscreteExteriorCalculusSolver.h>
#include <DGtal/dec/VectorField.h>
#include <DGtal/geometry/surfaces/estimation/LocalEstimatorFromSurfelFunctorAdapter.h>
#include <DGtal/geometry/surfaces/estimation/IIGeometricFunctors.h>
#include <DGtal/geometry/surfaces/estimation/IntegralInvariantCovarianceEstimator.h>
#include <DGtal/io/readers/GenericReader.h>
#include <DGtal/io/colormaps/ColorBrightnessColorMap.h>
#include <DGtal/io/colormaps/TickedColorMap.h>
#include "DGtal/io/readers/GenericReader.h"
#include <DGtal/images/IntervalForegroundPredicate.h>
#include <DGtal/images/imagesSetsUtils/SetFromImage.h>
#include <DGtal/shapes/parametric/Ball3D.h>
#include <DGtal/shapes/Shapes.h>
#include <DGtal/shapes/GaussDigitizer.h>
struct Options
{
double h;
double normal_radius;
double convolution_radius;
};
using namespace Eigen;
{
return RealPoint( a.norm(), atan2( a[1], a[0] ), acos( a[2] ) );
}
std::function<double(
const RealPoint&)> xx_function =
{
return p_sphere[0] * p_sphere[0];
};
std::function<double(
const RealPoint&)> xx_derivative =
{
return 2. * cos( p_s[1] ) * cos( p_s[1] ) * ( 2 * cos( p_s[2] ) * cos( p_s[2] ) - sin( p_s[2] ) * sin( p_s[2] ) )
+ 2. * ( sin( p_s[1] ) * sin( p_s[1] ) - cos( p_s[1] ) * cos( p_s[1] ) );
};
template <typename Shape>
void convergence(
const Options& options,
Shape& shape,
const std::function<
double(
const RealPoint&) >& input_function,
const std::function<
double(
const RealPoint&) >& result_function)
{
typedef GaussDigitizer<Z3i::Space, Shape> Digitizer;
Digitizer digitizer;
digitizer.attach(shape);
digitizer.init(shape.getLowerBound() +
Z3i::Vector(-1,-1,-1), shape.getUpperBound() +
Z3i::Vector(1,1,1), options.h);
bool ok = kspace.init(
domain.lowerBound(),
domain.upperBound(),
true);
if( !ok ) std::cerr << "KSpace init failed" << std::endl;
typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
MySurfelAdjacency surfAdj( true );
MySetOfSurfels theSetOfSurfels( kspace, surfAdj );
kspace, digitizer,
trace.
info() <<
"Digital Surface has " << digSurf.size() <<
" surfels." << std::endl;
typedef CanonicSCellEmbedder<KSpace> CanonicSCellEmbedder;
CanonicSCellEmbedder canonicSCellEmbedder(kspace);
typedef functors::IINormalDirectionFunctor<Space> MyIINormalFunctor;
typedef IntegralInvariantCovarianceEstimator<KSpace, Digitizer, MyIINormalFunctor> MyIINormalEstimator;
const double radius = options.normal_radius * pow(options.h, 1. / 3.);
MyIINormalFunctor normalFunctor;
normalFunctor.init(options.h, radius);
MyIINormalEstimator normalEstimator(normalFunctor);
normalEstimator.attach(kspace, digitizer);
normalEstimator.setParams(radius / options.h);
normalEstimator.init(options.h, digSurf.begin(), digSurf.end());
typedef DiscreteExteriorCalculus<2, 3, EigenLinearAlgebraBackend> Calculus;
typedef DiscreteExteriorCalculusFactory<EigenLinearAlgebraBackend> CalculusFactory;
const Calculus
calculus = CalculusFactory::createFromNSCells<2>(digSurf.begin(), digSurf.end(), normalEstimator, options.h);
Calculus::DualForm0 input_func(
calculus);
for(auto itb = digSurf.begin(), ite = digSurf.end(); itb != ite; itb++)
{
input_func.myContainer( i_calc ) = input_function( options.h * canonicSCellEmbedder( *itb ) );
}
const double t = options.convolution_radius * pow(options.h, 2. / 3.);
const double K = log( - log1p( t ) ) + 2.;
const Calculus::DualIdentity0 laplace =
calculus.heatLaplace<
DUAL>(options.h, t,
K);
trace.
info() <<
"Matrix has " << ((double)laplace.myContainer.nonZeros() / (double)laplace.myContainer.size() * 100.) <<
"% of non-zeros elements." << std::endl;
const Eigen::VectorXd laplace_result = (laplace * input_func).myContainer;
Eigen::VectorXd
error( digSurf.size() );
Eigen::VectorXd real_laplacian_values( digSurf.size() );
Eigen::VectorXd estimated_laplacian_values( digSurf.size() );
int i = 0;
for(auto itb = digSurf.begin(), ite = digSurf.end(); itb != ite; itb++)
{
const RealPoint p = options.h * canonicSCellEmbedder( *itb );
const double real_laplacian_value = result_function( p_normalized );
const double estimated_laplacian_value = laplace_result( i_calc );
estimated_laplacian_values(i) = estimated_laplacian_value;
real_laplacian_values(i) = real_laplacian_value;
error(i) = estimated_laplacian_value - real_laplacian_value;
++i;
}
trace.
info() <<
"Estimated Laplacian Range : " << estimated_laplacian_values.minCoeff() <<
" / " << estimated_laplacian_values.maxCoeff() << std::endl;
trace.
info() <<
"Real Laplacian Range : " << real_laplacian_values.minCoeff() <<
" / " << real_laplacian_values.maxCoeff() << std::endl;
trace.
info() <<
"h = " << options.h <<
" t = " << t <<
" K = " <<
K << std::endl;
trace.
info() <<
"Mean error = " <<
error.array().abs().mean() <<
" max error = " <<
error.array().abs().maxCoeff() << std::endl;
}
{
Options options;
options.h = 0.1;
options.normal_radius = 2.0;
options.convolution_radius = 0.1;
typedef Ball3D<Z3i::Space> Ball;
Ball ball(
Point(0.0,0.0,0.0), 1.0);
convergence<Ball>(options, ball, xx_function, xx_derivative);
return 0;
}
static void sMakeBoundary(SCellSet &aBoundary, const KSpace &aKSpace, const PointPredicate &pp, const Point &aLowerBound, const Point &aUpperBound)
void beginBlock(const std::string &keyword="")
Space::RealVector RealVector
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
MyDigitalSurface::SurfelSet SurfelSet
HyperRectDomain< Space > Domain
SpaceND< 3, Integer > Space
KhalimskySpaceND< 3, Integer > KSpace
Space::RealVector RealVector
Space::RealPoint RealPoint
DGtal is the top-level namespace which contains all DGtal functions and types.
RealPoint cartesian_to_spherical(const RealPoint3D &a)
int main(int argc, char **argv)
PointVector< 3, double > RealPoint