Developer Documentation
Spherical.hh
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 /*===========================================================================*\
43  * *
44  * $Revision$ *
45  * $Author$ *
46  * $Date$ *
47  * *
48 \*===========================================================================*/
49 
50 
51 /*
52  * Spherical.hh
53  *
54  * Created on: Sep 18, 2012
55  * Author: ebke
56  */
57 
58 #ifndef ACG_GEOMETRY_SPHERICAL_HH_
59 #define ACG_GEOMETRY_SPHERICAL_HH_
60 
61 #include <ACG/Math/GLMatrixT.hh>
62 #include <cmath>
63 #include <stdexcept>
64 
65 namespace ACG {
66 namespace Geometry {
67 
68 static const double epsilon = 1e-6;
69 
70 namespace Spherical_Private {
71 
72 template<class Vec>
73 static inline typename Vec::value_type angleBetween(const Vec &v1, const Vec &v2, const Vec &normal) {
74  typedef typename Vec::value_type Scalar;
75 
76  /*
77  * Handle unstable 0 degree special case.
78  * (0 degrees can easily become 360 degrees.)
79  */
80  const Scalar dotProd = v1 | v2;
81  if (std::abs(dotProd - 1.0) < epsilon) return 0;
82 
83  /*
84  * General case: Use determinant to check >/< 180 degree.
85  */
86  const Scalar det = GLMatrixT<Scalar>(normal, v1, v2).determinant();
87 
88  /*
89  * Interpret arc cos accrodingly.
90  */
91  const Scalar arcos_angle = std::acos(std::max(-1.0, std::min(1.0, dotProd)));
92 
93  if (det >= -1e-6)
94  return arcos_angle;
95  else
96  return 2 * M_PI - arcos_angle;
97 }
98 
99 template<class Vec>
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);
103 }
104 
105 } /* namespace Spherical_Private */
106 
117 template<class Vec>
118 static inline typename Vec::value_type sphericalInnerAngleSum(const Vec &n0, const Vec &n1, const Vec &n2) {
119  typedef typename Vec::value_type Scalar;
120 
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;
125 
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);
131 
132 #ifndef NDEBUG
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");
136 #endif
137 
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))));
141 
142  return 2 * (alpha_2 + beta_2 + gamma_2);
143 }
144 
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;
155 
156  if (normals_begin == normals_end) return 0;
157  Vec n0 = *(normals_begin++);
158 
159  if (normals_begin == normals_end) return 0;
160  Vec n2 = *(normals_begin++);
161 
162  Scalar result = 0;
163  while (normals_begin != normals_end) {
164  /*
165  * Next triangle.
166  */
167  const Vec n1 = n2;
168  n2 = *(normals_begin++);
169 
170  const Scalar sign = GLMatrixT<Scalar>(n0, n1, n2).determinant() >= 0 ? 1 : -1;
171  result += sign * (sphericalInnerAngleSum(n0, n1, n2) - M_PI);
172  }
173 
174  return result;
175 }
176 
177 } /* namespace Geometry */
178 } /* namespace ACG */
179 
180 #endif /* ACG_GEOMETRY_SPHERICAL_HH_ */
Namespace providing different geometric functions concerning angles.
Definition: DBSCANT.cc:51