ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/algorithm/angle.hpp
Go to the documentation of this file.
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