DGtal  1.4.beta
NaiveParametricCurveDigitizer3D.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file NaiveParametricCurveDigitizer3D.ih
19  * @author Kacper Pluta (\c kacper.pluta@esiee.fr )
20  * Laboratoire d'Informatique Gaspard-Monge - LIGM, A3SI, France
21  *
22  * @date 2014/09/26
23  *
24  * Implementation of inline methods defined in NaiveParametricCurveDigitizer3D.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 ///////////////////////////////////////////////////////////////////////////////
30 // IMPLEMENTATION of inline methods.
31 ///////////////////////////////////////////////////////////////////////////////
32 
33 //////////////////////////////////////////////////////////////////////////////
34 #include <cassert>
35 #include <cmath>
36 #include <exception>
37 #include <cfloat>
38 #include <utility>
39 #include "DGtal/kernel/BasicPointFunctors.h"
40 //////////////////////////////////////////////////////////////////////////////
41 
42 
43 template <typename T> int sgn(T val) {
44  return ( T ( 0 ) < val ) - ( val < T( 0 ) );
45 }
46 
47 
48 namespace DGtal
49 {
50 
51  template <typename T>
52  inline
53  bool NaiveParametricCurveDigitizer3D<T>::is26Connected ( const Point &x, const Point &y )
54  {
55  return std::abs ( x[0] - y[0] ) < 2 && std::abs ( x[1] - y[1] ) < 2 && std::abs ( x[2] - y[2] ) < 2 && x != y;
56  }
57 
58  ///////////////////////////////////////////////////////////////////////////////
59  // Implementation of inline methods //
60  template <typename T>
61  inline
62  NaiveParametricCurveDigitizer3D<T>::NaiveParametricCurveDigitizer3D ()
63  {
64  curve = nullptr;
65  initOK = false;
66  metaData = false;
67  K_NEXT = 5;
68  BUFFER_SIZE = K_NEXT * 3;
69  }
70 
71  template <typename T>
72  inline
73  void NaiveParametricCurveDigitizer3D<T>::attach ( ConstAlias<T> p_curve )
74  {
75  curve = &p_curve;
76  }
77 
78 
79  template <typename T>
80  inline
81  void NaiveParametricCurveDigitizer3D<T>::init ( long double tmin, long double tmax, long double timeStep )
82  {
83  if ( tmin > tmax )
84  throw std::runtime_error ( "Starting time is bigger than the end time!" );
85 
86  if ( timeStep > ( tmax - tmin ) )
87  throw std::runtime_error ( "The step is too big!" );
88 
89  timeMin = tmin;
90  timeMax = tmax;
91  step = timeStep;
92  initOK = true;
93  }
94 
95 
96  template <typename T>
97  inline
98  unsigned int NaiveParametricCurveDigitizer3D<T>::setKNext ( unsigned int knext )
99  {
100  if ( knext > 0 )
101  {
102  unsigned int tmp = K_NEXT;
103  K_NEXT = knext;
104  BUFFER_SIZE = K_NEXT * 3;
105  return tmp;
106  }
107  throw std::runtime_error ( "The value of k-next cannot be 0!" );
108  }
109 
110 
111  template <typename T>
112  inline
113  bool NaiveParametricCurveDigitizer3D<T>::isValid ( ) const
114  {
115  return initOK && K_NEXT > 0 && curve != nullptr;
116  }
117 
118 
119  template <typename T>
120  inline
121  void NaiveParametricCurveDigitizer3D<T>::syncData ( ConstIterator bbegin, ConstIterator bend, DataInfo & weights )
122  {
123  if ( bbegin == bend )
124  return;
125  auto it = bbegin;
126  if ( digitalCurve.size() == 0 )
127  {
128  digitalCurve.push_back ( *bbegin );
129  it++;
130  if ( metaData )
131  metaDataContainter.push_back ( weights[*bbegin] );
132  }
133 
134  for (; it != bend; it++ )
135  {
136  // search for better candidates i.e. search for 26-connected points of higher scores in the k-neighborhood.
137  for ( KConstIter s = { it + 1, 0 }; s.jt != bend && s.k < K_NEXT; s.jt++ )
138  {
139  if ( is26Connected ( digitalCurve.back(), *s.jt ) && weights[*s.jt].second >= weights[*it].second )
140  {
141  it = s.jt;
142  s.k = 0;
143  }
144  else if ( ! is26Connected ( digitalCurve.back(), *s.jt ) )
145  s.k++;
146  }
147 
148  digitalCurve.push_back ( *it );
149  if ( metaData )
150  metaDataContainter.push_back( weights[*it] );
151  }
152  }
153 
154 
155  template <typename T>
156  inline
157  void NaiveParametricCurveDigitizer3D<T>::flashBuffers ( Buffer & buffer, DataInfo & weights )
158  {
159  syncData ( buffer.begin(), buffer.end() - K_NEXT, weights );
160  // keep the last few points for re-evaluation or because they may not be well evaluated yet.
161  for ( auto it = buffer.begin(); it != buffer.end() - K_NEXT; it++ )
162  weights.erase ( *it );
163  buffer.erase ( buffer.begin(), buffer.end() - K_NEXT );
164  }
165 
166  template <typename T>
167  inline
168  void NaiveParametricCurveDigitizer3D<T>::updateMetaData ( const Point & p, const RealPoint & pc,
169  DataInfo & weights, long double t )
170  {
171  if ( metaData )
172  {
173  if ( weights[p].second == 1 )
174  weights[p].first = t;
175  else if ( (p - pc).norm() < (curve->x ( weights[p].first ) - p).norm() )
176  weights[p].first = t;
177  }
178  }
179 
180  template <typename T>
181  inline
182  void NaiveParametricCurveDigitizer3D<T>::cleanClosedPart ( )
183  {
184  bool isClosed = false;
185  auto it = digitalCurve.end () - K_NEXT;
186  auto jt = digitalCurve.begin () + K_NEXT;
187  for ( ; it != digitalCurve.end (); it++ )
188  for (; jt != digitalCurve.begin(); jt--)
189  if ( is26Connected ( *jt, *it ) )
190  {
191  isClosed = true;
192  break;
193  }
194  if ( isClosed && std::distance ( it, digitalCurve.end () ) > 1 )
195  {
196  if ( metaData )
197  metaDataContainter.erase ( metaDataContainter.end ( ) + std::distance ( it, digitalCurve.end ( ) ) + 1, metaDataContainter.end ( ) );
198  digitalCurve.erase ( it + 1, digitalCurve.end ( ) );
199  }
200  if ( isClosed && jt != digitalCurve.begin() )
201  {
202  if ( metaData )
203  metaDataContainter.erase ( metaDataContainter.begin (), metaDataContainter.begin () + std::distance ( digitalCurve.begin (), jt ) );
204  digitalCurve.erase ( digitalCurve.begin ( ), jt );
205  }
206  }
207 
208  template <typename T>
209  inline
210  void NaiveParametricCurveDigitizer3D<T>::cleanCurve ( )
211  {
212  cleanClosedPart ();
213  for ( auto it = digitalCurve.begin (); it != digitalCurve.end (); )
214  {
215  auto tmp = it + 1;
216  for ( KIter s = { tmp, 0 }; s.jt != digitalCurve.end () && s.k < K_NEXT; s.jt++ )
217  if ( is26Connected ( *it, *s.jt ) )
218  {
219  tmp = s.jt;
220  s.k = 0;
221  }
222  else
223  s.k++;
224  if (tmp != it + 1)
225  {
226  if ( metaData )
227  metaDataContainter.erase ( metaDataContainter.begin () + std::distance ( digitalCurve.begin ( ), it ) + 1,
228  metaDataContainter.begin () + std::distance ( digitalCurve.begin(), tmp ) );
229  it = digitalCurve.erase ( it + 1, tmp );
230  }
231  else
232  it++;
233  }
234  }
235 
236 
237  template <typename T>
238  inline
239  void NaiveParametricCurveDigitizer3D<T>::digitize ( std::back_insert_iterator < DigitalCurve > inserter )
240  {
241  assert ( isValid() );
242 
243  DataInfo weights;
244  Buffer buffer;
245 
246  for ( double t = timeMin; t < timeMax + step; t += step )
247  {
248  RealPoint pc = curve->x ( t );
249  Point p ( std::round ( pc[0] ), std::round ( pc[1] ), std::round ( pc[2] ) );
250  weights[p].second++;
251 
252  updateMetaData ( p, pc, weights, t );
253  if ( std::find ( buffer.begin (), buffer.end (), p ) == buffer.end ( ) )
254  buffer.push_back ( p );
255 
256  if ( buffer.size() == BUFFER_SIZE )
257  flashBuffers(buffer, weights);
258  }
259  syncData ( buffer.begin (), buffer.end (), weights );
260  cleanCurve ( );
261 
262  std::move ( digitalCurve.begin (), digitalCurve.end (), inserter );
263  digitalCurve.clear ();
264  }
265 
266  template <typename T>
267  inline
268  void NaiveParametricCurveDigitizer3D<T>::digitize ( std::back_insert_iterator < DigitalCurve > inserter,
269  std::back_insert_iterator < MetaData > meta_inserter )
270  {
271  metaData = true;
272  digitize ( inserter );
273  std::move ( metaDataContainter.begin (), metaDataContainter.end (), meta_inserter );
274  metaDataContainter.clear ();
275  metaData = false;
276  }
277 
278  template <typename T>
279  inline
280  void NaiveParametricCurveDigitizer3D<T>::selfDisplay ( std::ostream & out ) const
281  {
282  out << "[NaiveParametricCurveDigitizer3D]";
283  }
284 
285 }
286 
287 ///////////////////////////////////////////////////////////////////////////////
288 // Implementation of inline functions and external operators //
289 
290 /**
291  * Overloads 'operator<<' for displaying objects of class 'NaiveParametricCurveDigitizer3D'.
292  * @param out the output stream where the object is written.
293  * @param object the object of class 'NaiveParametricCurveDigitizer3D' to write.
294  * @return the output stream after the writing.
295  */
296 template <typename T>
297 inline
298 std::ostream&
299 operator<< ( std::ostream & out, const DGtal::NaiveParametricCurveDigitizer3D<T> & object )
300 {
301  object.selfDisplay ( out );
302  return out;
303 }
304 
305 // //
306 ///////////////////////////////////////////////////////////////////////////////
307 
308