coord_conversion.h

Go to the documentation of this file.
00001 /* -*- C++ -*- ------------------------------------------------------------
00002  
00003 Copyright (c) 2007 Jesse Anders and Demian Nave http://cmldev.net/
00004 
00005 The Configurable Math Library (CML) is distributed under the terms of the
00006 Boost Software License, v1.0 (see cml/LICENSE for details).
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 /* Functions for converting between Cartesian, polar, cylindrical and
00021  * spherical coordinates.
00022  *
00023  * The 3D conversion functions take an integer axis index argument. For
00024  * cylindrical coordinates this determines the axis of the cylinder, and for
00025  * spherical it determines which cardinal axis is normal to the azimuth plane.
00026  *
00027  * For spherical coordinates the option of whether to treat phi as latitude
00028  * or colatitude is also available. The 'type' argument takes either of the
00029  * enumerants cml::latitude and cml::colatitude to reflect this.
00030  */
00031 
00032 namespace cml {
00033 
00035 // Conversion to Cartesian coordinates
00037 
00038 /* Convert cylindrical coordinates to Cartesian coordinates in R3 */
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     /* Checking */
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 /* Convert spherical coordinates to Cartesian coordinates in R3 */
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     /* Checking */
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 /* Convert polar coordinates to Cartesian coordinates in R2 */
00087 template < typename E, class A > void
00088 polar_to_cartesian(E radius, E theta, vector<E,A>& v)
00089 {
00090     /* Checking handled by set() */
00091     v.set(std::cos(theta) * double(radius), std::sin(theta) * double(radius));
00092 }
00093 
00095 // Conversion from Cartesian coordinates
00097 
00098 /* Convert Cartesian coordinates to cylindrical coordinates in R3  */
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     /* Checking */
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 /* Convert Cartesian coordinates to spherical coordinates in R3 */
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     /* Checking */
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         //phi = type.convert(phi);
00140         if (type == latitude) {
00141             phi = constants<value_type>::pi_over_2() - phi;
00142         }
00143     }
00144 }
00145 
00146 /* Convert Cartesian coordinates to polar coordinates in R2 */
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     /* Checking */
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 } // namespace cml
00161 
00162 #endif

Generated on Sat Jul 18 19:35:21 2009 for CML 1.0 by  doxygen 1.5.9