inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_a3 00005 #define inlib_a3 00006 00007 #include "sqm" 00008 00009 #include <cmath> //sqrt 00010 00011 namespace inlib { 00012 namespace a3 { 00013 00014 // vec is an a3 00015 00016 template <class T> 00017 class vec : public array<T> { 00018 public: 00019 vec():array<T>(1,3){} 00020 vec(const T a_vec[3]):array<T>(1,3) { 00021 array<T>::m_vector[0] = a_vec[0]; 00022 array<T>::m_vector[1] = a_vec[1]; 00023 array<T>::m_vector[2] = a_vec[2]; 00024 } 00025 vec(const T& a0,const T& a1,const T& a2):array<T>(1,3) { 00026 array<T>::m_vector[0] = a0; 00027 array<T>::m_vector[1] = a1; 00028 array<T>::m_vector[2] = a2; 00029 } 00030 virtual ~vec() {} 00031 public: 00032 vec(const vec& a_from):array<T>(a_from){} 00033 vec& operator=(const vec& a_from) { 00034 array<T>::operator=(a_from); 00035 return *this; 00036 } 00037 public: 00038 T v0() const { return array<T>::m_vector[0];} 00039 T v1() const { return array<T>::m_vector[1];} 00040 T v2() const { return array<T>::m_vector[2];} 00041 00042 void v0(const T& a_value) { array<T>::m_vector[0] = a_value;} 00043 void v1(const T& a_value) { array<T>::m_vector[1] = a_value;} 00044 void v2(const T& a_value) { array<T>::m_vector[2] = a_value;} 00045 00046 void set_value(const T& a1,const T& a2,const T& a3) { 00047 array<T>::m_vector[0] = a1; 00048 array<T>::m_vector[1] = a2; 00049 array<T>::m_vector[2] = a3; 00050 } 00051 void set_value(const T aV[3]) { 00052 array<T>::m_vector[0] = aV[0]; 00053 array<T>::m_vector[1] = aV[1]; 00054 array<T>::m_vector[2] = aV[2]; 00055 } 00056 void value(T& a1,T& a2,T& a3) const { 00057 a1 = array<T>::m_vector[0]; 00058 a2 = array<T>::m_vector[1]; 00059 a3 = array<T>::m_vector[2]; 00060 } 00061 00062 bool set_value(unsigned int a_index,const T& a_value) { 00063 if(a_index>=3) return false; 00064 array<T>::m_vector[a_index] = a_value; 00065 return true; 00066 } 00067 00068 T length() const { 00069 T m0 = array<T>::m_vector[0]; 00070 T m1 = array<T>::m_vector[1]; 00071 T m2 = array<T>::m_vector[2]; 00072 return (T)::sqrt(m0*m0+m1*m1+m2*m2); 00073 } 00074 T normalize() { 00075 T norme = length(); 00076 if(norme==T()) return 0; 00077 divide(norme); 00078 return norme; 00079 } 00080 00081 T dot(const vec& aV) const { 00082 return (v0() * aV.v0() + 00083 v1() * aV.v1() + 00084 v2() * aV.v2()); 00085 } 00086 00087 public: //operators 00088 //vec operator-(const vec& a_v) const { 00089 // return vec(v0()-a_v.v0(), 00090 // v1()-a_v.v1(), 00091 // v1()-a_v.v2()); 00092 //} 00093 00094 }; 00095 00096 // sqm is an a33 00097 00098 template <class T> 00099 class sqm : public inlib::sqm<T> { 00100 public: 00101 sqm():inlib::sqm<T>(3){} 00102 virtual ~sqm() {} 00103 public: 00104 sqm(const sqm& a_from):inlib::sqm<T>(a_from){} 00105 sqm& operator=(const sqm& a_from) { 00106 inlib::sqm<T>::operator=(a_from); 00107 return *this; 00108 } 00109 public: 00110 void v00(const T& a_value) { array<T>::m_vector[0 + 0 * 3] = a_value;} 00111 void v10(const T& a_value) { array<T>::m_vector[1 + 0 * 3] = a_value;} 00112 void v20(const T& a_value) { array<T>::m_vector[2 + 0 * 3] = a_value;} 00113 00114 void v01(const T& a_value) { array<T>::m_vector[0 + 1 * 3] = a_value;} 00115 void v11(const T& a_value) { array<T>::m_vector[1 + 1 * 3] = a_value;} 00116 void v21(const T& a_value) { array<T>::m_vector[2 + 1 * 3] = a_value;} 00117 00118 void v02(const T& a_value) { array<T>::m_vector[0 + 2 * 3] = a_value;} 00119 void v12(const T& a_value) { array<T>::m_vector[1 + 2 * 3] = a_value;} 00120 void v22(const T& a_value) { array<T>::m_vector[2 + 2 * 3] = a_value;} 00121 00122 T v00() const { return array<T>::m_vector[0 + 0 * 3];} 00123 T v10() const { return array<T>::m_vector[1 + 0 * 3];} 00124 T v20() const { return array<T>::m_vector[2 + 0 * 3];} 00125 00126 T v01() const { return array<T>::m_vector[0 + 1 * 3];} 00127 T v11() const { return array<T>::m_vector[1 + 1 * 3];} 00128 T v21() const { return array<T>::m_vector[2 + 1 * 3];} 00129 00130 T v02() const { return array<T>::m_vector[0 + 2 * 3];} 00131 T v12() const { return array<T>::m_vector[1 + 2 * 3];} 00132 T v22() const { return array<T>::m_vector[2 + 2 * 3];} 00133 00134 virtual T determinant() const { 00135 T e00 = D22(v11(),v12(),v21(),v22()); 00136 T e01 = -D22(v01(),v02(),v21(),v22()); 00137 T e02 = D22(v01(),v02(),v11(),v12()); 00138 return ( v00() * e00 00139 + v10() * e01 00140 + v20() * e02); 00141 00142 } 00143 00144 bool invert(sqm<T>& a_result) const { 00145 a_result.v00( 00146 D22(v11(),v12(), 00147 v21(),v22())); 00148 a_result.v01( 00149 -D22(v01(),v02(), 00150 v21(),v22())); 00151 a_result.v02( 00152 D22(v01(),v02(), 00153 v11(),v12())); 00154 00155 T deter = 00156 v00() * a_result.v00() 00157 + v10() * a_result.v01() 00158 + v20() * a_result.v02(); 00159 00160 if(deter==array<T>::zero()) return false; 00161 00162 a_result.v10( 00163 -D22(v10(),v12(), 00164 v20(),v22())); 00165 a_result.v11( 00166 D22(v00(),v02(), 00167 v20(),v22())); 00168 a_result.v12( 00169 -D22(v00(),v02(), 00170 v10(),v12())); 00171 00172 a_result.v20( 00173 D22(v10(),v11(), 00174 v20(),v21())); 00175 a_result.v21( 00176 -D22(v00(),v01(), 00177 v20(),v21())); 00178 a_result.v22( 00179 D22(v00(),v01(), 00180 v10(),v11())); 00181 00182 a_result.multiply(1./deter); 00183 00184 return true; 00185 } 00186 private: 00187 T D22(const T& a_11,const T& a_12,const T& a_21,const T& a_22) const { 00188 return (a_11 * a_22 - a_21 * a_12); 00189 } 00190 }; 00191 00192 template <class T> 00193 class cbm : public array<T> { //cbm for cubic matrix. 00194 public: 00195 cbm():array<T>(3,3){} 00196 virtual ~cbm() {} 00197 public: 00198 cbm(const cbm& a_from):array<T>(a_from){} 00199 cbm& operator=(const cbm& a_from){ 00200 inlib::array<T>::operator=(a_from); 00201 return *this; 00202 } 00203 public: 00204 T value(unsigned int a1,unsigned int a2,unsigned int a3) const { 00205 return array<T>::m_vector[a1 + a2 * 3 + a3 * 9]; 00206 } 00207 00208 void value(unsigned int a1,unsigned int a2,unsigned int a3,const T& a_value) { 00209 array<T>::m_vector[a1 + a2 * 3 + a3 * 9] = a_value; 00210 } 00211 00212 void v000(const T& a_value) {array<T>::m_vector[0+0*3+0*9] = a_value;} 00213 void v100(const T& a_value) {array<T>::m_vector[1+0*3+0*9] = a_value;} 00214 void v200(const T& a_value) {array<T>::m_vector[2+0*3+0*9] = a_value;} 00215 void v010(const T& a_value) {array<T>::m_vector[0+1*3+0*9] = a_value;} 00216 void v110(const T& a_value) {array<T>::m_vector[1+1*3+0*9] = a_value;} 00217 void v210(const T& a_value) {array<T>::m_vector[2+1*3+0*9] = a_value;} 00218 void v020(const T& a_value) {array<T>::m_vector[0+2*3+0*9] = a_value;} 00219 void v120(const T& a_value) {array<T>::m_vector[1+2*3+0*9] = a_value;} 00220 void v220(const T& a_value) {array<T>::m_vector[2+2*3+0*9] = a_value;} 00221 00222 void v001(const T& a_value) {array<T>::m_vector[0+0*3+1*9] = a_value;} 00223 void v101(const T& a_value) {array<T>::m_vector[1+0*3+1*9] = a_value;} 00224 void v201(const T& a_value) {array<T>::m_vector[2+0*3+1*9] = a_value;} 00225 void v011(const T& a_value) {array<T>::m_vector[0+1*3+1*9] = a_value;} 00226 void v111(const T& a_value) {array<T>::m_vector[1+1*3+1*9] = a_value;} 00227 void v211(const T& a_value) {array<T>::m_vector[2+1*3+1*9] = a_value;} 00228 void v021(const T& a_value) {array<T>::m_vector[0+2*3+1*9] = a_value;} 00229 void v121(const T& a_value) {array<T>::m_vector[1+2*3+1*9] = a_value;} 00230 void v221(const T& a_value) {array<T>::m_vector[2+2*3+1*9] = a_value;} 00231 00232 void v002(const T& a_value) {array<T>::m_vector[0+0*3+2*9] = a_value;} 00233 void v102(const T& a_value) {array<T>::m_vector[1+0*3+2*9] = a_value;} 00234 void v202(const T& a_value) {array<T>::m_vector[2+0*3+2*9] = a_value;} 00235 void v012(const T& a_value) {array<T>::m_vector[0+1*3+2*9] = a_value;} 00236 void v112(const T& a_value) {array<T>::m_vector[1+1*3+2*9] = a_value;} 00237 void v212(const T& a_value) {array<T>::m_vector[2+1*3+2*9] = a_value;} 00238 void v022(const T& a_value) {array<T>::m_vector[0+2*3+2*9] = a_value;} 00239 void v122(const T& a_value) {array<T>::m_vector[1+2*3+2*9] = a_value;} 00240 void v222(const T& a_value) {array<T>::m_vector[2+2*3+2*9] = a_value;} 00241 00242 }; 00243 00244 template <class T> 00245 inline sqm<T> operator-(const sqm<T>& a1,const sqm<T>& a2) { 00246 sqm<T> res(a1); 00247 res.subtract(a2); 00248 return res; 00249 } 00250 template <class T> 00251 inline sqm<T> operator+(const sqm<T>& a1,const sqm<T>& a2) { 00252 sqm<T> res(a1); 00253 res.add(a2); 00254 return res; 00255 } 00256 template <class T> 00257 inline sqm<T> operator*(const sqm<T>& a1,const sqm<T>& a2) { 00258 sqm<T> res; 00259 a1.mx_mul(a2,res); 00260 return res; 00261 } 00262 00263 template <class T> 00264 inline sqm<T> commutator(const sqm<T>& a1,const sqm<T>& a2) { 00265 return a1*a2-a2*a1; 00266 } 00267 template <class T> 00268 inline sqm<T> anticommutator(const sqm<T>& a1,const sqm<T>& a2) { 00269 return a1*a2+a2*a1; 00270 } 00271 00275 00276 //template <class T> 00277 //class point : public vec<T> { 00278 //}; 00279 00280 // Parametric description: 00281 // l(t) = pos + t * dir 00282 00283 template <class T> 00284 class line { 00285 public: 00286 line(){} 00287 line(const vec<T>& a_p0,const vec<T>& a_p1) { 00288 // Construct a line from two points lying on the line. If you 00289 // want to construct a line from a position and a direction, use 00290 // line(p, p + d). 00291 // line is directed from p0 to p1. 00292 m_pos = a_p0; 00293 //m_dir = a_p1-a_p0; 00294 m_dir = a_p0; 00295 m_dir.multiply(-1); 00296 m_dir.add(a_p1); 00297 m_dir.normalize(); 00298 } 00299 virtual ~line() {} 00300 public: 00301 line(const line& a_from) 00302 :m_pos(a_from.m_pos) 00303 ,m_dir(a_from.m_dir) 00304 {} 00305 line& operator=(const line& a_from) { 00306 m_pos = a_from.m_pos; 00307 m_dir = a_from.m_dir; 00308 return *this; 00309 } 00310 public: 00311 void set_value(const vec<T>& a_p0,const vec<T>& a_p1) { 00312 // Set that value! 00313 m_pos = a_p0; 00314 //m_dir = a_p1-a_p0; 00315 m_dir = a_p0; 00316 m_dir.multiply(-1); 00317 m_dir.add(a_p1); 00318 m_dir.normalize(); 00319 } 00320 00321 const vec<T>& position() const {return m_pos;} 00322 const vec<T>& direction() const {return m_dir;} 00323 private: 00324 vec<T> m_pos; 00325 vec<T> m_dir; //normalized. 00326 }; 00327 00328 template <class T> 00329 class plane { 00330 public: 00331 plane(){} 00332 00333 plane(const vec<T>& a_p0,const vec<T>& a_p1,const vec<T>& a_p2) { 00334 // Construct a plane given 3 points. 00335 // Orientation is computed by taking (p1 - p0) x (p2 - p0) and 00336 // pointing the normal in that direction. 00337 00338 vec<T> P = a_p1; 00339 P.subtract(a_p0); 00340 vec<T> P2 = a_p2; 00341 P2.subtract(a_p0); 00342 m_normal = P.cross(P2); 00343 m_normal.normalize(); 00344 m_distance = 00345 m_normal.v0() * a_p0.v0() + 00346 m_normal.value1() * a_p0.value1() + 00347 m_normal.value2() * a_p0.value2(); 00348 } 00349 00350 plane(const vec<T>& a_normal,const T& a_distance){ 00351 // Construct a plane given normal and distance from origin along normal. 00352 // Orientation is given by the normal vector n. 00353 m_normal = a_normal; 00354 m_normal.normalize(); 00355 m_distance = a_distance; 00356 } 00357 00358 plane(const vec<T>& a_normal,const vec<T>& a_point){ 00359 // Construct a plane given normal and a point to pass through 00360 // Orientation is given by the normal vector n. 00361 m_normal = a_normal; 00362 m_normal.normalize(); 00363 m_distance = 00364 m_normal.v0() * a_point.v0() + 00365 m_normal.v1() * a_point.v1() + 00366 m_normal.v2() * a_point.v2(); 00367 } 00368 00369 virtual ~plane() {} 00370 public: 00371 plane(const plane& a_from) 00372 :m_normal(a_from.m_normal) 00373 ,m_distance(a_from.m_distance) 00374 {} 00375 plane& operator=(const plane& a_from) { 00376 m_normal = a_from.m_normal; 00377 m_distance = a_from.m_distance; 00378 return *this; 00379 } 00380 00381 public: 00382 void offset(const T& a_distance){ 00383 // Offset a plane by a given distance. 00384 m_distance += a_distance; 00385 } 00386 00387 bool intersect(const line<T>& a_line,vec<T>& a_intersection) const { 00388 // Intersect line and plane, returning true if there is an intersection 00389 // false if line is parallel to plane 00390 const vec<T>& pos = a_line.position(); 00391 const vec<T>& dir = a_line.direction(); 00392 T d = m_normal.dot(dir); 00393 if(d==array<T>::zero()) return false; 00394 T t = (m_distance - m_normal.dot(pos))/d; 00395 a_intersection = dir; 00396 a_intersection.multiply(t); 00397 a_intersection.add(pos); 00398 //a_intersection = pos + t * dir; 00399 return true; 00400 } 00401 00402 bool is_in_half_space(const vec<T>& a_point) const { 00403 // Returns true if the given point is within the half-space 00404 // defined by the plane 00405 //vec pos = m_normal * m_distance; 00406 vec<T> pos = m_normal; 00407 pos.multiply(-m_distance); 00408 pos.add(a_point); 00409 return (m_normal.dot(pos) >= array<T>::zero() ? true : false); 00410 } 00411 00412 const vec<T>& normal() const {return m_normal;} 00413 T distance_from_origin() const {return m_distance;} 00414 00415 T distance(const vec<T>& a_point) const { 00416 // Return the distance from point to plane. Positive distance means 00417 // the point is in the plane's half space. 00418 return a_point.dot(m_normal) - m_distance; 00419 } 00420 private: 00421 vec<T> m_normal; //normalized. 00422 T m_distance; 00423 }; 00424 00425 // not tested yet. 00426 template <class T> 00427 class clip { 00428 public: 00429 clip():m_cur(0){} 00430 virtual ~clip() {} 00431 private: 00432 clip(const clip& a_from):m_cur(0){} 00433 clip& operator=(const clip& a_from){return *this;} 00434 public: 00435 void reset() { 00436 m_data[0].clear(); 00437 m_data[1].clear(); 00438 m_cur = 0; 00439 } 00440 void add(const vec<T>& a_point) { 00441 m_data[m_cur].push_back(a_point); 00442 } 00443 00444 void execute(const plane<T>& plane) { 00445 //Clip polygon against plane. This might change the number of 00446 //vertices in the polygon. 00447 00448 unsigned int n = m_data[m_cur].size(); 00449 if (n == 0) return; 00450 00451 // create a loop : 00452 vec<T> dummy = m_data[m_cur][0]; 00453 m_data[m_cur].push_back(dummy); 00454 00455 const vec<T>& planeN = plane.normal(); 00456 00457 for(unsigned int i = 0; i < n; i++) { 00458 vec<T> v0 = m_data[m_cur][i]; 00459 vec<T> v1 = m_data[m_cur][i+1]; 00460 00461 T d0 = plane.distance(v0); 00462 T d1 = plane.distance(v1); 00463 00464 if (d0 >= 0.0f && d1 < 0.0f) { // exit plane 00465 vec<T> dir = v1-v0; 00466 // we know that v0 != v1 since we got here 00467 dir.normalize(); 00468 T dot = dir.dot(planeN); 00469 vec<T> newvertex = v0 - dir * (d0/dot); 00470 out_point(newvertex); 00471 } else if (d0 < 0.0f && d1 >= 0.0f) { // enter plane 00472 vec<T> dir = v1-v0; 00473 // we know that v0 != v1 since we got here 00474 dir.normalize(); 00475 T dot = dir.dot(planeN); 00476 vec<T> newvertex = v0 - dir * (d0/dot); 00477 out_point(newvertex); 00478 out_point(v1); 00479 } else if (d0 >= 0.0f && d1 >= 0.0f) { // in plane 00480 out_point(v1); 00481 } 00482 } 00483 m_data[m_cur].clear(); 00484 m_cur ^= 1; 00485 } 00486 00487 const std::vector< vec<T> >& result() const { 00488 return m_data[m_cur]; 00489 } 00490 00491 private: 00492 void out_point(const vec<T>& a_p) { 00493 m_data[m_cur ^ 1].push_back(a_p); 00494 } 00495 00496 private: 00497 std::vector< vec<T> > m_data[2]; 00498 unsigned int m_cur; 00499 }; 00500 00501 }} 00502 00503 #endif