2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU Lesser General Public License as
4 * published by the Free Software Foundation, either version 3 of the
5 * License, or (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 * @file VoronoiCovarianceMeasureOnDigitalSurface.ih
19 * @author Jacques-Olivier Lachaud (\c jacques-olivier.lachaud@univ-savoie.fr )
20 * Laboratory of Mathematics (CNRS, UMR 5127), University of Savoie, France
24 * Implementation of inline methods defined in VoronoiCovarianceMeasureOnDigitalSurface.h
26 * This file is part of the DGtal library.
30//////////////////////////////////////////////////////////////////////////////
32#include "DGtal/topology/CanonicSCellEmbedder.h"
33#include "DGtal/math/ScalarFunctors.h"
34#include "DGtal/geometry/surfaces/estimation/LocalEstimatorFromSurfelFunctorAdapter.h"
35#include "DGtal/geometry/surfaces/estimation/estimationFunctors/ElementaryConvolutionNormalVectorEstimator.h"
36#include "DGtal/geometry/volumes/distance/LpMetric.h"
38//////////////////////////////////////////////////////////////////////////////
40///////////////////////////////////////////////////////////////////////////////
41// IMPLEMENTATION of inline methods.
42///////////////////////////////////////////////////////////////////////////////
44///////////////////////////////////////////////////////////////////////////////
45// ----------------------- Standard services ------------------------------
47//-----------------------------------------------------------------------------
48template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
50DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
51~VoronoiCovarianceMeasureOnDigitalSurface()
54//-----------------------------------------------------------------------------
55template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
57DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
58VoronoiCovarianceMeasureOnDigitalSurface( ConstAlias< Surface > _surface,
59 Surfel2PointEmbedding _surfelEmbedding,
62 Scalar t, Metric aMetric, bool verbose )
63 : mySurface( _surface ), mySurfelEmbedding( _surfelEmbedding ), myChi( chi_r ),
64 myVCM( _R, _r, aMetric, verbose ), myRadiusTrivial( t )
66 if ( verbose ) trace.beginBlock( "Computing VCM on digital surface." );
67 const KSpace & ks = mySurface->container().space();
68 std::vector<Point> vectPoints;
71 if ( verbose ) trace.beginBlock( "Getting points." );
72 std::set<Point> pointSet;
73 for ( ConstIterator it = mySurface->begin(), itE = mySurface->end(); it != itE; ++it )
74 getPoints( std::inserter( pointSet, pointSet.begin() ), *it );
75 vectPoints.resize( pointSet.size() );
76 std::copy( pointSet.begin(), pointSet.end(), vectPoints.begin() );
78 if ( verbose ) trace.endBlock();
80 // Compute Voronoi Covariance Matrix for all points.
81 myVCM.init( vectPoints.begin(), vectPoints.end() );
83 // Compute VCM( chi_r ) for each point.
84 if ( verbose ) trace.beginBlock ( "Integrating VCM( chi_r(p) ) for each point." );
86 // HatPointFunction< Point, Scalar > chi_r( 1.0, r );
87 for ( typename std::vector<Point>::const_iterator it = vectPoints.begin(), itE = vectPoints.end();
90 if ( verbose ) trace.progressBar( ++i, vectPoints.size() );
92 MatrixNN measure = myVCM.measure( myChi, p );
93 // On diagonalise le résultat.
94 EigenStructure & evcm = myPt2EigenStructure[ p ];
95 LinearAlgebraTool::getEigenDecomposition( measure, evcm.vectors, evcm.values );
97 myVCM.clean(); // free some memory.
98 if ( verbose ) trace.endBlock();
100 if ( verbose ) trace.beginBlock ( "Computing average orientation for each surfel." );
101 typedef functors::HatFunction<Scalar> Functor;
102 Functor fct( 1.0, myRadiusTrivial );
103 LpMetric<Space> l2(2.0); //L2 metric in R^3 for surface propagation.
104 typedef functors::ElementaryConvolutionNormalVectorEstimator< Surfel, CanonicSCellEmbedder<KSpace> >
106 typedef LocalEstimatorFromSurfelFunctorAdapter< DigitalSurfaceContainer, LpMetric<Space>, SurfelFunctor, Functor>
109 CanonicSCellEmbedder<KSpace> canonic_embedder( ks );
110 SurfelFunctor surfelFct( canonic_embedder, 1.0 );
111 NormalEstimator estimator;
112 estimator.attach( *mySurface);
113 estimator.setParams( l2, surfelFct, fct , myRadiusTrivial);
114 estimator.init( 1.0, mySurface->begin(), mySurface->end());
116 std::vector<Point> pts;
117 int surf_size = mySurface->size();
118 for ( ConstIterator it = mySurface->begin(), itE = mySurface->end(); it != itE; ++it )
120 if ( verbose ) trace.progressBar(++i, surf_size );
122 Normals & normals = mySurfel2Normals[ s ];
123 // get rough estimation of normal
124 normals.trivialNormal = estimator.eval( it );
125 // get points associated with surfel s
126 getPoints( std::back_inserter( pts ), s );
127 for ( typename std::vector<Point>::const_iterator itPts = pts.begin(), itPtsE = pts.end();
128 itPts != itPtsE; ++itPts )
131 const EigenStructure& evcm = myPt2EigenStructure[ p ];
132 VectorN n = evcm.vectors.column( Space::dimension-1 );
133 if ( n.dot( normals.trivialNormal ) < 0 ) normals.vcmNormal -= n;
134 else normals.vcmNormal += n;
136 if ( pts.size() > 1 ) normals.vcmNormal /= pts.size();
139 if ( verbose ) trace.endBlock();
141 if ( verbose ) trace.endBlock();
144//-----------------------------------------------------------------------------
145template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
147DGtal::CountedConstPtrOrConstPtr< typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Surface >
148DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
153//-----------------------------------------------------------------------------
154template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
156DGtal::Surfel2PointEmbedding
157DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
158surfelEmbedding() const
160 return mySurfelEmbedding;
162//-----------------------------------------------------------------------------
163template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
165typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Scalar
166DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
171//-----------------------------------------------------------------------------
172template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
174typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Scalar
175DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
180//-----------------------------------------------------------------------------
181template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
183typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Scalar
184DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
187 return myRadiusTrivial;
189//-----------------------------------------------------------------------------
190template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
192const typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Surfel2Normals&
193DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
194mapSurfel2Normals() const
196 return mySurfel2Normals;
198//-----------------------------------------------------------------------------
199template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
201const typename DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::Point2EigenStructure&
202DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
203mapPoint2ChiVCM() const
205 return myPt2EigenStructure;
208//-----------------------------------------------------------------------------
209template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
212DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
213getChiVCMEigenvalues( VectorN& values, Surfel s ) const
215 std::vector<Point> pts;
216 getPoints( std::back_inserter( pts ), s );
219 values = VectorN(); // Setting values to 0 before averaging.
220 for ( typename std::vector<Point>::const_iterator itPts = pts.begin(), itPtsE = pts.end();
221 itPts != itPtsE; ++itPts, ++i )
224 typename Point2EigenStructure::const_iterator itEigen = myPt2EigenStructure.find( p );
225 if ( itEigen == myPt2EigenStructure.end() )
230 const EigenStructure& evcm = itEigen->second;
231 values += evcm.values;
233 if ( i > 1 ) values /= i;
237//-----------------------------------------------------------------------------
238template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
241DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
242getChiVCMEigenStructure( VectorN& values, MatrixNN& vectors, Surfel s ) const
244 std::vector<Point> pts;
245 getPoints( std::back_inserter( pts ), s );
248 values = VectorN(); // Setting values to 0 before averaging.
249 vectors = MatrixNN(); // Setting values to 0 before averaging.
250 for ( typename std::vector<Point>::const_iterator itPts = pts.begin(), itPtsE = pts.end();
251 itPts != itPtsE; ++itPts, ++i )
254 typename Point2EigenStructure::const_iterator itEigen = myPt2EigenStructure.find( p );
255 if ( itEigen == myPt2EigenStructure.end() )
260 const EigenStructure& evcm = itEigen->second;
261 values += evcm.values;
262 vectors += evcm.vectors;
271//-----------------------------------------------------------------------------
272template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
273template <typename PointOutputIterator>
276DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
277getPoints( PointOutputIterator outIt, Surfel s ) const
279 BOOST_CONCEPT_ASSERT(( boost::OutputIterator< PointOutputIterator, Point > ));
280 const KSpace & ks = mySurface->container().space();
281 Dimension k = ks.sOrthDir( s );
282 switch ( mySurfelEmbedding ) {
285 typename KSpace::Cells faces = ks.uFaces( ks.unsigns( s ) );
286 for ( typename KSpace::Cells::const_iterator it = faces.begin(), itE = faces.end();
289 if ( ks.uDim( *it ) == 0 ) // get only pointels (cell of dim 0)
290 *outIt++ = ks.uCoords( *it );
292 // Dimension i = (k+1)%3;
293 // Dimension j = (i+1)%3;
294 // SCell l1 = ks.sIncident( s, i, true );
295 // SCell l2 = ks.sIncident( s, i, false );
296 // *outIt++ = ks.sCoords( ks.sIncident( l1, j, true ) );
297 // *outIt++ = ks.sCoords( ks.sIncident( l1, j, false ) );
298 // *outIt++ = ks.sCoords( ks.sIncident( l2, j, true ) );
299 // *outIt++ = ks.sCoords( ks.sIncident( l2, j, false ) );
303 *outIt++ = ks.sCoords( ks.sDirectIncident( s, k ) );
306 *outIt++ = ks.sCoords( ks.sIndirectIncident( s, k ) );
312///////////////////////////////////////////////////////////////////////////////
313// Interface - public :
316 * Writes/Displays the object on an output stream.
317 * @param out the output stream where the object is written.
319template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
322DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
323selfDisplay ( std::ostream & out ) const
325 out << "[VoronoiCovarianceMeasureOnDigitalSurface"
326 << " #pts=" << myPt2EigenStructure.size()
327 << " #surf=" << mySurfel2Normals.size()
332 * Checks the validity/consistency of the object.
333 * @return 'true' if the object is valid, 'false' otherwise.
335template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
338DGtal::VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction>::
346///////////////////////////////////////////////////////////////////////////////
347// Implementation of inline functions //
349template <typename TDigitalSurfaceContainer, typename TSeparableMetric, typename TKernelFunction>
352DGtal::operator<< ( std::ostream & out,
353 const VoronoiCovarianceMeasureOnDigitalSurface<TDigitalSurfaceContainer, TSeparableMetric, TKernelFunction> & object )
355 object.selfDisplay( out );
360///////////////////////////////////////////////////////////////////////////////