DGtal 1.4.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
68
69template<typename TP, typename TI>
70struct 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
79template<typename TKSpace, typename Integer>
80void 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;
125 BOOST_CONCEPT_ASSERT(( concepts::CDrawableWithBoard2D<GeomDSS> ));
126 BOOST_CONCEPT_ASSERT(( concepts::CBidirectionalSegmentComputer<GeomDSS> ));
127}
128
129/*
130* simple drawing
131*/
132template <typename TCurve>
133bool 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
169template <typename TCurve>
170bool 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
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
330template <typename TCurve>
331bool 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
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
407int 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
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
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 is a wrapper around ArithmeticalDSS that is devoted to the dynamic recognition of dig...
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
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: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
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
int main()
Definition testBits.cpp:56
MyPointD Point
bool drawingTestStabbingCircleComputer(const TCurve &curve, const string &suffix)
void testStabbingCircleComputerConceptChecking()
bool testRecognition()
void ballGenerator(const TKSpace &aKSpace, GridCurve< TKSpace > &aGC, const Integer &aR, const bool &aFlagIsCW)
bool testStabbingCircleComputer(const TCurve &curve)