Developer Documentation
Loading...
Searching...
No Matches
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#ifndef ACG_GEOMETRY_SPHERICAL_HH_
43#define ACG_GEOMETRY_SPHERICAL_HH_
44
45#include <ACG/Math/GLMatrixT.hh>
46#include <cmath>
47#include <stdexcept>
48
49namespace ACG {
50namespace Geometry {
51
52static const double epsilon = 1e-6;
53
54namespace Spherical_Private {
55
56template<class Vec>
57static inline typename Vec::value_type angleBetween(const Vec &v1, const Vec &v2, const Vec &normal) {
58 typedef typename Vec::value_type Scalar;
59
60 /*
61 * Handle unstable 0 degree special case.
62 * (0 degrees can easily become 360 degrees.)
63 */
64 const Scalar dotProd = v1 | v2;
65 if (std::abs(dotProd - 1.0) < epsilon) return 0;
66
67 /*
68 * General case: Use determinant to check >/< 180 degree.
69 */
70 const Scalar det = GLMatrixT<Scalar>(normal, v1, v2).determinant();
71
72 /*
73 * Interpret arc cos accrodingly.
74 */
75 const Scalar arcos_angle = std::acos(std::max(-1.0, std::min(1.0, dotProd)));
76
77 if (det >= -1e-6)
78 return arcos_angle;
79 else
80 return 2 * M_PI - arcos_angle;
81}
82
83template<class Vec>
84static inline typename Vec::value_type angleBetween(const Vec &v1, const Vec &v2) {
85 const Vec normal = (v1 % v2).normalized();
86 return angleBetween(v1, v2, normal);
87}
88
89} /* namespace Spherical_Private */
90
101template<class Vec>
102static inline typename Vec::value_type sphericalInnerAngleSum(const Vec &n0, const Vec &n1, const Vec &n2) {
103 typedef typename Vec::value_type Scalar;
104
105 const Scalar a = Spherical_Private::angleBetween(n0, n1);
106 const Scalar b = Spherical_Private::angleBetween(n1, n2);
107 const Scalar c = Spherical_Private::angleBetween(n2, n0);
108 if (a < epsilon || b < epsilon || c < epsilon) return M_PI;
109
110 const Scalar s = .5 * (a + b + c);
111 const Scalar sin_s = std::sin(s);
112 const Scalar sin_a = std::sin(a);
113 const Scalar sin_b = std::sin(b);
114 const Scalar sin_c = std::sin(c);
115
116#ifndef NDEBUG
117 if (std::sin(s - a) < -1e-4) throw std::logic_error("ACG::Geometry::sphericalInnerAngleSum(): 0 > s-a");
118 if (std::sin(s - b) < -1e-4) throw std::logic_error("ACG::Geometry::sphericalInnerAngleSum(): 0 > s-b");
119 if (std::sin(s - c) < -1e-4) throw std::logic_error("ACG::Geometry::sphericalInnerAngleSum(): 0 > s-c");
120#endif
121
122 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))));
123 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))));
124 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))));
125
126 return 2 * (alpha_2 + beta_2 + gamma_2);
127}
128
136template<class Vec, class INPUT_ITERATOR>
137static inline typename Vec::value_type sphericalPolyhedralGaussCurv(INPUT_ITERATOR normals_begin, INPUT_ITERATOR normals_end) {
138 typedef typename Vec::value_type Scalar;
139
140 if (normals_begin == normals_end) return 0;
141 Vec n0 = *(normals_begin++);
142
143 if (normals_begin == normals_end) return 0;
144 Vec n2 = *(normals_begin++);
145
146 Scalar result = 0;
147 while (normals_begin != normals_end) {
148 /*
149 * Next triangle.
150 */
151 const Vec n1 = n2;
152 n2 = *(normals_begin++);
153
154 const Scalar sign = GLMatrixT<Scalar>(n0, n1, n2).determinant() >= 0 ? 1 : -1;
155 result += sign * (sphericalInnerAngleSum(n0, n1, n2) - M_PI);
156 }
157
158 return result;
159}
160
161} /* namespace Geometry */
162} /* namespace ACG */
163
164#endif /* ACG_GEOMETRY_SPHERICAL_HH_ */
Namespace providing different geometric functions concerning angles.