ViennaGrid - The Vienna Grid Library
2.1.0
|
00001 #ifndef VIENNAGRID_ALGORITHM_ANGLE_HPP 00002 #define VIENNAGRID_ALGORITHM_ANGLE_HPP 00003 00004 /* ======================================================================= 00005 Copyright (c) 2011-2014, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 00009 ----------------- 00010 ViennaGrid - The Vienna Grid Library 00011 ----------------- 00012 00013 License: MIT (X11), see file LICENSE in the base directory 00014 ======================================================================= */ 00015 00016 #include "viennagrid/algorithm/inner_prod.hpp" 00017 #include "viennagrid/algorithm/cross_prod.hpp" 00018 #include "viennagrid/algorithm/norm.hpp" 00019 00024 namespace viennagrid 00025 { 00026 00028 template<typename PointT> 00029 typename viennagrid::result_of::coord<PointT>::type angle(PointT const & v0, PointT const & v1) 00030 { 00031 typedef typename viennagrid::result_of::coord<PointT>::type ValueType; 00032 00033 ValueType numerator = viennagrid::inner_prod(v0, v1); 00034 ValueType denominator = viennagrid::norm_2(v0) * viennagrid::norm_2(v1); 00035 if (numerator > denominator) //possible due to round-off 00036 return 0; 00037 if (numerator < -denominator) 00038 return std::acos(static_cast<ValueType>(-1)); 00039 return std::acos( numerator / denominator ); 00040 } 00041 00043 template<typename PointT> 00044 typename viennagrid::result_of::coord<PointT>::type angle(PointT const & p0, PointT const & p1, PointT const & origin) 00045 { 00046 PointT v0 = p0 - origin; 00047 PointT v1 = p1 - origin; 00048 00049 return angle(v0, v1); 00050 } 00051 00053 // http://en.wikipedia.org/wiki/Solid_angle#Tetrahedron 00054 template<typename PointT> 00055 typename viennagrid::result_of::coord<PointT>::type solid_angle(PointT const & a, PointT const & b, PointT const & c) 00056 { 00057 typedef typename viennagrid::result_of::coord<PointT>::type coord_type; 00058 00059 coord_type determinant = a[0]*b[1]*c[2] + b[0]*c[1]*a[2] + c[0]*a[1]*b[2] - a[2]*b[1]*c[0] - b[2]*c[1]*a[0] - c[2]*a[1]*b[0]; 00060 00061 coord_type al = viennagrid::norm_2(a); 00062 coord_type bl = viennagrid::norm_2(b); 00063 coord_type cl = viennagrid::norm_2(c); 00064 00065 coord_type div = al*bl*cl + viennagrid::inner_prod(a,b)*cl + viennagrid::inner_prod(a,c)*bl + viennagrid::inner_prod(b,c)*al; 00066 coord_type at = std::atan2(determinant, div); 00067 00068 return std::abs(2*at); 00069 } 00070 00072 template<typename PointT> 00073 typename viennagrid::result_of::coord<PointT>::type solid_angle(PointT const & p0, PointT const & p1, PointT const & p2, PointT const & origin) 00074 { 00075 PointT v0 = p0 - origin; 00076 PointT v1 = p1 - origin; 00077 PointT v2 = p2 - origin; 00078 00079 return solid_angle(v0, v1, v2); 00080 } 00081 00082 00084 template<typename PointT> 00085 typename viennagrid::result_of::coord<PointT>::type dihedral_angle( PointT const & p0, PointT const & p1, PointT const & p2, 00086 PointT const & q0, PointT const & q1, PointT const & q2) 00087 { 00088 PointT np = viennagrid::cross_prod( p1-p0, p2-p0 ); 00089 PointT nq = viennagrid::cross_prod( q1-q0, q2-q0 ); 00090 00091 return angle(np, nq); 00092 } 00093 00094 00095 // /** @brief Implementation of the solid angle from an origin to p0, p1 and p2, same as angle(origin, p0, p1, p2) */ 00096 // same as above, http://en.wikipedia.org/wiki/Solid_angle#Tetrahedron 00097 //template<typename PointT> 00098 //typename viennagrid::result_of::coord<PointT>::type angle2( PointT const & origin, PointT const & a, PointT const & b, PointT const & c ) 00099 //{ 00100 // double da_ab = dihedral_angle( origin, a, c, origin, b, c ); 00101 // double da_ac = dihedral_angle( origin, a, b, origin, c, b ); 00102 // double da_bc = dihedral_angle( origin, b, a, origin, c, a ); 00103 // 00104 // return da_ab + da_ac + da_bc - M_PI; 00105 //} 00106 00107 } 00108 00109 #endif