DGtal  1.4.beta
testStabbingCircleComputer.cpp
Go to the documentation of this file.
1 
31 #include <iostream>
32 #include "DGtal/base/Common.h"
33 
34 //space / domain
35 #include "DGtal/kernel/SpaceND.h"
36 #include "DGtal/kernel/domains/HyperRectDomain.h"
37 #include "DGtal/topology/KhalimskySpaceND.h"
38 
39 //shape and digitizer
40 #include "DGtal/shapes/ShapeFactory.h"
41 #include "DGtal/shapes/Shapes.h"
42 #include "DGtal/topology/helpers/Surfaces.h"
43 #include "DGtal/shapes/GaussDigitizer.h"
44 #include "DGtal/geometry/curves/GridCurve.h"
45 
46 //Segment computer and DCA
47 #include "DGtal/geometry/curves/CBidirectionalSegmentComputer.h"
48 
49 #include "DGtal/geometry/curves/StabbingCircleComputer.h"
50 
51 #include "DGtal/geometry/curves/SegmentComputerUtils.h"
52 #include "DGtal/geometry/curves/GreedySegmentation.h"
53 #include "DGtal/geometry/curves/SaturatedSegmentation.h"
54 
55 //boards
56 #include "DGtal/io/boards/Board2D.h"
57 #include "DGtal/io/boards/CDrawableWithBoard2D.h"
58 
59 #include "ConfigTest.h"
60 
62 
63 using namespace std;
64 using namespace DGtal;
65 
67 // digital circle generator
68 
69 template<typename TP, typename TI>
70 struct MyBallPredicate
71 {
72  typedef TP Point;
73  typedef TI Integer;
74  MyBallPredicate(const Integer& aR) : myRad(aR) {};
75  bool operator()(const Point &aP) const { return aP.dot(aP) <= myRad*myRad; };
76  Integer myRad;
77 };
78 
79 template<typename TKSpace, typename Integer>
80 void ballGenerator(const TKSpace& aKSpace, GridCurve<TKSpace>& aGC, const Integer& aR, const bool& aFlagIsCW)
81 {
82 
83  // Types
84  typedef TKSpace KSpace;
85  typedef typename KSpace::SCell SCell;
86  typedef typename KSpace::Space Space;
87  typedef typename Space::Point Point;
88 
89  MyBallPredicate<Point,Integer> predicate(aR);
90  try
91  {
92  // Extracts shape boundary
94  SCell bel = Surfaces<KSpace>::findABel( aKSpace, predicate, 10000 );
95  // Getting the consecutive surfels of the 2D boundary
96  std::vector<Point> points, points2;
97  Surfaces<KSpace>::track2DBoundaryPoints( points, aKSpace, SAdj, predicate, bel );
98  //counter-clockwise oriented by default
99  if (aFlagIsCW)
100  {
101  points2.assign( points.rbegin(), points.rend() );
102  aGC.initFromVector(points2);
103  }
104  else
105  {
106  aGC.initFromVector(points);
107  }
108  }
109  catch ( InputException& e )
110  {
111  std::cerr << " "
112  << " error in finding a bel." << std::endl;
113  }
114 }
115 
117 // Functions for testing class StabbingCircleComputer.
119 
121 {
122  typedef std::pair<PointVector<2,int>, PointVector<2,int> > Pair;
123  typedef std::vector<Pair>::const_iterator ConstIterator;
124  typedef StabbingCircleComputer<ConstIterator> GeomDSS;
125  BOOST_CONCEPT_ASSERT(( concepts::CDrawableWithBoard2D<GeomDSS> ));
126  BOOST_CONCEPT_ASSERT(( concepts::CBidirectionalSegmentComputer<GeomDSS> ));
127 }
128 
129 /*
130 * simple drawing
131 */
132 template <typename TCurve>
133 bool drawingTestStabbingCircleComputer(const TCurve& curve, const string& suffix)
134 {
135 
136  typedef typename TCurve::IncidentPointsRange Range; //range
137  Range r = curve.getIncidentPointsRange(); //range
138 
139  {
140  typedef typename Range::ConstIterator ConstIterator; //iterator
142  longestSegment(s,r.begin(),r.end());
143 
144  Board2D board;
145  board << r << s;
146  std::stringstream ss;
147  ss << "StabbingCircleComputerDrawingTest" << suffix << ".eps";
148  board.saveEPS(ss.str().c_str());
149  }
150 
151  {
152  typedef typename Range::ConstReverseIterator ConstReverseIterator; //iterator
154  longestSegment(s,r.rbegin(),r.rend());
155 
156  Board2D board;
157  board << r << s;
158  std::stringstream ss;
159  ss << "StabbingCircleComputerDrawingTest" << suffix << "2.eps";
160  board.saveEPS(ss.str().c_str());
161  }
162 
163  return true;
164 }
165 
169 template <typename TCurve>
170 bool testStabbingCircleComputer(const TCurve& curve)
171 {
172 
173  typedef typename TCurve::IncidentPointsRange Range; //range
174  typedef typename Range::ConstIterator ConstIterator; //iterator
175  typedef typename Range::ConstReverseIterator ConstReverseIterator; //reverse iterator
176 
177  unsigned int nbok = 0;
178  unsigned int nb = 0;
179 
180  trace.beginBlock ( "Constructors, copy, assignement" );
181  {
182  Range r = curve.getIncidentPointsRange(); //range
183 
185  longestSegment(s2, r.begin(), r.end());
186  longestSegment(s3, r.begin()+1, r.end());
189  s3 = s1;
190 
191  trace.info() << s1.isValid() << s1 << endl;
192  trace.info() << s2.isValid() << s2 << endl;
193  trace.info() << s3.isValid() << s3 << endl;
194  trace.info() << s4.isValid() << s4 << endl;
195  trace.info() << s5.isValid() << s5 << endl;
196 
197  bool myFlag = (!s1.isValid())&&(!s3.isValid())
198  &&(s2.isValid())&&(s4.isValid())&&(s5.isValid())
199  &&(s2 == s4)&&(s2 != s5)&&(s2 != s1)
200  &&(s3 != s5)&&(s1 == s3);
201 
202  nbok += myFlag ? 1 : 0;
203  nb++;
204  }
205  trace.endBlock();
206 
207 
208  trace.beginBlock ( "Extension operations" );
209  {
210  Range r = curve.getIncidentPointsRange(); //range
211 
213 
214  trace.info() << "forward extension " << endl;
215 
216  ConstIterator itBegin (r.begin());
217  ConstIterator itEnd (r.end());
218 
219  s.init( itBegin );
220  while ( (s.end() != itEnd) && (s.isExtendableFront()) && (s.extendFront()) ) {}
221  trace.info() << s << endl;
222 
223  ConstIterator itLast (s.end()); --itLast;
224 
225  t.init( itLast );
226  while ( (t.begin() != itBegin) && (t.extendBack()) ) {}
227  trace.info() << t << endl;
228 
229  trace.info() << "backward extension " << endl;
230 
232  ConstReverseIterator ritBegin ( s.end() );
233  ConstReverseIterator ritEnd ( itBegin );
234 
235  rs.init( ritBegin );
236  while ( (rs.end() != ritEnd) && (rs.isExtendableFront()) && (rs.extendFront()) ) {}
237  trace.info() << rs << endl;
238 
239  ConstReverseIterator ritLast (rs.end()); --ritLast;
240 
242  rt.init( ritLast );
243  while ( (rt.begin() != ritBegin) && (rt.extendBack()) ) {}
244  trace.info() << rt << endl;
245 
246  trace.info() << "comparison... " << endl;
247  bool myFlag = (s == t)
248  &&(rs == rt);
249 
250  nbok += myFlag ? 1 : 0;
251  nb++;
252  }
253  trace.endBlock();
254 
255  trace.info() << "(" << nbok << "/" << nb << ") " << endl;
256  return nbok == nb;
257 }
258 
263 {
265  //Note: int64_t is enough for radii less than 200
266  typedef KSpace::Space Space;
267  typedef Space::Point Point;
268 
269  unsigned int nbok = 0;
270  unsigned int nb = 0;
271 
272  trace.beginBlock ( "Recognition" );
273  bool flag=true;
274 
275  for (unsigned int i = 1; i < 200 && flag; ++i)
276  {
277  int radius = i;
278  KSpace kspace( Point::diagonal(-2*radius), Point::diagonal(2*radius), true );
279  GridCurve<KSpace> c(kspace);
280  ballGenerator<KSpace>( kspace, c, radius, ((i%2)==0) );
281  trace.info() << " #ball c(0,0) r=" << radius
282  << " cw=" << ((i%2)==0) << endl;
283 
284  //range
286  Range r = c.getIncidentPointsRange();
287 
288  //recognition
289  typedef Range::ConstIterator ConstIterator; //iterator
291  longestSegment(s,r.begin(),r.end());
292 
293  if (s.end() != r.end())
294  {
295  trace.info()<< "Complete circle not recognized"<<std::endl;
296  flag=false;
297  }
298 
299  //checking if the circle is separating
300  typedef CircleFrom3Points<KSpace::Point> Circle;
301  typedef functors::Point2ShapePredicate<Circle,false,true> FirstInCirclePred;
302  typedef functors::Point2ShapePredicate<Circle,true,true> SecondInCirclePred;
303  for (ConstIterator it = s.begin(); ((it != s.end()) && flag) ; ++it)
304  {
305  FirstInCirclePred p1( s.getSeparatingCircle() );
306  SecondInCirclePred p2( s.getSeparatingCircle() );
307  flag = ( p1(it->first)&&p2(it->second) );
308  if (!flag)
309  {
310  trace.info() << s.getSeparatingCircle() << " "
311  << it->first << " "
312  << it->second << std::endl;
313  }
314  }
315 
316  //conclusion
317  nbok += flag ? 1 : 0;
318  nb++;
319  }
320 
321  trace.endBlock();
322 
323  trace.info() << "(" << nbok << "/" << nb << ") " << endl;
324  return nbok == nb;
325 }
326 
330 template <typename TCurve>
331 bool testSegmentation(const TCurve& curve)
332 {
333 
334  typedef typename TCurve::IncidentPointsRange Range; //range
335  Range r = curve.getIncidentPointsRange(); //range
336 
337  typedef typename Range::ConstIterator ConstIterator; //iterator
338  typedef StabbingCircleComputer<ConstIterator> SegmentComputer; //segment computer
339 
340  unsigned int nbok = 0;
341  unsigned int nb = 0;
342 
343  trace.beginBlock ( "Greedy segmentation" );
344  {
346  Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
347 
348  Board2D board;
349  board << r;
350 
351  typename Segmentation::SegmentComputerIterator it = theSegmentation.begin();
352  typename Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
353  unsigned int n = 0;
354  unsigned int suml = 0;
355  for ( ; it != itEnd; ++it, ++n) {
356  board << SetMode(SegmentComputer().className(), "Sector")
357  << (*it);
358  for (ConstIterator i = it->begin(); i != it->end(); ++i)
359  suml += 1;
360  }
361 
362  board.saveSVG("StabbingCircleComputerGreedySegmentationTest.svg", Board2D::BoundingBox, 5000 );
363 
364  trace.info() << r.size() << ";" << n << ";" << suml << endl;
365  //comparison with the results given by another program
366  bool flag = ((r.size()==85)&&(n==6)&&(suml==90)&&((r.size()+n-1)==suml));
367  nbok += flag ? 1 : 0;
368  nb++;
369  }
370  trace.endBlock();
371 
372  trace.beginBlock ( "Saturated segmentation" );
373  {
375  Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
376  theSegmentation.setMode("Last");
377 
378  Board2D board;
379  board << curve;
380 
381  typename Segmentation::SegmentComputerIterator it = theSegmentation.begin();
382  typename Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
383  unsigned int n = 0;
384  unsigned int suml = 0;
385  for ( ; it != itEnd; ++it, ++n) {
386  board << SetMode(SegmentComputer().className(), "Annulus")
387  << (*it);
388  for (ConstIterator i = it->begin(); i != it->end(); ++i)
389  suml += 1;
390  }
391 
392  board.saveSVG("StabbingCircleComputerSaturatedSegmentationTest.svg", Board2D::BoundingBox, 5000 );
393 
394  trace.info() << r.size() << ";" << n << ";" << suml << endl;
395  //comparison with the results given by another program
396  nbok += ((r.size()==85)&&(n==20)&&(suml==326)) ? 1 : 0;
397  nb++;
398  }
399  trace.endBlock();
400 
401  trace.info() << "(" << nbok << "/" << nb << ") " << endl;
402  return (nbok == nb);
403 }
405 // Standard services - public :
406 
407 int main( int argc, char** argv )
408 {
409  trace.beginBlock ( "Testing class StabbingCircleComputer" );
410  trace.info() << "Args:";
411  for ( int i = 0; i < argc; ++i )
412  trace.info() << " " << argv[ i ];
413  trace.info() << endl;
414 
415  bool res;
416 
417  {//concept checking
419  }
420 
421  {//basic operations
423  typedef KSpace::Space::Point Point;
424  KSpace kspace(Point::diagonal(-10),Point::diagonal(10),true);
425  GridCurve<KSpace> c, rc;
426  ballGenerator(kspace,c,6,false);
427  ballGenerator(kspace,rc,6,true);
428 
431  && drawingTestStabbingCircleComputer(rc, "CW");
432  }
433 
434  {//recognition
435  res = res && testRecognition();
436  }
437 
438  {//segmentations
439  std::string filename = testPath + "samples/sinus2D4.dat";
440  ifstream instream; // input stream
441  instream.open (filename.c_str(), ifstream::in);
442 
444  GridCurve<KSpace> c; //grid curve
445  c.initFromVectorStream(instream);
446 
447  res = res && testSegmentation(c);
448  }
449 
450  trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
451  trace.endBlock();
452  return res ? 0 : 1;
453 }
454 // //
Aim: This class specializes a 'Board' class so as to display DGtal objects more naturally (with <<)....
Definition: Board2D.h:71
Aim: Represents a circle uniquely defined by three 2D points and that is able to return for any given...
Aim: model of CConstBidirectionalRange that adapts any range of elements bounded by two iterators [it...
Aim: Computes the greedy segmentation of a range given by a pair of ConstIterators....
Aim: describes, in a cellular space of dimension n, a closed or open sequence of signed d-cells (or d...
Definition: GridCurve.h:173
bool initFromVectorStream(std::istream &in)
bool initFromVector(const std::vector< Point > &aVectorOfPoints)
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
Aim: Specific iterator to visit all the maximal segments of a saturated segmentation.
Aim: Computes the saturated segmentation, that is the whole set of maximal segments within a range gi...
SaturatedSegmentation::SegmentComputerIterator end() const
void setMode(const std::string &aMode)
SaturatedSegmentation::SegmentComputerIterator begin() const
Aim: model of CBidirectionalRangeFromPoint that adapts any range of elements bounded by two iterators...
std::reverse_iterator< ConstIterator > ConstReverseIterator
Aim: On-line recognition of a digital circular arcs (DCA) defined as a sequence of connected grid edg...
ConstIterator begin() const
void init(const ConstIterator &anIt)
ConstIterator end() const
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:79
void beginBlock(const std::string &keyword="")
std::ostream & emphase()
std::ostream & info()
double endBlock()
void saveEPS(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:804
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1011
Z3i::SCell SCell
MyDigitalSurface::ConstIterator ConstIterator
DGtal is the top-level namespace which contains all DGtal functions and types.
void longestSegment(SC &s, const typename SC::ConstIterator &i, const typename SC::ConstIterator &end, IteratorType)
Trace trace
Definition: Common.h:153
Modifier class in a Board2D stream. Useful to choose your own mode for a given class....
Definition: Board2D.h:247
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value.
Aim: Defines the concept describing a bidirectional segment computer, ie. a model of concepts::CSeg...
Aim: The concept CDrawableWithBoard2D specifies what are the classes that admit an export with Board2...
ArithmeticalDSSComputer< std::vector< Z2i::Point >::const_iterator, int, 4 > SegmentComputer
SaturatedSegmentation< SegmentComputer > Segmentation
MyPointD Point
Definition: testClone2.cpp:383
bool drawingTestStabbingCircleComputer(const TCurve &curve, const string &suffix)
void testStabbingCircleComputerConceptChecking()
int main(int argc, char **argv)
bool testRecognition()
bool testSegmentation(const TCurve &curve)
void ballGenerator(const TKSpace &aKSpace, GridCurve< TKSpace > &aGC, const Integer &aR, const bool &aFlagIsCW)
bool testStabbingCircleComputer(const TCurve &curve)