1 | #include <cstdio>
|
---|
2 | #include <cstring>
|
---|
3 | #include <cmath>
|
---|
4 | #include <ctime>
|
---|
5 |
|
---|
6 | #include "Metric.h"
|
---|
7 | #include "../shared/shared.h"
|
---|
8 |
|
---|
9 | namespace bamg {
|
---|
10 |
|
---|
11 | /*Constructor*/
|
---|
12 | EigenMetric::EigenMetric(const Metric& M){/*{{{*/
|
---|
13 | /*From a metric (a11,a21,a22), get eigen values lambda1 and lambda2 and one eigen vector v*/
|
---|
14 |
|
---|
15 | /*Intermediaries*/
|
---|
16 | double a11=M.a11,a21=M.a21,a22=M.a22;
|
---|
17 | double normM;
|
---|
18 | double delta,b;
|
---|
19 |
|
---|
20 | /*To get the eigen values, we must solve the following equation:
|
---|
21 | * | a11 - lambda a21 |
|
---|
22 | * det | | = 0
|
---|
23 | * | a21 a22-lambda |
|
---|
24 | *
|
---|
25 | * We have to solve the following polynom:
|
---|
26 | * lamda^2 + ( -a11 -a22)*lambda + (a11*a22-a21*a21) = 0*/
|
---|
27 |
|
---|
28 | /*Compute polynom determinant*/
|
---|
29 | b=-a11-a22;
|
---|
30 | delta=b*b - 4*(a11*a22-a21*a21);
|
---|
31 |
|
---|
32 | /*Compute norm of M to avoid round off errors*/
|
---|
33 | normM=a11*a11 + a22*a22 + a21*a21;
|
---|
34 |
|
---|
35 | /*1: normM too small: eigen values = 0*/
|
---|
36 | if(normM<1.e-30){
|
---|
37 | lambda1=0;
|
---|
38 | lambda2=0;
|
---|
39 | vx=1;
|
---|
40 | vy=0;
|
---|
41 | }
|
---|
42 | /*2: delta is small -> double root*/
|
---|
43 | else if (delta < 1.e-5*normM){
|
---|
44 | lambda1=-b/2;
|
---|
45 | lambda2=-b/2;
|
---|
46 | vx=1;
|
---|
47 | vy=0;
|
---|
48 | }
|
---|
49 | /*3: general case -> two roots*/
|
---|
50 | else{
|
---|
51 | delta = sqrt(delta);
|
---|
52 | lambda1 = (-b-delta)/2.0;
|
---|
53 | lambda2 = (-b+delta)/2.0;
|
---|
54 |
|
---|
55 | /*Now, one must find the eigen vectors. For that we use the following property of the inner product
|
---|
56 | * <Ax,y> = <x,tAy>
|
---|
57 | * Here, M'(M-lambda*Id) is symmetrical, which gives:
|
---|
58 | * ∀(x,y)∈R²xR² <M'x,y> = <M'y,x>
|
---|
59 | * And we have the following:
|
---|
60 | * if y∈Ker(M'), ∀x∈R² <M'x,y> = <x,M'y> = 0
|
---|
61 | * We have shown that
|
---|
62 | * Im(M') ⊥ Ker(M')
|
---|
63 | *
|
---|
64 | * To find the eigen vectors of M, we only have to find two vectors
|
---|
65 | * of the image of M' and take their perpendicular as long as they are
|
---|
66 | * not 0.
|
---|
67 | * To do that, we take the images (1,0) and (0,1):
|
---|
68 | * x1 = (a11 - lambda) x2 = a21
|
---|
69 | * y1 = a21 y2 = (a22-lambda)
|
---|
70 | *
|
---|
71 | * We take the vector that has the larger norm and take its perpendicular.*/
|
---|
72 |
|
---|
73 | double norm1 = (a11-lambda1)*(a11-lambda1) + a21*a21;
|
---|
74 | double norm2 = a21*a21 + (a22-lambda1)*(a22-lambda1);
|
---|
75 |
|
---|
76 | if (norm2<norm1){
|
---|
77 | norm1=sqrt(norm1);
|
---|
78 | vx = - a21/norm1;
|
---|
79 | vy = (a11-lambda1)/norm1;
|
---|
80 | }
|
---|
81 | else{
|
---|
82 | norm2=sqrt(norm2);
|
---|
83 | vx = - (a22-lambda1)/norm2;
|
---|
84 | vy = a21/norm2;
|
---|
85 | }
|
---|
86 | }
|
---|
87 |
|
---|
88 | }
|
---|
89 | /*}}}*/
|
---|
90 | EigenMetric::EigenMetric(double r1,double r2,const D2& vp1){/*{{{*/
|
---|
91 | this->lambda1 = r1;
|
---|
92 | this->lambda2 = r2;
|
---|
93 | this->vx = vp1.x;
|
---|
94 | this->vy = vp1.y;
|
---|
95 | }/*}}}*/
|
---|
96 |
|
---|
97 | /*Methods*/
|
---|
98 | void EigenMetric::Abs(){/*{{{*/
|
---|
99 | lambda1=bamg::Abs(lambda1),lambda2=bamg::Abs(lambda2);
|
---|
100 | }/*}}}*/
|
---|
101 | double EigenMetric::Aniso2() const { /*{{{*/
|
---|
102 | return lmax()/lmin();
|
---|
103 | }/*}}}*/
|
---|
104 | void EigenMetric::Echo(void){/*{{{*/
|
---|
105 |
|
---|
106 | _printf_("EigenMetric:\n");
|
---|
107 | _printf_(" lambda1: " << lambda1 << "\n");
|
---|
108 | _printf_(" lambda2: " << lambda2 << "\n");
|
---|
109 | _printf_(" vx: " << vx << "\n");
|
---|
110 | _printf_(" vy: " << vy << "\n");
|
---|
111 |
|
---|
112 | return;
|
---|
113 | }
|
---|
114 | /*}}}*/
|
---|
115 | double EigenMetric::hmin() const {/*{{{*/
|
---|
116 | return sqrt(1/bamg::Max3(lambda1,lambda2,1e-30));
|
---|
117 | }/*}}}*/
|
---|
118 | double EigenMetric::hmax() const {/*{{{*/
|
---|
119 | return sqrt(1/bamg::Max(bamg::Min(lambda1,lambda2),1e-30));
|
---|
120 | }/*}}}*/
|
---|
121 | double EigenMetric::lmax() const {/*{{{*/
|
---|
122 | return bamg::Max3(lambda1,lambda2,1e-30);
|
---|
123 | }/*}}}*/
|
---|
124 | double EigenMetric::lmin() const {/*{{{*/
|
---|
125 | return bamg::Max(bamg::Min(lambda1,lambda2),1e-30);
|
---|
126 | }/*}}}*/
|
---|
127 | void EigenMetric::Min(double a) { /*{{{*/
|
---|
128 | lambda1=bamg::Min(a,lambda1); lambda2=bamg::Min(a,lambda2) ;
|
---|
129 | }/*}}}*/
|
---|
130 | void EigenMetric::Max(double a) { /*{{{*/
|
---|
131 | //change eigen values
|
---|
132 | lambda1=bamg::Max(a,lambda1); lambda2=bamg::Max(a,lambda2) ;
|
---|
133 | }/*}}}*/
|
---|
134 | void EigenMetric::Minh(double h) {/*{{{*/
|
---|
135 | Min(1.0/(h*h));
|
---|
136 | }/*}}}*/
|
---|
137 | void EigenMetric::Maxh(double h) {/*{{{*/
|
---|
138 | //Call Max function
|
---|
139 | Max(1.0/(h*h));
|
---|
140 | }/*}}}*/
|
---|
141 | void EigenMetric::pow(double p){/*{{{*/
|
---|
142 | lambda1=::pow(lambda1,p);lambda2=::pow(lambda2,p);
|
---|
143 | }/*}}}*/
|
---|
144 |
|
---|
145 | }
|
---|