DGtal  1.4.beta
sphereCotangentLaplaceOperator.cpp File Reference
#include <DGtal/helpers/StdDefs.h>
#include <DGtal/base/BasicFunctors.h>
#include <DGtal/topology/DigitalSurface.h>
#include <DGtal/topology/SetOfSurfels.h>
#include <DGtal/topology/CanonicCellEmbedder.h>
#include <DGtal/topology/LightImplicitDigitalSurface.h>
#include <DGtal/io/colormaps/ColorBrightnessColorMap.h>
#include <DGtal/geometry/surfaces/estimation/LocalEstimatorFromSurfelFunctorAdapter.h>
#include <DGtal/geometry/surfaces/estimation/IIGeometricFunctors.h>
#include <DGtal/geometry/surfaces/estimation/IntegralInvariantCovarianceEstimator.h>
#include <DGtal/shapes/parametric/Ball3D.h>
#include <DGtal/shapes/Shapes.h>
#include <DGtal/shapes/GaussDigitizer.h>
#include <DGtal/shapes/Mesh.h>
#include <DGtal/shapes/MeshHelpers.h>
#include "DGtal/shapes/TriangulatedSurface.h"
#include <DGtal/io/viewers/Viewer3D.h>
#include <DGtal/math/linalg/EigenSupport.h>
Include dependency graph for sphereCotangentLaplaceOperator.cpp:

Go to the source code of this file.

Typedefs

typedef Z3i::RealVector RealVector3D
 
typedef Z3i::RealPoint RealPoint3D
 

Functions

RealPoint cartesian_to_spherical (const RealPoint3D &a)
 
template<typename Shape >
void laplacian (Shape &shape, const Options &options, std::function< double(const RealPoint3D &)> input_function, std::function< double(const RealPoint3D &)> target_function, int argc, char **argv)
 
int main (int argc, char **argv)
 

Detailed Description

This program is free software : you can redistribuate it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at you option) any later version.

This program is distributed int the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, set http://www.gnu.org/license/.

Author
Thomas Caissard (thoma.nosp@m.s.ca.nosp@m.issar.nosp@m.d@li.nosp@m.ris.c.nosp@m.nrs..nosp@m.fr ) Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), INSA-Lyon, France LAboratoire de MAthématiques - LAMA (CNRS, UMR 5127), Université de Savoie, France
Date
2017/06/20

An example file named exampleTriangulatedSurface.

This file is part of the DGtal library.

Definition in file sphereCotangentLaplaceOperator.cpp.

Typedef Documentation

◆ RealPoint3D

Definition at line 70 of file sphereCotangentLaplaceOperator.cpp.

◆ RealVector3D

Function Documentation

◆ cartesian_to_spherical()

RealPoint cartesian_to_spherical ( const RealPoint3D a)
Examples
dec/exampleHeatLaplace.cpp.

Definition at line 72 of file sphereCotangentLaplaceOperator.cpp.

73 {
74  return RealPoint3D(a.norm(), atan2(a[1], a[0]), acos(a[2]));
75 }
Z3i::RealPoint RealPoint3D

Referenced by laplacian(), and main().

◆ laplacian()

template<typename Shape >
void laplacian ( Shape shape,
const Options &  options,
std::function< double(const RealPoint3D &)>  input_function,
std::function< double(const RealPoint3D &)>  target_function,
int  argc,
char **  argv 
)

Definition at line 87 of file sphereCotangentLaplaceOperator.cpp.

91 {
92  trace.beginBlock("Laplacian");
93  typedef GaussDigitizer<Z3i::Space, Shape> Digitizer;
94 
95  trace.beginBlock("Digitizing the shape");
96  Digitizer digitizer;
97  digitizer.attach(shape);
98  digitizer.init(shape.getLowerBound() + Z3i::Vector(-1,-1,-1), shape.getUpperBound() + Z3i::Vector(1,1,1), options.h);
99 
100  Z3i::Domain domain = digitizer.getDomain();
101  trace.endBlock();
102 
103  trace.beginBlock( "Construct the Khalimsky space from the image domain." );
104  Z3i::KSpace kspace;
105  bool space_ok = kspace.init( domain.lowerBound(),
106  domain.upperBound(), true );
107  if (!space_ok)
108  {
109  trace.error() << "Error in the Khamisky space construction."<<std::endl;
110  return;
111  }
112  trace.endBlock();
113 
114  trace.beginBlock( "Extracting boundary by scanning the space. " );
115 
116  typedef SurfelAdjacency<Z3i::KSpace::dimension> MySurfelAdjacency;
117  MySurfelAdjacency surfAdj( true ); // interior in all directions.
118 
120  typedef SetOfSurfels< KSpace, SurfelSet > MySetOfSurfels;
122  MySetOfSurfels theSetOfSurfels( kspace, surfAdj );
123  Surfaces<Z3i::KSpace>::sMakeBoundary( theSetOfSurfels.surfelSet(),
124  kspace, digitizer,
125  domain.lowerBound(),
126  domain.upperBound() );
127  MyDigitalSurface digSurf( theSetOfSurfels );
128  trace.info() << "Digital surface has " << digSurf.size() << " surfels."
129  << std::endl;
130  trace.endBlock();
131 
132  trace.beginBlock( "Making triangulated surface. " );
135  typedef std::map< MyDigitalSurface::Vertex, TriMesh::Index > VertexMap;
136  TriMesh trimesh;
137  CanonicCellEmbedder canonicCellembedder(kspace);
138 
139  VertexMap vmap; // stores the map Vertex -> Index
140  MeshHelpers::digitalSurface2DualTriangulatedSurface
141  ( digSurf, canonicCellembedder, trimesh, vmap );
142 
143  trace.info() << "Triangulated surface is " << trimesh << std::endl;
144 
145  trace.endBlock();
146  trace.beginBlock("Computing Laplacian");
149 
150  //Grid scaling factor and sphere projection
151  for(auto v : vertices)
152  {
153  trimesh.position( v ) *= options.h;
154  if(options.smooth == 1)
155  trimesh.position( v ) /= trimesh.position( v ).norm();
156  }
157 
158  std::ofstream error_out(options.error_output, std::ofstream::app);
159  std::ofstream function_out("function.dat");
160 
161  Eigen::VectorXd laplacian_result( trimesh.nbVertices() );
162  Eigen::VectorXd error( trimesh.nbVertices() );
163  Eigen::VectorXd error_faces( trimesh.nbFaces() );
164  int i = 0;
165  double total_area = 0.;
166 
167  // Iteration over all vertices
168  for(auto v : vertices)
169  {
170  const RealPoint3D p_i = trimesh.position(v);
171  const TriangulatedSurface::ArcRange out_arcs = trimesh.outArcs(v);
172  double accum = 0.;
173 
174  // We compute here \Delta f(p_i) by iteration over arcs going out from p_i
175  for(auto a : out_arcs)
176  {
177  // The point p_i -----> p_j
178  const RealPoint3D p_j = trimesh.position( trimesh.head(a) );
179 
180  const TriangulatedSurface::Arc next_left_arc = trimesh.next( a );
181  const TriangulatedSurface::Arc next_right_arc = trimesh.next( trimesh.opposite(a) );
182 
183  // Three points of the left triangle
184  const RealPoint3D p1 = p_j;
185  const RealPoint3D p2 = trimesh.position( trimesh.head( next_left_arc ) );
186  const RealPoint3D p3 = p_i;
187 
188  // Three points of the right triangle
189  const RealPoint3D pp1 = p_j;
190  const RealPoint3D pp2 = trimesh.position(trimesh.head( next_right_arc ));
191  const RealPoint3D pp3 = p_i;
192 
193  // Left and right angles
194  const RealPoint3D v1 = (p1 - p2) / (p1 - p2).norm();
195  const RealPoint3D v2 = (p3 - p2) / (p3 - p2).norm();
196  const RealPoint3D vv1 = (pp1 - pp2) / (pp1 - pp2).norm();
197  const RealPoint3D vv2 = (pp3 - pp2) / (pp3 - pp2).norm();
198 
199  const double alpha = acos( v1.dot(v2) );
200  const double beta = acos( vv1.dot(vv2) );
201 
202  // Cotan accumulator
203  accum += (tan(M_PI_2 - alpha) + tan(M_PI_2 - beta)) * (input_function(p_j) - input_function(p_i));
204  }
205 
206  double accum_area = 0.;
207  const TriangulatedSurface::FaceRange faces_around = trimesh.facesAroundVertex( v );
208  for(auto f : faces_around)
209  {
211  RealPoint3D p = trimesh.position(vr[0]);
212  RealPoint3D q = trimesh.position(vr[1]);
213  RealPoint3D r = trimesh.position(vr[2]);
214 
215  const RealPoint3D cross = (r - p).crossProduct(r - q);
216  const double faceArea = .5 * cross.norm();
217 
218  accum_area += faceArea / 3.;
219  }
220 
221  total_area += accum_area;
222 
223  (options.smooth == 1)
224  ? laplacian_result(i) = (1 / (2. * accum_area)) * accum
225  : laplacian_result(i) = .5 * accum;
226 
227  const RealPoint3D w_projected = p_i / p_i.norm();
228  const double real_laplacian_value = target_function(w_projected);
229 
230  const RealPoint3D w_s = cartesian_to_spherical(w_projected);
231 
232  function_out << w_s[1] << " "
233  << w_s[2] << " "
234  << laplacian_result(i) << " "
235  << real_laplacian_value << " "
236  << input_function(p_i) << std::endl;
237 
238  error(i) = laplacian_result(i) - real_laplacian_value;
239  for(auto f : faces_around)
240  error_faces( f ) += error(i) / faces_around.size();
241 
242  i++;
243  }
244 
245  int max_index;
246 
247  trace.info() << "Computed Area / Real Area : " << total_area << " " << 4 * M_PI << std::endl;
248  trace.info() << "Mean Error / Max Error : "
249  << error.array().abs().mean() << " / " << error.array().abs().maxCoeff(&max_index) << std::endl;
250  error_out << options.h << " "
251  << error.array().abs().mean() << " "
252  << error.array().abs().maxCoeff() << std::endl;
253 
254  trace.endBlock();
255 
256  typedef Mesh< CanonicCellEmbedder::Value > ViewMesh;
257  ViewMesh viewmesh;
258  MeshHelpers::triangulatedSurface2Mesh( trimesh, viewmesh );
259  trace.info() << "Mesh has " << viewmesh.nbVertex()
260  << " vertices and " << viewmesh.nbFaces() << " faces." << std::endl;
261 
262  DGtal::ColorBrightnessColorMap<float> colormap_error(error_faces.minCoeff(), error_faces.maxCoeff(), DGtal::Color::Red);
263  for(unsigned int k = 0; k < viewmesh.nbFaces(); k++)
264  viewmesh.setFaceColor(k, colormap_error( error_faces(k) ));
265 
266  QApplication application(argc,argv);
267  Viewer3D<> viewer;
268  viewer.show();
269  viewer << viewmesh;
270  viewer << Viewer3D<>::updateDisplay;
271  application.exec();
272 
273  trace.endBlock();
274 }
RealPoint getLowerBound() const
Definition: Astroid2D.h:122
RealPoint getUpperBound() const
Definition: Astroid2D.h:131
Aim: This class template may be used to (linearly) convert scalar values in a given range into a colo...
static const Color Red
Definition: Color.h:416
Aim: Represents a set of n-1-cells in a nD space, together with adjacency relation between these cell...
Aim: A class for computing the Gauss digitization of some Euclidean shape, i.e. its intersection with...
const Point & lowerBound() const
const Point & upperBound() const
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.
Aim: This class is defined to represent a surface mesh through a set of vertices and faces....
Definition: Mesh.h:92
auto dot(const PointVector< dim, OtherComponent, OtherStorage > &v) const -> decltype(DGtal::dotProduct(*this, v))
Dot product with a PointVector.
double norm(const NormType type=L_2) const
Aim: A model of CDigitalSurfaceContainer which defines the digital surface as connected surfels....
Definition: SetOfSurfels.h:74
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:79
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
std::ostream & error()
void beginBlock(const std::string &keyword="")
std::ostream & info()
double endBlock()
Aim: Represents a triangulated surface. The topology is stored with a half-edge data structure....
HalfEdgeDataStructure::HalfEdgeIndex Arc
std::vector< Vertex > VertexRange
Vertex head(const Arc &a) const
FaceRange facesAroundVertex(const Vertex &v) const
Point & position(Vertex v)
Arc opposite(const Arc &a) const
VertexRange allVertices() const
Arc next(const Arc &a) const
ArcRange outArcs(const Vertex &v) const
VertexRange verticesAroundFace(const Face &f) const
virtual void show()
Overload QWidget method in order to add a call to updateList() method (to ensure that the lists are w...
DigitalSurface< MyDigitalSurfaceContainer > MyDigitalSurface
MyDigitalSurface::SurfelSet SurfelSet
auto crossProduct(PointVector< 3, LeftEuclideanRing, LeftContainer > const &lhs, PointVector< 3, RightEuclideanRing, RightContainer > const &rhs) -> decltype(DGtal::constructFromArithmeticConversion(lhs, rhs))
Cross product of two 3D Points/Vectors.
Trace trace
Definition: Common.h:153
MessageStream error
std::pair< typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator, typename graph_traits< DGtal::DigitalSurface< TDigitalSurfaceContainer > >::vertex_iterator > vertices(const DGtal::DigitalSurface< TDigitalSurfaceContainer > &digSurf)
RealPoint cartesian_to_spherical(const RealPoint3D &a)
Aim: A trivial embedder for signed and unsigned cell, which corresponds to the canonic injection of c...
Domain domain
TriangulatedSurface< RealPoint > TriMesh

References DGtal::TriangulatedSurface< TPoint >::allVertices(), DGtal::Trace::beginBlock(), cartesian_to_spherical(), DGtal::crossProduct(), domain, DGtal::PointVector< dim, TEuclideanRing, TContainer >::dot(), DGtal::Trace::endBlock(), DGtal::Trace::error(), DGtal::TriangulatedSurface< TPoint >::facesAroundVertex(), DGtal::Astroid2D< TSpace >::getLowerBound(), DGtal::Astroid2D< TSpace >::getUpperBound(), DGtal::TriangulatedSurface< TPoint >::head(), DGtal::Trace::info(), DGtal::KhalimskySpaceND< dim, TInteger >::init(), DGtal::HyperRectDomain< TSpace >::lowerBound(), DGtal::TriangulatedSurface< TPoint >::nbFaces(), DGtal::TriangulatedSurface< TPoint >::nbVertices(), DGtal::TriangulatedSurface< TPoint >::next(), DGtal::PointVector< dim, TEuclideanRing, TContainer >::norm(), DGtal::TriangulatedSurface< TPoint >::opposite(), DGtal::TriangulatedSurface< TPoint >::outArcs(), DGtal::TriangulatedSurface< TPoint >::position(), DGtal::Color::Red, DGtal::Viewer3D< TSpace, TKSpace >::show(), DGtal::DigitalSurface< TDigitalSurfaceContainer >::size(), DGtal::trace, DGtal::HyperRectDomain< TSpace >::upperBound(), and DGtal::TriangulatedSurface< TPoint >::verticesAroundFace().

Referenced by DGtal::GeodesicsInHeat< TPolygonalCalculus >::init(), and DGtal::VectorsInHeat< TPolygonalCalculus >::init().

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 276 of file sphereCotangentLaplaceOperator.cpp.

277 {
278  Options options;
279  options.h = 0.1;
280  options.function = 0;
281  options.smooth = 0;
282  options.error_output = "error_out.dat";
283 
284  typedef Ball3D<Z3i::Space> Ball;
285  Ball ball(Point(0.0,0.0,0.0), 1.0);
286 
287  std::function<double(const RealPoint3D&)> xx_function = [](const RealPoint3D& p) {return p[0] * p[0];};
288  std::function<double(const RealPoint3D&)> xx_result = [](const RealPoint3D& p)
289  {
290  const RealPoint3D p_s = cartesian_to_spherical(p);
291  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]))
292  + 2 * (sin(p_s[1]) * sin(p_s[1]) - cos(p_s[1]) * cos(p_s[1]));
293  };
294 
295  std::function<double(const RealPoint3D&)> cos_function = [](const RealPoint3D& p) {return p[2];};
296  std::function<double(const RealPoint3D&)> cos_result = [](const RealPoint3D& p)
297  {
298  const RealPoint3D p_s = cartesian_to_spherical(p);
299  return - 2 * cos(p_s[2]);
300  };
301 
302  std::function<double(const RealPoint3D&)> exp_function = [](const RealPoint3D& p)
303  {
304  const RealPoint3D p_sphere = p / p.norm();
305  return exp(p_sphere[0]);
306  };
307  std::function<double(const RealPoint3D&)> exp_result = [](const RealPoint3D& p)
308  {
309  const RealPoint3D p_sphere = p / p.norm();
310  const RealPoint3D p_s = cartesian_to_spherical(p);
311 
312  if(p_s[1] == 0 && p_s[2] == 0) return 1.;
313 
314  const double theta_derivative = (sin(p_s[1]) * sin(p_s[1]) * sin(p_s[2])
315  - cos(p_s[1])) * (1 / sin(p_s[2])) * exp(p_sphere[0]);
316  const double phi_derivative = ( cos(p_s[1]) * cos(p_s[2]) * cos(p_s[2])
317  - sin(p_s[2])
318  + cos(p_s[2]) * cos(p_s[2]) / sin(p_s[2])) * cos(p_s[1]) * exp(p_sphere[0]);
319 
320  return theta_derivative + phi_derivative;
321  };
322 
323  std::function<double(const RealPoint3D&)> input_function
324  = ( options.function == 0 ) ? xx_function : ( (options.function == 1) ? cos_function : exp_function );
325  std::function<double(const RealPoint3D&)> target_function
326  = ( options.function == 0 ) ? xx_result : ( (options.function == 1) ? cos_result : exp_result );
327 
328  laplacian<Ball>(ball, options, input_function, target_function, argc, argv);
329 
330  return 0;
331 }
Aim: Model of the concept StarShaped3D represents any Sphere in the space.
Definition: Ball3D.h:61
MyPointD Point
Definition: testClone2.cpp:383

References cartesian_to_spherical(), and DGtal::PointVector< dim, TEuclideanRing, TContainer >::norm().