vector_ortho.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  *-----------------------------------------------------------------------*/
00015 #ifndef vector_ortho_h
00016 #define vector_ortho_h
00017 
00018 #include <cml/mathlib/vector_misc.h>
00019 #include <cml/mathlib/misc.h>
00020 
00021 namespace cml {
00022 
00024 // Orthonormalization in 3D and 2D
00026 
00027 
00042 template < typename E, class A > void
00043 orthonormalize(vector<E,A>& v0, vector<E,A>& v1, vector<E,A>& v2,
00044     size_t stable_axis = 2, size_t num_iter = 0, E s = E(1))
00045 {
00046     /* Checking */
00047     detail::CheckVec3(v0);
00048     detail::CheckVec3(v1);
00049     detail::CheckVec3(v2);
00050     detail::CheckIndex3(stable_axis);
00051 
00052     typedef vector< E, fixed<3> > vector_type;
00053     typedef typename vector_type::value_type value_type;
00054 
00055     /* Iterative Gram-Schmidt; this step is skipped by default. */
00056     
00057     for (size_t i = 0; i < num_iter; ++i) {
00058         value_type dot01 = dot(v0,v1);
00059         value_type dot12 = dot(v1,v2);
00060         value_type dot20 = dot(v2,v0);
00061         value_type inv_dot00 = value_type(1) / dot(v0,v0);
00062         value_type inv_dot11 = value_type(1) / dot(v1,v1);
00063         value_type inv_dot22 = value_type(1) / dot(v2,v2);
00064 
00065         vector_type temp0 = v0 - s*dot01*inv_dot11*v1 - s*dot20*inv_dot22*v2;
00066         vector_type temp1 = v1 - s*dot12*inv_dot22*v2 - s*dot01*inv_dot00*v0;
00067         vector_type temp2 = v2 - s*dot20*inv_dot00*v0 - s*dot12*inv_dot11*v1;
00068         
00069         v0 = temp0;
00070         v1 = temp1;
00071         v2 = temp2;
00072     }
00073 
00074     /* Final Gram-Schmidt step to ensure orthonormality. If no iterations
00075      * have been requested (num_iter = 0), this is the only step. The step
00076      * is performed such that the direction of the axis indexed by
00077      * 'stable_axis' is unchanged.
00078      */
00079 
00080     size_t i, j, k;
00081     cyclic_permutation(stable_axis, i, j, k);
00082     vector_type v[] = { v0, v1, v2 };
00083 
00084     v[i].normalize();
00085     v[j] = normalize(project_to_hplane(v[j],v[i]));
00086     v[k] = normalize(project_to_hplane(project_to_hplane(v[k],v[i]),v[j]));
00087     
00088     v0 = v[0];
00089     v1 = v[1];
00090     v2 = v[2];
00091 }
00092 
00094 template < typename E, class A > void
00095 orthonormalize(vector<E,A>& v0, vector<E,A>& v1,
00096     size_t stable_axis = 0, size_t num_iter = 0, E s = E(1))
00097 {
00098     typedef vector< E, fixed<2> > vector_type;
00099     typedef typename vector_type::value_type value_type;
00100 
00101     /* Checking */
00102     detail::CheckVec2(v0);
00103     detail::CheckVec2(v1);
00104     detail::CheckIndex2(stable_axis);
00105 
00106     /* Iterative Gram-Schmidt; this step is skipped by default. */
00107     
00108     for (size_t i = 0; i < num_iter; ++i) {
00109         value_type dot01 = dot(v0,v1);
00110 
00111         vector_type temp0 = v0 - (s * dot01 * v1) / dot(v1,v1);
00112         vector_type temp1 = v1 - (s * dot01 * v0) / dot(v0,v0);
00113         
00114         v0 = temp0;
00115         v1 = temp1;
00116     }
00117 
00118     /* Final Gram-Schmidt step to ensure orthonormality. If no iterations
00119      * have been requested (num_iter = 0), this is the only step. The step
00120      * is performed such that the direction of the axis indexed by
00121      * 'stable_axis' is unchanged.
00122      */
00123 
00124     size_t i, j;
00125     cyclic_permutation(stable_axis, i, j);
00126     vector_type v[] = { v0, v1 };
00127 
00128     v[i].normalize();
00129     v[j] = normalize(project_to_hplane(v[j],v[i]));
00130     
00131     v0 = v[0];
00132     v1 = v[1];
00133 }
00134 
00136 // Orthonormal basis construction in 3D and 2D
00138 
00158 template < class VecT_1, class VecT_2, typename E, class A > void
00159 orthonormal_basis(
00160     const VecT_1& align,
00161     const VecT_2& reference,
00162     vector<E,A>& x,
00163     vector<E,A>& y,
00164     vector<E,A>& z,
00165     bool normalize_align = true,
00166     AxisOrder order = axis_order_zyx)
00167 {
00168     typedef vector< E,fixed<3> > vector_type;
00169     typedef typename vector_type::value_type value_type;
00170     
00171     /* Checking handled by cross() and assignment to fixed<3>. */
00172     
00173     size_t i, j, k;
00174     bool odd;
00175     detail::unpack_axis_order(order, i, j, k, odd);
00176 
00177     vector_type axis[3];
00178 
00179     axis[i] = normalize_align ? normalize(align) : align;
00180     axis[k] = unit_cross(axis[i],reference);
00181     axis[j] = cross(axis[k],axis[i]);
00182     
00183     if (odd) {
00184         axis[k] = -axis[k];
00185     }
00186     
00187     x = axis[0];
00188     y = axis[1];
00189     z = axis[2];
00190 }
00191 
00200 template < class VecT, typename E, class A >
00201 void orthonormal_basis(
00202     const VecT& align,
00203     vector<E,A>& x,
00204     vector<E,A>& y,
00205     vector<E,A>& z,
00206     bool normalize_align = true,
00207     AxisOrder order = axis_order_zyx)
00208 {
00209     /* Checking (won't be necessary with index_of_min_abs() member function */
00210     detail::CheckVec3(align);
00211 
00212     /* @todo: vector member function index_of_min_abs() would clean this up */
00213     
00214     orthonormal_basis(
00215         align,
00216         axis_3D(cml::index_of_min_abs(align[0],align[1],align[2])),
00217         x, y, z, normalize_align, order
00218     );
00219 }
00220 
00234 template < class VecT_1, class VecT_2, typename E, class A >
00235 void orthonormal_basis_axial(
00236     const VecT_1& align,
00237     const VecT_2& axis,
00238     vector<E,A>& x,
00239     vector<E,A>& y,
00240     vector<E,A>& z,
00241     bool normalize_align = true,
00242     AxisOrder order = axis_order_zyx)
00243 {
00244     orthonormal_basis(
00245         axis,
00246         align,
00247         x,
00248         y,
00249         z,
00250         normalize_align,
00251         detail::swap_axis_order(order));
00252 }
00253 
00260 template < class MatT, typename E, class A >
00261 void orthonormal_basis_viewplane(
00262     const MatT& view_matrix,
00263     vector<E,A>& x,
00264     vector<E,A>& y,
00265     vector<E,A>& z,
00266     Handedness handedness,
00267     AxisOrder order = axis_order_zyx)
00268 {
00269     typedef MatT matrix_type;
00270     typedef typename matrix_type::value_type value_type;
00271 
00272     orthonormal_basis(
00273         -(handedness == left_handed ? value_type(1) : value_type(-1)) *
00274             matrix_get_transposed_z_basis_vector(view_matrix),
00275         matrix_get_transposed_y_basis_vector(view_matrix),
00276         x, y, z, false, order
00277     );
00278 }
00279 
00281 template < class MatT, typename E, class A >
00282 void orthonormal_basis_viewplane_LH(
00283     const MatT& view_matrix,
00284     vector<E,A>& x,
00285     vector<E,A>& y,
00286     vector<E,A>& z,
00287     AxisOrder order = axis_order_zyx)
00288 {
00289     orthonormal_basis_viewplane(
00290         view_matrix,x,y,z,left_handed,order);
00291 }
00292 
00294 template < class MatT, typename E, class A >
00295 void orthonormal_basis_viewplane_RH(
00296     const MatT& view_matrix,
00297     vector<E,A>& x,
00298     vector<E,A>& y,
00299     vector<E,A>& z,
00300     AxisOrder order = axis_order_zyx)
00301 {
00302     orthonormal_basis_viewplane(
00303         view_matrix,x,y,z,right_handed,order);
00304 }
00305 
00307 template < class VecT, typename E, class A >
00308 void orthonormal_basis_2D(
00309     const VecT& align,
00310     vector<E,A>& x,
00311     vector<E,A>& y,
00312     bool normalize_align = true,
00313     AxisOrder2D order = axis_order_xy)
00314 {
00315     typedef vector< E,fixed<2> > vector_type;
00316 
00317     /* Checking handled by perp() and assignment to fixed<2>. */
00318 
00319     size_t i, j;
00320     bool odd;
00321     detail::unpack_axis_order_2D(order, i, j, odd);
00322     
00323     vector_type axis[2];
00324 
00325     axis[i] = normalize_align ? normalize(align) : align;
00326     axis[j] = perp(axis[i]);
00327 
00328     if (odd) {
00329         axis[j] = -axis[j];
00330     }
00331 
00332     x = axis[0];
00333     y = axis[1];
00334 }
00335 
00336 } // namespace cml
00337 
00338 #endif

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