DGtal 1.4.0
Loading...
Searching...
No Matches
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
43template <typename T> int sgn(T val) {
44 return ( T ( 0 ) < val ) - ( val < T( 0 ) );
45}
46
47
48namespace 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 */
296template <typename T>
297inline
298std::ostream&
299operator<< ( std::ostream & out, const DGtal::NaiveParametricCurveDigitizer3D<T> & object )
300{
301 object.selfDisplay ( out );
302 return out;
303}
304
305// //
306///////////////////////////////////////////////////////////////////////////////
307
308