namespace LensSimulatorCore.Optical; public class Material { public SellmeierCoefficients Sellmeier { get; set; } public double RefractiveIndex(double wavelength) { return Sellmeier.CalculateRefractiveIndex(wavelength); } private readonly Func _reflectivity; private readonly Func _transmissivity; public Material(SellmeierCoefficients sellmeierCoefficients) { Sellmeier = sellmeierCoefficients; _reflectivity = ComputeReflectivity; _transmissivity = (angle, n1, wavelength) => 1.0 - Reflectivity(angle, n1, wavelength); } private double ComputeReflectivity(double angleDegrees, double n1, double wavelength) { // Convert angle to radians var angleRadians = angleDegrees * Math.PI / 180.0; // Check for total internal reflection var criticalAngle = Math.Asin(RefractiveIndex(wavelength) / n1); if (angleRadians > criticalAngle) { return 1.0; } var rs = ComputeFresnelCoefficient(angleRadians, n1, wavelength, isSPolarized: true); var rp = ComputeFresnelCoefficient(angleRadians, n1, wavelength, isSPolarized: false); return (rs + rp) / 2.0; } private double ComputeFresnelCoefficient(double angle, double n1, double wavelength, bool isSPolarized) { double numerator; double denominator; if (isSPolarized) { numerator = n1 * Math.Cos(angle) - RefractiveIndex(wavelength) * Math.Sqrt(1 - Math.Pow((n1 / RefractiveIndex(wavelength) * Math.Sin(angle)), 2)); denominator = n1 * Math.Cos(angle) + RefractiveIndex(wavelength) * Math.Sqrt(1 - Math.Pow((n1 / RefractiveIndex(wavelength) * Math.Sin(angle)), 2)); } else { numerator = n1 * Math.Sqrt(1 - Math.Pow((n1 / RefractiveIndex(wavelength) * Math.Sin(angle)), 2)) - RefractiveIndex(wavelength) * Math.Cos(angle); denominator = n1 * Math.Sqrt(1 - Math.Pow((n1 / RefractiveIndex(wavelength) * Math.Sin(angle)), 2)) + RefractiveIndex(wavelength) * Math.Cos(angle); } return Math.Pow(numerator / denominator, 2); } // ReSharper disable once MemberCanBePrivate.Global public double Reflectivity(double angle, double n1, double wavelength) { return _reflectivity(angle, n1, wavelength); } public double Transmissivity(double angle, double n1, double wavelength) { return _transmissivity(angle, n1, wavelength); } }