2 unstable releases

new 0.2.0 Dec 9, 2024
0.1.0 Sep 30, 2024

#231 in Graphics APIs

Download history 132/week @ 2024-09-25 35/week @ 2024-10-02 11/week @ 2024-10-09 8/week @ 2024-10-16 3/week @ 2024-10-30 4/week @ 2024-11-06 96/week @ 2024-12-04

96 downloads per month

Custom license

145KB
3K SLoC

Cherry is a library for sequential optical system design.

The core structure of sequential optical design is the SequentialModel which is a set of submodels containing surfaces and gaps between surfaces. Each SequentialSubModel corresponds to a unique set of system parameters, i.e. a wavelength and a transverse axis. A submodel provides an interface to iterate over the surfaces and gaps in the system.

Inputs to the system are provided by specs, of which there are several types:

  • SurfaceSpec - Describes a surface in the system for which surface sag or paraxial ray trace matrices can be calculated.
  • GapSpec - Describes a gap between surfaces in the system. Refractive index data is located here.
  • ApertureSpec - Describes the aperture of the system. This may differ from any pupils that can be derived directly from the surfaces and gaps.
  • FieldSpec - Describes the field points of the system.
  • RefractiveIndexSpec - Describes the refractive index of a gap.
  • Wavelength - Describes a single wavelength to model.

The outputs of the system are provided by views, such as:

  • ParaxialView - A paraxial view of the system. Contains information such as focal length, principal planes, etc.
  • RayTrace3DView - A 3D ray trace view of the system.
  • CutawayView - A cutaway view of the system. Used primarily for drawing the system.
  • ComponentsView - A view of the components of the system. Used for grouping surfaces into lenses.

Quick Start

use cherry_rs::{
    n, ray_trace_3d_view, ApertureSpec, FieldSpec, GapSpec, ImagePlane, ParaxialView, Pupil, PupilSampling, RealSpec, RefractiveIndexSpec,
    SequentialModel, SurfaceSpec, SurfaceType,
};

// Create a convexplano lens with an object at infinity.
let air = n!(1.0);
let nbk7 = n!(1.515);

// Define a set of gaps between surfaces.
let gaps = vec![
    GapSpec {
        thickness: f64::INFINITY,
        refractive_index: air.clone(),
    },
    GapSpec {
        thickness: 5.3,
        refractive_index: nbk7,
    },
    GapSpec {
       thickness: 46.6,
       refractive_index: air,
    },
];

// Define a set of surfaces in the system.
let surfaces = vec![
    SurfaceSpec::Object,
    SurfaceSpec::Conic {
        semi_diameter: 12.5,
        radius_of_curvature: 25.8,
        conic_constant: 0.0,
        surf_type: SurfaceType::Refracting,
    },
    SurfaceSpec::Conic {
        semi_diameter: 12.5,
        radius_of_curvature: f64::INFINITY,
        conic_constant: 0.0,
        surf_type: SurfaceType::Refracting,
    },
    SurfaceSpec::Image,
];

// Define a set of wavelengths to model.
let wavelengths: Vec<f64> = vec![0.567];

// Create a sequential model from the gaps, surfaces, and wavelengths.
let sequential_model = SequentialModel::new(&gaps, &surfaces, &wavelengths).unwrap();

// Define a user-defined system aperture.
let aperture_spec = ApertureSpec::EntrancePupil { semi_diameter: 5.0 };

// Analyze the system at two different field points, sampling the pupil
// with a square grid with a spacing of 0.1 in normalized pupil coordinates.
let field_specs = vec![
    FieldSpec::Angle {
        angle: 0.0,
        pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
    },
    FieldSpec::Angle {
        angle: 5.0,
        pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
    },
];

// Compute the paraxial view of the system.
let paraxial_view = ParaxialView::new(&sequential_model, &field_specs, false).unwrap();

// Compute the effective focal length of the lens for each submodel.
for (sub_model_id, _) in sequential_model.submodels() {
    let sub_view = paraxial_view.subviews().get(sub_model_id).unwrap();
    let result = sub_view.effective_focal_length();

    println!("Submodel ID: {:?}, Effective focal length: {}", sub_model_id, result);
}

// Compute a 3D ray trace of the system.
let rays = ray_trace_3d_view(
    &aperture_spec, &field_specs,
    &sequential_model,
    &paraxial_view,
    None,
).unwrap();

Dependencies

~1.7–2.4MB
~49K SLoC