172 lines
5.3 KiB
C++
172 lines
5.3 KiB
C++
/*
|
|
WARNING - Do not remove this header.
|
|
|
|
This code is a templated version of the 'magic-software' spherical
|
|
interpolation code by Dave Eberly. The original (un-hacked) code can be
|
|
obtained from here: http://www.magic-software.com/gr_appr.htm
|
|
This code is derived from linintp2.h/cpp and sphrintp.h/cpp.
|
|
|
|
Dave Eberly says that the conditions for use are:
|
|
|
|
* You may distribute the original source code to others at no charge.
|
|
|
|
* You may modify the original source code and distribute it to others at
|
|
no charge. The modified code must be documented to indicate that it is
|
|
not part of the original package.
|
|
|
|
* You may use this code for non-commercial purposes. You may also
|
|
incorporate this code into commercial packages. However, you may not
|
|
sell any of your source code which contains my original and/or modified
|
|
source code. In such a case, you need to factor out my code and freely
|
|
distribute it.
|
|
|
|
* The original code comes with absolutely no warranty and no guarantee is
|
|
made that the code is bug-free.
|
|
|
|
This does not seem incompatible with GPL - so this modified version
|
|
is hereby placed under GPL along with the rest of FlightGear.
|
|
|
|
Christian Mayer
|
|
*/
|
|
|
|
#include <math.h>
|
|
#include "sphrintp.h"
|
|
|
|
static const double PI = 4.0*atan(1.0);
|
|
static const double TWOPI = 2.0*PI;
|
|
|
|
//---------------------------------------------------------------------------
|
|
template<class T>
|
|
SphereInterpolate<T>::SphereInterpolate (int n, const double* x,
|
|
const double* y, const double* z,
|
|
const T* f)
|
|
{
|
|
// Assumes (x[i],y[i],z[i]) is unit length for all 0 <= i < n.
|
|
// For complete spherical coverage, include the two antipodal points
|
|
// (0,0,1,f(0,0,1)) and (0,0,-1,f(0,0,-1)) in the data set.
|
|
|
|
cout << "Initialising spherical interpolator.\n";
|
|
cout << "[ 0%] Allocating memory \r";
|
|
|
|
theta = new double[3*n];
|
|
phi = new double[3*n];
|
|
func = new T[3*n];
|
|
|
|
// convert data to spherical coordinates
|
|
int i;
|
|
T empty;
|
|
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
GetSphericalCoords(x[i],y[i],z[i],theta[i],phi[i]);
|
|
func[i] = f[i];
|
|
}
|
|
|
|
// use periodicity to get wrap-around in the Delaunay triangulation
|
|
cout << "[ 10%] copying vertices for wrap-around\r";
|
|
int j, k;
|
|
for (i = 0, j = n, k = 2*n; i < n; i++, j++, k++)
|
|
{
|
|
theta[j] = theta[i]+TWOPI;
|
|
theta[k] = theta[i]-TWOPI;
|
|
phi[j] = phi[i];
|
|
phi[k] = phi[i];
|
|
func[j] = func[i];
|
|
func[k] = func[i];
|
|
}
|
|
|
|
pInterp = new mgcLinInterp2D<T>(3*n,theta,phi,func);
|
|
|
|
cout << "[100%] Finished initialising spherical interpolator. \n";
|
|
}
|
|
|
|
template<class T>
|
|
SphereInterpolate<T>::SphereInterpolate (int n, const sgVec2* p, const T* f)
|
|
{
|
|
// Assumes (x[i],y[i],z[i]) is unit length for all 0 <= i < n.
|
|
// For complete spherical coverage, include the two antipodal points
|
|
// (0,0,1,f(0,0,1)) and (0,0,-1,f(0,0,-1)) in the data set.
|
|
cout << "Initialising spherical interpolator.\n";
|
|
cout << "[ 0%] Allocating memory \r";
|
|
|
|
theta = new double[3*n];
|
|
phi = new double[3*n];
|
|
func = new T[3*n];
|
|
|
|
// convert data to spherical coordinates
|
|
cout << "[ 10%] copying vertices for wrap-around \r";
|
|
|
|
int i, j, k;
|
|
for (i = 0, j = n, k = 2*n; i < n; i++, j++, k++)
|
|
{
|
|
phi[i] = p[i][0];
|
|
theta[i] = p[i][1];
|
|
func[i] = f[i];
|
|
|
|
// use periodicity to get wrap-around in the Delaunay triangulation
|
|
phi[j] = phi[i];
|
|
phi[k] = phi[i];
|
|
theta[j] = theta[i]+TWOPI;
|
|
theta[k] = theta[i]-TWOPI;
|
|
func[j] = func[i];
|
|
func[k] = func[i];
|
|
}
|
|
|
|
pInterp = new mgcLinInterp2D<T>(3*n,theta,phi,func);
|
|
|
|
cout << "[100%] Finished initialising spherical interpolator. \n";
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
template<class T>
|
|
SphereInterpolate<T>::~SphereInterpolate ()
|
|
{
|
|
delete pInterp;
|
|
delete[] theta;
|
|
delete[] phi;
|
|
delete[] func;
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
template<class T>
|
|
void SphereInterpolate<T>::GetSphericalCoords (const double x, const double y, const double z,
|
|
double& thetaAngle,
|
|
double& phiAngle) const
|
|
{
|
|
// Assumes (x,y,z) is unit length. Returns -PI <= thetaAngle <= PI
|
|
// and 0 <= phiAngle <= PI.
|
|
|
|
if ( z < 1.0f )
|
|
{
|
|
if ( z > -1.0f )
|
|
{
|
|
thetaAngle = atan2(y,x);
|
|
phiAngle = acos(z);
|
|
}
|
|
else
|
|
{
|
|
thetaAngle = -PI;
|
|
phiAngle = PI;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
thetaAngle = -PI;
|
|
phiAngle = 0.0f;
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
template<class T>
|
|
int SphereInterpolate<T>::Evaluate (const double x, const double y, const double z, T& f) const
|
|
{
|
|
// assumes (x,y,z) is unit length
|
|
|
|
double thetaAngle, phiAngle;
|
|
GetSphericalCoords(x,y,z,thetaAngle,phiAngle);
|
|
return pInterp->Evaluate(thetaAngle,phiAngle,f);
|
|
}
|
|
//---------------------------------------------------------------------------
|
|
template<class T>
|
|
int SphereInterpolate<T>::Evaluate (const double thetaAngle, const double phiAngle, T& f) const
|
|
{
|
|
return pInterp->Evaluate(thetaAngle,phiAngle,f);
|
|
}
|
|
//---------------------------------------------------------------------------
|