| [1811] | 1 | #include <stdlib.h> | 
|---|
|  | 2 | #include <stdio.h> | 
|---|
|  | 3 | #include <math.h> | 
|---|
| [2615] | 4 | #include "sopnamsp.h" | 
|---|
| [1811] | 5 | #include "mollweide.h" | 
|---|
|  | 6 |  | 
|---|
|  | 7 | /*! \ingroup XAstroPack | 
|---|
|  | 8 | \brief La vraie projection Mollweide (longitude,latitude) -> (xmoll,ymoll) | 
|---|
|  | 9 | \param input: longitude [0,2PI[ en radians | 
|---|
|  | 10 | \param input: latitude  [-Pi/2,Pi/2] en radians | 
|---|
|  | 11 | \param output: xmoll dans [-2*sqrt(2),2*sqrt(2)] | 
|---|
|  | 12 | \param output: ymoll dans [-sqrt(2),sqrt(2)] | 
|---|
|  | 13 | \warning Probleme de precision pour t pres de Pi/2 (latitude pres de -Pi/2 ou Pi/2) | 
|---|
| [1813] | 14 | \warning Longitude=Pi=180 au milieu en xmoll=0 | 
|---|
| [1811] | 15 | \return t | 
|---|
|  | 16 | \verbatim | 
|---|
|  | 17 | - La vraie MollWeide: | 
|---|
|  | 18 | Equation implicite en t: 2*t+sin(2*t) = Pi*sin(lat) = a | 
|---|
|  | 19 | | xmoll = 2*sqrt(2)*(lon-Pi)/Pi*cos(t) | 
|---|
|  | 20 | | ymoll = sqrt(2)*sin(t) | 
|---|
|  | 21 | -------------------------------------------------------- | 
|---|
|  | 22 | INPUT: longitude [0,2PI[      en radians | 
|---|
|  | 23 | latitude  [-Pi/2,Pi/2] en radians | 
|---|
|  | 24 | OUTPUT: xmoll dans [-2*sqrt(2),2*sqrt(2)] | 
|---|
|  | 25 | ymoll dans [-sqrt(2),sqrt(2)] | 
|---|
|  | 26 | RETURN: t | 
|---|
|  | 27 | -------------------------------------------------------- | 
|---|
|  | 28 | REMARQUES: | 
|---|
|  | 29 | - xmoll varie [-2*sqrt(2),2*sqrt(2)] | 
|---|
| [1813] | 30 | centre galactique (longitude=0) au bord, | 
|---|
|  | 31 | anti-centre (longitude=180) au milieu. | 
|---|
|  | 32 | pour centre galactique (longitude=0) au milieu, | 
|---|
|  | 33 | anti-centre (longitude=180) au bord: | 
|---|
|  | 34 | xmoll' = 2*sqrt(2)*longitude/Pi*cos(t) = xmoll+2*sqrt(2) | 
|---|
|  | 35 | xmoll' varie [0,4*sqrt(2)] | 
|---|
| [1811] | 36 | - ymoll varie [-sqrt(2),sqrt(2)] plan gal en 0 | 
|---|
|  | 37 | - t varie [-Pi/2,Pi/2] | 
|---|
|  | 38 | - a varie [-Pi,Pi]  (a <-> -a  <==> t <-> -t) | 
|---|
|  | 39 | - Pour latitude --> -latitude alors t --> -t | 
|---|
|  | 40 | latitude=90   --> t=Pi/2 | 
|---|
|  | 41 | latitude=-90  --> t=-Pi/2 | 
|---|
|  | 42 | RAPIDITE: 10^6 appels a MollWeide_XY en 5.2 seconde (PC Linux 500Mhz) | 
|---|
|  | 43 | PRECISION: eps=1e-16  -> |t-tvrai|<1e-6 toujours | 
|---|
|  | 44 | |t-tvrai|<1e-10 pour t<1.57 | 
|---|
|  | 45 | |t-tvrai|<1e-10 pour t<1.57 | 
|---|
|  | 46 | |t-tvrai|<3e-14 pour t<1.50 | 
|---|
|  | 47 | |t-tvrai|<5e-15 pour t<1.40 | 
|---|
|  | 48 | \endverbatim | 
|---|
|  | 49 | */ | 
|---|
| [3572] | 50 | double MollWeide_XY(double longitude,double latitude,double& xmoll,double& ymoll) | 
|---|
| [1811] | 51 | { | 
|---|
|  | 52 | int i,niter=2; | 
|---|
|  | 53 | double tini,t0,f0,f1,f2,e1,e2,dt,a,asgn,eps=1.e-16; | 
|---|
|  | 54 |  | 
|---|
|  | 55 | a = M_PI*sin(latitude); | 
|---|
|  | 56 | if(a<0.) {a*=-1.; asgn=-1.;} else asgn=1.; | 
|---|
|  | 57 | // premier guess t1 ok pour t->0 (droite) | 
|---|
|  | 58 | f1 = a/4.; | 
|---|
|  | 59 | // second guess t2 ok pour t->Pi/2 (DL en Pi/2, type a+b*x^3) | 
|---|
|  | 60 | f2 = 0.75*(M_PI-a); | 
|---|
|  | 61 | if(f2>0.) f2=M_PI_2-pow(f2,0.33333333333333333); else f2=M_PI_2; | 
|---|
|  | 62 | e1 = 2.*f1+sin(2.*f1)-a; if(e1<0.) e1 *= -1.; | 
|---|
|  | 63 | e2 = 2.*f2+sin(2.*f2)-a; if(e2<0.) e2 *= -1.; | 
|---|
|  | 64 | tini = (f1*e2+f2*e1)/(e1+e2); | 
|---|
|  | 65 | //printf("---> a=%e tini=%e f1=%e f2=%e\n",a,tini,f1,f2); | 
|---|
|  | 66 | if(tini<0) tini=0.; else if(tini>M_PI_2) tini=M_PI_2; | 
|---|
|  | 67 | // L'approximation par le DL au 2sd ordre, on resoud: | 
|---|
|  | 68 | // a = f(x0) + f'(x0)*(x-x0) + f''(x0)*(x-x0)^2/2 | 
|---|
|  | 69 | t0 = tini; | 
|---|
|  | 70 | for(i=0;i<niter;i++) { | 
|---|
|  | 71 | e1 = sin(2.*t0); | 
|---|
|  | 72 | f0 = 2.*t0+e1;           // (f(x0))     >=0 sur 0<t<Pi/2 | 
|---|
|  | 73 | //printf(".%d    a-f0=%e\n",i,a-f0); | 
|---|
|  | 74 | if(a-f0<eps && a-f0>-eps) break; | 
|---|
|  | 75 | f1 = 2.*(1.+cos(2.*t0)); // (f'(x0))    >=0 sur 0<t<Pi/2 | 
|---|
|  | 76 | f2 = -2.*e1;             // (f''(x0)/2) <=0 sur 0<t<Pi/2 | 
|---|
|  | 77 | dt = f1*f1 - 4.*(f0-a)*f2; | 
|---|
|  | 78 | //printf(".%d    f0=%e f1=%e f2=%e disc=%e\n",i,f0,f1,f2,dt); | 
|---|
|  | 79 | if(dt>=0.) dt=-f1+sqrt(dt); else dt=0.; | 
|---|
|  | 80 | ////printf(".%d    -b+sqrt(disc)=%e\n",i,dt); | 
|---|
|  | 81 | if(f2<-eps && (dt>eps || dt<-eps)) { // approx parabolique | 
|---|
|  | 82 | t0 += dt/(2.*f2); | 
|---|
|  | 83 | //printf(".%d  parab  t0=%e\n",i,t0); | 
|---|
|  | 84 | } else if(f1>eps) { | 
|---|
|  | 85 | t0 += (a-f0)/f1; // approx lineaire | 
|---|
|  | 86 | //printf(".%d  lin  t0=%e\n",i,t0); | 
|---|
|  | 87 | } | 
|---|
|  | 88 | if(t0<0) t0=0.; else if(t0>M_PI_2) t0=M_PI_2; | 
|---|
|  | 89 | } | 
|---|
|  | 90 |  | 
|---|
|  | 91 | t0 *= asgn; | 
|---|
| [3572] | 92 | xmoll = 2.*M_SQRT2*(longitude-M_PI)/M_PI*cos(t0); | 
|---|
|  | 93 | ymoll = M_SQRT2*sin(t0); | 
|---|
| [1811] | 94 |  | 
|---|
|  | 95 | return t0; | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
|  | 98 | /*! \ingroup XAstroPack | 
|---|
|  | 99 | \brief La vraie projection Mollweide (xmoll,ymoll) -> (longitude,latitude) | 
|---|
|  | 100 | \param input: xmoll dans [-2*sqrt(2),2*sqrt(2)] | 
|---|
|  | 101 | \param input: ymoll dans [-sqrt(2),sqrt(2)] | 
|---|
|  | 102 | \param output: longitude [0,2PI[ en radians | 
|---|
|  | 103 | \param output: latitude  [-Pi/2,Pi/2] en radians | 
|---|
|  | 104 | \return t | 
|---|
|  | 105 | \warning Probleme de precision pour t pres de Pi/2 (latitude pres de -Pi/2 ou Pi/2) | 
|---|
| [1813] | 106 | \warning Longitude=Pi=180 au milieu en xmoll=0 | 
|---|
| [1811] | 107 | \verbatim | 
|---|
|  | 108 | -------------------------------------------------------- | 
|---|
|  | 109 | INPUT: xmoll dans [-2*sqrt(2),2*sqrt(2)] | 
|---|
|  | 110 | ymoll dans [-sqrt(2),sqrt(2)] | 
|---|
|  | 111 | OUTPUT: longitude [0,2PI[      en radians | 
|---|
|  | 112 | latitude  [-Pi/2,Pi/2] en radians | 
|---|
|  | 113 | RETURN: t if OK | 
|---|
|  | 114 | -991 : xmoll hors limites | 
|---|
|  | 115 | -992 : ymoll hors limites | 
|---|
|  | 116 | -993 : non inversible (poles de la sphere) | 
|---|
|  | 117 | -------------------------------------------------------- | 
|---|
|  | 118 | \endverbatim | 
|---|
|  | 119 | */ | 
|---|
| [3572] | 120 | double MollWeide_LL(double xmoll,double ymoll,double& longitude,double& latitude) | 
|---|
| [1811] | 121 | { | 
|---|
|  | 122 | double t,a,eps=1.e-20; | 
|---|
|  | 123 |  | 
|---|
| [3572] | 124 | longitude = latitude = -999.; | 
|---|
| [1811] | 125 | if(xmoll<-2*M_SQRT2 || xmoll>2*M_SQRT2) return(-901.); | 
|---|
|  | 126 | if(ymoll<-M_SQRT2 || ymoll>M_SQRT2) return(-902.); | 
|---|
|  | 127 |  | 
|---|
|  | 128 | t = ymoll/M_SQRT2; if(t<-1.) t=-1.; else if(t>1.) t=1.; | 
|---|
|  | 129 | t = asin(t); | 
|---|
|  | 130 |  | 
|---|
|  | 131 | a = (2.*t+sin(2.*t))/M_PI; if(a<-1.) a=-1.; else if(a>1.) a=1.; | 
|---|
| [3572] | 132 | latitude = asin(a); | 
|---|
| [1811] | 133 |  | 
|---|
|  | 134 | a= cos(t); | 
|---|
|  | 135 | if(fabs(a)<eps) return(-903.); | 
|---|
| [3572] | 136 | longitude = M_PI*(xmoll/(2.*M_SQRT2*a)+1.); | 
|---|
| [1811] | 137 |  | 
|---|
|  | 138 | return(t); | 
|---|
|  | 139 | } | 
|---|
|  | 140 |  | 
|---|