DGtal  0.9.4.1
testProjection.cpp
Go to the documentation of this file.
1 
29 #include <iostream>
31 
32 #include "DGtal/helpers/StdDefs.h"
33 
34 #include "DGtal/topology/SurfelAdjacency.h"
35 #include "DGtal/topology/DigitalSurface.h"
36 #include "DGtal/topology/helpers/BoundaryPredicate.h"
37 #include "DGtal/topology/SetOfSurfels.h"
38 #include "DGtal/topology/SCellsFunctors.h"
39 
40 #include "DGtal/shapes/Shapes.h"
41 #include "DGtal/shapes/ShapeFactory.h"
42 #include "DGtal/shapes/GaussDigitizer.h"
43 
44 #include "DGtal/io/boards/Board2D.h"
45 
46 #include "DGtalCatch.h"
48 
49 using namespace std;
50 using namespace DGtal;
51 using namespace Z2i;
52 
54 // Standard services - public :/
55 
56 double angle(const DGtal::Z2i::RealPoint& point)
57 {
58  double angle = atan2(point[1], point[0]);
59  if(angle < 0.) angle += 2. * M_PI;
60  return angle;
61 }
62 
63 double angle(const DGtal::Z2i::KSpace& kspace, const DGtal::Z2i::SCell& cell, const double h)
64 {
66  return angle(h * emb(cell));
67 }
68 
69 struct AngleLessCell
70 {
71  typedef DGtal::Z2i::KSpace KSpace;
72  typedef KSpace::SCell SCell;
73  typedef KSpace::Point Point;
74 
75  AngleLessCell(const KSpace& kspace, const double h) : _kspace(kspace), _h(h)
76  {
77  }
78 
79  inline bool operator()(const SCell& a, const SCell& b) const
80  {
81  return angle(_kspace, a, _h) < angle(_kspace, b, _h);
82  }
83 
84  const KSpace& _kspace;
85  const double _h;
86 };
87 
89 
90 template <typename Shape>
91 void digitize(Shape& shape, std::vector<SCell>& sCells0, std::vector<SCell>& sCells1, KSpace& kspace, const double h)
92 {
93  // -------------------------------------------------------------------------- Type declaring
94  typedef typename DGtal::GaussDigitizer<Space, Shape> Digitizer;
95  typedef SurfelAdjacency<2> SurfelAdj;
96  typedef Surfaces<KSpace> Surf;
97 
98  sCells0.clear();
99  sCells1.clear();
100 
101  // -------------------------------------------------------------------------- Creating the shape
102  Digitizer digitizer;
103  digitizer.attach(shape);
104  digitizer.init(shape.getLowerBound() + Vector(-1,-1), shape.getUpperBound() + Vector(1,1), h);
105  domain = digitizer.getDomain();
106 
107  kspace.init(digitizer.getLowerBound(), digitizer.getUpperBound(), true);
108 
109  const SurfelAdj surfel_adjacency(true);
110  const KSpace::SCell cell_bel = Surf::findABel(kspace, digitizer);
111  Surf::track2DBoundary(sCells1, kspace, surfel_adjacency, digitizer, cell_bel);
112  {
113  typedef std::vector<Point> Points;
114  Points points;
115  Surf::track2DBoundaryPoints(points, kspace, surfel_adjacency, digitizer, cell_bel);
116  const KSpace::SCell point_ref = kspace.sCell(Point(0,0));
117  for(Points::const_iterator pi = points.begin(), pe = points.end(); pi != pe; ++pi) sCells0.push_back(kspace.sCell(*pi, point_ref));
118  }
119 
120  std::sort(sCells0.begin(), sCells0.end(), AngleLessCell(kspace, h));
121  std::sort(sCells1.begin(), sCells1.end(), AngleLessCell(kspace, h));
122 
123  ASSERT(sCells0.size() == sCells1.size());
124 }
125 
126 template <typename Shape>
127 bool test_shape(Shape& shape, const double h, const double epsilon)
128 {
129  std::vector<SCell> sCells0, sCells1;
130 
131  KSpace kspace;
132 
133  digitize(shape, sCells0, sCells1, kspace, h);
134 
135  CanonicSCellEmbedder<KSpace> canonicSCellEmbedder(kspace);
136 
137  for(unsigned int i = 0; i < sCells0.size(); i++)
138  {
139  functors::SCellToInnerPoint<KSpace> sCellToInnerPoint(kspace);
140  functors::SCellToOuterPoint<KSpace> sCellToOuterPoint(kspace);
141 
142  const int prev = ( i + sCells0.size() - 3 ) % sCells0.size(), next = (i + 3) % sCells0.size();
143 
144  RealPoint inner_prev = sCellToInnerPoint( sCells0[prev] );
145  RealPoint outer_prev = sCellToOuterPoint( sCells0[prev] );
146 
147  RealPoint inner_next = sCellToInnerPoint( sCells0[next] );
148  RealPoint outer_next = sCellToOuterPoint( sCells0[next] );
149 
150  inner_prev *= h;
151  inner_next *= h;
152 
153  outer_prev *= h;
154  outer_next *= h;
155 
156  RealPoint q_prev = shape.findIntersection(inner_prev, outer_prev, epsilon);
157  RealPoint q_next = shape.findIntersection(inner_next, outer_next, epsilon);
158  RealPoint p = shape.closestPointWithWitnesses(h * canonicSCellEmbedder( sCells0[i] ), q_prev, q_next, 300);
159 
160  const double norm2 = (p - h * canonicSCellEmbedder( sCells0[i]) ).norm();
161 
162  if ( norm2 > sqrt(2.) * h)
163  return false;
164  }
165 
166  return true;
167 }
168 
169 TEST_CASE( "Projection test on various shapes" )
170 {
171  typedef Ball2D<Space> Ball;
172  const Ball ball(Point(0,0), 1.0);
173 
174  typedef Flower2D<Space> Flower2D;
175  const Flower2D flower2D(Point(0,0), 1., 0.3, 5, 0.);
176 
178  const AccFlower2D accFlower2D(Point(0,0), 1., 0.3, 5, 0.);
179 
180  typedef Ellipse2D<Space> Ellipse2D;
181  const Ellipse2D ellipse2D(Point(0,0), 1., 0.4, 0.2);
182 
183  double h = 0.1;
184 
185  SECTION( "Actual test" )
186  {
187  while(h > 0.01)
188  {
189  REQUIRE( test_shape( ball, h, h * 0.01 ) );
190  REQUIRE( test_shape( flower2D, h, h * 0.01 ) );
191  REQUIRE( test_shape( ellipse2D, h, h * 0.01 ) );
192  h /= 1.3;
193  }
194  }
195 }
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:78
double angle(const DGtal::Z2i::RealPoint &point)
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
Aim: Model of the concept StarShaped represents any ellipse in the plane.
Definition: Ellipse2D.h:64
STL namespace.
Domain domain
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:141
Aim: Model of the concept StarShaped represents any flower with k-petals in the plane.
Definition: Flower2D.h:64
Aim: Model of the concept StarShaped represents any circle in the plane.
Definition: Ball2D.h:60
REQUIRE(domain.isInside(aPoint))
bool init(const Point &lower, const Point &upper, bool isClosed)
Aim: A class for computing the Gauss digitization of some Euclidean shape, i.e. its intersection with...
bool test_shape(Shape &shape, const double h, const double epsilon)
Aim: Model of the concept StarShaped represents any accelerated flower in the plane.
Definition: AccFlower2D.h:64
Aim: A trivial embedder for signed cell, which corresponds to the canonic injection of cell centroids...
DGtal is the top-level namespace which contains all DGtal functions and types.
MyPointD Point
Definition: testClone2.cpp:383
Aim: transforms a signed cell c into a point corresponding to the signed cell of greater dimension th...
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value...
FreemanChain< int >::Vector Vector
void digitize(Shape &shape, std::vector< SCell > &sCells0, std::vector< SCell > &sCells1, KSpace &kspace, const double h)
SECTION("Testing constant forward iterators")
Aim: This class is a model of CCellularGridSpaceND. It represents the cubical grid as a cell complex...
Aim: transforms a signed cell c into a point corresponding to the signed cell of greater dimension th...
TEST_CASE("Projection test on various shapes")
SCell sCell(const SPreCell &c) const