3 namespace til { namespace geo
6 //---------------------------------------------------------------------------------------------
8 template < typename T >
9 inline T herons_formula(T a, T b, T c)
11 T s = (a + b + c) / T(2.0);
12 // NB: it actually happened that this product is negative even though a, b and c are positive.
13 // This happens when one of the numbers is very small compared to the others.
14 // So the max really is necessary.
15 return std::sqrt(std::max(s*(s-a)*(s-b)*(s-c), T(0)));
18 //---------------------------------------------------------------------------------------------
20 template < typename T >
21 inline T herons_formula(numeric_array<T,3> const & lengths)
23 return herons_formula(lengths[0], lengths[1], lengths[2]);
26 //---------------------------------------------------------------------------------------------
28 template < typename T >
29 inline T law_of_cosines(T a, T b, T c)
31 return (b*b + c*c - a*a) / (2*b*c);
34 //---------------------------------------------------------------------------------------------
36 template < typename T >
37 inline T law_of_tangents(T a, T b, T c, T area)
39 return 4 * area / (b*b + c*c - a*a);
42 //---------------------------------------------------------------------------------------------
44 template < typename T >
45 inline T law_of_tangents(T a, T b, T c)
47 return law_of_tangents(a, b, c, herons_formula(a, b, c));
50 //---------------------------------------------------------------------------------------------
52 // TODO: Add a policy to return the angle between 0 and 2PI, or between -PI and PI.
53 template < typename T >
54 inline T angle(T x, T y, T norm)
58 if (y < 0) return -M_PI - 2.0 * std::atan( y / (norm - x) );
59 else return M_PI - 2.0 * std::atan( y / (norm - x) );
61 else return 2.0 * std::atan( y / (norm + x) );
64 //---------------------------------------------------------------------------------------------
66 // TODO: a policy could be used for the case when the norm is too small.
67 template < typename T >
68 inline T angle(T x, T y)
71 if (norm < 128*std::numeric_limits<T>::epsilon())
75 norm = std::sqrt(norm);
76 return angle(x,y,norm);
79 //---------------------------------------------------------------------------------------------
81 /// Converts cartesian coordinates into spherical coordinates
82 template < typename T >
84 cartesian2spherical(T x, T y, T z, T & theta, T & phi, T & rho)
88 phi = std::acos(z / rho);
91 //---------------------------------------------------------------------------------------------
93 template < typename T >
96 spherical2cartesian(T theta, T phi, T rho, T & x, T & y, T & z)
98 T rsinphi = rho * std::sin(phi);
99 x = std::cos(theta) * rsinphi;
100 y = std::sin(theta) * rsinphi;
101 z = rho * std::cos(phi);
104 //---------------------------------------------------------------------------
106 template < typename TArray >
107 bool Triangle2Segment<TArray>::operator()
109 const TArray & A, ///< Input: first triangle vertex
110 const TArray & B, ///< Input: second triangle vertex
111 const TArray & C, ///< Input: third triangle vertex
112 TArray & X, ///< Output: first segment end
113 TArray & Y ///< Output: second segment end
116 const prec_type EPSILON = 128 * std::numeric_limits<prec_type>::epsilon();
118 if (norm_inf(m_N) < EPSILON)
121 if (norm_inf(m_N) < EPSILON)
125 this->doit(A, C, B, X, Y);
129 this->doit(A, B, C, X, Y);
134 //---------------------------------------------------------------------------
136 template < typename TArray >
137 void Triangle2Segment<TArray>::doit
139 const TArray & A, ///< Input: first triangle vertex
140 const TArray & B, ///< Input: second triangle vertex
141 const TArray & C, ///< Input: third triangle vertex
142 TArray & X, ///< Output: first segment end
143 TArray & Y ///< Output: second segment end
146 prec_type lambda = dot(m_N, C-A);
152 else if (lambda > norm2(m_N))
164 //---------------------------------------------------------------------------
166 template < typename TArray, typename TResArray >
167 bool TriangleNormal<TArray, TResArray >::operator()
169 const TArray & A, ///< Input: first triangle vertex
170 const TArray & B, ///< Input: second triangle vertex
171 const TArray & C, ///< Input: third triangle vertex
172 TResArray & N ///< Output: triangle normal
175 const prec_type EPSILON = 128 * std::numeric_limits<prec_type>::epsilon();
176 N = cross(B-A, C-A, prec<prec_type>());
177 if (norm_inf(N) > EPSILON) return true;
178 N = cross(C-B, A-B, prec<prec_type>());
179 if (norm_inf(N) > EPSILON) return true;
180 N = cross(A-C, B-C, prec<prec_type>());
181 if (norm_inf(N) > EPSILON) return true;
183 //throw InvalidTriangle();
186 //---------------------------------------------------------------------------
188 template < typename TArray, typename TResArray >
190 triangle_normal(const TArray & A, const TArray & B, const TArray & C, TResArray & result)
192 return TriangleNormal<TArray, TResArray>()(A,B,C, result);
195 }} // namespace til::geo