35 const Scalar r_sun_mag = janus::norm(r_sun);
36 const Vec3<Scalar> s_hat = r_sun / r_sun_mag;
39 const Scalar proj = r_sat.dot(s_hat);
42 const Vec3<Scalar> r_perp = r_sat - proj * s_hat;
43 const Scalar d_perp = janus::norm(r_perp);
48 const Scalar behind_earth =
49 janus::where(proj < 0.0, Scalar(1.0), Scalar(0.0));
50 const Scalar in_cylinder =
51 janus::where(d_perp < R_body, Scalar(1.0), Scalar(0.0));
53 const Scalar in_shadow = behind_earth * in_cylinder;
56 return 1.0 - in_shadow;
78 const Vec3<Scalar> r_sat_to_sun = r_sun - r_sat;
79 const Scalar s = janus::norm(r_sat_to_sun);
82 const Scalar r_sat_mag = janus::norm(r_sat);
85 const Scalar theta_body = janus::asin(R_body / r_sat_mag);
86 const Scalar theta_sun = janus::asin(R_sun / s);
89 const Scalar cos_theta = -r_sat.dot(r_sat_to_sun) / (r_sat_mag * s);
91 const Scalar cos_theta_clamped =
92 janus::where(cos_theta > 1.0, Scalar(1.0),
93 janus::where(cos_theta < -1.0, Scalar(-1.0), cos_theta));
94 const Scalar theta = janus::acos(cos_theta_clamped);
97 const Scalar sum_angles = theta_body + theta_sun;
98 const Scalar diff_angles = janus::abs(theta_body - theta_sun);
101 const Scalar full_sun =
102 janus::where(theta >= sum_angles, Scalar(1.0), Scalar(0.0));
105 const Scalar in_penumbra_region =
106 janus::where(theta > diff_angles, Scalar(1.0), Scalar(0.0)) *
107 janus::where(theta < sum_angles, Scalar(1.0), Scalar(0.0));
109 const Scalar penumbra_frac =
110 (theta - diff_angles) / (sum_angles - diff_angles + 1e-12);
113 const Scalar full_umbra =
114 janus::where(theta <= diff_angles, Scalar(0.0), penumbra_frac);
117 return full_sun + (1.0 - full_sun) * in_penumbra_region * full_umbra;