diff --git a/opossum/src/nodes/paraxial_surface.rs b/opossum/src/nodes/paraxial_surface.rs index ffff1c31fbb581936b191070b70b49e408438f01..2abee2afbb8cbbabe36d45618404656f9fe627a7 100644 --- a/opossum/src/nodes/paraxial_surface.rs +++ b/opossum/src/nodes/paraxial_surface.rs @@ -181,6 +181,7 @@ mod test { nodes::test_helper::test_helper::*, optic_ports::PortType, ray::Ray, rays::Rays, utils::geom_transformation::Isometry, }; + use approx::assert_relative_eq; use assert_matches::assert_matches; use nalgebra::Vector3; #[test] @@ -255,7 +256,7 @@ mod test { test_analyze_wrong_data_type::<ParaxialSurface>("input_1"); } #[test] - fn analyze_geometric_no_isometery() { + fn analyze_geometric_no_isometry() { test_analyze_geometric_no_isometry::<ParaxialSurface>("input_1"); } #[test] @@ -283,13 +284,121 @@ mod test { assert!(false, "could not get LightData"); } } - // #[test] - // #[ignore] - // fn export_data() { - // assert!(ParaxialSurface::default() - // .export_data(Path::new("")) - // .is_ok()); - // } + #[test] + fn test_shifted_x() { + let mut node = ParaxialSurface::new("test", millimeter!(10.)).unwrap(); + node.set_isometry( + Isometry::new(millimeter!(10.0, 0.0, 10.0), degree!(0.0, 0.0, 0.0)).unwrap(), + ); + let mut rays = Rays::default(); + rays.add_ray( + Ray::new_collimated(millimeter!(0.0, 0.0, 0.0), nanometer!(1000.0), joule!(1.0)) + .unwrap(), + ); + let mut input = LightResult::default(); + input.insert("input_1".into(), LightData::Geometric(rays)); + let output = + AnalysisRayTrace::analyze(&mut node, input, &RayTraceConfig::default()).unwrap(); + + if let Some(LightData::Geometric(rays)) = output.get("output_1") { + assert_eq!(rays.nr_of_rays(true), 1); + let ray = rays.iter().next().unwrap(); + assert_eq!(ray.position(), millimeter!(0.0, 0.0, 10.0)); + assert_eq!(ray.direction(), Vector3::new(1., 0., 1.)); + } else { + assert!(false, "could not get LightData"); + } + } + #[test] + fn test_shifted_y() { + let mut node = ParaxialSurface::new("test", millimeter!(10.)).unwrap(); + node.set_isometry( + Isometry::new(millimeter!(0.0, 10.0, 10.0), degree!(0.0, 0.0, 0.0)).unwrap(), + ); + let mut rays = Rays::default(); + rays.add_ray( + Ray::new_collimated(millimeter!(0.0, 0.0, 0.0), nanometer!(1000.0), joule!(1.0)) + .unwrap(), + ); + let mut input = LightResult::default(); + input.insert("input_1".into(), LightData::Geometric(rays)); + let output = + AnalysisRayTrace::analyze(&mut node, input, &RayTraceConfig::default()).unwrap(); + + if let Some(LightData::Geometric(rays)) = output.get("output_1") { + assert_eq!(rays.nr_of_rays(true), 1); + let ray = rays.iter().next().unwrap(); + assert_eq!(ray.position(), millimeter!(0.0, 0.0, 10.0)); + assert_eq!(ray.direction(), Vector3::new(0., 1., 1.)); + } else { + assert!(false, "could not get LightData"); + } + } + + #[test] + fn test_rotated_y() { + let mut node = ParaxialSurface::new("test", millimeter!(10.)).unwrap(); + node.set_isometry( + Isometry::new(millimeter!(0.0, 0.0, 10.0), degree!(45.0, 0.0, 0.0)).unwrap(), + ); + let mut rays = Rays::default(); + rays.add_ray( + Ray::new_collimated( + millimeter!(0.0, 10.0 / f64::sqrt(2.), 0.0), + nanometer!(1000.0), + joule!(1.0), + ) + .unwrap(), + ); + let mut input = LightResult::default(); + input.insert("input_1".into(), LightData::Geometric(rays)); + let output = + AnalysisRayTrace::analyze(&mut node, input, &RayTraceConfig::default()).unwrap(); + + if let Some(LightData::Geometric(rays)) = output.get("output_1") { + assert_eq!(rays.nr_of_rays(true), 1); + let ray = rays.iter().next().unwrap(); + assert_relative_eq!(ray.position()[0].value, 0.0); + assert_relative_eq!(ray.position()[1].value, 0.01 / f64::sqrt(2.)); + assert_relative_eq!(ray.position()[2].value, 0.01 / f64::sqrt(2.) + 0.01); + assert_relative_eq!(ray.direction(), Vector3::new(0., -1., 1.).normalize()); + } else { + assert!(false, "could not get LightData"); + } + } + + #[test] + fn test_rotated_x() { + let mut node = ParaxialSurface::new("test", millimeter!(10.)).unwrap(); + node.set_isometry( + Isometry::new(millimeter!(0.0, 0.0, 10.0), degree!(0.0, 45.0, 0.0)).unwrap(), + ); + let mut rays = Rays::default(); + rays.add_ray( + Ray::new_collimated( + millimeter!(-10.0 / f64::sqrt(2.), 0.0, 0.0), + nanometer!(1000.0), + joule!(1.0), + ) + .unwrap(), + ); + let mut input = LightResult::default(); + input.insert("input_1".into(), LightData::Geometric(rays)); + let output = + AnalysisRayTrace::analyze(&mut node, input, &RayTraceConfig::default()).unwrap(); + + if let Some(LightData::Geometric(rays)) = output.get("output_1") { + assert_eq!(rays.nr_of_rays(true), 1); + let ray = rays.iter().next().unwrap(); + assert_relative_eq!(ray.position()[0].value, -0.01 / f64::sqrt(2.)); + assert_relative_eq!(ray.position()[1].value, 0.0); + assert_relative_eq!(ray.position()[2].value, 0.01 / f64::sqrt(2.) + 0.01); + assert_relative_eq!(ray.direction(), Vector3::new(1., 0., 1.).normalize()); + } else { + assert!(false, "could not get LightData"); + } + } + #[test] fn as_ref_node_mut() { let mut node = ParaxialSurface::default(); diff --git a/opossum/src/ray.rs b/opossum/src/ray.rs index 770df71710098530b29c78dd592b02340fce3632..cadabd30e83bb00ab146d7899e85267f396bdc09 100644 --- a/opossum/src/ray.rs +++ b/opossum/src/ray.rs @@ -302,28 +302,7 @@ impl Ray { pub fn to_isometry(&self, up_direction: Vector3<f64>) -> Isometry { Isometry::new_from_view(self.position(), self.direction(), up_direction) } - /// Propagate a ray freely along its direction. The length is given as the projection on the z-axis (=optical axis). - /// - /// This function also respects the refractive index stored in the ray while calculating the optical path length. - /// - /// # Errors - /// This functions returns an error if the initial ray direction has a zero z component (= ray not propagating in z direction). - // pub fn propagate_along_z(&mut self, length_along_z: Length) -> OpmResult<()> { - // if self.dir[2].abs() < f64::EPSILON { - // return Err(OpossumError::Other( - // "z-Axis of direction vector must be != 0.0".into(), - // )); - // } - // self.pos_hist.push(self.pos); - // let length_in_ray_dir = length_along_z / self.dir[2]; - // self.pos += vector![ - // length_in_ray_dir * self.dir.x, - // length_in_ray_dir * self.dir.y, - // length_in_ray_dir * self.dir.z - // ]; - // self.path_length += length_in_ray_dir * self.refractive_index * self.dir.norm(); - // Ok(()) - // } + /// Refract a ray on a paraxial surface of a given focal length. /// /// Modify the ray direction in order to simulate a perfect lens. **Note**: This function also