source: Sophya/trunk/SophyaExt/XAstroPack/mollweide.cc@ 3619

Last change on this file since 3619 was 3572, checked in by cmv, 17 years ago

char* -> const char* pour regler les problemes de deprecated string const... + comparaison unsigned signed + suppression EVOL_PLANCK rz+cmv 07/02/2009

File size: 4.9 KB
RevLine 
[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]50double 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]120double 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
Note: See TracBrowser for help on using the repository browser.