3 /*----------------------------------------------------------------------------*/
4 double factorial_div( double value, int x)
18 /*----------------------------------------------------------------------------*/
19 double powerd( double x, int y)
37 /*----------------------------------------------------------------------------*/
52 while ( x > 360.0*M_PI/180)
57 if( x > (270.0 * M_PI / 180) )
60 x = 360.0*M_PI/180 - x;
62 else if ( x > (180.0 * M_PI / 180) )
65 x = x - 180.0 *M_PI / 180;
67 else if ( x > (90.0 * M_PI / 180) )
69 x = 180.0 *M_PI / 180 - x;
72 while( powerd( diff, 2) > 1.0E-16 )
75 diff = j * factorial_div( powerd( x, (2*i -1)) ,(2*i -1));
82 /*----------------------------------------------------------------------------*/
85 return SIN(90 * M_PI / 180 - x);
88 /*----------------------------------------------------------------------------*/
89 double ATAN( double x)
91 int i=0; /* counter for terms in binomial series */
92 int j=1; /* sign of nth term in series */
94 int sign = 1; /* sign of the input x */
95 double y = 0.0; /* the output */
96 double deltay = 1.0; /* the value of the next term in the series */
97 double addangle = 0.0; /* used if arctan > 22.5 degrees */
105 while( x > 0.3249196962 )
108 x = (x - 0.3249196962) / (1 + x * 0.3249196962);
111 addangle = k * 18.0 *M_PI/180;
113 while( powerd( deltay, 2) > 1.0E-16 )
116 deltay = j * powerd( x, (2*i -1)) / (2*i -1);
120 return (sign * (y + addangle) );
123 double ASIN(double x)
125 return 2 * ATAN( x / (1 + std::sqrt(1.0 - x*x)));
128 double Radians( double number )
130 return number*M_PI/180;
133 double Deg( double number )
135 return number*180/M_PI;
138 double Rev( double number )
140 return number - std::floor( number / 360.0 ) * 360;
143 double calcElevation( double SatLon, double SiteLat, double SiteLon, int Height_over_ocean = 0 )
145 double a0=0.58804392,
151 f = 1.00 / 298.257, // Earth flattning factor
153 r_sat=42164.57, // Distance from earth centre to satellite
155 r_eq=6378.14, // Earth radius
157 sinRadSiteLat=SIN(Radians(SiteLat)),
158 cosRadSiteLat=COS(Radians(SiteLat)),
160 Rstation = r_eq / ( std::sqrt( 1.00 - f*(2.00-f)*sinRadSiteLat*sinRadSiteLat ) ),
162 Ra = (Rstation+Height_over_ocean)*cosRadSiteLat,
163 Rz= Rstation*(1.00-f)*(1.00-f)*sinRadSiteLat,
165 alfa_rx=r_sat*COS(Radians(SatLon-SiteLon)) - Ra,
166 alfa_ry=r_sat*SIN(Radians(SatLon-SiteLon)),
169 alfa_r_north=-alfa_rx*sinRadSiteLat + alfa_rz*cosRadSiteLat,
170 alfa_r_zenith=alfa_rx*cosRadSiteLat + alfa_rz*sinRadSiteLat,
172 El_geometric=Deg(ATAN( alfa_r_zenith/std::sqrt(alfa_r_north*alfa_r_north+alfa_ry*alfa_ry))),
174 x = std::fabs(El_geometric+0.589),
175 refraction=std::fabs(a0+a1*x+a2*x*x+a3*x*x*x+a4*x*x*x*x),
179 if (El_geometric > 10.2)
180 El_observed = El_geometric+0.01617*(COS(Radians(std::fabs(El_geometric)))/SIN(Radians(std::fabs(El_geometric))) );
182 El_observed = El_geometric+refraction;
184 if (alfa_r_zenith < -3000)
190 double calcAzimuth(double SatLon, double SiteLat, double SiteLon, int Height_over_ocean=0)
192 double f = 1.00 / 298.257, // Earth flattning factor
194 r_sat=42164.57, // Distance from earth centre to satellite
196 r_eq=6378.14, // Earth radius
198 sinRadSiteLat=SIN(Radians(SiteLat)),
199 cosRadSiteLat=COS(Radians(SiteLat)),
201 Rstation = r_eq / ( std::sqrt( 1 - f*(2-f)*sinRadSiteLat*sinRadSiteLat ) ),
202 Ra = (Rstation+Height_over_ocean)*cosRadSiteLat,
203 Rz = Rstation*(1-f)*(1-f)*sinRadSiteLat,
205 alfa_rx = r_sat*COS(Radians(SatLon-SiteLon)) - Ra,
206 alfa_ry = r_sat*SIN(Radians(SatLon-SiteLon)),
209 alfa_r_north = -alfa_rx*sinRadSiteLat + alfa_rz*cosRadSiteLat,
213 if (alfa_r_north < 0)
214 Azimuth = 180+Deg(ATAN(alfa_ry/alfa_r_north));
216 Azimuth = Rev(360+Deg(ATAN(alfa_ry/alfa_r_north)));
221 double calcDeclination( double SiteLat, double Azimuth, double Elevation)
223 return Deg( ASIN(SIN(Radians(Elevation)) *
224 SIN(Radians(SiteLat)) +
225 COS(Radians(Elevation)) *
226 COS(Radians(SiteLat)) +
227 COS(Radians(Azimuth))
232 double calcSatHourangle( double SatLon, double SiteLat, double SiteLon )
234 double Azimuth=calcAzimuth(SatLon, SiteLat, SiteLon ),
235 Elevation=calcElevation( SatLon, SiteLat, SiteLon ),
237 a = - COS(Radians(Elevation)) * SIN(Radians(Azimuth)),
239 b = SIN(Radians(Elevation)) * COS(Radians(SiteLat))
241 COS(Radians(Elevation)) * SIN(Radians(SiteLat)) * COS(Radians(Azimuth)),
243 // Works for all azimuths (northern & southern hemisphere)
244 returnvalue = 180 + Deg(ATAN(a/b));
248 returnvalue = ( (returnvalue-180) + 360 );
250 returnvalue = 360 - (returnvalue-360);
254 returnvalue = ( 180 - returnvalue );