You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

102 lines
4.2 KiB

  1. // This file is available in electronic form at http://www.psa.es/sdg/sunpos.htm
  2. #include "sunpos.h"
  3. #include <math.h>
  4. void sunpos(cTime udtTime,cLocation udtLocation, cSunCoordinates *udtSunCoordinates)
  5. {
  6. // Main variables
  7. double dElapsedJulianDays;
  8. double dDecimalHours;
  9. double dEclipticLongitude;
  10. double dEclipticObliquity;
  11. double dRightAscension;
  12. double dDeclination;
  13. // Auxiliary variables
  14. double dY;
  15. double dX;
  16. // Calculate difference in days between the current Julian Day
  17. // and JD 2451545.0, which is noon 1 January 2000 Universal Time
  18. {
  19. double dJulianDate;
  20. long int liAux1;
  21. long int liAux2;
  22. // Calculate time of the day in UT decimal hours
  23. dDecimalHours = udtTime.dHours + (udtTime.dMinutes
  24. + udtTime.dSeconds / 60.0 ) / 60.0;
  25. // Calculate current Julian Day
  26. liAux1 =(udtTime.iMonth-14)/12;
  27. liAux2=(1461*(udtTime.iYear + 4800 + liAux1))/4 + (367*(udtTime.iMonth
  28. - 2-12*liAux1))/12- (3*((udtTime.iYear + 4900
  29. + liAux1)/100))/4+udtTime.iDay-32075;
  30. dJulianDate=(double)(liAux2)-0.5+dDecimalHours/24.0;
  31. // Calculate difference between current Julian Day and JD 2451545.0
  32. dElapsedJulianDays = dJulianDate-2451545.0;
  33. }
  34. // Calculate ecliptic coordinates (ecliptic longitude and obliquity of the
  35. // ecliptic in radians but without limiting the angle to be less than 2*Pi
  36. // (i.e., the result may be greater than 2*Pi)
  37. {
  38. double dMeanLongitude;
  39. double dMeanAnomaly;
  40. double dOmega;
  41. dOmega=2.1429-0.0010394594*dElapsedJulianDays;
  42. dMeanLongitude = 4.8950630+ 0.017202791698*dElapsedJulianDays; // Radians
  43. dMeanAnomaly = 6.2400600+ 0.0172019699*dElapsedJulianDays;
  44. dEclipticLongitude = dMeanLongitude + 0.03341607*sin( dMeanAnomaly )
  45. + 0.00034894*sin( 2*dMeanAnomaly )-0.0001134
  46. -0.0000203*sin(dOmega);
  47. dEclipticObliquity = 0.4090928 - 6.2140e-9*dElapsedJulianDays
  48. +0.0000396*cos(dOmega);
  49. }
  50. // Calculate celestial coordinates ( right ascension and declination ) in radians
  51. // but without limiting the angle to be less than 2*Pi (i.e., the result may be
  52. // greater than 2*Pi)
  53. {
  54. double dSin_EclipticLongitude;
  55. dSin_EclipticLongitude= sin( dEclipticLongitude );
  56. dY = cos( dEclipticObliquity ) * dSin_EclipticLongitude;
  57. dX = cos( dEclipticLongitude );
  58. dRightAscension = atan2( dY,dX );
  59. if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + twopi;
  60. dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude );
  61. }
  62. // Calculate local coordinates ( azimuth and zenith angle ) in degrees
  63. {
  64. double dGreenwichMeanSiderealTime;
  65. double dLocalMeanSiderealTime;
  66. double dLatitudeInRadians;
  67. double dHourAngle;
  68. double dCos_Latitude;
  69. double dSin_Latitude;
  70. double dCos_HourAngle;
  71. double dParallax;
  72. dGreenwichMeanSiderealTime = 6.6974243242 +
  73. 0.0657098283*dElapsedJulianDays
  74. + dDecimalHours;
  75. dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15
  76. + udtLocation.dLongitude)*rad;
  77. dHourAngle = dLocalMeanSiderealTime - dRightAscension;
  78. dLatitudeInRadians = udtLocation.dLatitude*rad;
  79. dCos_Latitude = cos( dLatitudeInRadians );
  80. dSin_Latitude = sin( dLatitudeInRadians );
  81. dCos_HourAngle= cos( dHourAngle );
  82. udtSunCoordinates->dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle
  83. *cos(dDeclination) + sin( dDeclination )*dSin_Latitude));
  84. dY = -sin( dHourAngle );
  85. dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle;
  86. udtSunCoordinates->dAzimuth = atan2( dY, dX );
  87. if ( udtSunCoordinates->dAzimuth < 0.0 )
  88. udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth + twopi;
  89. udtSunCoordinates->dAzimuth = udtSunCoordinates->dAzimuth/rad;
  90. // Parallax Correction
  91. dParallax=(dEarthMeanRadius/dAstronomicalUnit)
  92. *sin(udtSunCoordinates->dZenithAngle);
  93. udtSunCoordinates->dZenithAngle=(udtSunCoordinates->dZenithAngle
  94. + dParallax)/rad;
  95. }
  96. }