IntpSphere2.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. // David Eberly, Geometric Tools, Redmond WA 98052
  2. // Copyright (c) 1998-2020
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // https://www.boost.org/LICENSE_1_0.txt
  5. // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
  6. // Version: 4.0.2019.08.13
  7. #pragma once
  8. #include <Mathematics/Delaunay2Mesh.h>
  9. #include <Mathematics/IntpQuadraticNonuniform2.h>
  10. #include <memory>
  11. // Interpolation of a scalar-valued function defined on a sphere. Although
  12. // the sphere lives in 3D, the interpolation is a 2D method whose input
  13. // points are angles (theta,phi) from spherical coordinates. The domains of
  14. // the angles are -pi <= theta <= pi and 0 <= phi <= pi.
  15. namespace WwiseGTE
  16. {
  17. template <typename InputType, typename ComputeType, typename RationalType>
  18. class IntpSphere2
  19. {
  20. public:
  21. // Construction and destruction. For complete spherical coverage,
  22. // include the two antipodal (theta,phi) points (-pi,0,F(-pi,0)) and
  23. // (-pi,pi,F(-pi,pi)) in the input data. These correspond to the
  24. // sphere poles x = 0, y = 0, and |z| = 1.
  25. ~IntpSphere2() = default;
  26. IntpSphere2(int numPoints, InputType const* theta, InputType const* phi, InputType const* F)
  27. :
  28. mMesh(mDelaunay)
  29. {
  30. // Copy the input data. The larger arrays are used to support
  31. // wrap-around in the Delaunay triangulation for the interpolator.
  32. int totalPoints = 3 * numPoints;
  33. mWrapAngles.resize(totalPoints);
  34. mWrapF.resize(totalPoints);
  35. for (int i = 0; i < numPoints; ++i)
  36. {
  37. mWrapAngles[i][0] = theta[i];
  38. mWrapAngles[i][1] = phi[i];
  39. mWrapF[i] = F[i];
  40. }
  41. // Use periodicity to get wrap-around in the Delaunay
  42. // triangulation.
  43. int i0 = 0, i1 = numPoints, i2 = 2 * numPoints;
  44. for (/**/; i0 < numPoints; ++i0, ++i1, ++i2)
  45. {
  46. mWrapAngles[i1][0] = mWrapAngles[i0][0] + (InputType)GTE_C_TWO_PI;
  47. mWrapAngles[i2][0] = mWrapAngles[i0][0] - (InputType)GTE_C_TWO_PI;
  48. mWrapAngles[i1][1] = mWrapAngles[i0][1];
  49. mWrapAngles[i2][1] = mWrapAngles[i0][1];
  50. mWrapF[i1] = mWrapF[i0];
  51. mWrapF[i2] = mWrapF[i0];
  52. }
  53. mDelaunay(totalPoints, &mWrapAngles[0], (ComputeType)0);
  54. mInterp = std::make_unique<IntpQuadraticNonuniform2<InputType, TriangleMesh>>(
  55. mMesh, &mWrapF[0], (InputType)1);
  56. }
  57. // Spherical coordinates are
  58. // x = cos(theta)*sin(phi)
  59. // y = sin(theta)*sin(phi)
  60. // z = cos(phi)
  61. // for -pi <= theta <= pi, 0 <= phi <= pi. The application can use
  62. // this function to convert unit length vectors (x,y,z) to (theta,phi).
  63. static void GetSphericalCoordinates(InputType x, InputType y, InputType z,
  64. InputType& theta, InputType& phi)
  65. {
  66. // Assumes (x,y,z) is unit length. Returns -pi <= theta <= pi and
  67. // 0 <= phiAngle <= pi.
  68. if (z < (InputType)1)
  69. {
  70. if (z > -(InputType)1)
  71. {
  72. theta = std::atan2(y, x);
  73. phi = std::acos(z);
  74. }
  75. else
  76. {
  77. theta = -(InputType)GTE_C_PI;
  78. phi = (InputType)GTE_C_PI;
  79. }
  80. }
  81. else
  82. {
  83. theta = -(InputType)GTE_C_PI;
  84. phi = (InputType)0;
  85. }
  86. }
  87. // The return value is 'true' if and only if the input point is in the
  88. // convex hull of the input (theta,pi) array, in which case the
  89. // interpolation is valid.
  90. bool operator()(InputType theta, InputType phi, InputType& F) const
  91. {
  92. Vector2<InputType> angles{ theta, phi };
  93. InputType thetaDeriv, phiDeriv;
  94. return (*mInterp)(angles, F, thetaDeriv, phiDeriv);
  95. }
  96. private:
  97. typedef Delaunay2Mesh<InputType, ComputeType, RationalType> TriangleMesh;
  98. std::vector<Vector2<InputType>> mWrapAngles;
  99. Delaunay2<InputType, ComputeType> mDelaunay;
  100. TriangleMesh mMesh;
  101. std::vector<InputType> mWrapF;
  102. std::unique_ptr<IntpQuadraticNonuniform2<InputType, TriangleMesh>> mInterp;
  103. };
  104. }