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.
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.
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/>.
18 * @file SphericalAccumulator.ih
19 * @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
24 * Implementation of inline methods defined in SphericalAccumulator.h
26 * This file is part of the DGtal library.
30 //////////////////////////////////////////////////////////////////////////////
32 //////////////////////////////////////////////////////////////////////////////
34 ///////////////////////////////////////////////////////////////////////////////
35 // IMPLEMENTATION of inline methods.
36 ///////////////////////////////////////////////////////////////////////////////
38 ///////////////////////////////////////////////////////////////////////////////
39 // ----------------------- Standard services ------------------------------
46 DGtal::SphericalAccumulator<T>::SphericalAccumulator(const Size aP)
51 myAccumulator.resize(myNphi*myNtheta,0);
52 myAccumulatorDir.resize(myNphi*myNtheta, Vector::zero);
59 for(Size posPhi=0; posPhi < myNphi; posPhi++)
60 for(Size posTheta=0; posTheta < myNtheta; posTheta++)
62 double dphi = M_PI/((double)myNphi-1);
63 double Ntheta_i = floor(2.0*((double)myNphi)*sin((double)posPhi*dphi)) ;
65 if (((posPhi == 0) || (posPhi == (myNphi-1))) && (posTheta==0))
68 if ((posPhi < myNphi) && (posTheta<Ntheta_i) && (posTheta< myNtheta))
77 DGtal::SphericalAccumulator<T>::~SphericalAccumulator()
80 // --------------------------------------------------------
83 void DGtal::SphericalAccumulator<T>::binCoordinates(const Vector &aDir,
87 double theta,phi, theta2;
88 double norm = aDir.norm();
92 phi = acos(NumberTraits<typename T::Component>::castToDouble(aDir[2])/norm);
94 double dphi = M_PI/(double)(myNphi-1);
96 posPhi = static_cast<Size>(floor( (phi+dphi/2.) *(myNphi-1)/ M_PI));
97 if(posPhi == 0 || posPhi== (myNphi-1))
103 theta2=atan2(NumberTraits<typename T::Component>::castToDouble(aDir[1]),
104 NumberTraits<typename T::Component>::castToDouble(aDir[0]));
107 theta = theta2 + 2.0*M_PI;
110 Nthetai = floor(2.0*(myNphi)*sin(posPhi*dphi));
111 double dtheta = 2.0*M_PI/(Nthetai);
112 posTheta = static_cast<Size>(floor( (theta+dtheta/2.0)/dtheta));
114 if (posTheta >= Nthetai)
118 ASSERT(posPhi < myNphi);
119 ASSERT( isValidBin(posPhi,posTheta) );
121 // --------------------------------------------------------
122 template <typename T>
124 void DGtal::SphericalAccumulator<T>::addDirection(const Vector &aDir)
126 Size posPhi,posTheta;
128 binCoordinates(aDir , posPhi, posTheta);
129 myAccumulator[posTheta + posPhi*myNtheta] += 1;
130 myAccumulatorDir[posTheta + posPhi*myNtheta] += aDir;
134 if ( myAccumulator[posTheta + posPhi*myNtheta] >
135 myAccumulator[ myMaxBinTheta + myMaxBinPhi*myNtheta])
137 myMaxBinTheta = posTheta;
138 myMaxBinPhi = posPhi;
141 // --------------------------------------------------------
142 template <typename T>
144 typename DGtal::SphericalAccumulator<T>::Quantity
145 DGtal::SphericalAccumulator<T>::samples() const
149 // --------------------------------------------------------
150 template <typename T>
153 DGtal::SphericalAccumulator<T>::maxCountBin(Size &phi, Size &theta) const
156 theta = myMaxBinTheta;
158 // --------------------------------------------------------
159 template <typename T>
161 typename DGtal::SphericalAccumulator<T>::Quantity
162 DGtal::SphericalAccumulator<T>::count(const Size &posPhi,
163 const Size &posTheta) const
165 ASSERT( isValidBin(posPhi,posTheta) );
166 return myAccumulator[posTheta + posPhi*myNtheta];
168 // --------------------------------------------------------
169 template <typename T>
172 DGtal::SphericalAccumulator<T>::representativeDirection(const Size &posPhi,
173 const Size &posTheta) const
175 ASSERT( isValidBin(posPhi,posTheta) );
176 Vector p=myAccumulatorDir[posTheta + posPhi*myNtheta] ;
179 // --------------------------------------------------------
180 template <typename T>
183 DGtal::SphericalAccumulator<T>::representativeDirection(ConstIterator &it) const
185 Size dist = it - myAccumulator.begin();
186 Vector p = *(myAccumulatorDir.begin() + dist);
189 // --------------------------------------------------------
190 // --------------------------------------------------------
191 template <typename T>
194 DGtal::SphericalAccumulator<T>::binCoordinates(ConstIterator &it,
196 Size &posTheta) const
198 Size dist = it - myAccumulator.begin();
199 posPhi = dist/ myNtheta;
200 posTheta = dist % myNtheta;
202 // --------------------------------------------------------
203 template <typename T>
206 DGtal::SphericalAccumulator<T>::isValidBin(const Size &posPhi,
207 const Size &posTheta) const
209 ASSERT( myNphi != 1 );
210 double dphi = M_PI/((double)myNphi-1.0);
211 double Ntheta_i = floor(2.0*((double)myNphi)*sin((double)posPhi*dphi));
213 if ((posPhi == 0) || (posPhi == (myNphi-1)))
214 return (posTheta==0);
216 return (posPhi < myNphi) && (posTheta<Ntheta_i) && (posTheta< myNtheta);
218 // --------------------------------------------------------
219 template <typename T>
222 DGtal::SphericalAccumulator<T>::getBinGeometry(const Size &posPhi,
223 const Size &posTheta,
229 ASSERT( isValidBin(posPhi,posTheta) );
230 double dphi = M_PI/(double)((double)myNphi-1);
231 double phi= (double)posPhi*dphi;
233 double Nthetai = floor(2.0*(myNphi)*sin(phi) );
236 if ((posPhi == 0) ||(posPhi == (myNphi-1)))
238 a[0]=cos(theta-dphi/2.0)*sin(phi -dphi/2.0);
239 a[1]=sin(theta-dphi/2.0)*sin(phi -dphi/2.0);
240 a[2]=cos(phi -dphi/2.0);
242 b[0]=cos(theta+dphi/2.0)*sin(phi -dphi/2.0);
243 b[1]=sin(theta+dphi/2.0)*sin(phi -dphi/2.0);
244 b[2]=cos(phi -dphi/2.0);
246 c[0]=cos(theta-dphi/2.0)*sin(phi+dphi/2.0);
247 c[1]=sin(theta-dphi/2.0)*sin(phi+dphi/2.0);
248 c[2]=cos(phi+dphi/2.0);
250 d[0]=cos(theta+dphi/2.0)*sin(phi+dphi/2.0);
251 d[1]=sin(theta+dphi/2.0)*sin(phi+dphi/2.0);
252 d[2]=cos(phi+dphi/2.0);
257 dtheta = 2.0*M_PI/(Nthetai);
258 theta=posTheta*dtheta;
260 a[0]=cos(theta-dtheta/2.0)*sin(phi -dphi/2.0);
261 a[1]=sin(theta-dtheta/2.0)*sin(phi -dphi/2.0);
262 a[2]=cos(phi -dphi/2.0);
265 if ((double)posTheta -1 >= Nthetai)
267 b[0]=cos(-dtheta/2.0)*sin(phi -dphi/2.0);
268 b[1]=sin(-dtheta/2.0)*sin(phi -dphi/2.0);
269 b[2]=cos(phi -dphi/2.0);
271 c[0]=cos(- dtheta/2.0)*sin(phi+dphi/2.0);
272 c[1]=sin( - dtheta/2.0)*sin(phi+dphi/2.0);
273 c[2]=cos(phi+dphi/2.0);
277 b[0]=cos(theta+dtheta/2.0)*sin(phi -dphi/2.0);
278 b[1]=sin(theta+dtheta/2.0)*sin(phi -dphi/2.0);
279 b[2]=cos(phi -dphi/2.0);
281 c[0]=cos(theta+dtheta/2.0)*sin(phi+dphi/2.0);
282 c[1]=sin(theta+dtheta/2.0)*sin(phi+dphi/2.0);
283 c[2]=cos(phi+dphi/2.0);
286 d[0]=cos(theta-dtheta/2.0)*sin(phi+dphi/2.0);
287 d[1]=sin(theta-dtheta/2.0)*sin(phi+dphi/2.0);
288 d[2]=cos(phi+dphi/2.0);
291 // --------------------------------------------------------
292 template <typename T>
294 typename DGtal::SphericalAccumulator<T>::RealVector
295 DGtal::SphericalAccumulator<T>::getBinDirection(const Size &posPhi,
296 const Size &posTheta) const
298 ASSERT( isValidBin(posPhi,posTheta) );
299 double dphi = M_PI/(double)((double)myNphi-1);
300 double phi= (double)posPhi*dphi;
301 double Nthetai = floor(2.0*(myNphi)*sin(phi) );
305 if ((posPhi == 0) || (posPhi == (myNphi-1)))
308 theta=posTheta*2.0*M_PI/(Nthetai);
310 midpoint[0]=cos(theta)*sin(phi);
311 midpoint[1]=sin(theta)*sin(phi);
312 midpoint[2]=cos(phi);
316 // --------------------------------------------------------
317 template <typename T>
320 DGtal::SphericalAccumulator<T>::clear()
323 for(Size i=0; i < myNphi; i++)
324 for(Size j=0; j < myNtheta; j++)
326 myAccumulator[j + i*myNtheta]=0;
328 myAccumulator[j+ i*myNtheta]=-1;
330 std::fill(myAccumulatorDir.begin(), myAccumulatorDir.end(), Vector::zero);
334 ///////////////////////////////////////////////////////////////////////////////
335 // Interface - public :
338 * Writes/Displays the object on an output stream.
339 * @param out the output stream where the object is written.
341 template <typename T>
344 DGtal::SphericalAccumulator<T>::selfDisplay ( std::ostream & out ) const
346 out << "[SphericalAccumulator] Nphi="<<myNphi<<" Ntheta=" <<myNtheta
347 <<" Number of samples="<<myTotal
348 <<" Number of bins="<<myBinNumber;
352 * Checks the validity/consistency of the object.
353 * @return 'true' if the object is valid, 'false' otherwise.
355 template <typename T>
358 DGtal::SphericalAccumulator<T>::isValid() const
365 ///////////////////////////////////////////////////////////////////////////////
366 // Implementation of inline functions //
368 template <typename T>
371 DGtal::operator<< ( std::ostream & out,
372 const SphericalAccumulator<T> & object )
374 object.selfDisplay( out );
379 ///////////////////////////////////////////////////////////////////////////////