00001
00002
00003
00004
00005
00006
00007
00008
00013 #ifndef vector_misc_h
00014 #define vector_misc_h
00015
00016 #include <cml/mathlib/coord_conversion.h>
00017
00018
00019
00020 namespace cml {
00021
00022
00023
00024
00025
00026
00027
00028 template < class VecT_1, class VecT_2 >
00029 typename detail::CrossPromote<VecT_1,VecT_2>::promoted_vector
00030 project_to_hplane(const VecT_1& v, const VecT_2& n)
00031 {
00032 typedef typename detail::CrossPromote<VecT_1,VecT_2>::promoted_vector
00033 result_type;
00034
00035 result_type result;
00036 et::detail::Resize(result, v.size());
00037
00038 result = v - dot(v,n) * n;
00039 return result;
00040 }
00041
00042
00043 template < class VecT > vector< typename VecT::value_type, fixed<2> >
00044 perp(const VecT& v)
00045 {
00046 typedef vector< typename VecT::value_type, fixed<2> > temporary_type;
00047
00048
00049 detail::CheckVec2(v);
00050
00051 return temporary_type(-v[1],v[0]);
00052 }
00053
00054
00055
00056
00057
00058
00060 template< class LeftT, class RightT >
00061 typename detail::CrossPromote<LeftT,RightT>::promoted_vector
00062 unit_cross(const LeftT& left, const RightT& right) {
00063
00064 return normalize(cross(left,right));
00065 }
00066
00068 template < class VecT > vector< typename VecT::value_type, fixed<3> >
00069 cross_cardinal(const VecT& v, size_t i)
00070 {
00071 typedef vector< typename VecT::value_type, fixed<3> > vector_type;
00072 typedef typename vector_type::value_type value_type;
00073
00074
00075 detail::CheckVec3(v);
00076 detail::CheckIndex3(i);
00077
00078 size_t j, k;
00079 cyclic_permutation(i, i, j, k);
00080 vector_type result;
00081 result[i] = value_type(0);
00082 result[j] = v[k];
00083 result[k] = -v[j];
00084 return result;
00085 }
00086
00088 template < class VecT > vector< typename VecT::value_type, fixed<3> >
00089 cross_cardinal(size_t i, const VecT& v)
00090 {
00091 typedef vector< typename VecT::value_type, fixed<3> > vector_type;
00092 typedef typename vector_type::value_type value_type;
00093
00094
00095 detail::CheckVec3(v);
00096 detail::CheckIndex3(i);
00097
00098 size_t j, k;
00099 cyclic_permutation(i, i, j, k);
00100 vector_type result;
00101 result[i] = value_type(0);
00102 result[j] = -v[k];
00103 result[k] = v[j];
00104 return result;
00105 }
00106
00108 template< class VecT_1, class VecT_2, typename Real >
00109 vector<
00110 typename et::ScalarPromote<
00111 typename VecT_1::value_type,
00112 typename VecT_2::value_type
00113 >::type,
00114 fixed<3>
00115 >
00116 rotate_vector(const VecT_1& v, const VecT_2& n, Real angle)
00117 {
00118 typedef vector<
00119 typename et::ScalarPromote<
00120 typename VecT_1::value_type,
00121 typename VecT_2::value_type
00122 >::type,
00123 fixed<3>
00124 > result_type;
00125
00126
00127 detail::CheckVec3(v);
00128 detail::CheckVec3(n);
00129
00130 result_type parallel = dot(v,n)*n;
00131 return (
00132 std::cos(angle)*(v-parallel) + std::sin(angle)*cross(n,v) + parallel
00133 );
00134 }
00135
00137 template< class VecT, typename Real >
00138 vector< typename VecT::value_type, fixed<2> >
00139 rotate_vector_2D(const VecT& v, Real angle)
00140 {
00141 typedef vector< typename VecT::value_type, fixed<2> > result_type;
00142 typedef typename result_type::value_type value_type;
00143
00144
00145 detail::CheckVec2(v);
00146
00147 value_type s = std::sin(angle);
00148 value_type c = std::cos(angle);
00149
00150 return result_type(c * v[0] - s * v[1], s * v[0] + c * v[1]);
00151 }
00152
00172 template < typename E, class A > void
00173 random_unit(vector<E,A>& v)
00174 {
00175 typedef vector<E,A> vector_type;
00176 typedef typename vector_type::value_type value_type;
00177
00178 switch (v.size()) {
00179 case 3:
00180 {
00181 vector< E, fixed<3> > temp;
00182 spherical_to_cartesian(
00183 value_type(1),
00184 value_type(random_unit() * constants<value_type>::two_pi()),
00185 acos_safe(random_real(value_type(-1),value_type(1))),
00186 2,
00187 colatitude,
00188 temp
00189 );
00190 v[0] = temp[0];
00191 v[1] = temp[1];
00192 v[2] = temp[2];
00193 break;
00194 }
00195 case 2:
00196 {
00197 vector< E, fixed<2> > temp;
00198 polar_to_cartesian(
00199 value_type(1),
00200 value_type(random_unit() * constants<value_type>::two_pi()),
00201 temp
00202 );
00203 v[0] = temp[0];
00204 v[1] = temp[1];
00205 break;
00206 }
00207 default:
00208 throw std::invalid_argument(
00209 "random_unit() for N-d vectors not implemented yet");
00210 break;
00211 }
00212 }
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 template < typename E, class A, class VecT > void
00229 random_unit(vector<E,A>& v, const VecT& axis, E theta)
00230 {
00231 typedef vector<E,A> vector_type;
00232 typedef typename vector_type::value_type value_type;
00233
00234 switch (v.size()) {
00235 case 3:
00236 {
00237 vector< E, fixed<3> > temp, n, temp_axis;
00238 temp_axis[0] = axis[0];
00239 temp_axis[1] = axis[1];
00240 temp_axis[2] = axis[2];
00241
00242
00243 n = axis_3D(cml::index_of_min_abs(axis[0],axis[1],axis[2]));
00244 n = cross(n,temp_axis);
00245
00246
00247
00248
00249 temp = rotate_vector(temp_axis,n,random_real(-theta,theta));
00250
00251
00252
00253 temp = rotate_vector(
00254 temp,
00255 temp_axis,
00256 random_real(
00257 -constants<value_type>::pi(),
00258 constants<value_type>::pi()
00259 )
00260 );
00261
00262 v[0] = temp[0];
00263 v[1] = temp[1];
00264 v[2] = temp[2];
00265 break;
00266 }
00267 case 2:
00268 {
00269 vector< E, fixed<2> > temp, temp_axis;
00270 temp_axis[0] = axis[0];
00271 temp_axis[1] = axis[1];
00272 temp = rotate_vector_2D(temp_axis, random_real(-theta,theta));
00273 v[0] = temp[0];
00274 v[1] = temp[1];
00275 break;
00276 }
00277 default:
00278 throw std::invalid_argument(
00279 "random_unit(v,axis,theta) only implemented for 2D and 3D");
00280 break;
00281 }
00282 }
00283
00284
00285
00286 template< class VecT_1, class VecT_2 >
00287 typename detail::DotPromote< VecT_1, VecT_2 >::promoted_scalar
00288 manhattan_distance(const VecT_1& v1, const VecT_2& v2) {
00289
00290 typedef typename et::VectorPromote<
00291 VecT_1,VecT_2>::temporary_type promoted_vector;
00292
00293 typedef typename detail::DotPromote< VecT_1, VecT_2 >::promoted_scalar scalar_type;
00294
00295 scalar_type sum = scalar_type(0);
00296 for (size_t i = 0; i < v1.size(); ++i) {
00297 sum += std::fabs(v2[i]-v1[i]);
00298 }
00299 return sum;
00300 }
00301
00302 }
00303
00304 #endif