Avionics
Dropship Simulator
Solar.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <math.h>
4 
5 #define PI 3.1415926f
6 // official is 90 at 50'
7 // civil is 96
8 // nautical is 102
9 // astronomical is 108
10 
11 namespace Library
12 {
13  class Solar
14  {
15  float lat = 0.0f, lng = 0.0f, ALTITUDE = 0.0f, ZENITH = 0.0f;
16 
17  public:
18  Solar() {};
19  Solar(float prmLatitude, float prmLongitude, float prmAltitudeFeet, float prmZenithDegrees)
20  {
21  lat = prmLatitude;
22  lng = prmLongitude;
23  ALTITUDE = prmAltitudeFeet;
24  ZENITH = prmZenithDegrees;
25  }
26 
27  float calculateSunrise(int year, int month, int day, int localOffset, int daylightSavings) const
28  {
29  /*
30  localOffset will be <0 for western hemisphere and >0 for eastern hemisphere
31  daylightSavings should be 1 if it is in effect during the summer otherwise it should be 0
32  */
33  //1. first calculate the day of the year
34  float N1 = floor(275.0f * month / 9.0f);
35  float N2 = floor((month + 9.0f) / 12.0f);
36  float N3 = 1.0f + floor((year - 4.0f * floor(year / 4.0f) + 2.0f) / 3.0f);
37  float N = N1 - (N2 * N3) + day - 30.0f;
38 
39  //2. convert the longitude to hour value and calculate an approximate time
40  float lngHour = lng / 15.0f;
41  float t = N + ((6.0f - lngHour) / 24.0f); //if rising time is desired:
42 
43  //3. calculate the Sun's mean anomaly
44  float M = (0.9856f * t) - 3.289f;
45 
46  //4. calculate the Sun's true longitude
47  float L = fmod(M + (1.916f * sin((PI / 180.0f)*M)) + (0.020f * sin(2.0f * (PI / 180.0f) * M)) + 282.634f, 360.0f);
48 
49  //5a. calculate the Sun's right ascension
50  float RA = fmod(180.0f / PI*atan(0.91764f * tan((PI / 180.0f)*L)), 360.0f);
51 
52  //5b. right ascension value needs to be in the same quadrant as L
53  float Lquadrant = floor(L / 90.0f) * 90.0f;
54  float RAquadrant = floor(RA / 90.0f) * 90.0f;
55  RA = RA + (Lquadrant - RAquadrant);
56 
57  //5c. right ascension value needs to be converted into hours
58  RA = RA / 15.0f;
59 
60  //6. calculate the Sun's declination
61  float sinDec = 0.39782f * sin((PI / 180.0f)*L);
62  float cosDec = cos(asin(sinDec));
63 
64  //7a. calculate the Sun's local hour angle
65  float altAdj = 1.15f * sqrtf(ALTITUDE) / 60.0f;
66  float cosH = (cos((PI / 180.0f)*(ZENITH + altAdj)) - (sinDec * sin((PI / 180.0f)*lat))) / (cosDec * cos((PI / 180.0f)*lat));
67 
69  assert(cosH <= 1.0f && cosH >= -1.0f);
70 
71  //7b. finish calculating H and convert into hours
72  float H = 360.0f - (180.0f / PI)*acos(cosH); // if if rising time is desired:
73  H = H / 15.0f;
74 
75  //8. calculate local mean time of rising/setting
76  float T = H + RA - (0.06571f * t) - 6.622f;
77 
78  //9. adjust back to UTC
79  float UT = T - lngHour;
80 
81  //10. convert UT value to local time zone of latitude/longitude
82  float LT = UT + localOffset + daylightSavings;
83  if (LT < 0.0f) LT += 24.0f;
84  if (LT >= 24.0f) LT -= 24.0f;
85  return LT;
86  }
87 
88  float calculateSunset(int year, int month, int day, int localOffset, int daylightSavings) const
89  {
90  /*
91  localOffset will be <0 for western hemisphere and >0 for eastern hemisphere
92  daylightSavings should be 1 if it is in effect during the summer otherwise it should be 0
93  */
94  //1. first calculate the day of the year
95  float N1 = floor(275.0f * month / 9.0f);
96  float N2 = floor((month + 9.0f) / 12.0f);
97  float N3 = (1.0f + floor((year - 4.0f * floor(year / 4.0f) + 2.0f) / 3.0f));
98  float N = N1 - (N2 * N3) + day - 30.0f;
99 
100  //2. convert the longitude to hour value and calculate an approximate time
101  float lngHour = lng / 15.0f;
102  float t = N + ((18 - lngHour) / 24.0f); //if setting time is desired:
103 
104  //3. calculate the Sun's mean anomaly
105  float M = (0.9856f * t) - 3.289f;
106 
107  //4. calculate the Sun's true longitude
108  float L = fmod(M + (1.916f * sin((PI / 180.0f)*M)) + (0.020f * sin(2.0f * (PI / 180.0f) * M)) + 282.634f, 360.0f);
109 
110  //5a. calculate the Sun's right ascension
111  float RA = fmod(180.0f / PI*atan(0.91764f * tan((PI / 180.0f)*L)), 360.0f);
112 
113  //5b. right ascension value needs to be in the same quadrant as L
114  float Lquadrant = floor(L / 90.0f) * 90.0f;
115  float RAquadrant = floor(RA / 90.0f) * 90.0f;
116  RA = RA + (Lquadrant - RAquadrant);
117 
118  //5c. right ascension value needs to be converted into hours
119  RA = RA / 15.0f;
120 
121  //6. calculate the Sun's declination
122  float sinDec = 0.39782f * sin(PI / 180.0f*L);
123  float cosDec = cos(asin(sinDec));
124 
125  //7a. calculate the Sun's local hour angle
126  float altAdj = 1.15f * sqrtf(ALTITUDE) / 60.0f;
127  float cosH = (cos(PI / 180.0f*(ZENITH + altAdj)) - (sinDec * sin(PI / 180.0f*lat))) / (cosDec * cos(PI / 180.0f*lat));
128 
130  assert(cosH <= 1.0f && cosH >= -1.0f);
131 
132  //7b. finish calculating H and convert into hours
133  float H = (180.0f / PI)*acos(cosH);
134  H = H / 15.0f;
135 
136  //8. calculate local mean time of rising/setting
137  float T = H + RA - (0.06571f * t) - 6.622f;
138 
139  //9. adjust back to UTC
140  float UT = T - lngHour;
141 
142  //10. convert UT value to local time zone of latitude/longitude
143  float LT = UT + localOffset + daylightSavings;
144  if (LT < 0.0f) LT += 24.0f;
145  if (LT >= 24.0f) LT -= 24.0f;
146  return LT + 12.0f; // PM
147  }
148  };
149 }
float ALTITUDE
Definition: Solar.h:15
float lng
Definition: Solar.h:15
float lat
Definition: Solar.h:15
float calculateSunrise(int year, int month, int day, int localOffset, int daylightSavings) const
Definition: Solar.h:27
#define PI
Definition: Solar.h:5
float ZENITH
Definition: Solar.h:15
float calculateSunset(int year, int month, int day, int localOffset, int daylightSavings) const
Definition: Solar.h:88
Solar(float prmLatitude, float prmLongitude, float prmAltitudeFeet, float prmZenithDegrees)
Definition: Solar.h:19