Surface Mesh Segmentation
 All Classes Namespaces Files Functions Typedefs Pages
Disk_samplers.h
Go to the documentation of this file.
1 #ifndef CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H
2 #define CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H
3 
7 #include <cmath>
8 #include <CGAL/number_type_basic.h>
9 
10 #define CGAL_ANGLE_ST_DEV_DIVIDER 3.0
11 
12 namespace CGAL {
14 namespace internal {
15 
17 // * // // * //
18 // * // // * //
19 // * * * * // // //
20 // * * // // * * * * //
21 // * * // // * //
22 // * * * * // // * * //
23 // * * * * * // // * * * * * //
24 // * * * * // // * * * //
25 // * * * // // * * * * * * * //
26 // * * * * // // * * * //
27 // * * * * * // // * * *** * * * //
28 // * * * * * // // * * * * * * //
29 // * * // // * * * * //
30 // * * * * // // * * * * //
31 // * * * // // * * * //
32 // * * // // * * * //
33 // * * * * * // // * * //
34 // * // // * * //
35 // * * * // // * //
36 // * * // // * * //
37 // * * // // * //
39  // Uniform // // Custom power (biased to center) //
47 template<class Tuple, bool uniform = false>
48 class Vogel_disk_sampling
49 {
50 public:
60  template<class OutputIterator>
61  void operator()(int number_of_points,
62  double cone_angle,
63  OutputIterator out_it) const
64  {
65  const double golden_ratio = 3.0 - std::sqrt(5.0);
66 
67  if(uniform)
68  {
69  const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
70  const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
71  for(int i = 0; i < number_of_points; ++i)
72  {
73  double Q = i * golden_ratio * CGAL_PI;
74  double R = std::sqrt(static_cast<double>(i) / number_of_points);
75  double angle = atan(R / length_of_normal);
76  double weight = exp(-0.5 * (std::pow(angle / angle_st_dev, 2)));
77  *out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
78  }
79  }
80  else
81  {
82  const double custom_power = 1.0; // it determines how much sampling is biased to center
83  // for uniform result one can use 0.5 (i.e. sqrt)
84  for(int i = 0; i < number_of_points; ++i)
85  {
86  double Q = i * golden_ratio * CGAL_PI;
87  double R = std::pow(static_cast<double>(i) / number_of_points, custom_power);
88  // use uniform weigths, since we already give importance to locations that are close to center.
89  *out_it++ = Tuple(R * cos(Q), R * sin(Q), 1.0);
90  }
91  }
92  }
93 };
94 
96 // * //
97 // * //
98 // * //
99 // * * //
100 // * * * //
101 // * * * //
102 // * * //
103 // * * * //
104 // * * * //
105 // * * //
106 // * * * //
107 // * * * * * * * * * * * * * * * * //
108 // * * * //
109 // * * //
110 // * * * //
111 // * * * //
112 // * * //
113 // * * * //
114 // * * * //
115 // * * //
116 // * //
117 // * //
118 // * //
120 
125 template<class Tuple>
126 class Polar_disk_sampling
127 {
128 public:
140  template<class OutputIterator>
141  void operator()(int number_of_points,
142  double cone_angle,
143  OutputIterator out_it) const
144  {
145  const int number_of_points_sqrt = static_cast<int>(std::sqrt(
146  static_cast<double>(number_of_points)));
147  const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
148  // use cone_angle / 3 as one standard deviation while weighting.
149  const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
150 
151  for(int i = 1; i <= number_of_points_sqrt; ++i)
152  for(int j = 1; j <= number_of_points_sqrt; ++j)
153  {
154  double w1 = static_cast<double>(i) / number_of_points_sqrt;
155  double w2 = static_cast<double>(j) / number_of_points_sqrt;
156  double R = w1;
157  double Q = 2 * w2 * CGAL_PI;
158  double angle = atan(R / length_of_normal);
159  double weight = exp(-0.5 * (pow(angle / angle_st_dev, 2)));
160  *out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
161  }
162  }
163 };
164 
166 // * * * * //
167 // * * //
168 // //
169 // * * * * * * //
170 // * * //
171 // * * //
172 // * * //
173 // * * * * * * //
174 // //
175 // * * * * * * * * //
176 // //
177 // * * * * * * * * //
178 // //
179 // * * * * * * //
180 // * * //
181 // * * //
182 // * * //
183 // * * * * * * //
184 // //
185 // * * //
186 // * * * * //
188 
193 template<class Tuple>
194 class Concentric_disk_sampling
195 {
196 public:
208  template<class OutputIterator>
209  void operator()(int number_of_points,
210  double cone_angle,
211  OutputIterator out_it) const
212  {
213  const int number_of_points_sqrt = static_cast<int>(std::sqrt(
214  static_cast<double>(number_of_points)));
215  const double length_of_normal = 1.0 / tan(cone_angle / 2.0);
216  const double fraction = (number_of_points_sqrt == 1) ? 0.0
217  : 2.0 / (number_of_points_sqrt -1);
218  // use cone_angle / 3 as one standard deviation while weighting.
219  const double angle_st_dev = cone_angle / CGAL_ANGLE_ST_DEV_DIVIDER;
220 
221  for(int i = 0; i < number_of_points_sqrt; ++i)
222  for(int j = 0; j < number_of_points_sqrt; ++j)
223  {
224  double w1 = -1 + i * fraction;
225  double w2 = -1 + j * fraction;
226  double R, Q;
227  if(w1 == 0 && w2 == 0)
228  {
229  R = 0; Q = 0;
230  }
231  else if(w1 > -w2)
232  {
233  if(w1 > w2) { R = w1; Q = (w2 / w1); }
234  else { R = w2; Q = (2 - w1 / w2); }
235  }
236  else
237  {
238  if(w1 < w2) { R = -w1; Q = (4 + w2 / w1); }
239  else { R = -w2; Q = (6 - w1 / w2); }
240  }
241  Q *= (CGAL_PI / 4.0);
242  double angle = atan(R / length_of_normal);
243  double weight = exp(-0.5 * (pow(angle / angle_st_dev, 2)));
244  *out_it++ = Tuple(R * cos(Q), R * sin(Q), weight);
245  }
246  }
247 };
248 
249 }//namespace internal
251 }//namespace CGAL
252 #undef CGAL_ANGLE_ST_DEV_DIVIDER
253 #endif //CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H