DGtal 1.4.0
Loading...
Searching...
No Matches
exampleHeatLaplace.cpp
1
17
24
25#include <DGtal/helpers/StdDefs.h>
26
27#include <DGtal/topology/DigitalSurface.h>
28#include <DGtal/topology/DigitalSetBoundary.h>
29#include <DGtal/topology/SetOfSurfels.h>
30#include <DGtal/topology/LightImplicitDigitalSurface.h>
31
32#include <DGtal/math/linalg/EigenSupport.h>
33
34#include <DGtal/dec/DiscreteExteriorCalculus.h>
35#include <DGtal/dec/DiscreteExteriorCalculusFactory.h>
36#include <DGtal/dec/DiscreteExteriorCalculusSolver.h>
37#include <DGtal/dec/VectorField.h>
38
39#include <DGtal/geometry/surfaces/estimation/LocalEstimatorFromSurfelFunctorAdapter.h>
40#include <DGtal/geometry/surfaces/estimation/IIGeometricFunctors.h>
41#include <DGtal/geometry/surfaces/estimation/IntegralInvariantCovarianceEstimator.h>
42
43#include <DGtal/io/readers/GenericReader.h>
44#include <DGtal/io/colormaps/ColorBrightnessColorMap.h>
45#include <DGtal/io/colormaps/TickedColorMap.h>
46#include "DGtal/io/readers/GenericReader.h"
47
48#include <DGtal/images/IntervalForegroundPredicate.h>
49#include <DGtal/images/imagesSetsUtils/SetFromImage.h>
50
51#include <DGtal/shapes/parametric/Ball3D.h>
52#include <DGtal/shapes/Shapes.h>
53#include <DGtal/shapes/GaussDigitizer.h>
54
55struct Options
56{
57 double h;
58 double normal_radius;
59 double convolution_radius;
60};
61
63
64using namespace DGtal;
65using namespace Eigen;
66
68
69typedef Z3i::Space Space;
72typedef Z3i::Point Point;
73
75
76RealPoint cartesian_to_spherical( const RealPoint& a )
77{
78 return RealPoint( a.norm(), atan2( a[1], a[0] ), acos( a[2] ) );
79}
80
82std::function<double(const RealPoint&)> xx_function =
83 [] ( const RealPoint& p )
84{
85 const RealPoint p_sphere = p / p.norm();
86 return p_sphere[0] * p_sphere[0];
87};
88
89std::function<double(const RealPoint&)> xx_derivative =
90 [] ( const RealPoint& p )
91{
92 const RealPoint p_s = cartesian_to_spherical( p );
93 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] ) )
94 + 2. * ( sin( p_s[1] ) * sin( p_s[1] ) - cos( p_s[1] ) * cos( p_s[1] ) );
95};
97
98template <typename Shape>
99void convergence(const Options& options, Shape& shape,
100 const std::function< double(const RealPoint&) >& input_function,
101 const std::function< double(const RealPoint&) >& result_function)
102{
103 trace.beginBlock("Laplacian 3D");
104
105 trace.beginBlock("Extracting Digital Surface");
106
107 typedef Z3i::KSpace KSpace;
108
110 typedef GaussDigitizer<Z3i::Space, Shape> Digitizer;
111
112 Digitizer digitizer;
113 digitizer.attach(shape);
114 digitizer.init(shape.getLowerBound() + Z3i::Vector(-1,-1,-1), shape.getUpperBound() + Z3i::Vector(1,1,1), options.h);
115
116 Z3i::Domain domain = digitizer.getDomain();
117
118 Z3i::KSpace kspace;
119 bool ok = kspace.init(domain.lowerBound(), domain.upperBound(), true);
120 if( !ok ) std::cerr << "KSpace init failed" << std::endl;
121
123 typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
125 typedef SurfelAdjacency<KSpace::dimension> MySurfelAdjacency;
126
127 MySurfelAdjacency surfAdj( true ); // interior in all directions.
128 MySetOfSurfels theSetOfSurfels( kspace, surfAdj );
129 Surfaces<KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
130 kspace, digitizer,
132 domain.upperBound() );
133 MyDigitalSurface digSurf( theSetOfSurfels );
135 trace.info() << "Digital Surface has " << digSurf.size() << " surfels." << std::endl;
136
137 trace.endBlock();
138
139 trace.beginBlock("Initializing Normal Functor");
142 CanonicSCellEmbedder canonicSCellEmbedder(kspace);
143
144 typedef functors::IINormalDirectionFunctor<Space> MyIINormalFunctor;
146
147 const double radius = options.normal_radius * pow(options.h, 1. / 3.);
148
149 MyIINormalFunctor normalFunctor;
150 normalFunctor.init(options.h, radius);
151
152 MyIINormalEstimator normalEstimator(normalFunctor);
153 normalEstimator.attach(kspace, digitizer);
154 normalEstimator.setParams(radius / options.h);
155
156 normalEstimator.init(options.h, digSurf.begin(), digSurf.end());
158 trace.endBlock();
159
160 trace.beginBlock("Initializing DEC");
164
165 const Calculus calculus = CalculusFactory::createFromNSCells<2>(digSurf.begin(), digSurf.end(), normalEstimator, options.h);
167 trace.info() << calculus << std::endl;
168
169 trace.endBlock();
170 trace.beginBlock("Computing the input function");
172 Calculus::DualForm0 input_func(calculus);
173
174 for(auto itb = digSurf.begin(), ite = digSurf.end(); itb != ite; itb++)
175 {
176 const Calculus::Index i_calc = calculus.getCellIndex( kspace.unsigns( *itb ) );
177 input_func.myContainer( i_calc ) = input_function( options.h * canonicSCellEmbedder( *itb ) );
178 }
180 trace.endBlock();
181
182 trace.beginBlock("Computing the Laplace operator");
184 const double t = options.convolution_radius * pow(options.h, 2. / 3.);
185 const double K = log( - log1p( t ) ) + 2.;
186 const Calculus::DualIdentity0 laplace = calculus.heatLaplace<DUAL>(options.h, t, K);
188 trace.info() << "Matrix has " << ((double)laplace.myContainer.nonZeros() / (double)laplace.myContainer.size() * 100.) << "% of non-zeros elements." << std::endl;
189 trace.endBlock();
190
192 const Eigen::VectorXd laplace_result = (laplace * input_func).myContainer;
194 Eigen::VectorXd error( digSurf.size() );
195 Eigen::VectorXd real_laplacian_values( digSurf.size() );
196 Eigen::VectorXd estimated_laplacian_values( digSurf.size() );
197
198 int i = 0;
199 for(auto itb = digSurf.begin(), ite = digSurf.end(); itb != ite; itb++)
200 {
201 const Calculus::Index i_calc = calculus.getCellIndex( kspace.unsigns( *itb ) );
202
203 const RealPoint p = options.h * canonicSCellEmbedder( *itb );
204 const RealPoint p_normalized = p / p.norm();
205 const RealPoint p_s = cartesian_to_spherical( p );
206
207 const double real_laplacian_value = result_function( p_normalized );
208 const double estimated_laplacian_value = laplace_result( i_calc );
209
210 estimated_laplacian_values(i) = estimated_laplacian_value;
211 real_laplacian_values(i) = real_laplacian_value;
212
213 error(i) = estimated_laplacian_value - real_laplacian_value;
214
215 ++i;
216 }
217
218 trace.info() << "Estimated Laplacian Range : " << estimated_laplacian_values.minCoeff() << " / " << estimated_laplacian_values.maxCoeff() << std::endl;
219 trace.info() << "Real Laplacian Range : " << real_laplacian_values.minCoeff() << " / " << real_laplacian_values.maxCoeff() << std::endl;
220
221 trace.info() << "h = " << options.h << " t = " << t << " K = " << K << std::endl;
222 trace.info() << "Mean error = " << error.array().abs().mean() << " max error = " << error.array().abs().maxCoeff() << std::endl;
223
224 trace.endBlock();
225}
226
227int main()
228{
229 Options options;
230
231 options.h = 0.1;
232 options.normal_radius = 2.0;
233 options.convolution_radius = 0.1;
234
235 typedef Ball3D<Z3i::Space> Ball;
236 Ball ball(Point(0.0,0.0,0.0), 1.0);
237
238 std::function<double(const RealPoint&, const RealPoint&)> l2_distance =
239 [](const RealPoint& a, const RealPoint& b) { return (a - b).norm(); };
240
241 convergence<Ball>(options, ball, xx_function, xx_derivative);
242
243 return 0;
244}
RealPoint getLowerBound() const
Definition Astroid2D.h:122
RealPoint getUpperBound() const
Definition Astroid2D.h:131
Aim: Model of the concept StarShaped3D represents any Sphere in the space.
Definition Ball3D.h:61
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Aim: This class provides static members to create DEC structures from various other DGtal structures.
Aim: DiscreteExteriorCalculus represents a calculus in the dec package. This is the main structure in...
Aim: A class for computing the Gauss digitization of some Euclidean shape, i.e. its intersection with...
void attach(ConstAlias< EuclideanShape > shape)
const Point & lowerBound() const
const Point & upperBound() const
Aim: This class implement an Integral Invariant estimator which computes for each surfel the covarian...
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
std::set< SCell > SurfelSet
Preferred type for defining a set of surfels (always signed cells).
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
Cell unsigns(const SCell &p) const
Creates an unsigned cell from a signed one.
Aim: Implements basic operations that will be used in Point and Vector classes.
double norm(const NormType type=L_2) const
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as connected surfels....
static void sMakeBoundary(SCellSet &aBoundary, const KSpace &aKSpace, const PointPredicate &pp, const Point &aLowerBound, const Point &aUpperBound)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
void beginBlock(const std::string &keyword="")
std::ostream & info()
double endBlock()
Aim: A functor Matrix -> RealVector that returns the normal direction by diagonalizing the given cova...
PolyCalculus * calculus
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
MyDigitalSurface::SurfelSet SurfelSet
DGtal is the top-level namespace which contains all DGtal functions and types.
Trace trace
Definition Common.h:153
@ DUAL
Definition Duality.h:62
MessageStream error
Aim: A trivial embedder for signed cell, which corresponds to the canonic injection of cell centroids...
int main(int argc, char **argv)
MyPointD Point
KSpace K
Domain domain