use eulumdat::{Eulumdat, IesExporter, PhotometricCalculations, Symmetry, TypeIndicator};
const TEST_LDT: &str = r#"RUCO Licht GmbH
1
1
1
0
19
5
0
SY-D-1500-195-30-5-ACW
Supersky
SY-D-1500-195-30-5-ACW
22.11.2021
1500
0
129
1486
0
0
0
0
0
100
100.0
1.0
0.0
1
1
LED 830
19800
3000
80
195
0.358
0.468
0.545
0.619
0.675
0.733
0.776
0.802
0.847
0.874
0
0
5
10
15
20
25
30
35
40
45
50
55
60
65
70
75
80
85
90
386.8106
384.3521
377.1348
365.4063
349.7785
330.3969
307.8906
283.0269
256.5533
228.7582
200.5965
172.3095
144.3752
116.2986
88.6199
62.3291
38.4389
17.8507
0
"#;
#[test]
fn test_parse_real_ldt() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
assert_eq!(ldt.identification, "RUCO Licht GmbH");
assert_eq!(ldt.type_indicator, TypeIndicator::PointSourceSymmetric);
assert_eq!(ldt.symmetry, Symmetry::VerticalAxis);
assert_eq!(ldt.num_c_planes, 1);
assert_eq!(ldt.num_g_planes, 19);
assert_eq!(ldt.luminaire_name, "SY-D-1500-195-30-5-ACW");
assert_eq!(ldt.luminaire_number, "Supersky");
assert_eq!(ldt.lamp_sets.len(), 1);
assert_eq!(ldt.lamp_sets[0].lamp_type, "LED 830");
assert!((ldt.lamp_sets[0].total_luminous_flux - 19800.0).abs() < 0.001);
assert!((ldt.lamp_sets[0].wattage_with_ballast - 195.0).abs() < 0.001);
assert!((ldt.length - 1500.0).abs() < 0.001);
assert!((ldt.height - 129.0).abs() < 0.001);
assert_eq!(ldt.intensities.len(), 1); assert_eq!(ldt.intensities[0].len(), 19); assert!((ldt.intensities[0][0] - 386.8106).abs() < 0.001); assert!((ldt.intensities[0][18] - 0.0).abs() < 0.001); }
#[test]
fn test_validation() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
let warnings = ldt.validate();
for w in &warnings {
println!("Warning: {}", w);
}
assert!(ldt.validate_strict().is_ok());
}
#[test]
fn test_roundtrip() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
let output = ldt.to_ldt();
let ldt2 = Eulumdat::parse(&output).unwrap();
assert_eq!(ldt.identification, ldt2.identification);
assert_eq!(ldt.type_indicator, ldt2.type_indicator);
assert_eq!(ldt.symmetry, ldt2.symmetry);
assert_eq!(ldt.luminaire_name, ldt2.luminaire_name);
assert_eq!(ldt.lamp_sets.len(), ldt2.lamp_sets.len());
assert_eq!(ldt.intensities.len(), ldt2.intensities.len());
for (row1, row2) in ldt.intensities.iter().zip(ldt2.intensities.iter()) {
for (v1, v2) in row1.iter().zip(row2.iter()) {
assert!(
(v1 - v2).abs() < 0.01,
"Intensity mismatch: {} vs {}",
v1,
v2
);
}
}
}
#[test]
fn test_calculations() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
let flux = ldt.total_luminous_flux();
assert!((flux - 19800.0).abs() < 0.001);
let wattage = ldt.total_wattage();
assert!((wattage - 195.0).abs() < 0.001);
let efficacy = ldt.luminous_efficacy();
assert!((efficacy - 101.538).abs() < 1.0);
let max = ldt.max_intensity();
assert!((max - 386.8106).abs() < 0.001);
let beam = PhotometricCalculations::beam_angle(&ldt);
assert!(beam > 0.0 && beam < 180.0, "Beam angle: {}", beam);
}
#[test]
fn test_ies_export() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
let ies = IesExporter::export(&ldt);
assert!(ies.contains("IES:LM-63-2019"));
assert!(ies.contains("[LUMINAIRE] SY-D-1500-195-30-5-ACW"));
assert!(ies.contains("[ISSUEDATE]")); assert!(ies.contains("TILT=NONE"));
assert!(
ies.contains("7658"),
"IES should contain absolute candela values"
);
let ies_2002 = IesExporter::export_2002(&ldt);
assert!(ies_2002.contains("IESNA:LM-63-2002"));
assert!(!ies_2002.contains("[ISSUEDATE]")); }
#[test]
fn test_direct_ratios() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
assert!((ldt.direct_ratios[0] - 0.358).abs() < 0.001);
assert!((ldt.direct_ratios[9] - 0.874).abs() < 0.001);
}
#[test]
fn test_symmetry_calc() {
let ldt = Eulumdat::parse(TEST_LDT).unwrap();
assert_eq!(ldt.actual_c_planes(), 1);
assert_eq!(Symmetry::None.calc_mc(36), 36);
assert_eq!(Symmetry::VerticalAxis.calc_mc(36), 1);
assert_eq!(Symmetry::PlaneC0C180.calc_mc(36), 19);
assert_eq!(Symmetry::PlaneC90C270.calc_mc(36), 19);
assert_eq!(Symmetry::BothPlanes.calc_mc(36), 10);
}
#[test]
fn test_european_number_format() {
let content = r#"Test
1
1
1
0
3
5
Report
Luminaire
LUM-001
test.ldt
2024-01-01
100,5
50,25
30
80
40
0
0
0
0
100
85
1,0
0
1
1
LED
1000,5
3000K
80
10,5
0,5
0,55
0,6
0,65
0,7
0,75
0,8
0,82
0,85
0,88
0
0
45
90
100,5
80,25
50
"#;
let ldt = Eulumdat::parse(content).unwrap();
assert!((ldt.length - 100.5).abs() < 0.001);
assert!((ldt.width - 50.25).abs() < 0.001);
assert!((ldt.lamp_sets[0].total_luminous_flux - 1000.5).abs() < 0.001);
assert!((ldt.intensities[0][0] - 100.5).abs() < 0.001);
}
#[test]
fn test_italo_ies_isolux() {
let content = std::fs::read_to_string(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../eulumdat-wasm/templates/ITALO 1 5P5 S05 3.140-3M.IES"
))
.unwrap();
let ldt = eulumdat::IesParser::parse(&content).unwrap();
eprintln!("=== ITALO IES parsed ===");
eprintln!("num_lamps: {}", ldt.lamp_sets[0].num_lamps);
eprintln!(
"total_luminous_flux: {:.1}",
ldt.lamp_sets[0].total_luminous_flux
);
eprintln!(
"c_angles: {} ({:.0}..{:.0})",
ldt.c_angles.len(),
ldt.c_angles.first().unwrap_or(&0.0),
ldt.c_angles.last().unwrap_or(&0.0)
);
eprintln!(
"g_angles: {} ({:.0}..{:.0})",
ldt.g_angles.len(),
ldt.g_angles.first().unwrap_or(&0.0),
ldt.g_angles.last().unwrap_or(&0.0)
);
eprintln!(
"intensities: {}x{}",
ldt.intensities.len(),
ldt.intensities.first().map(|v| v.len()).unwrap_or(0)
);
eprintln!("symmetry: {:?}", ldt.symmetry);
eprintln!(
"sample(0,0)={:.2} sample(0,45)={:.2} sample(0,90)={:.2}",
ldt.sample(0.0, 0.0),
ldt.sample(0.0, 45.0),
ldt.sample(0.0, 90.0)
);
eprintln!("max_intensity: {:.2}", ldt.max_intensity());
let total_flux: f64 = ldt
.lamp_sets
.iter()
.map(|ls| ls.total_luminous_flux * ls.num_lamps.unsigned_abs() as f64)
.sum();
eprintln!(
"total_flux: {:.1}, flux_scale: {:.4}",
total_flux,
total_flux / 1000.0
);
use eulumdat::diagram::{IsoluxDiagram, IsoluxParams};
let params = IsoluxParams {
mounting_height: 10.0,
tilt_angle: 0.0,
area_half_width: 20.0,
area_half_depth: 20.0,
grid_resolution: 60,
};
let diagram = IsoluxDiagram::from_eulumdat(&ldt, 600.0, 500.0, params);
eprintln!("max_lux: {:.4}", diagram.max_lux);
eprintln!("cells: {}", diagram.cells.len());
let nonzero = diagram.cells.iter().filter(|c| c.lux > 0.001).count();
eprintln!("cells with lux>0.001: {}", nonzero);
eprintln!("contours: {}", diagram.contours.len());
assert!(
diagram.max_lux > 0.0,
"ITALO isolux must have positive illuminance"
);
}