Allolib  1.0
C++ Components For Interactive Multimedia
al_Spherical.hpp
1 #ifndef INCLUDE_AL_SPHERICAL_HPP
2 #define INCLUDE_AL_SPHERICAL_HPP
3 
4 /* Allocore --
5  Multimedia / virtual environment application class library
6 
7  Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
8  Copyright (C) 2012. The Regents of the University of California.
9  All rights reserved.
10 
11  Redistribution and use in source and binary forms, with or without
12  modification, are permitted provided that the following conditions are met:
13 
14  Redistributions of source code must retain the above copyright notice,
15  this list of conditions and the following disclaimer.
16 
17  Redistributions in binary form must reproduce the above copyright
18  notice, this list of conditions and the following disclaimer in the
19  documentation and/or other materials provided with the distribution.
20 
21  Neither the name of the University of California nor the names of its
22  contributors may be used to endorse or promote products derived from
23  this software without specific prior written permission.
24 
25  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  POSSIBILITY OF SUCH DAMAGE.
36 
37 
38  File description:
39  A collection of classes related to spherical geometry
40 
41  File author(s):
42  Lance Putnam, 2011, putnam.lance@gmail.com
43 */
44 
45 #include "al/math/al_Complex.hpp"
46 #include "al/math/al_Functions.hpp"
47 #include "al/math/al_Vec.hpp"
48 
49 namespace al {
50 
51 template <class T>
52 class SphereCoord;
53 
56 
58 
63 template <class T>
64 void sphericalToCart(T& r2x, T& t2y, T& p2z);
65 
67 template <class T>
68 void sphericalToCart(T* vec3);
69 
71 
76 template <class T>
77 void cartToSpherical(T& x2r, T& y2t, T& z2p);
78 
80 template <class T>
81 void cartToSpherical(T* vec3);
82 
84 
89 template <int N, class T>
90 Vec<N - 1, T> sterProj(const Vec<N, T>& v);
91 
93 
99 template <class T>
100 class SphereCoord {
101  public:
102  typedef Complex<T> C;
103 
104  C t;
105  C p;
106 
108  SphereCoord(const C& theta = C(1, 0), const C& phi = C(1, 0))
109  : t(theta), p(phi) {}
110 
112  template <class U>
113  SphereCoord(const Vec<3, U>& v) {
114  fromCart(v);
115  }
116 
118  SphereCoord operator-() const { return SphereCoord(t, -p); }
119  SphereCoord& operator*=(T v) {
120  p *= v;
121  return *this;
122  }
123  SphereCoord operator*(T v) const { return SphereCoord(t, p * v); }
124 
126  T radius() const { return p.mag(); }
127 
129  Vec<3, T> toCart() const { return Vec<3, T>(t.r * p.i, t.i * p.i, p.r); }
130 
132 
136  SphereCoord& fromAngle(const T& theta, const T& phi, const T& radius = T(1)) {
137  t.fromPolar(theta);
138  p.fromPolar(radius, phi);
139  return *this;
140  }
141 
143  template <class U>
145  t.set(v[0], v[1]);
146  T tmag = t.mag();
147  p.set(v[2], tmag);
148  tmag != 0 ? t *= (1. / tmag) : t.set(1, 0);
149  return *this;
150  }
151 };
152 
154 
166 template <int L_MAX = 16>
168  public:
169  SphericalHarmonic() { createLUT(); }
170 
172 
179  template <class T>
180  Complex<T> operator()(int l, int m, const Complex<T>& ctheta,
181  const Complex<T>& cphi) const {
182  return coef(l, m) * al::legendreP(l, std::abs(m), cphi.r, cphi.i) *
183  expim(m, ctheta);
184  }
185 
186  template <class T>
187  static Complex<T> expim(int m, const Complex<T>& ctheta) {
188  Complex<T> res = al::powN(ctheta, std::abs(m));
189  if (m < 0) res.i = -res.i;
190  return res;
191  }
192 
194  static double coef(int l, int m) {
195  return l <= L_MAX ? coefTab(l, m) : coefCalc(l, m);
196  }
197 
199  static const double& coefTab(int l, int m) { return LUT(l, m); }
200 
202  static double coefCalc(int l, int m) {
203  int M = std::abs(m);
204  double res = ::sqrt((2 * l + 1) / M_4PI) * al::factorialSqrt(l - M) /
205  al::factorialSqrt(l + M);
206  return (m < 0 && al::odd(M)) ? -res : res;
207  }
208 
209  private:
210  // this holds precomputed coefficients for each basis
211  static double& LUT(int l, int m) {
212  static double t[L_MAX + 1][L_MAX * 2 + 1];
213  return t[l][m + L_MAX];
214  }
215 
216  static void createLUT() {
217  static bool make = true;
218  if (make) {
219  make = false;
220  for (int l = 0; l <= L_MAX; ++l) {
221  for (int m = -L_MAX; m <= L_MAX; ++m) {
222  double c = 0;
223  // m must be in [-l,l]
224  if (std::abs(m) <= l) c = coefCalc(l, m);
225  LUT(l, m) = c;
226  }
227  }
228  }
229  }
230 };
231 
233 static SphericalHarmonic<> spharm;
234 
235 // Implementation
236 //------------------------------------------------------------------------------
237 
238 template <class T>
239 void sphericalToCart(T& r, T& t, T& p) {
240  T rsinp = r * sin(p);
241  T rcosp = r * cos(p);
242  r = rsinp * cos(t);
243  t = rsinp * sin(t);
244  p = rcosp;
245 }
246 
247 template <class T>
248 inline void sphericalToCart(T* vec3) {
249  sphericalToCart(vec3[0], vec3[1], vec3[2]);
250 }
251 
252 template <class T>
253 void cartToSpherical(T& x, T& y, T& z) {
254  T r = sqrt(x * x + y * y + z * z);
255  T t = atan2(y, x);
256  z = acos(z / r);
257  y = t;
258  x = r;
259 }
260 
261 template <class T>
262 inline void cartToSpherical(T* vec3) {
263  cartToSpherical(vec3[0], vec3[1], vec3[2]);
264 }
265 
266 template <int N, class T>
267 inline Vec<N - 1, T> sterProj(const Vec<N, T>& v) {
268  return sub<N - 1>(v) * (T(1) / v[N - 1]);
269 }
270 
271 } // namespace al
272 
273 #endif
C & set(T vr, T vi)
Set real and imaginary components.
Definition: al_Complex.hpp:129
T i
Imaginary component.
Definition: al_Complex.hpp:102
T r
Real component.
Definition: al_Complex.hpp:101
T mag() const
Returns norm (radius), |z|.
Definition: al_Complex.hpp:272
C & fromPolar(T phase)
Set phase and normalize.
Definition: al_Complex.hpp:119
Spherical coordinate in terms of two complex numbers.
SphereCoord & fromAngle(const T &theta, const T &phi, const T &radius=T(1))
Set from two angles, in radians, and radius.
SphereCoord operator-() const
Get negation in Cartesian space.
C p
Phi component, latitudinal angle (angle from +z axis)
T radius() const
Get radius.
SphereCoord(const Vec< 3, U > &v)
Vec< 3, T > toCart() const
Returns Cartesian coordinate.
SphereCoord & fromCart(const Vec< 3, U > &v)
Set from Cartesian coordinate.
C t
Theta component, longitudinal angle (angle from +x towards +y)
Spherical harmonic evaluator using cached coefficients.
static double coefCalc(int l, int m)
Get normalization coefficient (calculated)
Complex< T > operator()(int l, int m, const Complex< T > &ctheta, const Complex< T > &cphi) const
Evaluate spherical harmonic.
static const double & coefTab(int l, int m)
Get normalization coefficient (tabulated)
static double coef(int l, int m)
Get normalization coefficient.
Fixed-size n-vector.
Definition: al_Vec.hpp:117
Vec3 sterProj(const al::Complex< T > &c)
Definition: al_Complex.hpp:331
bool odd(const T &v)
T powN(T base, unsigned power)
Returns value to a positive integer power.
T legendreP(int l, int m, T t)
double factorialSqrt(int v)
Definition: al_App.hpp:23
Vec< M, T > sub(const Vec< N, T > &v, int begin=0)
Get a subvector.
Definition: al_Vec.hpp:568
SphereCoord< double > SphereCoordd
double SphereCoord
void cartToSpherical(T &x2r, T &y2t, T &z2p)
Convert Cartesian to spherical coordinates in-place.
SphereCoord< float > SphereCoordf
float SphereCoord
void sphericalToCart(T &r2x, T &t2y, T &p2z)
Convert spherical to Cartesian coordinates in-place.