|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// 3-dim real vector class
|
|
|
|
// $Id$
|
|
|
|
// Copyright (C) 2004 Georg Drenkhahn
|
|
|
|
//
|
|
|
|
// This file is free software; you can redistribute it and/or modify it under
|
|
|
|
// the terms of the GNU General Public License version 2 as published by the
|
|
|
|
// Free Software Foundation.
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#if !defined(NAN)
|
|
|
|
static inline double nan__()
|
|
|
|
{
|
|
|
|
static const unsigned int one = 1;
|
|
|
|
static const bool BigEndian = (*((unsigned char *) &one) == 0);
|
|
|
|
|
|
|
|
static const unsigned char be_nan_bytes[] = { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 };
|
|
|
|
static const unsigned char le_nan_bytes[] = { 0, 0, 0, 0, 0, 0, 0xf8, 0x7f };
|
|
|
|
|
|
|
|
return *( ( const double * )( BigEndian ? be_nan_bytes : le_nan_bytes ) );
|
|
|
|
}
|
|
|
|
# define NAN (::nan__())
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
|
|
|
|
#ifdef HAVE_NUMERIC_LIMITS
|
|
|
|
#include <limits>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <cerrno>
|
|
|
|
#include "vec3.h"
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
vec3<T>& vec3<T>::normalize()
|
|
|
|
{
|
|
|
|
T n = norm(*this);
|
|
|
|
if (n != 0)
|
|
|
|
{
|
|
|
|
(*this) /= n;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errno = EDOM; // indicate domain error
|
|
|
|
// TODO: throw an exception?
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
vec3<T>& vec3<T>::rotate(const vec3<T>& r)
|
|
|
|
{
|
|
|
|
T phi = norm(r);
|
|
|
|
if (phi != 0)
|
|
|
|
{
|
|
|
|
// part of vector which is parallel to r
|
|
|
|
vec3<T> par(r*(*this)/(r*r) * r);
|
|
|
|
// part of vector which is perpendicular to r
|
|
|
|
vec3<T> perp(*this);
|
|
|
|
std::valarray<T> &perp_ = perp;
|
|
|
|
perp -= std::valarray<T>(par);
|
|
|
|
// rotation direction, size of perp
|
|
|
|
vec3<T> rotdir(norm(perp) * normalized(crossprod(r,perp)));
|
|
|
|
*this = par + cos(phi)*perp + sin(phi)*rotdir;
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*--- static member functions ---*/
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T vec3<T>::cos_angle(const vec3<T>& a, const vec3<T>& b)
|
|
|
|
{
|
|
|
|
T den = norm(a) * norm(b);
|
|
|
|
T ret = 0;
|
|
|
|
// if |a|=0 or |b|=0 then angle is not defined. We return NAN in this case.
|
|
|
|
if (den != 0.0)
|
|
|
|
{
|
|
|
|
ret = a*b/den;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
errno = EDOM; // indicate domain error
|
|
|
|
#ifdef HAVE_NUMERIC_LIMITS
|
|
|
|
// TODO test
|
|
|
|
ret = std::numeric_limits<T>::quiet_NaN();
|
|
|
|
#else
|
|
|
|
ret = NAN; // return NAN from ISO C99
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
T vec3<T>::angle(const vec3<T>& a, const vec3<T>& b, const vec3<T>& c)
|
|
|
|
{
|
|
|
|
// if |a|=0 or |b|=0 then angle is not defined. We return NAN in this case.
|
|
|
|
T ang = vec3<T>::angle(a,b);
|
|
|
|
return (crossprod(a,b)*c<0) ?
|
|
|
|
T(2.*M_PI)-ang : ang;
|
|
|
|
}
|
|
|
|
|
|
|
|
// explicite instantiation
|
|
|
|
template class vec3<double>;
|