/// Builds a vector that points towards the sun.
///
/// Z is up, Y is North and X is East
Builds a vector that points towards the sun.
Z is up, Y is North and X is East
Builds a vector that points towards the sun . Z is up Y is North and X is East
pub fn sun_position(&self, n: Time) -> Option<Vector3D> {
        let n = self.unwrap_solar_time(n);
        // if it is night-time, return None
        let (sunrise, sunset) = self.sunrise_sunset(n);
        if n < self.unwrap_solar_time(sunrise) || n > self.unwrap_solar_time(sunset) {
            return None;
        }
        // else, calculate stuff
        let cos_phi = self.latitude.cos();
        let sin_phi = self.latitude.sin();
        let delta = self.declination(n);
        let cos_delta = delta.cos();
        let sin_delta = delta.sin();
        let omega = self.hour_angle(Time::Solar(n));
        let cos_omega = omega.cos();
        // Equation 1.6.5, for Zenith
        let cos_zenith = cos_phi * cos_delta * cos_omega + sin_phi * sin_delta;
        let sin_zenith = cos_zenith.acos().sin();
        if cos_zenith < 0. {
            // it should be daytime; i.e., zenith < 90 (i.e., cos(zenith)>0)
            return None;
        }
        debug_assert!((1.0 - (cos_zenith * cos_zenith + sin_zenith * sin_zenith)).abs() < 0.000001);
        // Is vertical? If so, return vertical... otherwise, carry on.
        const LIMIT_ANGLE: Float = 0.9999; // A zenith angle of less than 0.8 degrees (ish) is considered vertical.
        if cos_zenith > LIMIT_ANGLE {
            return Some(Vector3D::new(0., 0., 1.));
        }
        let z = cos_zenith;
        // Equation 1.6.6 for Azimuth
        let mut cos_azimuth = (cos_zenith * sin_phi - sin_delta) / (sin_zenith * cos_phi);
        if cos_azimuth > 1. {
            cos_azimuth = 1.0;
        } else if cos_azimuth < -1. {
            cos_azimuth = -1.;
        }
        let sin_azimuth = cos_azimuth.acos().sin();
        debug_assert!(
            (1.0 - (cos_azimuth * cos_azimuth + sin_azimuth * sin_azimuth)).abs() < 0.0000001
        );
        // Trigonometry
        let mut x = sin_azimuth * sin_zenith;
        let y = -cos_azimuth * sin_zenith;
        // (x should be positive at this stage, right? then, if omega is
        // positive, we need to change the sign of x)
        if omega > 0. {
            x *= -1.
        }
        // Check length of vector
        debug_assert!(((x * x + y * y + z * z).sqrt() - 1.0).abs() < 0.000001);
        // Build the vector and return
        Some(Vector3D::new(x, y, z))
    }
pub fn sun_position ( & self , n : Time ) -> Option < Vector3D > { let n = self . unwrap_solar_time ( n ) ; // if it is night-time, return None let ( sunrise , sunset ) = self . sunrise_sunset ( n ) ; if n < self . unwrap_solar_time ( sunrise ) || n > self . unwrap_solar_time ( sunset ) { return None ; } // else, calculate stuff let cos_phi = self . latitude . cos ( ) ; let sin_phi = self . latitude . sin ( ) ; let delta = self . declination ( n ) ; let cos_delta = delta . cos ( ) ; let sin_delta = delta . sin ( ) ; let omega = self . hour_angle ( Time :: Solar ( n ) ) ; let cos_omega = omega . cos ( ) ; // Equation 1.6.5, for Zenith let cos_zenith = cos_phi * cos_delta * cos_omega + sin_phi * sin_delta ; let sin_zenith = cos_zenith . acos ( ) . sin ( ) ; if cos_zenith < 0. { // it should be daytime; i.e., zenith < 90 (i.e., cos(zenith)>0) return None ; } debug_assert ! ( ( 1.0 ( cos_zenith cos_zenith sin_zenith sin_zenith ) ) abs ( ) 0.000001 ) ; // Is vertical? If so, return vertical... otherwise, carry on. const LIMIT_ANGLE : Float = 0.9999 ; // A zenith angle of less than 0.8 degrees (ish) is considered vertical. if cos_zenith > LIMIT_ANGLE { return Some ( Vector3D :: new ( 0. , 0. , 1. ) ) ; } let z = cos_zenith ; // Equation 1.6.6 for Azimuth let mut cos_azimuth = ( cos_zenith * sin_phi - sin_delta ) / ( sin_zenith * cos_phi ) ; if cos_azimuth > 1. { cos_azimuth = 1.0 ; } else if cos_azimuth < - 1. { cos_azimuth = - 1. ; } let sin_azimuth = cos_azimuth . acos ( ) . sin ( ) ; debug_assert ! ( ( 1.0 ( cos_azimuth cos_azimuth sin_azimuth sin_azimuth ) ) abs ( ) 0.0000001 ) ; // Trigonometry let mut x = sin_azimuth * sin_zenith ; let y = - cos_azimuth * sin_zenith ; // (x should be positive at this stage, right? then, if omega is // positive, we need to change the sign of x) if omega > 0. { x *= - 1. } // Check length of vector debug_assert ! ( ( ( x x y y z z ) sqrt ( ) 1.0 ) abs ( ) 0.000001 ) ; // Build the vector and return Some ( Vector3D :: new ( x , y , z ) ) }
Builds a vector that points towards the sun.
Builds a vector that points towards the sun .
&self
n
Time