58 #ifndef ACG_GEOMETRY_SPHERICAL_HH_
59 #define ACG_GEOMETRY_SPHERICAL_HH_
61 #include <ACG/Math/GLMatrixT.hh>
68 static const double epsilon = 1e-6;
70 namespace Spherical_Private {
73 static inline typename Vec::value_type angleBetween(
const Vec &v1,
const Vec &v2,
const Vec &normal) {
74 typedef typename Vec::value_type Scalar;
80 const Scalar dotProd = v1 | v2;
81 if (std::abs(dotProd - 1.0) < epsilon)
return 0;
86 const Scalar det = GLMatrixT<Scalar>(normal, v1, v2).determinant();
91 const Scalar arcos_angle = std::acos(std::max(-1.0, std::min(1.0, dotProd)));
96 return 2 * M_PI - arcos_angle;
100 static inline typename Vec::value_type angleBetween(
const Vec &v1,
const Vec &v2) {
101 const Vec normal = (v1 % v2).normalized();
102 return angleBetween(v1, v2, normal);
118 static inline typename Vec::value_type sphericalInnerAngleSum(
const Vec &n0,
const Vec &n1,
const Vec &n2) {
119 typedef typename Vec::value_type Scalar;
121 const Scalar a = Spherical_Private::angleBetween(n0, n1);
122 const Scalar b = Spherical_Private::angleBetween(n1, n2);
123 const Scalar c = Spherical_Private::angleBetween(n2, n0);
124 if (a < epsilon || b < epsilon || c < epsilon)
return M_PI;
126 const Scalar s = .5 * (a + b + c);
127 const Scalar sin_s = std::sin(s);
128 const Scalar sin_a = std::sin(a);
129 const Scalar sin_b = std::sin(b);
130 const Scalar sin_c = std::sin(c);
133 if (std::sin(s - a) < -1e-4)
throw std::logic_error(
"ACG::Geometry::sphericalInnerAngleSum(): 0 > s-a");
134 if (std::sin(s - b) < -1e-4)
throw std::logic_error(
"ACG::Geometry::sphericalInnerAngleSum(): 0 > s-b");
135 if (std::sin(s - c) < -1e-4)
throw std::logic_error(
"ACG::Geometry::sphericalInnerAngleSum(): 0 > s-c");
138 const Scalar alpha_2 = std::acos(std::min(1.0, std::sqrt(sin_s * std::max(.0, std::sin(s - a)) / (sin_b * sin_c))));
139 const Scalar beta_2 = std::acos(std::min(1.0, std::sqrt(sin_s * std::max(.0, std::sin(s - b)) / (sin_c * sin_a))));
140 const Scalar gamma_2 = std::acos(std::min(1.0, std::sqrt(sin_s * std::max(.0, std::sin(s - c)) / (sin_a * sin_b))));
142 return 2 * (alpha_2 + beta_2 + gamma_2);
152 template<
class Vec,
class INPUT_ITERATOR>
153 static inline typename Vec::value_type sphericalPolyhedralGaussCurv(INPUT_ITERATOR normals_begin, INPUT_ITERATOR normals_end) {
154 typedef typename Vec::value_type Scalar;
156 if (normals_begin == normals_end)
return 0;
157 Vec n0 = *(normals_begin++);
159 if (normals_begin == normals_end)
return 0;
160 Vec n2 = *(normals_begin++);
163 while (normals_begin != normals_end) {
168 n2 = *(normals_begin++);
170 const Scalar sign = GLMatrixT<Scalar>(n0, n1, n2).determinant() >= 0 ? 1 : -1;
171 result += sign * (sphericalInnerAngleSum(n0, n1, n2) - M_PI);
Namespace providing different geometric functions concerning angles.