Go to the documentation of this file.00001 #ifndef OPENTISSUE_COLLISION_GJK_GJK_SUPPORT_FUNCTORS_CONE_H
00002 #define OPENTISSUE_COLLISION_GJK_GJK_SUPPORT_FUNCTORS_CONE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_is_number.h>
00013
00014 #include <cmath>
00015 #include <cassert>
00016
00017 namespace OpenTissue
00018 {
00019 namespace gjk
00020 {
00033 template<typename math_types>
00034 class Cone
00035 {
00036 protected:
00037
00038 typedef typename math_types::real_type T;
00039 typedef typename math_types::vector3_type V;
00040 typedef typename math_types::value_traits value_traits;
00041
00042 T m_half_height;
00043 T m_base_radius;
00044
00045 public:
00046
00052 T const & half_height() const { this->m_half_height; }
00053 T & half_height() { this->m_half_height; }
00054
00060 T const & base_radius() const { this->m_base_radius; }
00061 T & base_radius() { this->m_base_radius; }
00062
00063 public:
00064
00065 Cone()
00066 : m_half_height( value_traits::one() )
00067 , m_base_radius( value_traits::one() )
00068 {}
00069
00070 public:
00071
00072 V operator()(V const & v) const
00073 {
00074 using std::sqrt;
00075
00076 assert( this->m_half_height >= value_traits::zero() || !"Cone::operator(): Negative half height");
00077 assert( this->m_base_radius >= value_traits::zero() || !"Cone::operator(): Negative base radius");
00078
00079 T vv = dot(v,v);
00080 assert( is_number(vv) || !"Cone::operator(): NaN encountered");
00081
00082
00083 if (vv <= value_traits::zero() )
00084 {
00085 return V( value_traits::zero(), value_traits::zero(), -this->m_half_height );
00086 }
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166 T const sine_alpha = this->m_base_radius / (value_traits::two()*this->m_half_height);
00167
00168 assert( is_number( sine_alpha ) || !"Cone::operator(): NaN encountered");
00169 assert( sine_alpha >= value_traits::zero() || !"Cone::operator(): sine(alpha) can not be negative");
00170 assert( sine_alpha <= value_traits::one() || !"Cone::operator(): sine(alpha) can not be larger than one");
00171
00172 T const norm_v = sqrt(vv);
00173 assert( is_number( norm_v ) || !"Cone::operator(): NaN encountered");
00174 assert( norm_v >= value_traits::zero() || !"Cone::operator(): Norm can not be negative");
00175
00176
00177 if( v(2) >= norm_v*sine_alpha)
00178 {
00179 V const s = V( value_traits::zero(), value_traits::zero(), this->m_half_height );
00180 assert( is_number( s(0) ) || !"Cone::operator(): NaN encountered");
00181 assert( is_number( s(1) ) || !"Cone::operator(): NaN encountered");
00182 assert( is_number( s(2) ) || !"Cone::operator(): NaN encountered");
00183 return s;
00184 }
00185
00186 T const norm_sigma = sqrt( v(0)*v(0) + v(1)*v(1) );
00187
00188 assert( is_number( norm_sigma ) || !"Cone::operator(): NaN encountered");
00189 assert( norm_sigma >= value_traits::zero() || !"Cone::operator(): Norm can not be negative");
00190
00191
00192 if(norm_sigma > value_traits::zero() )
00193 {
00194 V const s = V( this->m_base_radius*v(0)/norm_sigma, this->m_base_radius*v(1)/norm_sigma, -(this->m_half_height) );
00195 assert( is_number( s(0) ) || !"Cone::operator(): NaN encountered");
00196 assert( is_number( s(1) ) || !"Cone::operator(): NaN encountered");
00197 assert( is_number( s(2) ) || !"Cone::operator(): NaN encountered");
00198 return s;
00199 }
00200
00201
00202 return V( value_traits::zero(), value_traits::zero(), -this->m_half_height );
00203 }
00204
00205 };
00206
00207 }
00208
00209 }
00210
00211
00212 #endif