00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef coord_conversion_h
00014 #define coord_conversion_h
00015
00016 #include <cml/mathlib/checking.h>
00017 #include <cml/mathlib/epsilon.h>
00018 #include <cml/mathlib/helper.h>
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 namespace cml {
00033
00035
00037
00038
00039 template < typename E, class A > void
00040 cylindrical_to_cartesian(
00041 E radius, E theta, E height, size_t axis, vector<E,A>& v)
00042 {
00043 typedef vector<E,A> vector_type;
00044 typedef typename vector_type::value_type value_type;
00045
00046
00047 detail::CheckVec3(v);
00048 detail::CheckIndex3(axis);
00049
00050 size_t i, j, k;
00051 cyclic_permutation(axis, i, j, k);
00052
00053 v[i] = height;
00054 v[j] = std::cos(theta) * radius;
00055 v[k] = std::sin(theta) * radius;
00056 }
00057
00058
00059 template < typename E, class A > void
00060 spherical_to_cartesian(E radius, E theta, E phi, size_t axis,
00061 SphericalType type, vector<E,A>& v)
00062 {
00063 typedef vector<E,A> vector_type;
00064 typedef typename vector_type::value_type value_type;
00065
00066
00067 detail::CheckVec3(v);
00068 detail::CheckIndex3(axis);
00069
00070 if (type == latitude) {
00071 phi = constants<value_type>::pi_over_2() - phi;
00072 }
00073
00074 value_type sin_phi = std::sin(phi);
00075 value_type cos_phi = std::cos(phi);
00076 value_type sin_phi_r = sin_phi * radius;
00077
00078 size_t i, j, k;
00079 cyclic_permutation(axis, i, j, k);
00080
00081 v[i] = cos_phi * radius;
00082 v[j] = sin_phi_r * std::cos(theta);
00083 v[k] = sin_phi_r * std::sin(theta);
00084 }
00085
00086
00087 template < typename E, class A > void
00088 polar_to_cartesian(E radius, E theta, vector<E,A>& v)
00089 {
00090
00091 v.set(std::cos(theta) * double(radius), std::sin(theta) * double(radius));
00092 }
00093
00095
00097
00098
00099 template < class VecT, typename Real > void
00100 cartesian_to_cylindrical(const VecT& v, Real& radius, Real& theta,
00101 Real& height, size_t axis, Real tolerance = epsilon<Real>::placeholder())
00102 {
00103 typedef Real value_type;
00104
00105
00106 detail::CheckVec3(v);
00107 detail::CheckIndex3(axis);
00108
00109 size_t i, j, k;
00110 cyclic_permutation(axis, i, j, k);
00111
00112 radius = length(v[j],v[k]);
00113 theta = radius < tolerance ? value_type(0) : std::atan2(v[k],v[j]);
00114 height = v[i];
00115 }
00116
00117
00118 template < class VecT, typename Real > void
00119 cartesian_to_spherical(const VecT& v, Real& radius, Real& theta, Real& phi,
00120 size_t axis, SphericalType type,
00121 Real tolerance = epsilon<Real>::placeholder())
00122 {
00123 typedef Real value_type;
00124
00125
00126 detail::CheckVec3(v);
00127 detail::CheckIndex3(axis);
00128
00129 size_t i, j, k;
00130 cyclic_permutation(axis, i, j, k);
00131
00132 value_type len = length(v[j],v[k]);
00133 theta = len < tolerance ? value_type(0) : std::atan2(v[k],v[j]);
00134 radius = length(v[i], len);
00135 if (radius < tolerance) {
00136 phi = value_type(0);
00137 } else {
00138 phi = std::atan2(len,v[i]);
00139
00140 if (type == latitude) {
00141 phi = constants<value_type>::pi_over_2() - phi;
00142 }
00143 }
00144 }
00145
00146
00147 template < class VecT, typename Real > void
00148 cartesian_to_polar(const VecT& v, Real& radius, Real& theta,
00149 Real tolerance = epsilon<Real>::placeholder())
00150 {
00151 typedef Real value_type;
00152
00153
00154 detail::CheckVec2(v);
00155
00156 radius = v.length();
00157 theta = radius < tolerance ? value_type(0) : std::atan2(v[1],v[0]);
00158 }
00159
00160 }
00161
00162 #endif