34 #include "DGtal/base/Common.h"
36 #include "DGtal/kernel/SpaceND.h"
37 #include "DGtal/kernel/domains/HyperRectDomain.h"
38 #include "DGtal/kernel/BasicPointPredicates.h"
39 #include "DGtal/kernel/domains/DomainPredicate.h"
40 #include "DGtal/kernel/sets/SetPredicate.h"
41 #include "DGtal/kernel/sets/DigitalSetFromMap.h"
42 #include "DGtal/images/ImageContainerBySTLMap.h"
43 #include "DGtal/images/imagesSetsUtils/SimpleThresholdForegroundPredicate.h"
46 #include "DGtal/images/ImageSelector.h"
47 #include "DGtal/geometry/volumes/distance/DistanceTransformation.h"
50 #include "DGtal/geometry/volumes/distance/FMM.h"
53 #include "DGtal/io/colormaps/HueShadeColorMap.h"
54 #include "DGtal/io/boards/Board2D.h"
57 #include "DGtal/shapes/ShapeFactory.h"
58 #include "DGtal/shapes/Shapes.h"
59 #include "DGtal/topology/helpers/Surfaces.h"
60 #include "DGtal/shapes/GaussDigitizer.h"
61 #include "DGtal/geometry/curves/GridCurve.h"
66 using namespace DGtal;
70 template <
typename TImage,
typename TSet,
int norm>
76 template <
typename TImage,
typename TSet>
84 template <
typename TPo
int>
93 myCx(aCx), myCy(aCy), myR(aR)
96 bool operator()(
const TPoint& aPoint)
const
98 double d = std::sqrt( std::pow( (myCx-aPoint[0] ), 2)
99 + std::pow( (myCy-aPoint[1] ), 2) );
100 if (d <= myR)
return true;
104 double myCx, myCy, myR;
107 template <
typename TPo
int>
116 myCx(aCx), myCy(aCy), myR(aR)
117 { ASSERT(myR > 0); };
119 Value operator()(
const TPoint& aPoint)
const
121 double d = std::sqrt( std::pow( (myCx-aPoint[0] ), 2)
122 + std::pow( (myCy-aPoint[1] ), 2) );
126 double myCx, myCy, myR;
130 template<
typename TKSpace>
132 ballGenerator(
const int& size,
double aCx,
double aCy,
double aR,
GridCurve<TKSpace>& gc)
135 ASSERT( aR < (
double) size );
139 typedef typename KSpace::SCell
SCell;
141 typedef typename KSpace::Space
Space;
142 typedef typename Space::Point
Point;
145 bool ok = K.init( Point(-size,-size), Point(size,size),
true );
148 std::cerr <<
" error in creating KSpace." << std::endl;
157 std::vector<Point> points;
163 std::cerr <<
" error in finding a bel." << std::endl;
167 template<
typename TIterator >
168 void draw(
const TIterator& itb,
const TIterator& ite,
const int& size, std::string basename)
170 typedef typename std::iterator_traits<TIterator>::value_type Pair;
171 typedef typename Pair::first_type Point;
172 typedef typename Pair::second_type Value;
179 for ( ; it != ite; ++it)
187 s << basename <<
".eps";
196 bool testDisplayDT2d(
int size,
int area,
double distance)
203 typedef Domain::Point Point;
204 Domain d(Point::diagonal(-size), Point::diagonal(size));
209 Image map( d, (size*size) );
210 map.setValue( Point::diagonal(0), 0.0 );
218 FMM fmm(map,
set, dp, area, distance);
226 s <<
"DTFrom2dPt-" << size <<
"-" << area <<
"-" << distance;
227 draw(map.begin(), map.end(), size, s.str());
229 return fmm.isValid();
234 bool accuracyTest(
int size)
241 typedef Domain::Point Point;
242 Domain d(Point::diagonal(-size), Point::diagonal(size));
243 double h = 1.0/(double)size;
246 int radius = (size/2);
248 Predicate predicate( 0, 0, radius );
251 trace.
info() <<
" # circle of radius 0.5 "
252 <<
"digitized in a square of size 1 "
253 <<
"at step h=" << h << endl;
257 KSpace K; K.
init( Point::diagonal(-size), Point::diagonal(size),
true);
260 std::vector<KSpace::SCell> vSCells;
263 double diff1, diff2, diff3 = 0.0;
277 FMM::initFromBelsRange( K,
278 vSCells.begin(), vSCells.end(),
284 FMM fmm(map,
set, predicate);
290 double truth = radius*h;
291 double found = ( std::max(std::abs(fmm.max()),std::abs(fmm.min())) )*h;
292 double diff = std::abs(found-truth);
293 trace.
info() <<
" # radius (low accuracy)" << std::endl;
294 trace.
info() <<
" # truth: " << truth << std::endl;
295 trace.
info() <<
" # found: " << found << std::endl;
296 trace.
info() <<
" # diff.: " << diff << std::endl;
312 Functor functor( 0, 0, radius );
314 FMM::initFromBelsRange( K,
315 vSCells.begin(), vSCells.end(),
320 FMM fmm(map,
set, predicate);
325 double truth = radius*h;
326 double found = ( std::max(std::abs(fmm.max()),std::abs(fmm.min())) )*h;
327 double diff = std::abs(found-truth);
328 trace.
info() <<
" # radius (medium accuracy)" << std::endl;
329 trace.
info() <<
" # truth: " << truth << std::endl;
330 trace.
info() <<
" # found: " << found << std::endl;
331 trace.
info() <<
" # diff.: " << diff << std::endl;
350 Functor functor( 0, 0, radius );
352 FMM::initFromBelsRange( K,
353 vSCells.begin(), vSCells.end(),
357 Distance distance(map,
set);
358 FMM fmm(map,
set, predicate, distance);
363 double truth = radius*h;
364 double found = ( std::max(std::abs(fmm.max()),std::abs(fmm.min())) )*h;
365 double diff = std::abs(found-truth);
366 trace.
info() <<
" # radius (high accuracy)" << std::endl;
367 trace.
info() <<
" # truth: " << truth << std::endl;
368 trace.
info() <<
" # found: " << found << std::endl;
369 trace.
info() <<
" # diff.: " << diff << std::endl;
376 return ( (diff1 >= diff2)&&(diff2 >= diff3) );
383 bool testDisplayDT3d(
int size,
int area,
double distance)
390 typedef Domain::Point Point;
391 Domain d(Point::diagonal(-size), Point::diagonal(size));
397 map.setValue( Point::diagonal(0), 0.0 );
405 FMM fmm(map,
set, dp, area, distance);
417 Domain::ConstIterator it = d.begin();
418 for ( ; it != d.end(); ++it)
431 s <<
"DTFrom3dPt-" << size <<
"-" << area <<
"-" << distance
436 return fmm.isValid();
439 bool testDisplayDTFromCircle(
int size)
446 typedef Domain::Point Point;
447 Domain d(Point::diagonal(-size), Point::diagonal(size));
457 double radius = (rand()%size);
458 trace.
info() <<
" #ball c(" << 0 <<
"," << 0 <<
") r=" << radius << endl;
459 ballGenerator<KSpace>( size, 0, 0, radius, gc );
462 unsigned int nbok = 0;
475 FMM::initFromPointsRange(r.begin(), r.end(), map,
set, 0.5);
478 Predicate bp(0,0,radius);
479 FMM fmm(map,
set, bp);
482 nbok += (fmm.isValid()?1:0);
483 trace.
info() << nbok <<
"/" << ++nb << std::endl;
486 dmaxInt = fmm.getMax();
490 s <<
"DTInCircle-" << size;
491 draw(map.begin(), map.end(), size, s.str());
508 FMM::initFromPointsRange(r.begin(), r.end(), map,
set, 0.5);
512 Predicate pred( bp, dp, andBF2 );
513 FMM fmm(map,
set, pred);
516 nbok += (fmm.isValid()?1:0);
517 trace.
info() << nbok <<
"/" << ++nb << std::endl;
520 dmaxExt = fmm.getMax();
524 s <<
"DTOutCircle-" << size;
525 draw(map.begin(), map.end(), size, s.str());
529 double dmin = 2*size*size;
540 FMM::initFromIncidentPointsRange(r.begin(), r.end(), map,
set, 0.5,
true);
543 FMM fmm(map,
set, dp);
546 nbok += (fmm.isValid()?1:0);
547 trace.
info() << nbok <<
"/" << ++nb << std::endl;
555 s <<
"DTfromCircle-" << size;
556 draw(map.begin(), map.end(), size, s.str());
562 double epsilon = 0.0001;
563 nbok += ( ( (std::abs(-dmaxInt - dmin) < epsilon)
564 && (std::abs(dmaxExt - dmax) < epsilon) )?1:0);
565 trace.
info() << nbok <<
"/" << ++nb << std::endl;
578 template<Dimension dim,
int norm>
579 bool testComparison(
int size,
int area,
double dist)
586 typedef typename Domain::Point Point;
587 Domain d(Point::diagonal(-size), Point::diagonal(size));
593 map.setValue( Point::diagonal(0), 0.0 );
596 set.
insert( Point::diagonal(0) );
599 typedef Image Image2;
601 typename Domain::Iterator dit = d.begin();
602 typename Domain::Iterator ditEnd = d.end();
603 for ( ; dit != ditEnd; ++dit)
605 image.setValue(*dit, 128);
607 image.setValue(Point::diagonal(0), 0);
614 Distance distance(map,
set);
615 FMM fmm( map,
set, dp, area, dist, distance );
623 Predicate aPredicate(image,0);
626 typename DT::OutputImage resultImage = dt.compute ( );
627 trace.
info() << resultImage << std::endl;
631 bool flagIsOk =
true;
635 typename Domain::ConstIterator it = d.begin();
636 typename Domain::ConstIterator itEnd = d.end();
637 for ( ; ( (it != itEnd)&&(flagIsOk) ); ++it)
639 if (
set.find(*it) ==
set.end())
643 if (resultImage(*it) != map(*it))
658 int main (
int argc,
char** argv )
662 for (
int i = 0; i < argc; ++i )
668 int area = int( std::pow(
double(2*size+1),2) )+1;
670 = testDisplayDT2d( size, area, std::sqrt(2*size*size) )
671 && testDisplayDT2d( size, area, size )
672 && testDisplayDT2d( size, 2*area, std::sqrt(2*size*size) )
673 && testDisplayDTFromCircle(size)
674 && accuracyTest(size)
678 area = 4*int( std::pow(
double(size),3) );
680 res = res && testDisplayDT3d( size, area, std::sqrt(size*size*size) )
685 area = int( std::pow(
double(2*size+1),3) )+1;
687 && testComparison<3,1>( size, area, 3*size+1 )
688 && testComparison<3,0>( size, area, size+1 )
691 area = int( std::pow(
double(2*size+1),4) ) + 1;
693 && testComparison<4,1>( size, area, 4*size+1 )
694 && testComparison<4,0>( size, area, size+1 )
698 trace.
emphase() << ( res ?
"Passed." :
"Error." ) << endl;