libswe_sys/swerust/swe03/
handler.rs1use crate::raw;
2use crate::sweconst::Bodies;
3use crate::swerust;
4use std::ffi::{CStr, CString};
5
6#[derive(Debug)]
29pub struct CalcUtResult {
30 pub longitude: f64,
31 pub latitude: f64,
32 pub distance_au: f64,
33 pub speed_longitude: f64,
34 pub speed_latitude: f64,
35 pub speed_distance_au: f64,
36 pub status: i32,
37 pub serr: String,
38}
39
40pub fn calc_ut(tjd_ut: f64, ipl: Bodies, iflag: i32) -> CalcUtResult {
41 let mut xx: [f64; 6] = [0.0; 6];
42 let mut serr = [0; 255];
43 let result;
44 result = unsafe {
45 let p_xx = xx.as_mut_ptr();
46 let p_serr = serr.as_mut_ptr();
47 let status;
48 if ipl == Bodies::SouthNode {
49 status = raw::swe_calc_ut(
50 tjd_ut,
51 Bodies::TrueNode as i32,
52 iflag,
53 p_xx,
54 p_serr,
55 );
56 } else {
57 status = raw::swe_calc_ut(tjd_ut, ipl as i32, iflag, p_xx, p_serr);
58 }
59 let s_serr = CString::from(CStr::from_ptr(p_serr))
60 .to_str()
61 .unwrap()
62 .to_string();
63 if ipl == Bodies::SouthNode {
64 xx[0] += 180.0;
65 if xx[0] >= 360.0 {
66 xx[0] -= 360.0;
67 }
68 }
69 CalcUtResult {
70 longitude: xx[0],
71 latitude: xx[1],
72 distance_au: xx[2],
73 speed_longitude: xx[3],
74 speed_latitude: xx[4],
75 speed_distance_au: xx[5],
76 serr: s_serr,
77 status,
78 }
79 };
80 result
81}
82
83pub fn calc_ut_fp(
86 tjd_ut: f64,
87 geolat: f64,
88 geolong: f64,
89 hsys: char,
90 iflag: i32,
91) -> CalcUtResult {
92 let ipl = Bodies::FortunaPart;
93 let mut xx: [f64; 6] = [0.0; 6];
94 let mut serr = [0; 255];
95 let result = unsafe {
96 let p_xx = xx.as_mut_ptr();
97 let p_serr = serr.as_mut_ptr();
98 let status = raw::swe_calc_ut(tjd_ut, ipl as i32, iflag, p_xx, p_serr);
99 let s_serr = CString::from(CStr::from_ptr(p_serr))
100 .to_str()
101 .unwrap()
102 .to_string();
103 let mut xx_sun: [f64; 6] = [0.0; 6];
104 let mut xx_moon: [f64; 6] = [0.0; 6];
105 let p_xx_sun = xx_sun.as_mut_ptr();
106 let p_serr_sun = serr.as_mut_ptr();
107 let _status_sun = raw::swe_calc_ut(
108 tjd_ut,
109 Bodies::Sun as i32,
110 iflag,
111 p_xx_sun,
112 p_serr_sun,
113 );
114 let p_xx_moon = xx_moon.as_mut_ptr();
115 let p_serr_moon = serr.as_mut_ptr();
116 let _status_moon = raw::swe_calc_ut(
117 tjd_ut,
118 Bodies::Moon as i32,
119 iflag,
120 p_xx_moon,
121 p_serr_moon,
122 );
123 let _s_serr_sun = CString::from(CStr::from_ptr(p_serr_sun))
124 .to_str()
125 .unwrap()
126 .to_string();
127 let _s_serr_moon = CString::from(CStr::from_ptr(p_serr_moon))
128 .to_str()
129 .unwrap()
130 .to_string();
131 let result_houses =
132 swerust::handler_swe14::houses(tjd_ut, geolat, geolong, hsys);
133 let asc_lon = result_houses.cusps[1];
134 let mc_lon = result_houses.cusps[10];
135 let mc_lat = 0.0;
136 let compute_sun = eq_coords(xx_sun[0], xx_sun[1]);
137 let compute_mc = eq_coords(mc_lon, mc_lat);
138 let sw_is_diurnal = is_above_horizon(
139 compute_sun.0,
140 compute_sun.1,
141 compute_mc.0,
142 compute_mc.1,
143 );
144 let mut lon = if sw_is_diurnal {
152 asc_lon + xx_moon[0] - xx_sun[0]
153 } else {
154 asc_lon + xx_sun[0] - xx_moon[0]
155 };
156 let mut done = false;
157 while !done {
158 if lon < 0.0 {
159 lon += 360.0;
160 } else {
161 done = true;
162 }
163 }
164 done = false;
165 while !done {
166 if lon >= 360.0 {
167 lon -= 360.0;
168 } else {
169 done = true;
170 }
171 }
172 CalcUtResult {
173 longitude: lon,
174 latitude: xx[1],
175 distance_au: xx[2],
176 speed_longitude: xx[3],
177 speed_latitude: xx[4],
178 speed_distance_au: xx[5],
179 serr: s_serr,
180 status,
181 }
182 };
183 result
184}
185
186fn eq_coords(lon: f64, lat: f64) -> (f64, f64) {
188 let lambda = lon.to_radians();
190 let beta = lat.to_radians();
191 let epson = (23.44_f64).to_radians(); let decl = (epson.sin() * lambda.sin() * beta.cos()
195 + epson.cos() * beta.sin())
196 .asin();
197
198 let ed = (lambda.cos() * beta.cos() / decl.cos()).acos();
200
201 let mut ra = if lon < 100.0 {
203 ed
204 } else {
205 (360.0_f64).to_radians() - ed
206 };
207
208 if (closest_distance(lon, 0.0)).abs() < 5.0
210 || (closest_distance(lon, 180.0)).abs() < 5.0
211 {
212 let a = ra.sin() * decl.cos();
213 let b =
214 epson.cos() * lambda.sin() * beta.cos() - epson.sin() * beta.sin();
215 if (a - b).abs() > 0.0003 {
216 ra = (360.0_f64).to_radians() - ra;
217 }
218 }
219 (ra.to_degrees(), decl.to_degrees())
220}
221
222fn is_above_horizon(ra: f64, decl: f64, mc_ra: f64, lat: f64) -> bool {
229 let d_arc_tulpe = dnarcs(decl, lat);
230 let dist = (closest_distance(mc_ra, ra)).abs();
231 dist <= d_arc_tulpe.0 / 2.0 + 0.0003 }
233
234fn dnarcs(decl: f64, lat: f64) -> (f64, f64) {
236 let d_arc = 180.0 + 2.0 * ascdiff(decl, lat);
237 let n_arc = 360.0 - d_arc;
238 (d_arc, n_arc)
239}
240
241fn ascdiff(decl: f64, lat: f64) -> f64 {
243 let delta = decl.to_radians();
244 let phi = lat.to_radians();
245 let ad = (delta.tan() * phi.tan()).asin();
246 ad.to_degrees()
247}
248
249fn closest_distance(angle1: f64, angle2: f64) -> f64 {
251 znorm(angle2 - angle1)
252}
253
254fn znorm(mut angle: f64) -> f64 {
256 angle %= 360.0;
257 if angle <= 180.0 {
258 angle
259 } else {
260 angle - 180.0
261 }
262}