The Higher Education and Research forge

Home My Page Projects Code Snippets Project Openings Garamon
Summary Activity SCM

SCM Repository

1 // Copyright (c) 2018 by University Paris-Est Marne-la-Vallee
2 // p3ga2Tools.hpp
3 // Authors: Stephane Breuils and Vincent Nozick
4 // Contact: vincent.nozick@u-pem.fr
6 /// \file qc3gaC3ga2P3ga2MappingTools.hpp
7 /// \author Stephane Breuils, Vincent Nozick
8 /// \brief some useful functions when using the mapping between double projective geometric algebra of R^3 (c3ga2).
9 ///  Use this file if you generated the lib using the "p3ga2.conf" configuration file. Double projective geometric algebra of R^3 is described in the following paper: Juan, D., Goldman, R., Mann, S.: Modeling 3D geometry in the Clifford Algebra R 4,4 . Adv. Appl. Clifford Algebras 27(4), 3039–3062 (2017)
13 // Anti-doublon
14 #ifndef QC3GAC3GA2P3GA2MAPPINGTOOLS_HPP__
15 #define QC3GAC3GA2P3GA2MAPPINGTOOLS_HPP__
16 #pragma once
18 // Internal Includes
19 #include <p3ga2/Mvec.hpp> // double  projective geometric algebra
20 #include <c3ga2/Mvec.hpp> // double  conformal  geometric algebra
21 #include <qc3ga/Mvec.hpp> // quadric conformal  geometric algebra
27     //////////////////////////////////////// P3GA2QUADRIC //////////////////////////////////////////
28 namespace p3ga2{
29     /// \brief build a point from a vector
30     /// \param x vector component related to e1
31     /// \param y vector component related to e2
32     /// \param z vector component related to e3
33     /// \return a multivector corresponding to a point of DPGA
34     template<typename T>
35     p3ga2::Mvec<T> point(const T &x, const T &y, const T &z){
37         p3ga2::Mvec<T> mv;
38         mv[p3ga2::E0] = x;
39         mv[p3ga2::E1] = y;
40         mv[p3ga2::E2] = z;
41         mv[p3ga2::E3] = 1.0;
43         return mv;
44     }
46     /// \brief build a dual point from a vector (actually, more a conjugate than a dual)
47     /// \param x vector component related to e1
48     /// \param y vector component related to e2
49     /// \param z vector component related to e3
50     /// \return a multivector corresponding to a dual point of DPGA
51     template<typename T>
52     p3ga2::Mvec<T> dualPoint(const T &x, const T &y, const T &z){
54         p3ga2::Mvec<T> mv;
55         mv[p3ga2::Ed0] = x;
56         mv[p3ga2::Ed1] = y;
57         mv[p3ga2::Ed2] = z;
58         mv[p3ga2::Ed3] = 1.0;
60         return mv;
61     }
63     /// \brief build a dual point from a vector (actually, more a conjugate than a dual)
64     /// \param pt point of DPGA
65     /// \return a multivector corresponding to a dual point of DPGA
66     template<typename T>
67     p3ga2::Mvec<T> dualPoint(const p3ga2::Mvec<T> &pt){
69         p3ga2::Mvec<T> dualPt;
70         dualPt[p3ga2::Ed0] = pt[p3ga2::E0];
71         dualPt[p3ga2::Ed1] = pt[p3ga2::E1];
72         dualPt[p3ga2::Ed2] = pt[p3ga2::E2];
73         dualPt[p3ga2::Ed3] = pt[p3ga2::E3];
75         return dualPt;
76     }
79     /// a quadric has the form (a b c d e f g h i j)
80     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0 
81     template<typename T>
82     std::vector<T> ga2quadric(const p3ga2::Mvec<T> &mv){
84         std::vector<T> quadric(10);
85         quadric[0] = - mv[p3ga2::E0d0] / 4.0;
86         quadric[1] = - mv[p3ga2::E1d1] / 4.0;
87         quadric[2] = - mv[p3ga2::E2d2] / 4.0;
88         quadric[9] = - mv[p3ga2::E3d3] / 4.0;
90         quadric[3] = - mv[p3ga2::E0d1] / 2.0;
91         quadric[4] = - mv[p3ga2::E0d2] / 2.0;
92         quadric[5] = - mv[p3ga2::E2d1] / 2.0;
93         quadric[6] = - mv[p3ga2::E0d3] / 2.0;
94         quadric[7] = - mv[p3ga2::E3d1] / 2.0;
95         quadric[8] = - mv[p3ga2::E2d3] / 2.0;
97         return quadric;
98     }
100     /// a quadric has the form (a b c d e f g h i j)
101     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0 
102     template<typename T>
103     p3ga2::Mvec<T> quadric2ga(const std::vector<T> &quadric){
105         p3ga2::Mvec<T> mv;
107         mv[p3ga2::E0d0] = - 4.0 * quadric[0];
108         mv[p3ga2::E1d1] = - 4.0 * quadric[1];
109         mv[p3ga2::E2d2] = - 4.0 * quadric[2];
110         mv[p3ga2::E3d3] = - 4.0 * quadric[9];
112         mv[p3ga2::E0d1] = mv[p3ga2::E1d0] = - 2.0 * quadric[3];
113         mv[p3ga2::E0d2] = mv[p3ga2::E2d0] = - 2.0 * quadric[4];
114         mv[p3ga2::E1d2] = mv[p3ga2::E2d1] = - 2.0 * quadric[5];
115         mv[p3ga2::E0d3] = mv[p3ga2::E3d0] = - 2.0 * quadric[6];
116         mv[p3ga2::E1d3] = mv[p3ga2::E3d1] = - 2.0 * quadric[7];
117         mv[p3ga2::E2d3] = mv[p3ga2::E3d2] = - 2.0 * quadric[8];
119         return mv;
120     }
122 } // namespace
126 //////////////////////////////////////// C3GA2 QUADRIC //////////////////////////////////////////
127 namespace c3ga2{
129    /// \brief build a point from a vector, see Equation (5.25) of the considered paper
130     /// \param x vector component 
131     /// \param y vector component 
132     /// \param z vector component 
133     /// \return a multivector corresponding to a point of DCGA
134     template<typename T>
135     c3ga2::Mvec<T> point(const T &x, const T &y, const T &z){
136        c3ga2::Mvec<T> c3ga2Point;
137         
138        c3ga2::Mvec<T> mvCGA1;
139         c3ga2::Mvec<T> mvCGA2;
140         mvCGA1[c3ga2::E01] = mvCGA2[c3ga2::E02] = 1.0;
141         mvCGA1[c3ga2::E1]  = mvCGA2[c3ga2::E4]  = x;
142         mvCGA1[c3ga2::E2]  = mvCGA2[c3ga2::E5]  = y;
143         mvCGA1[c3ga2::E3]  = mvCGA2[c3ga2::E6]  = z;
144         mvCGA1[c3ga2::Ei1] = mvCGA2[c3ga2::Ei2] = 0.5*(x*x+y*y+z*z);
146        c3ga2Point = mvCGA1^mvCGA2;
147         
148        return c3ga2Point;
149     }
152         /// \brief build Txsquared
153     /// \return the multivector corresponding to the Txsquared
154     template<typename T>
155     c3ga2::Mvec<T> Tx2(){
156        c3ga2::Mvec<T> mv;
157        mv[c3ga2::E14] = -1.0;
158         
159        return mv;
160     }
162     /// \brief build Tysquared
163     /// \return the multivector corresponding to the Tysquared
164     template<typename T>
165     c3ga2::Mvec<T> Ty2(){
166         c3ga2::Mvec<T> mv;
167         mv[c3ga2::E25] = -1.0;
168             
169         return mv;
170     }
172     /// \brief build Tzsquared
173     /// \return the multivector corresponding to the Tzsquared
174     template<typename T>
175     c3ga2::Mvec<T> Tz2(){
176         c3ga2::Mvec<T> mv;
177         mv[c3ga2::E36] = -1.0;
178         return mv;
179     }
182     /// \brief build the cross term operator Txy
183     /// \return the multivector corresponding to the operator Txy
184     template<typename T>
185     c3ga2::Mvec<T> Txy(){
186         c3ga2::Mvec<T> mv;
187         mv[c3ga2::E15] = -0.5;
188         mv[c3ga2::E24] = -0.5;
189         return mv;
190     }
193     /// \brief build the cross term operator Tzx
194     /// \return the multivector corresponding to the operator Tzx
195     template<typename T>
196     c3ga2::Mvec<T> Tzx(){
197         c3ga2::Mvec<T> mv;
198         mv[c3ga2::E16] = -0.5;
199         mv[c3ga2::E34] = -0.5;
200         return mv;
201     }
203     /// \brief build the cross term operator Tyz
204     /// \return the multivector corresponding to the operator Tyz
205     template<typename T>
206     c3ga2::Mvec<T> Tyz(){
207         c3ga2::Mvec<T> mv;
208         mv[c3ga2::E35] = -0.5;
209         mv[c3ga2::E26] = -0.5;
210         return mv;
211     }
214     /// \brief build the single term operator Tx
215     /// \return the multivector corresponding to the operator Tx
216     template<typename T>
217     c3ga2::Mvec<T> Tx(){
218         c3ga2::Mvec<T> mv;
219         mv[c3ga2::E1i2] = 0.5;
220         mv[c3ga2::Ei14] = 0.5;
221         return mv;
222     }
225     /// \brief build the single term operator Ty
226     /// \return the multivector corresponding to the operator Ty
227     template<typename T>
228     c3ga2::Mvec<T> Ty(){
229         c3ga2::Mvec<T> mv;
230         mv[c3ga2::E2i2] = 0.5;
231         mv[c3ga2::Ei15] = 0.5;
232         return mv;
233     }
235     /// \brief build the single term operator Tz
236     /// \return the multivector corresponding to the operator Tz
237     template<typename T>
238     c3ga2::Mvec<T> Tz(){
239         c3ga2::Mvec<T> mv;
240         mv[c3ga2::E3i2] = 0.5;
241         mv[c3ga2::Ei16] = 0.5;
242         return mv;
243     }
245     /// \brief build the unit term operator Tz
246     /// \return the multivector corresponding to the operator T1
247     template<typename T>
248     c3ga2::Mvec<T> T1(){
249         c3ga2::Mvec<T> mv;
250         mv[c3ga2::Ei1i2] = -1.0;
251         return mv;
252     }
256     /// \brief build the reciprocal squared term operator Tx2_reciprocal
257     /// \return the multivector corresponding to the reciprocal extraction operator Tx2
258     template<typename T>
259     c3ga2::Mvec<T> Tx2_reciprocal(){
260         return -Tx2<T>();
261     }
263     /// \brief build the reciprocal squared term operator Ty2_reciprocal
264     /// \return the multivector corresponding to the reciprocal extraction operator Ty2
265     template<typename T>
266     c3ga2::Mvec<T> Ty2_reciprocal(){
267         return -Ty2<T>();
268     }
270     /// \brief build the reciprocal squared term operator Tz2_reciprocal
271     /// \return the multivector corresponding to the reciprocal extraction operator Tz2
272     template<typename T>
273     c3ga2::Mvec<T> Tz2_reciprocal(){
274         return -Tz2<T>();
275     }
277     /// \brief build the reciprocal cross term operator Txy_reciprocal
278     /// \return the multivector corresponding to the reciprocal extraction operator Txy
279     template<typename T>
280     c3ga2::Mvec<T> Txy_reciprocal(){
281         return -2*Txy<T>();
282     }
284     /// \brief build the reciprocal cross term operator Tzx_reciprocal
285     /// \return the multivector corresponding to the reciprocal extraction operator Tzx
286     template<typename T>
287     c3ga2::Mvec<T> Tzx_reciprocal(){
288         return -2*Tzx<T>();
289     }
291     /// \brief build the reciprocal cross term operator Tzx_reciprocal
292     /// \return the multivector corresponding to the reciprocal extraction operator Tzx
293     template<typename T>
294     c3ga2::Mvec<T> Tyz_reciprocal(){
295         return -2*Tyz<T>();
296     }
298     /// \brief build the reciprocal single term operator Tx_reciprocal
299     /// \return the multivector corresponding to the reciprocal extraction operator Tx
300     template<typename T>
301     c3ga2::Mvec<T> Tx_reciprocal(){
302         c3ga2::Mvec<T> mv;
303         mv[c3ga2::E102] = 1.0;
304         mv[c3ga2::E014] = 1.0;
305         return mv;
306     }
308     /// \brief build the reciprocal single term operator Ty_reciprocal
309     /// \return the multivector corresponding to the reciprocal extraction operator Ty
310     template<typename T>
311     c3ga2::Mvec<T> Ty_reciprocal(){
312         c3ga2::Mvec<T> mv;
313         mv[c3ga2::E202] = 1.0;
314         mv[c3ga2::E015] = 1.0;
315         return mv;
316     }
318     /// \brief build the reciprocal single term operator Tz_reciprocal
319     /// \return the multivector corresponding to the reciprocal extraction operator Tz
320     template<typename T>
321     c3ga2::Mvec<T> Tz_reciprocal(){
322         c3ga2::Mvec<T> mv;
323         mv[c3ga2::E302] = 1.0;
324         mv[c3ga2::E016] = 1.0;
325         return mv;
326     }
328     /// \brief build the reciprocal unit term operator Tz
329     /// \return the multivector corresponding to the reciprocal extraction operator T1
330     template<typename T>
331     c3ga2::Mvec<T> T1_reciprocal(){
332         c3ga2::Mvec<T> mv;
333         mv[c3ga2::E0102] = 1.0;
334         return mv;
335     }
339     /// \brief build the cyclide component extraction operator
340     /// \return the multivector corresponding to the operator Tt4
341     template<typename T>
342     c3ga2::Mvec<T> Tt4(){
343         c3ga2::Mvec<T> mv;
344         mv[c3ga2::E0102] = -4.0;
345         return mv;
346     }
348     /// \brief build the cyclide component extraction operator
349     /// \return the multivector corresponding to the operator Tt2
350     template<typename T>
351     c3ga2::Mvec<T> Tt2(){
352         c3ga2::Mvec<T> mv;
353         mv[c3ga2::Ei102] = -1.0;
354         mv[c3ga2::E01i2] = -1.0;
355         return mv;
356     }
358     /// \brief build the cyclide component extraction operator
359     /// \return the multivector corresponding to the operator Txt2
360     template<typename T>
361     c3ga2::Mvec<T> Txt2(){
362         c3ga2::Mvec<T> mv;
363         mv[c3ga2::E102] = 1.0;
364         mv[c3ga2::E014] = 1.0;
365         return mv;
366     }
368     /// \brief build the cyclide component extraction operator
369     /// \return the multivector corresponding to the operator Tyt2
370     template<typename T>
371     c3ga2::Mvec<T> Tyt2(){
372         c3ga2::Mvec<T> mv;
373         mv[c3ga2::E202] = 1.0;
374         mv[c3ga2::E015] = 1.0;
375         return mv;
376     }
378     /// \brief build the cyclide component extraction operator
379     /// \return the multivector corresponding to the operator Tzt2
380     template<typename T>
381     c3ga2::Mvec<T> Tzt2(){
382         c3ga2::Mvec<T> mv;
383         mv[c3ga2::E302] = 1.0;
384         mv[c3ga2::E016] = 1.0;
385         return mv;
386     }
392     /// a quadric has the form (a b c d e f g h i j)
393     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0
394     /// \brief construct the multivector representing the quadric whose coefficients are {a,b,c,d,e,f,g,h,i,j}
395     template<typename T>
396     c3ga2::Mvec<T> quadric2ga(const std::vector<T>& quadric){
397         c3ga2::Mvec<T> mv = quadric[0]*Tx2<T>() + quadric[1]*Ty2<T>() + quadric[2]*Tz2<T>() + quadric[3]*Txy<T>() + quadric[4]*Tzx<T>() + quadric[5]*Tyz<T>()  
398               + quadric[6]*Tx<T>()  + quadric[7]*Ty<T>()  + quadric[8]*Tz<T>()  + quadric[9]*T1<T>();
399     
400         return mv;
401     }
404     /// a quadric has the form (a b c d e f g h i j)
405     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0
406     /// \brief construct the quadric whose bivector multivector is mv, to achieve that we use the reciprocal bivector operators  
407     template<typename T>
408     std::vector<T> ga2quadric(c3ga2::Mvec<T> mv ){
409         std::vector<T> quadric(10);
410         quadric[0] = (Tx2_reciprocal<T>()|mv); // a coefficient
411         quadric[1] = (Ty2_reciprocal<T>()|mv); // b coefficient
412         quadric[2] = (Tz2_reciprocal<T>()|mv); // c coefficient
413         quadric[3] = (Txy_reciprocal<T>()|mv); // d coefficient
414         quadric[4] = (Tzx_reciprocal<T>()|mv); // e coefficient
415         quadric[5] = (Tyz_reciprocal<T>()|mv); // f coefficient
416         quadric[6] = (Tx_reciprocal<T>()|mv);  // g coefficient
417         quadric[7] = (Ty_reciprocal<T>()|mv);  // h coefficient
418         quadric[8] = (Tz_reciprocal<T>()|mv);  // i coefficient
419         quadric[9] = (T1_reciprocal<T>()|mv);  // j coefficient
420         return quadric;
421     }
423 } // end namespace
425 namespace qc3ga{
426     //////////////////////////////////////// QC3GA QUADRIC //////////////////////////////////////////
427     /// \brief build a point from a vector
428     /// \param x vector component related to e1
429     /// \param y vector component related to e2
430     /// \param z vector component related to e3
431     /// \return a multivector corresponding to a point of qc3ga
432     template<typename T>
433     qc3ga::Mvec<T> point(const T &x, const T &y, const T &z){
434         qc3ga::Mvec<T> mv;
435         mv[qc3ga::E1] = x;
436         mv[qc3ga::E2] = y;
437         mv[qc3ga::E3] = z;
438         mv[qc3ga::Ei1] = 0.5*(x*x);
439         mv[qc3ga::Ei2] = 0.5*(y*y);
440         mv[qc3ga::Ei3] = 0.5*(z*z);
441         mv[qc3ga::Ei4] = (x*y);
442         mv[qc3ga::Ei5] = (x*z);
443         mv[qc3ga::Ei6] = (y*z);
444             mv[qc3ga::E01] = mv[qc3ga::E02] = mv[qc3ga::E03] = 1.0;
445         return mv;
446     }
448     template<typename T>
449     qc3ga::Mvec<T> point(const Eigen::Matrix<T,3,1> &pt){
450         qc3ga::Mvec<T> mv;
451         mv[qc3ga::E1] = pt(0);
452         mv[qc3ga::E2] = pt(1);
453         mv[qc3ga::E3] = pt(2);
454         mv[qc3ga::Ei1] = 0.5*(pt(0)*pt(0));
455         mv[qc3ga::Ei2] = 0.5*(pt(1)*pt(1));
456         mv[qc3ga::Ei3] = 0.5*(pt(2)*pt(2));
457         mv[qc3ga::Ei4] = pt(0)*pt(1);
458         mv[qc3ga::Ei5] = pt(0)*pt(2);
459         mv[qc3ga::Ei6] = pt(1)*pt(2);
460         mv[qc3ga::E01] = mv[qc3ga::E02] = mv[qc3ga::E03] = 1.0;
461         return mv;
462     }
464         /// a quadric has the form (a b c d e f g h i j)
465     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0 
466     template<typename T>
467     std::vector<T> ga2DualQuadric(const qc3ga::Mvec<T> &mv){
469         std::vector<T> quadric(10);
470         quadric[0] = - mv[qc3ga::E01] / 2.0;
471         quadric[1] = - mv[qc3ga::E02] / 2.0;
472         quadric[2] = - mv[qc3ga::E03] / 2.0;
473         quadric[3] = - mv[qc3ga::E04] ;
474         quadric[4] = - mv[qc3ga::E05] ;
475         quadric[5] = - mv[qc3ga::E06] ;
477         quadric[6] =  mv[qc3ga::E1];
478         quadric[7] =  mv[qc3ga::E2];
479         quadric[8] =  mv[qc3ga::E3];
481         quadric[9] = - 3 * mv[qc3ga::Ei1];
483         return quadric;
484     }
487     /// a quadric has the form (a b c d e f g h i j)
488     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gx + hy + iz + j = 0 
489     template<typename T>
490     qc3ga::Mvec<T> dualQuadric2ga(const T a, const T b, const T c, const T d, const T e, const T f, const T g, const T h, const T i, const T j){
492         qc3ga::Mvec<T> mv;
494         mv[qc3ga::E01] = - 2.0 * a;
495         mv[qc3ga::E02] = - 2.0 * b;
496         mv[qc3ga::E03] = - 2.0 * c;
497         mv[qc3ga::E04] = - d;
498         mv[qc3ga::E05] = - e;
499         mv[qc3ga::E06] = - f;
501         mv[qc3ga::E1] = g;
502         mv[qc3ga::E2] = h;
503         mv[qc3ga::E3] = i;
505         mv[qc3ga::Ei1] = mv[qc3ga::Ei2] = mv[qc3ga::Ei3] = - j / 3.0;
506         
507         return mv;
508     }
510     /// a quadric has the form (a b c d e f g h i j)
511     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gx + hy + iz + j = 0 
512     template<typename T>
513     qc3ga::Mvec<T> dualQuadric2ga(const std::vector<T> &quadric){
514         return dualQuadric2ga<T>(quadric[0], quadric[1], quadric[2], quadric[3], quadric[4], quadric[5], quadric[6], quadric[7], quadric[8], quadric[9]);
515     }
517     
518     /// a quadric has the form (a b c d e f g h i j)
519     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0 
520     template<typename T>
521     std::vector<T> ga2quadric(const qc3ga::Mvec<T> &mv){
523         std::vector<T> quadric(10);
524         quadric[0] = - mv[qc3ga::E1230102i203i304i405i506i6] / 2.0; // dual(e01)
525         quadric[1] = - mv[qc3ga::E12301i10203i304i405i506i6] / 2.0; // dual(e02)
526         quadric[2] = - mv[qc3ga::E12301i102i20304i405i506i6] / 2.0; // dual(e03)
527         quadric[3] = - mv[qc3ga::E12301i102i203i30405i506i6]; // dual(e04)
528         quadric[4] = - mv[qc3ga::E12301i102i203i304i40506i6]; // dual(e05)
529         quadric[5] = - mv[qc3ga::E12301i102i203i304i405i506]; // dual(e06)
530         
531         quadric[6] = -mv[qc3ga::E2301i102i203i304i405i506i6]; // dual(e1)
532         quadric[7] =  mv[qc3ga::E1301i102i203i304i405i506i6]; // dual(e2)
533         quadric[8] = -mv[qc3ga::E1201i102i203i304i405i506i6]; // dual(e3)
534         
535         quadric[9] = 3 * mv[qc3ga::E123i102i203i304i405i506i6]; // dual(ei1)
537         return quadric;
538     }
540     /// a quadric has the form (a b c d e f g h i j)
541     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0
542     /// defines the primal form of a conic
543     template<typename T>
544     qc3ga::Mvec<T> quadric2ga(const T a, const T b, const T c, const T d, const T e, const T f, const T g, const T h, const T i, const T j){
545         qc3ga::Mvec<T> mv;
547         mv[qc3ga::E1230102i203i304i405i506i6] = - 2.0 * a; // dual(e01) component
548         mv[qc3ga::E12301i10203i304i405i506i6] = - 2.0 * b; // dual(e02) component
549         mv[qc3ga::E12301i102i20304i405i506i6] = - 2.0 * c; // dual(e03) component
550         mv[qc3ga::E12301i102i203i30405i506i6] = - d; // dual(e04) component
551         mv[qc3ga::E12301i102i203i304i40506i6] = - e; // dual(e05) component
552         mv[qc3ga::E12301i102i203i304i405i506] = - f; // dual(e06) component
555         mv[qc3ga::E2301i102i203i304i405i506i6] = g; // dual(e1) component 
556         mv[qc3ga::E1301i102i203i304i405i506i6] = -h; // dual(e2) component
557         mv[qc3ga::E1201i102i203i304i405i506i6] = i; // dual(e3) component
559         mv[qc3ga::E123i102i203i304i405i506i6] = mv[qc3ga::E12301i1i203i304i405i506i6] = mv[qc3ga::E12301i102i2i304i405i506i6] = j / 3.0; // dual(eij) component 
560         
561         return mv;
562     }
564     /// a quadric has the form (a b c d e f g h i j)
565     /// with ax^2 + by^2 + cz^2 + dxy + exz + fyz + gxw + hyw + izw + jw^2 = 0
566     /// defines the primal form of a conic
567     template<typename T>
568     qc3ga::Mvec<T> quadric2ga(const std::vector<T> &quadric){
569         return qc3ga::quadric2ga<T>(quadric[0], quadric[1], quadric[2], quadric[3], quadric[4], quadric[5], quadric[6], quadric[7], quadric[8], quadric[9]);
570     }
572 } // end namespace
575     /////////////////////////// MAPPING //////////////////////////
577     /// \brief transform a c3ga2 quadric to a qc3ga one
578     template<typename T>
579     qc3ga::Mvec<T> c3ga2quadric2qc3ga(const c3ga2::Mvec<T> & mvQuadric){
580     std::vector<T> quadCoeff = c3ga2::ga2quadric<T>(mvQuadric);
581         return qc3ga::dualQuadric2ga<T>(quadCoeff);
582     }
584     /// \brief transform a qc3ga quadric to a c3ga2 one
585     template<typename T>
586     c3ga2::Mvec<T> qc3gaquadric2c3ga2(const qc3ga::Mvec<T> & mvQuadric){
587     std::vector<T> quadCoeff = qc3ga::ga2DualQuadric<T>(mvQuadric);
588         return c3ga2::quadric2ga<T>(quadCoeff);
589     }
592     /// \brief transform a p3ga2 quadric to a qc3ga one
593     template<typename T>
594     qc3ga::Mvec<T> p3ga2quadric2qc3ga(const p3ga2::Mvec<T> & mvQuadric){
595     std::vector<T> quadCoeff = p3ga2::ga2quadric<T>(mvQuadric);
596         return qc3ga::dualQuadric2ga<T>(quadCoeff);
597     }
599     /// \brief transform a qc3ga quadric to a p3ga2 one
600     template<typename T>
601     p3ga2::Mvec<T> qc3gaquadric2p3ga2(const qc3ga::Mvec<T> & mvQuadric){
602     std::vector<T> quadCoeff = qc3ga::ga2DualQuadric<T>(mvQuadric);
603         return p3ga2::quadric2ga<T>(quadCoeff);
604     }
606     /// \brief transform a p3ga2 quadric to a qc3ga one
607     template<typename T>
608     qc3ga::Mvec<T> p3ga2quadric2c3ga2(const p3ga2::Mvec<T> & mvQuadric){
609     std::vector<T> quadCoeff = p3ga2::ga2quadric<T>(mvQuadric);
610         return c3ga2::quadric2ga<T>(quadCoeff);
611     }
613     /// \brief transform a qc3ga quadric to a p3ga2 one
614     template<typename T>
615     p3ga2::Mvec<T> c3ga2quadric2p3ga2(const c3ga2::Mvec<T> & mvQuadric){
616     std::vector<T> quadCoeff = c3ga2::ga2quadric<T>(mvQuadric);
617         return p3ga2::quadric2ga<T>(quadCoeff);
618     }
623 #endif // projection_inclusion_guard