1use crate::macros as pa_m;
2use crate::types as pa_t;
3use crate::util as pa_u;
4
5pub fn approximate_position_of_sun(
25 lct_hours: f64,
26 lct_minutes: f64,
27 lct_seconds: f64,
28 local_day: f64,
29 local_month: u32,
30 local_year: u32,
31 is_daylight_saving: bool,
32 zone_correction: i32,
33) -> (f64, f64, f64, f64, f64, f64) {
34 let daylight_saving = if is_daylight_saving == true { 1 } else { 0 };
35
36 let greenwich_date_day = pa_m::lct_gday(
37 lct_hours,
38 lct_minutes,
39 lct_seconds,
40 daylight_saving,
41 zone_correction,
42 local_day,
43 local_month,
44 local_year,
45 );
46 let greenwich_date_month = pa_m::lct_gmonth(
47 lct_hours,
48 lct_minutes,
49 lct_seconds,
50 daylight_saving,
51 zone_correction,
52 local_day,
53 local_month,
54 local_year,
55 );
56 let greenwich_date_year = pa_m::lct_gyear(
57 lct_hours,
58 lct_minutes,
59 lct_seconds,
60 daylight_saving,
61 zone_correction,
62 local_day,
63 local_month,
64 local_year,
65 );
66 let ut_hours = pa_m::lct_ut(
67 lct_hours,
68 lct_minutes,
69 lct_seconds,
70 daylight_saving,
71 zone_correction,
72 local_day,
73 local_month,
74 local_year,
75 );
76 let ut_days = ut_hours / 24.0;
77 let jd_days = pa_m::cd_jd(
78 greenwich_date_day,
79 greenwich_date_month,
80 greenwich_date_year,
81 ) + ut_days;
82 let d_days = jd_days - pa_m::cd_jd(0 as f64, 1, 2010);
83 let n_deg = 360.0 * d_days / 365.242191;
84 let m_deg1 = n_deg + pa_m::sun_e_long(0 as f64, 1, 2010) - pa_m::sun_peri(0 as f64, 1, 2010);
85 let m_deg2 = m_deg1 - 360.0 * (m_deg1 / 360.0).floor();
86 let e_c_deg =
87 360.0 * pa_m::sun_ecc(0 as f64, 1, 2010) * m_deg2.to_radians().sin() / std::f64::consts::PI;
88 let l_s_deg1 = n_deg + e_c_deg + pa_m::sun_e_long(0 as f64, 1, 2010);
89 let l_s_deg2 = l_s_deg1 - 360.0 * (l_s_deg1 / 360.0).floor();
90 let ra_deg = pa_m::ec_ra(
91 l_s_deg2,
92 0 as f64,
93 0 as f64,
94 0 as f64,
95 0 as f64,
96 0 as f64,
97 greenwich_date_day,
98 greenwich_date_month,
99 greenwich_date_year,
100 );
101 let ra_hours = pa_m::dd_dh(ra_deg);
102 let dec_deg = pa_m::ec_dec(
103 l_s_deg2,
104 0 as f64,
105 0 as f64,
106 0 as f64,
107 0 as f64,
108 0 as f64,
109 greenwich_date_day,
110 greenwich_date_month,
111 greenwich_date_year,
112 );
113
114 let sun_ra_hour = pa_m::dh_hour(ra_hours);
115 let sun_ra_min = pa_m::dh_min(ra_hours);
116 let sun_ra_sec = pa_m::dh_sec(ra_hours);
117 let sun_dec_deg = pa_m::dd_deg(dec_deg);
118 let sun_dec_min = pa_m::dd_min(dec_deg);
119 let sun_dec_sec = pa_m::dd_sec(dec_deg);
120
121 return (
122 sun_ra_hour as f64,
123 sun_ra_min as f64,
124 sun_ra_sec,
125 sun_dec_deg,
126 sun_dec_min,
127 sun_dec_sec,
128 );
129}
130
131pub fn precise_position_of_sun(
151 lct_hours: f64,
152 lct_minutes: f64,
153 lct_seconds: f64,
154 local_day: f64,
155 local_month: u32,
156 local_year: u32,
157 is_daylight_saving: bool,
158 zone_correction: i32,
159) -> (f64, f64, f64, f64, f64, f64) {
160 let daylight_saving = if is_daylight_saving == true { 1 } else { 0 };
161
162 let g_day = pa_m::lct_gday(
163 lct_hours,
164 lct_minutes,
165 lct_seconds,
166 daylight_saving,
167 zone_correction,
168 local_day,
169 local_month,
170 local_year,
171 );
172 let g_month = pa_m::lct_gmonth(
173 lct_hours,
174 lct_minutes,
175 lct_seconds,
176 daylight_saving,
177 zone_correction,
178 local_day,
179 local_month,
180 local_year,
181 );
182 let g_year = pa_m::lct_gyear(
183 lct_hours,
184 lct_minutes,
185 lct_seconds,
186 daylight_saving,
187 zone_correction,
188 local_day,
189 local_month,
190 local_year,
191 );
192 let sun_ecliptic_longitude_deg = pa_m::sun_long(
193 lct_hours,
194 lct_minutes,
195 lct_seconds,
196 daylight_saving,
197 zone_correction,
198 local_day,
199 local_month,
200 local_year,
201 );
202 let ra_deg = pa_m::ec_ra(
203 sun_ecliptic_longitude_deg,
204 0.0,
205 0.0,
206 0.0,
207 0.0,
208 0.0,
209 g_day,
210 g_month,
211 g_year,
212 );
213 let ra_hours = pa_m::dd_dh(ra_deg);
214 let dec_deg = pa_m::ec_dec(
215 sun_ecliptic_longitude_deg,
216 0.0,
217 0.0,
218 0.0,
219 0.0,
220 0.0,
221 g_day,
222 g_month,
223 g_year,
224 );
225
226 let sun_ra_hour = pa_m::dh_hour(ra_hours);
227 let sun_ra_min = pa_m::dh_min(ra_hours);
228 let sun_ra_sec = pa_m::dh_sec(ra_hours);
229 let sun_dec_deg = pa_m::dd_deg(dec_deg);
230 let sun_dec_min = pa_m::dd_min(dec_deg);
231 let sun_dec_sec = pa_m::dd_sec(dec_deg);
232
233 return (
234 sun_ra_hour as f64,
235 sun_ra_min as f64,
236 sun_ra_sec,
237 sun_dec_deg,
238 sun_dec_min,
239 sun_dec_sec,
240 );
241}
242
243pub fn sun_distance_and_angular_size(
261 lct_hours: f64,
262 lct_minutes: f64,
263 lct_seconds: f64,
264 local_day: f64,
265 local_month: u32,
266 local_year: u32,
267 is_daylight_saving: bool,
268 zone_correction: i32,
269) -> (f64, f64, f64, f64) {
270 let daylight_saving = if is_daylight_saving == true { 1 } else { 0 };
271
272 let g_day = pa_m::lct_gday(
273 lct_hours,
274 lct_minutes,
275 lct_seconds,
276 daylight_saving,
277 zone_correction,
278 local_day,
279 local_month,
280 local_year,
281 );
282 let g_month = pa_m::lct_gmonth(
283 lct_hours,
284 lct_minutes,
285 lct_seconds,
286 daylight_saving,
287 zone_correction,
288 local_day,
289 local_month,
290 local_year,
291 );
292 let g_year = pa_m::lct_gyear(
293 lct_hours,
294 lct_minutes,
295 lct_seconds,
296 daylight_saving,
297 zone_correction,
298 local_day,
299 local_month,
300 local_year,
301 );
302 let true_anomaly_deg = pa_m::sun_true_anomaly(
303 lct_hours,
304 lct_minutes,
305 lct_seconds,
306 daylight_saving,
307 zone_correction,
308 local_day,
309 local_month,
310 local_year,
311 );
312 let true_anomaly_rad = true_anomaly_deg.to_radians();
313 let eccentricity = pa_m::sun_ecc(g_day, g_month, g_year);
314 let f = (1.0 + eccentricity * true_anomaly_rad.cos()) / (1.0 - eccentricity * eccentricity);
315 let r_km = 149598500.0 / f;
316 let theta_deg = f * 0.533128;
317
318 let sun_dist_km = pa_u::round_f64(r_km, 0);
319 let sun_ang_size_deg = pa_m::dd_deg(theta_deg);
320 let sun_ang_size_min = pa_m::dd_min(theta_deg);
321 let sun_ang_size_sec = pa_m::dd_sec(theta_deg);
322
323 return (
324 sun_dist_km,
325 sun_ang_size_deg,
326 sun_ang_size_min,
327 sun_ang_size_sec,
328 );
329}
330
331pub fn sunrise_and_sunset(
351 local_day: f64,
352 local_month: u32,
353 local_year: u32,
354 is_daylight_saving: bool,
355 zone_correction: i32,
356 geographical_long_deg: f64,
357 geographical_lat_deg: f64,
358) -> (f64, f64, f64, f64, f64, f64, String) {
359 let daylight_saving = if is_daylight_saving == true { 1 } else { 0 };
360
361 let local_sunrise_hours = pa_m::sunrise_lct(
362 local_day,
363 local_month,
364 local_year,
365 daylight_saving,
366 zone_correction,
367 geographical_long_deg,
368 geographical_lat_deg,
369 );
370
371 let local_sunset_hours = pa_m::sunset_lct(
372 local_day,
373 local_month,
374 local_year,
375 daylight_saving,
376 zone_correction,
377 geographical_long_deg,
378 geographical_lat_deg,
379 );
380
381 let sun_rise_set_status = pa_m::e_sun_rs(
382 local_day,
383 local_month,
384 local_year,
385 daylight_saving,
386 zone_correction,
387 geographical_long_deg,
388 geographical_lat_deg,
389 );
390
391 let adjusted_sunrise_hours = local_sunrise_hours + 0.008333;
392 let adjusted_sunset_hours = local_sunset_hours + 0.008333;
393 let azimuth_of_sunrise_deg1 = pa_m::sunrise_az(
394 local_day,
395 local_month,
396 local_year,
397 daylight_saving,
398 zone_correction,
399 geographical_long_deg,
400 geographical_lat_deg,
401 );
402 let azimuth_of_sunset_deg1 = pa_m::sunset_az(
403 local_day,
404 local_month,
405 local_year,
406 daylight_saving,
407 zone_correction,
408 geographical_long_deg,
409 geographical_lat_deg,
410 );
411
412 let local_sunrise_hour = if sun_rise_set_status == "OK" {
413 pa_m::dh_hour(adjusted_sunrise_hours) as f64
414 } else {
415 0.0
416 };
417 let local_sunrise_minute = if sun_rise_set_status == "OK" {
418 pa_m::dh_min(adjusted_sunrise_hours) as f64
419 } else {
420 0.0
421 };
422 let local_sunset_hour = if sun_rise_set_status == "OK" {
423 pa_m::dh_hour(adjusted_sunset_hours) as f64
424 } else {
425 0.0
426 };
427 let local_sunset_minute = if sun_rise_set_status == "OK" {
428 pa_m::dh_min(adjusted_sunset_hours) as f64
429 } else {
430 0.0
431 };
432 let azimuth_of_sunrise_deg = if sun_rise_set_status == "OK" {
433 pa_u::round_f64(azimuth_of_sunrise_deg1, 2)
434 } else {
435 0.0
436 };
437 let azimuth_of_sunset_deg = if sun_rise_set_status == "OK" {
438 pa_u::round_f64(azimuth_of_sunset_deg1, 2)
439 } else {
440 0.0
441 };
442 let status = sun_rise_set_status.to_string();
443
444 return (
445 local_sunrise_hour,
446 local_sunrise_minute,
447 local_sunset_hour,
448 local_sunset_minute,
449 azimuth_of_sunrise_deg,
450 azimuth_of_sunset_deg,
451 status,
452 );
453}
454
455pub fn morning_and_evening_twilight(
474 local_day: f64,
475 local_month: u32,
476 local_year: u32,
477 is_daylight_saving: bool,
478 zone_correction: i32,
479 geographical_long_deg: f64,
480 geographical_lat_deg: f64,
481 twilight_type: pa_t::TwilightType,
482) -> (f64, f64, f64, f64, String) {
483 let daylight_saving = if is_daylight_saving == true { 1 } else { 0 };
484
485 let start_of_am_twilight_hours = pa_m::twilight_am_lct(
486 local_day,
487 local_month,
488 local_year,
489 daylight_saving,
490 zone_correction,
491 geographical_long_deg,
492 geographical_lat_deg,
493 &twilight_type,
494 );
495
496 let end_of_pm_twilight_hours = pa_m::twilight_pm_lct(
497 local_day,
498 local_month,
499 local_year,
500 daylight_saving,
501 zone_correction,
502 geographical_long_deg,
503 geographical_lat_deg,
504 &twilight_type,
505 );
506
507 let twilight_status = pa_m::e_twilight(
508 local_day,
509 local_month,
510 local_year,
511 daylight_saving,
512 zone_correction,
513 geographical_long_deg,
514 geographical_lat_deg,
515 &twilight_type,
516 );
517
518 let adjusted_am_start_time = start_of_am_twilight_hours + 0.008333;
519 let adjusted_pm_start_time = end_of_pm_twilight_hours + 0.008333;
520
521 let am_twilight_begins_hour = if twilight_status == "OK" {
522 pa_m::dh_hour(adjusted_am_start_time) as f64
523 } else {
524 -99.0
525 };
526 let am_twilight_begins_min = if twilight_status == "OK" {
527 pa_m::dh_min(adjusted_am_start_time) as f64
528 } else {
529 -99.0
530 };
531 let pm_twilight_ends_hour = if twilight_status == "OK" {
532 pa_m::dh_hour(adjusted_pm_start_time) as f64
533 } else {
534 -99.0
535 };
536 let pm_twilight_ends_min = if twilight_status == "OK" {
537 pa_m::dh_min(adjusted_pm_start_time) as f64
538 } else {
539 -99.0
540 };
541 let status = twilight_status;
542
543 return (
544 am_twilight_begins_hour,
545 am_twilight_begins_min,
546 pm_twilight_ends_hour,
547 pm_twilight_ends_min,
548 status,
549 );
550}
551
552pub fn equation_of_time(gwdate_day: f64, gwdate_month: u32, gwdate_year: u32) -> (f64, f64) {
563 let sun_longitude_deg =
564 pa_m::sun_long(12.0, 0.0, 0.0, 0, 0, gwdate_day, gwdate_month, gwdate_year);
565 let sun_ra_hours = pa_m::dd_dh(pa_m::ec_ra(
566 sun_longitude_deg,
567 0.0,
568 0.0,
569 0.0,
570 0.0,
571 0.0,
572 gwdate_day,
573 gwdate_month,
574 gwdate_year,
575 ));
576 let equivalent_ut_hours = pa_m::gst_ut(
577 sun_ra_hours,
578 0.0,
579 0.0,
580 gwdate_day,
581 gwdate_month,
582 gwdate_year,
583 );
584 let equation_of_time_hours = equivalent_ut_hours - 12.0;
585
586 let equation_of_time_min = pa_m::dh_min(equation_of_time_hours) as f64;
587 let equation_of_time_sec = pa_m::dh_sec(equation_of_time_hours);
588
589 return (equation_of_time_min, equation_of_time_sec);
590}
591
592pub fn solar_elongation(
610 ra_hour: f64,
611 ra_min: f64,
612 ra_sec: f64,
613 dec_deg: f64,
614 dec_min: f64,
615 dec_sec: f64,
616 gwdate_day: f64,
617 gwdate_month: u32,
618 gwdate_year: u32,
619) -> f64 {
620 let sun_longitude_deg =
621 pa_m::sun_long(0.0, 0.0, 0.0, 0, 0, gwdate_day, gwdate_month, gwdate_year);
622 let sun_ra_hours = pa_m::dd_dh(pa_m::ec_ra(
623 sun_longitude_deg,
624 0.0,
625 0.0,
626 0.0,
627 0.0,
628 0.0,
629 gwdate_day,
630 gwdate_month,
631 gwdate_year,
632 ));
633 let sun_dec_deg = pa_m::ec_dec(
634 sun_longitude_deg,
635 0.0,
636 0.0,
637 0.0,
638 0.0,
639 0.0,
640 gwdate_day,
641 gwdate_month,
642 gwdate_year,
643 );
644 let solar_elongation_deg = pa_m::angle(
645 sun_ra_hours,
646 0.0,
647 0.0,
648 sun_dec_deg,
649 0.0,
650 0.0,
651 ra_hour,
652 ra_min,
653 ra_sec,
654 dec_deg,
655 dec_min,
656 dec_sec,
657 pa_t::AngleMeasure::Hours,
658 );
659
660 return pa_u::round_f64(solar_elongation_deg, 2);
661}