triple.cpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. #include "triple.hpp"
  2. namespace sphereRemap {
  3. extern const Coord ORIGIN(0.0, 0.0, 0.0);
  4. std::ostream& operator<<(std::ostream& os, const Coord& c) {
  5. return os << "(" << c.x << ", " << c.y << ", " << c.z << ")";
  6. }
  7. std::ostream& operator<<(std::ostream& os, const Vector& vec)
  8. {
  9. return os << "(" << vec.u << ", " << vec.v << ", " << vec.w << ")";
  10. }
  11. double norm(const Coord &x)
  12. {
  13. return sqrt(x.x*x.x + x.y*x.y + x.z*x.z);
  14. }
  15. Coord proj(const Coord &x)
  16. {
  17. double n=norm(x);
  18. return Coord(x.x/n, x.y/n, x.z/n);
  19. }
  20. double scalarprod(const Coord &a, const Coord &b)
  21. {
  22. return a.x*b.x + a.y*b.y + a.z*b.z;
  23. }
  24. Coord crossprod(const Coord &a, const Coord &b)
  25. {
  26. return Coord(a.y*b.z - a.z*b.y,
  27. a.z*b.x - a.x*b.z,
  28. a.x*b.y - a.y*b.x);
  29. }
  30. /* arc distance (along great circle) */
  31. double arcdist(const Coord &x, const Coord &y)
  32. { // et angles aigus non orientes
  33. double n = norm(crossprod(x, y));
  34. if (n>1.) n=1. ;
  35. double a = asin(n);
  36. if (squaredist(x,y) > 2.0) a = M_PI - a;
  37. return a;
  38. }
  39. /* alternate way to compute distance along great circle */
  40. double ds(const Coord &x, const Coord &y)
  41. {
  42. return 2*asin(0.5*eucldist(x,y));
  43. }
  44. /* dp is both small circle distances */
  45. double dp(const Coord &x, const Coord &y, const Coord &pole)
  46. {
  47. return 2*asin(0.5 * eucldist(x,y) / sin(ds(pole,x)));
  48. }
  49. //* angle between `p` and `q` */
  50. /*double angle(const Vector &p, const Vector &q)
  51. {
  52. return acos(scalarprod(p, q));
  53. }*/
  54. void lonlat(const Coord &a, double &lon, double &lat)
  55. {
  56. lon = atan2(a.y, a.x) * 180.0/M_PI;
  57. lat = (M_PI_2 - acos(a.z)) * 180.0/M_PI;
  58. }
  59. Coord xyz(double lon, double lat)
  60. {
  61. double phi = M_PI/180.0*lon;
  62. double theta = M_PI_2 - M_PI/180.0*lat;
  63. return Coord(sin(theta)*cos(phi),
  64. sin(theta)*sin(phi),
  65. cos(theta));
  66. }
  67. /** computes the midpoint on spherical arc between a and b */
  68. Coord midpoint(const Coord &a, const Coord &b)
  69. {
  70. return proj(a + b);
  71. }
  72. /** computes the midpoint on *small circle* between a and b */
  73. Coord midpointSC(const Coord& p, const Coord& q)
  74. {
  75. double phi1 = atan2(p.y, p.x);
  76. double phi2 = atan2(q.y, q.x);
  77. if (phi1*phi2 < 0)
  78. phi1 += (phi1 < phi2) ? 2*M_PI : -2*M_PI;
  79. double theta = acos(p.z);
  80. double phi = 0.5*(phi1 + phi2);
  81. return Coord(sin(theta)*cos(phi),
  82. sin(theta)*sin(phi),
  83. cos(theta));
  84. }
  85. /* rotates us by angle theta around u (r is rotatiion matrix) */
  86. void Coord::rot(const Coord &u, double theta)
  87. {
  88. double x = this->x;
  89. double y = this->y;
  90. double z = this->z;
  91. double ux2 = u.x*u.x, uy2 = u.y*u.y, uz2 = u.z*u.z;
  92. double k = 1 - cos(theta);
  93. double r00 = ux2 + (1-ux2)*cos(theta), r01 = u.x*u.y*k - u.z*sin(theta), r02 = u.x*u.z*k + u.y*sin(theta);
  94. double r10 = u.x*u.y*k + u.z*sin(theta), r11 = uy2 + (1-uy2)*cos(theta), r12 = u.y*u.z*k - u.x*sin(theta);
  95. double r20 = u.x*u.z*k - u.y*sin(theta), r21 = u.y*u.z*k + u.x*sin(theta), r22 = uz2 + (1-uz2)*cos(theta);
  96. this->x = r00*x + r01*y + r02*z;
  97. this->y = r10*x + r11*y + r12*z;
  98. this->z = r20*x + r21*y + r22*z;
  99. }
  100. double angle(const Coord &a, const Coord &b, const Coord &pole)
  101. {
  102. return scalarprod(crossprod(a, b), pole);
  103. }
  104. // return oriented vector angle in range [-pi..pi], pole must be orthogonal to a and b
  105. double vectAngle(const Coord &a, const Coord &b, const Coord &pole)
  106. {
  107. double nab = 1./(norm(a)*norm(b)) ;
  108. Coord a_cross_b=crossprod(a, b)*nab ;
  109. double sinVect ;
  110. if (scalarprod(a_cross_b, pole) >= 0) sinVect=norm(a_cross_b) ;
  111. else sinVect=-norm(a_cross_b) ;
  112. double cosVect=scalarprod(a,b)*nab ;
  113. return atan2(sinVect,cosVect) ;
  114. }
  115. }