DGtal  1.5.beta
RBC_vec.h
1 
17 #pragma once
18 
28 #if defined(RBC_vec_RECURSES)
29 #error Recursive header files inclusion detected in RBC_vec.h
30 #else // defined(RBC_vec_RECURSES)
32 #define RBC_vec_RECURSES
33 
34 #if !defined RBC_vec_h
36 #define RBC_vec_h
37 
38 #include <vector>
39 #include "DGtal/base/Common.h"
40 #include "DGtal/kernel/BasicPointFunctors.h"
41 #include <DGtal/helpers/StdDefs.h>
42 #include "PointUtils.h"
43 #include <DGtal/kernel/CSpace.h>
44 #include <DGtal/io/readers/GenericReader.h>
45 #include <DGtal/images/ImageSelector.h>
46 
47 namespace DGtal {
55  template<typename TSpace, typename TInputValue = typename TSpace::RealPoint, typename TOutputValue = typename TSpace::Point>
56 struct RBC_vec {
57  typedef std::vector< TOutputValue > Circle;
58 
61  std::vector< Circle > circles;
64  std::map< TOutputValue, TOutputValue > point2circle;
65 
72  RBC_vec( int max_radius, bool smart = false ) {
73  init( max_radius, smart );
74  my_angle = 0.0;
75  my_center = TOutputValue( 0, 0 );
76  }
77 
85  void init( int R, bool smart ) {
86  TOutputValue c( 0, 0 );
87  circles.clear();
88  circles.resize( R + 1 );
89  circles[ 0 ].push_back( c );
90  point2circle[ c ] = TOutputValue( 0, 0 );
91  std::size_t N = 1;
92  std::vector< TOutputValue > points;
93  for ( int r = 1; r <= R; r++ )
94  {
95  circles[ r ] = computeCircle( r );
96  for ( int i = 0; i < circles[ r ].size(); i++, N++ )
97  {
98  point2circle[ circles[ r ][ i ] ] = TOutputValue( r, i );
99  points.push_back( circles[ r ][ i ] );
100  }
101  }
102  if ( ! smart ) return;
103  struct DistanceComparator {
104  bool operator()( TOutputValue p, TOutputValue q ) const
105  {
106  return p.squaredNorm() < q.squaredNorm();
107  }
108  };
109  struct AngleComparator {
110  bool operator()( TOutputValue p, TOutputValue q ) const
111  {
112  double ap = atan2( p[ 1 ], p[ 0 ] );
113  double aq = atan2( q[ 1 ], q[ 0 ] );
114  return ap < aq;
115  }
116  };
117 
118  // Try to improve circles.
119  // target number of points for circle r is
120  // n(r) = a * r, with a = 2( N - 1 ) / (R(R+1))
121  double a = 2.0 * double( N - 1 ) / double(R*(R+1));
122  DistanceComparator dcomp;
123  AngleComparator acomp;
124  std::sort( points.begin(), points.end(), dcomp );
125  int current = 1;
126  for ( int r = 1; r <= R; r++ )
127  {
128  int n = int( round( a * r / 8.0 ) * 8.0 );
129  circles[ r ].resize( n );
130  for ( int i = 0; i < n; i++ )
131  circles[ r ][ i ] = points[ current++ ];
132  std::sort( circles[ r ].begin(), circles[ r ].end(), acomp );
133  // std::cout << "r=" << r << " #C=" << circles[ r ].size() << std::endl;
134  }
135  }
136 
138  double angle() const {
139  return my_angle;
140  }
142  double& setAngle() {
143  return my_angle;
144  }
146  TOutputValue center() const {
147  return my_center;
148  }
150  TOutputValue& center() {
151  return my_center;
152  }
153 
157  TOutputValue rotate( TInputValue p ) const {
158  auto cp = static_cast<TOutputValue>((p - my_center));
159  const auto it = point2circle.find( cp );
160  if ( it == point2circle.end() ) return static_cast<TOutputValue>(p);
161  TOutputValue polar = it->second;
162  int r = polar[ 0 ];
163  int idx = polar[ 1 ];
164  const Circle& C = circle( r );
165  const int N = C.size();
166  int shift = int( round( -my_angle * N / ( 2.0 * M_PI ) ) );
167  int jdx = ( N + idx - shift ) % N;
168  return my_center + C[ jdx ];
169  }
170 
171  TOutputValue operator()( const TInputValue & aInput ) const
172  {
173  return this->rotate(aInput);
174  }
175 
177  std::size_t size() const {
178  return circles.size();
179  }
180 
183  const Circle& circle( int r ) const {
184  return circles[ r ];
185  }
186 
190  static Circle computeCircle( int r ) {
191  int d2_lo = r*r;
192  int d2_up = (r+1)*(r+1);
193  TOutputValue start( r, 0 );
194  Circle circle;
195  TOutputValue current = start;
196  do {
197  circle.push_back( current );
198  auto V = nextNeighbors<TOutputValue>( current );
199  std::vector<TOutputValue> P;
200  for ( auto p : V ) {
201  int d2 = p.squaredNorm();
202  // std::cout << "p=" << p << " d2=" << d2 << std::endl;
203  if ( d2_lo <= d2 && d2 < d2_up ) P.push_back( p );
204  }
205  if ( P.empty() ) std::cerr << "Error ! " << std::endl;
206  TOutputValue b = P[ 0 ];
207  for ( int i = 1; i < P.size(); i++ )
208  if ( less<TOutputValue>( P[ i ], b ) ) b = P[ i ];
209  current = b;
210  } while ( current != start );
211  return circle;
212  }
213 
214 
215 
216  protected:
218  double my_angle;
220  TOutputValue my_center;
221  };
222 }
223 
224 
225 #endif //RBC_vec
226 
227 #undef RBC_vec_RECURSES
228 #endif // else defined(RBC_vec_RECURSES)
DGtal is the top-level namespace which contains all DGtal functions and types.
RBC : Bijective Rotation through Circles.
Definition: RBC_vec.h:56
double my_angle
The angle of rotation.
Definition: RBC_vec.h:218
double angle() const
Definition: RBC_vec.h:138
void init(int R, bool smart)
Definition: RBC_vec.h:85
TOutputValue rotate(TInputValue p) const
Definition: RBC_vec.h:157
TOutputValue operator()(const TInputValue &aInput) const
Definition: RBC_vec.h:171
const Circle & circle(int r) const
Definition: RBC_vec.h:183
std::vector< TOutputValue > Circle
Definition: RBC_vec.h:57
RBC_vec(int max_radius, bool smart=false)
Definition: RBC_vec.h:72
TOutputValue & center()
Definition: RBC_vec.h:150
static Circle computeCircle(int r)
Definition: RBC_vec.h:190
double & setAngle()
Definition: RBC_vec.h:142
std::size_t size() const
Definition: RBC_vec.h:177
std::map< TOutputValue, TOutputValue > point2circle
Definition: RBC_vec.h:64
TOutputValue center() const
Definition: RBC_vec.h:146
TOutputValue my_center
The center of rotation.
Definition: RBC_vec.h:220
std::vector< Circle > circles
Definition: RBC_vec.h:61