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 ------------------------------
46DGtal::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))
77DGtal::SphericalAccumulator<T>::~SphericalAccumulator()
80// --------------------------------------------------------
83void 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// --------------------------------------------------------
124void 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// --------------------------------------------------------
144typename DGtal::SphericalAccumulator<T>::Quantity
145DGtal::SphericalAccumulator<T>::samples() const
149// --------------------------------------------------------
153DGtal::SphericalAccumulator<T>::maxCountBin(Size &phi, Size &theta) const
156 theta = myMaxBinTheta;
158// --------------------------------------------------------
161typename DGtal::SphericalAccumulator<T>::Quantity
162DGtal::SphericalAccumulator<T>::count(const Size &posPhi,
163 const Size &posTheta) const
165 ASSERT( isValidBin(posPhi,posTheta) );
166 return myAccumulator[posTheta + posPhi*myNtheta];
168// --------------------------------------------------------
172DGtal::SphericalAccumulator<T>::representativeDirection(const Size &posPhi,
173 const Size &posTheta) const
175 ASSERT( isValidBin(posPhi,posTheta) );
176 Vector p=myAccumulatorDir[posTheta + posPhi*myNtheta] ;
179// --------------------------------------------------------
183DGtal::SphericalAccumulator<T>::representativeDirection(ConstIterator &it) const
185 Size dist = it - myAccumulator.begin();
186 Vector p = *(myAccumulatorDir.begin() + dist);
189// --------------------------------------------------------
190// --------------------------------------------------------
194DGtal::SphericalAccumulator<T>::binCoordinates(ConstIterator &it,
196 Size &posTheta) const
198 Size dist = it - myAccumulator.begin();
199 posPhi = dist/ myNtheta;
200 posTheta = dist % myNtheta;
202// --------------------------------------------------------
206DGtal::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// --------------------------------------------------------
222DGtal::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// --------------------------------------------------------
294typename DGtal::SphericalAccumulator<T>::RealVector
295DGtal::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// --------------------------------------------------------
320DGtal::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.
344DGtal::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.
358DGtal::SphericalAccumulator<T>::isValid() const
365///////////////////////////////////////////////////////////////////////////////
366// Implementation of inline functions //
371DGtal::operator<< ( std::ostream & out,
372 const SphericalAccumulator<T> & object )
374 object.selfDisplay( out );
379///////////////////////////////////////////////////////////////////////////////