DGtal 1.3.0
Loading...
Searching...
No Matches
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
63using namespace std;
64using namespace DGtal;
65
67// digital circle generator
68template<typename TKSpace>
70ballGenerator(double aCx, double aCy, double aR, bool aFlagIsCW)
71{
72
73 // Types
74 typedef TKSpace KSpace;
75 typedef typename KSpace::SCell SCell;
77 typedef typename KSpace::Space Space;
78 typedef Ball2D<Space> Shape;
79 typedef typename Space::Point Point;
80 typedef typename Space::RealPoint RealPoint;
82
83 //Forme
84 Shape aShape(Point(aCx,aCy), aR);
85
86 // Window for the estimation
87 RealPoint xLow ( -aR-1, -aR-1 );
88 RealPoint xUp( aR+1, aR+1 );
90 dig.attach( aShape ); // attaches the shape.
91 dig.init( xLow, xUp, 1 );
92 Domain domain = dig.getDomain();
93 // Create cellular space
94 KSpace K;
95 bool ok = K.init( dig.getLowerBound(), dig.getUpperBound(), true );
96 if ( ! ok )
97 {
98 std::cerr << " "
99 << " error in creating KSpace." << std::endl;
100 return GridCurve();
101 }
102 try
103 {
104
105 // Extracts shape boundary
107 SCell bel = Surfaces<KSpace>::findABel( K, dig, 10000 );
108 // Getting the consecutive surfels of the 2D boundary
109 std::vector<Point> points, points2;
110 Surfaces<KSpace>::track2DBoundaryPoints( points, K, SAdj, dig, bel );
111 //counter-clockwise oriented by default
112 GridCurve c;
113 if (aFlagIsCW)
114 {
115 points2.assign( points.rbegin(), points.rend() );
116 c.initFromVector(points2);
117 }
118 else
119 {
120 c.initFromVector(points);
121 }
122 return c;
123 }
124 catch ( InputException& e )
125 {
126 std::cerr << " "
127 << " error in finding a bel." << std::endl;
128 return GridCurve();
129 }
130}
131
133// Functions for testing class StabbingCircleComputer.
135
137{
138 typedef std::pair<PointVector<2,int>, PointVector<2,int> > Pair;
139 typedef std::vector<Pair>::const_iterator ConstIterator;
141 BOOST_CONCEPT_ASSERT(( concepts::CDrawableWithBoard2D<GeomDSS> ));
142 BOOST_CONCEPT_ASSERT(( concepts::CBidirectionalSegmentComputer<GeomDSS> ));
143}
144
145/*
146* simple drawing
147*/
148template <typename TCurve>
149bool drawingTestStabbingCircleComputer(const TCurve& curve, const string& suffix)
150{
151
152 typedef typename TCurve::IncidentPointsRange Range; //range
153 Range r = curve.getIncidentPointsRange(); //range
154
155 {
156 typedef typename Range::ConstIterator ConstIterator; //iterator
158 longestSegment(s,r.begin(),r.end());
159
160 Board2D board;
161 board << r << s;
162 std::stringstream ss;
163 ss << "StabbingCircleComputerDrawingTest" << suffix << ".eps";
164 board.saveEPS(ss.str().c_str());
165 }
166
167 {
168 typedef typename Range::ConstReverseIterator ConstReverseIterator; //iterator
170 longestSegment(s,r.rbegin(),r.rend());
171
172 Board2D board;
173 board << r << s;
174 std::stringstream ss;
175 ss << "StabbingCircleComputerDrawingTest" << suffix << "2.eps";
176 board.saveEPS(ss.str().c_str());
177 }
178
179 return true;
180}
181
185template <typename TCurve>
186bool testStabbingCircleComputer(const TCurve& curve)
187{
188
189 typedef typename TCurve::IncidentPointsRange Range; //range
190 typedef typename Range::ConstIterator ConstIterator; //iterator
191 typedef typename Range::ConstReverseIterator ConstReverseIterator; //reverse iterator
192
193 unsigned int nbok = 0;
194 unsigned int nb = 0;
195
196 trace.beginBlock ( "Constructors, copy, assignement" );
197 {
198 Range r = curve.getIncidentPointsRange(); //range
199
201 longestSegment(s2, r.begin(), r.end());
202 longestSegment(s3, r.begin()+1, r.end());
205 s3 = s1;
206
207 trace.info() << s1.isValid() << s1 << endl;
208 trace.info() << s2.isValid() << s2 << endl;
209 trace.info() << s3.isValid() << s3 << endl;
210 trace.info() << s4.isValid() << s4 << endl;
211 trace.info() << s5.isValid() << s5 << endl;
212
213 bool myFlag = (!s1.isValid())&&(!s3.isValid())
214 &&(s2.isValid())&&(s4.isValid())&&(s5.isValid())
215 &&(s2 == s4)&&(s2 != s5)&&(s2 != s1)
216 &&(s3 != s5)&&(s1 == s3);
217
218 nbok += myFlag ? 1 : 0;
219 nb++;
220 }
221 trace.endBlock();
222
223
224 trace.beginBlock ( "Extension operations" );
225 {
226 Range r = curve.getIncidentPointsRange(); //range
227
229
230 trace.info() << "forward extension " << endl;
231
232 ConstIterator itBegin (r.begin());
233 ConstIterator itEnd (r.end());
234
235 s.init( itBegin );
236 while ( (s.end() != itEnd) && (s.isExtendableFront()) && (s.extendFront()) ) {}
237 trace.info() << s << endl;
238
239 ConstIterator itLast (s.end()); --itLast;
240
241 t.init( itLast );
242 while ( (t.begin() != itBegin) && (t.extendBack()) ) {}
243 trace.info() << t << endl;
244
245 trace.info() << "backward extension " << endl;
246
248 ConstReverseIterator ritBegin ( s.end() );
249 ConstReverseIterator ritEnd ( itBegin );
250
251 rs.init( ritBegin );
252 while ( (rs.end() != ritEnd) && (rs.isExtendableFront()) && (rs.extendFront()) ) {}
253 trace.info() << rs << endl;
254
255 ConstReverseIterator ritLast (rs.end()); --ritLast;
256
258 rt.init( ritLast );
259 while ( (rt.begin() != ritBegin) && (rt.extendBack()) ) {}
260 trace.info() << rt << endl;
261
262 trace.info() << "comparison... " << endl;
263 bool myFlag = (s == t)
264 &&(rs == rt);
265
266 nbok += myFlag ? 1 : 0;
267 nb++;
268 }
269 trace.endBlock();
270
271 trace.info() << "(" << nbok << "/" << nb << ") " << endl;
272 return nbok == nb;
273}
274
279{
280
283
284 unsigned int nbok = 0;
285 unsigned int nb = 0;
286
287 trace.beginBlock ( "Recognition" );
288
289 for (unsigned int i = 0; i < 50; ++i)
290 {
291 //generate digital circle
292 double cx = (rand()%100 ) / 100.0;
293 double cy = (rand()%100 ) / 100.0;
294 double radius = (rand()%100 )+100;
295 c = ballGenerator<KSpace>( cx, cy, radius, ((i%2)==1) );
296 trace.info() << " #ball #" << i << " c(" << cx << "," << cy << ") r=" << radius << endl;
297
298 //range
300 Range r = c.getIncidentPointsRange();
301
302 //recognition
303 typedef Range::ConstIterator ConstIterator; //iterator
305 longestSegment(s,r.begin(),r.end());
306
307 //checking if the circle is separating
308 bool flag = true;
309 typedef CircleFrom3Points<KSpace::Point> Circle;
311 FirstInCirclePred;
313 SecondInCirclePred;
314 for (ConstIterator it = s.begin(); ((it != s.end()) && flag) ; ++it)
315 {
316 FirstInCirclePred p1( s.getSeparatingCircle() );
317 SecondInCirclePred p2( s.getSeparatingCircle() );
318 flag = ( p1(it->first)&&p2(it->second) );
319 }
320
321 //conclusion
322 nbok += flag ? 1 : 0;
323 nb++;
324 }
325
326 trace.endBlock();
327
328 trace.info() << "(" << nbok << "/" << nb << ") " << endl;
329 return nbok == nb;
330}
331
335template <typename TCurve>
336bool testSegmentation(const TCurve& curve)
337{
338
339 typedef typename TCurve::IncidentPointsRange Range; //range
340 Range r = curve.getIncidentPointsRange(); //range
341
342 typedef typename Range::ConstIterator ConstIterator; //iterator
344
345 unsigned int nbok = 0;
346 unsigned int nb = 0;
347
348 trace.beginBlock ( "Greedy segmentation" );
349 {
351 Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
352
353 Board2D board;
354 board << r;
355
356 typename Segmentation::SegmentComputerIterator it = theSegmentation.begin();
357 typename Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
358 unsigned int n = 0;
359 unsigned int suml = 0;
360 for ( ; it != itEnd; ++it, ++n) {
361 board << SetMode(SegmentComputer().className(), "Sector")
362 << (*it);
363 for (ConstIterator i = it->begin(); i != it->end(); ++i)
364 suml += 1;
365 }
366
367 board.saveSVG("StabbingCircleComputerGreedySegmentationTest.svg", Board2D::BoundingBox, 5000 );
368
369 trace.info() << r.size() << ";" << n << ";" << suml << endl;
370 //comparison with the results given by another program
371 bool flag = ((r.size()==85)&&(n==6)&&(suml==90)&&((r.size()+n-1)==suml));
372 nbok += flag ? 1 : 0;
373 nb++;
374 }
375 trace.endBlock();
376
377 trace.beginBlock ( "Saturated segmentation" );
378 {
380 Segmentation theSegmentation( r.begin(), r.end(), SegmentComputer() );
381 theSegmentation.setMode("Last");
382
383 Board2D board;
384 board << curve;
385
386 typename Segmentation::SegmentComputerIterator it = theSegmentation.begin();
387 typename Segmentation::SegmentComputerIterator itEnd = theSegmentation.end();
388 unsigned int n = 0;
389 unsigned int suml = 0;
390 for ( ; it != itEnd; ++it, ++n) {
391 board << SetMode(SegmentComputer().className(), "Annulus")
392 << (*it);
393 for (ConstIterator i = it->begin(); i != it->end(); ++i)
394 suml += 1;
395 }
396
397 board.saveSVG("StabbingCircleComputerSaturatedSegmentationTest.svg", Board2D::BoundingBox, 5000 );
398
399 trace.info() << r.size() << ";" << n << ";" << suml << endl;
400 //comparison with the results given by another program
401 nbok += ((r.size()==85)&&(n==20)&&(suml==326)) ? 1 : 0;
402 nb++;
403 }
404 trace.endBlock();
405
406 trace.info() << "(" << nbok << "/" << nb << ") " << endl;
407 return (nbok == nb);
408}
410// Standard services - public :
411
412int main( int argc, char** argv )
413{
414 trace.beginBlock ( "Testing class StabbingCircleComputer" );
415 trace.info() << "Args:";
416 for ( int i = 0; i < argc; ++i )
417 trace.info() << " " << argv[ i ];
418 trace.info() << endl;
419
420 bool res;
421
422 {//concept checking
424 }
425
426 {//basic operations
428
429 GridCurve<KSpace> c, rc;
430 c = ballGenerator<KSpace>(0,0,6,false);
431 std::vector<PointVector<2,int> > rv;
432 rc = ballGenerator<KSpace>(0,0,6,true);
433
437 }
438
439 {//recognition
440 res = res && testRecognition();
441 }
442
443 {//segmentations
444 std::string filename = testPath + "samples/sinus2D4.dat";
445 ifstream instream; // input stream
446 instream.open (filename.c_str(), ifstream::in);
447
449 GridCurve<KSpace> c; //grid curve
450 c.initFromVectorStream(instream);
451
452 res = res && testSegmentation(c);
453 }
454
455 trace.emphase() << ( res ? "Passed." : "Error." ) << endl;
456 trace.endBlock();
457 return res ? 0 : 1;
458}
459// //
Aim: Model of the concept StarShaped represents any circle in the plane.
Definition: Ball2D.h:61
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: A class for computing the Gauss digitization of some Euclidean shape, i.e. its intersection with...
const Point & getUpperBound() const
void attach(ConstAlias< EuclideanShape > shape)
const Point & getLowerBound() const
void init(const RealPoint &xLow, const RealPoint &xUp, typename RealVector::Component gridStep)
Domain getDomain() const
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: Parallelepidec region of a digital space, model of a 'CDomain'.
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex,...
bool init(const Point &lower, const Point &upper, bool isClosed)
Specifies the upper and lower bounds for the maximal cells in this space.
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
static void track2DBoundaryPoints(std::vector< Point > &aVectorOfPoints, const KSpace &K, const SurfelAdjacency< KSpace::dimension > &surfel_adj, const PointPredicate &pp, const SCell &start_surfel)
static SCell findABel(const KSpace &K, const PointPredicate &pp, unsigned int nbtries=1000)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
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:805
void saveSVG(const char *filename, PageSize size=Board::BoundingBox, double margin=10.0) const
Definition: Board.cpp:1012
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:154
STL namespace.
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...
bool testSegmentation()
ArithmeticalDSSComputer< std::vector< Z2i::Point >::const_iterator, int, 4 > SegmentComputer
SaturatedSegmentation< SegmentComputer > Segmentation
Astroid2D< Space > Shape
Z2i::RealPoint RealPoint
int main()
Definition: testBits.cpp:56
MyPointD Point
Definition: testClone2.cpp:383
KSpace K
Domain domain
HyperRectDomain< Space > Domain
bool drawingTestStabbingCircleComputer(const TCurve &curve, const string &suffix)
void testStabbingCircleComputerConceptChecking()
bool testRecognition()
bool testStabbingCircleComputer(const TCurve &curve)
GridCurve< TKSpace > ballGenerator(double aCx, double aCy, double aR, bool aFlagIsCW)