DGtal  1.5.beta
testProjection.cpp
Go to the documentation of this file.
1 
30 #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  auto 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: Model of the concept StarShaped represents any accelerated flower in the plane.
Definition: AccFlower2D.h:65
RealPoint getLowerBound() const
Definition: Astroid2D.h:122
RealPoint getUpperBound() const
Definition: Astroid2D.h:131
Aim: Model of the concept StarShaped represents any circle in the plane.
Definition: Ball2D.h:61
Aim: Model of the concept StarShaped represents any ellipse in the plane.
Definition: Ellipse2D.h:65
Aim: Model of the concept StarShaped represents any flower with k-petals in the plane.
Definition: Flower2D.h:65
Aim: A class for computing the Gauss digitization of some Euclidean shape, i.e. its intersection with...
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.
SCell sCell(const SPreCell &c) const
From a signed cell, returns a signed cell lying into this Khalismky space.
Aim: Implements basic operations that will be used in Point and Vector classes.
Definition: PointVector.h:593
RealPoint closestPointWithWitnesses(const RealPoint &p, const RealPoint &left, const RealPoint &right, const int step) const
RealPoint findIntersection(const RealPoint &inner, const RealPoint &outer, const double epsilon) const
Aim: A utility class for constructing surfaces (i.e. set of (n-1)-cells).
Definition: Surfaces.h:79
Aim: Represent adjacencies between surfel elements, telling if it follows an interior to exterior ord...
Aim: transforms a signed cell c into a point corresponding to the signed cell of greater dimension th...
Aim: transforms a signed cell c into a point corresponding to the signed cell of greater dimension th...
Z3i::SCell SCell
DGtal is the top-level namespace which contains all DGtal functions and types.
Aim: A trivial embedder for signed cell, which corresponds to the canonic injection of cell centroids...
Represents a signed cell in a cellular grid space by its Khalimsky coordinates and a boolean value.
MyPointD Point
Definition: testClone2.cpp:383
Domain domain
void digitize(Shape &shape, std::vector< SCell > &sCells0, std::vector< SCell > &sCells1, KSpace &kspace, const double h)
double angle(const DGtal::Z2i::RealPoint &point)
bool test_shape(Shape &shape, const double h, const double epsilon)
TEST_CASE("Projection test on various shapes")
SECTION("Testing constant forward iterators")
REQUIRE(domain.isInside(aPoint))