MCPcopy Create free account
hub / github.com/FreeFem/FreeFem-sources / findCanonicalForm

Function findCanonicalForm

plugin/seq/plotPDF.cpp:1800–1872  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1798 GaussElimination(phi, a, NQ);
1799
1800 delete [] a[0];
1801
1802 return;
1803}
1804
1805void findCanonicalForm( double *const PHI, const double *const phi )
1806{
1807 const double &a = phi[0]; const double &b = phi[1]; const double &c = phi[2];
1808 const double &d = phi[3]; const double &e = phi[4]; const double &f = phi[5];
1809
1810 // phi(x,y) = a*x*x + b*x*y + c*y*y + d*x + e*y + f
1811 // = [x,y][ a, b/2; b/2, c ][x;y] + [d,e][x;y] + f
1812 // = [x,y]P P^T [ a, b/2; b/2, c ]P P^T[x;y] + [d,e]P P^T[x;y] + f
1813 // = [X,Y] [lambda1,0;0,lambda2] [X;Y] + [D,E][X;Y] + f
1814 // = lambda1*X*X + lambda2*Y*Y + D*X + E*Y + f
1815 // = lambda1 * (X + D/(2*lambda1))^2 + lambda2 * (Y + E/(2*lambda2))^2
1816 // + ( -D*D/(4*lambda1) - E*E/(4*lambda2) + f )
1817 // = PHI(X,Y)
1818 // where
1819 // v1 = [v1x;v1y] (resp. v2 = [v2x;v2y]) is an eigenvector of lambda1 (resp. lambda2)
1820 // P = [v1x, v2x; v1y, v2y], satisfying P^T P = I <=> || v1 || = || v2 || = 1, v1 \perp v2 = 0
1821 // [X;Y] = P^T[x;y] <=> [x;y] = P[X;Y]
1822 // [D;E] = P^T[d;e] <=> [d;e] = P[D;E]
1823
1824 const double det = (a-c)*(a-c)+b*b;
1825 const double sqdet = sqrt( det );
1826
1827 // eigenvalues of [ a, b /2; b/2, c]
1828 double &lambda1 = PHI[0]; double &lambda2 = PHI[1];
1829 lambda1 = ( (a+c) + sqdet ) / 2;
1830 lambda2 = ( (a+c) - sqdet ) / 2;
1831
1832 // corresponding eivenvectors
1833 double &v1x = PHI[2]; double &v1y= PHI[3];
1834 double &v2x = PHI[4]; double &v2y= PHI[5];
1835
1836 if( a < c ){
1837
1838 const double n = sqrt( 2*det - 2*(a-c)*sqdet );
1839 v1x = b / n;
1840 v1y = (-(a-c)+sqdet) / n;
1841 v2x = (a-c-sqdet) / n;
1842 v2y = b / n;
1843
1844 } else if( a > c ){
1845
1846 const double n = sqrt( 2*det + 2*(a-c)*sqdet );
1847 v1x = (a-c+sqdet) / n;
1848 v1y = b / n;
1849 v2x = b / n;
1850 v2y = (-(a-c)-sqdet) / n;
1851
1852 } else { // a == c
1853
1854 lambda1 = (2*a+b)/2;
1855 lambda2 = (2*a-b)/2;
1856 v1x = v1y = v2x = v2y = 1/sqrt(static_cast<double>(2)); v2y *= -1;
1857 }

Callers 2

plot_P2_isoline_bodyFunction · 0.85
plot_P2_fillFunction · 0.85

Calls 2

sqrtFunction · 0.50
fabsFunction · 0.50

Tested by

no test coverage detected