eulumdat 0.2.1__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {eulumdat-0.2.1 → eulumdat-0.2.2}/Cargo.lock +25 -9
- {eulumdat-0.2.1 → eulumdat-0.2.2}/Cargo.toml +2 -2
- {eulumdat-0.2.1 → eulumdat-0.2.2}/PKG-INFO +1 -1
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/eulumdat.rs +37 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/symmetry.rs +70 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/Cargo.toml +5 -5
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/types.rs +33 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/pyproject.toml +1 -1
- {eulumdat-0.2.1 → eulumdat-0.2.2}/README.md +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/Cargo.toml +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/README.md +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/examples/generate_watchface.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/examples/parse_road.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/batch.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/bug_rating.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/calculations.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/butterfly.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/cartesian.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/color.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/heatmap.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/mod.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/polar.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/projection.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/svg.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/diagram/watchface.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/error.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/ies.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/lib.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/parser.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/validation.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/src/writer.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat/tests/integration_test.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/README.md +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/batch.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/bug_rating.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/diagram.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/error.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/lib.rs +0 -0
- {eulumdat-0.2.1 → eulumdat-0.2.2}/crates/eulumdat-py/src/validation.rs +0 -0
|
@@ -1400,7 +1400,7 @@ dependencies = [
|
|
|
1400
1400
|
|
|
1401
1401
|
[[package]]
|
|
1402
1402
|
name = "eulumdat"
|
|
1403
|
-
version = "0.2.
|
|
1403
|
+
version = "0.2.2"
|
|
1404
1404
|
dependencies = [
|
|
1405
1405
|
"anyhow",
|
|
1406
1406
|
"approx",
|
|
@@ -1409,7 +1409,7 @@ dependencies = [
|
|
|
1409
1409
|
|
|
1410
1410
|
[[package]]
|
|
1411
1411
|
name = "eulumdat-cli"
|
|
1412
|
-
version = "0.2.
|
|
1412
|
+
version = "0.2.2"
|
|
1413
1413
|
dependencies = [
|
|
1414
1414
|
"anyhow",
|
|
1415
1415
|
"clap",
|
|
@@ -1419,7 +1419,7 @@ dependencies = [
|
|
|
1419
1419
|
|
|
1420
1420
|
[[package]]
|
|
1421
1421
|
name = "eulumdat-egui"
|
|
1422
|
-
version = "0.2.
|
|
1422
|
+
version = "0.2.2"
|
|
1423
1423
|
dependencies = [
|
|
1424
1424
|
"anyhow",
|
|
1425
1425
|
"eframe",
|
|
@@ -1434,16 +1434,32 @@ dependencies = [
|
|
|
1434
1434
|
|
|
1435
1435
|
[[package]]
|
|
1436
1436
|
name = "eulumdat-ffi"
|
|
1437
|
-
version = "0.2.
|
|
1437
|
+
version = "0.2.2"
|
|
1438
1438
|
dependencies = [
|
|
1439
1439
|
"eulumdat",
|
|
1440
1440
|
"thiserror 1.0.69",
|
|
1441
1441
|
"uniffi",
|
|
1442
1442
|
]
|
|
1443
1443
|
|
|
1444
|
+
[[package]]
|
|
1445
|
+
name = "eulumdat-harmonyos-ffi"
|
|
1446
|
+
version = "0.2.2"
|
|
1447
|
+
dependencies = [
|
|
1448
|
+
"eulumdat",
|
|
1449
|
+
"eulumdat-photweb",
|
|
1450
|
+
]
|
|
1451
|
+
|
|
1452
|
+
[[package]]
|
|
1453
|
+
name = "eulumdat-photweb"
|
|
1454
|
+
version = "0.2.2"
|
|
1455
|
+
dependencies = [
|
|
1456
|
+
"approx",
|
|
1457
|
+
"eulumdat",
|
|
1458
|
+
]
|
|
1459
|
+
|
|
1444
1460
|
[[package]]
|
|
1445
1461
|
name = "eulumdat-py"
|
|
1446
|
-
version = "0.2.
|
|
1462
|
+
version = "0.2.2"
|
|
1447
1463
|
dependencies = [
|
|
1448
1464
|
"eulumdat",
|
|
1449
1465
|
"pyo3",
|
|
@@ -1451,7 +1467,7 @@ dependencies = [
|
|
|
1451
1467
|
|
|
1452
1468
|
[[package]]
|
|
1453
1469
|
name = "eulumdat-wasm"
|
|
1454
|
-
version = "0.2.
|
|
1470
|
+
version = "0.2.2"
|
|
1455
1471
|
dependencies = [
|
|
1456
1472
|
"base64",
|
|
1457
1473
|
"eulumdat",
|
|
@@ -1467,7 +1483,7 @@ dependencies = [
|
|
|
1467
1483
|
|
|
1468
1484
|
[[package]]
|
|
1469
1485
|
name = "eulumdat-windows-preview"
|
|
1470
|
-
version = "0.2.
|
|
1486
|
+
version = "0.2.2"
|
|
1471
1487
|
dependencies = [
|
|
1472
1488
|
"anyhow",
|
|
1473
1489
|
"embed-resource",
|
|
@@ -1523,9 +1539,9 @@ checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
|
|
|
1523
1539
|
|
|
1524
1540
|
[[package]]
|
|
1525
1541
|
name = "flate2"
|
|
1526
|
-
version = "1.1.
|
|
1542
|
+
version = "1.1.5"
|
|
1527
1543
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
1528
|
-
checksum = "
|
|
1544
|
+
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
|
|
1529
1545
|
dependencies = [
|
|
1530
1546
|
"crc32fast",
|
|
1531
1547
|
"miniz_oxide",
|
|
@@ -3,7 +3,7 @@ resolver = "2"
|
|
|
3
3
|
members = ["crates/*"]
|
|
4
4
|
|
|
5
5
|
[workspace.package]
|
|
6
|
-
version = "0.2.
|
|
6
|
+
version = "0.2.2"
|
|
7
7
|
edition = "2021"
|
|
8
8
|
authors = ["Holger Trahe <trahe@mac.com>"]
|
|
9
9
|
license = "MIT OR Apache-2.0"
|
|
@@ -12,7 +12,7 @@ homepage = "https://github.com/holg/eulumdat-rs"
|
|
|
12
12
|
|
|
13
13
|
[workspace.dependencies]
|
|
14
14
|
# Internal crates
|
|
15
|
-
eulumdat = { path = "crates/eulumdat" }
|
|
15
|
+
eulumdat = { path = "crates/eulumdat", version = "0.2.2" }
|
|
16
16
|
|
|
17
17
|
# Shared dependencies
|
|
18
18
|
anyhow = "1.0"
|
|
@@ -361,4 +361,41 @@ impl Eulumdat {
|
|
|
361
361
|
0.0
|
|
362
362
|
}
|
|
363
363
|
}
|
|
364
|
+
|
|
365
|
+
/// Sample intensity at any C and G angle using bilinear interpolation.
|
|
366
|
+
///
|
|
367
|
+
/// This is the key method for generating beam meshes and smooth geometry.
|
|
368
|
+
/// It handles symmetry automatically and interpolates between stored data points.
|
|
369
|
+
///
|
|
370
|
+
/// # Arguments
|
|
371
|
+
/// * `c_angle` - C-plane angle in degrees (0-360, will be normalized)
|
|
372
|
+
/// * `g_angle` - Gamma angle in degrees (0-180, will be clamped)
|
|
373
|
+
///
|
|
374
|
+
/// # Returns
|
|
375
|
+
/// Interpolated intensity value in cd/klm
|
|
376
|
+
///
|
|
377
|
+
/// # Example
|
|
378
|
+
/// ```rust,no_run
|
|
379
|
+
/// use eulumdat::Eulumdat;
|
|
380
|
+
///
|
|
381
|
+
/// let ldt = Eulumdat::from_file("luminaire.ldt")?;
|
|
382
|
+
///
|
|
383
|
+
/// // Sample at exact stored angles
|
|
384
|
+
/// let intensity = ldt.sample(0.0, 45.0);
|
|
385
|
+
///
|
|
386
|
+
/// // Sample at arbitrary angles (will interpolate)
|
|
387
|
+
/// let intensity = ldt.sample(22.5, 67.5);
|
|
388
|
+
///
|
|
389
|
+
/// // Generate smooth beam mesh at 5° intervals
|
|
390
|
+
/// for c in (0..360).step_by(5) {
|
|
391
|
+
/// for g in (0..=180).step_by(5) {
|
|
392
|
+
/// let intensity = ldt.sample(c as f64, g as f64);
|
|
393
|
+
/// // Use intensity for mesh generation...
|
|
394
|
+
/// }
|
|
395
|
+
/// }
|
|
396
|
+
/// # Ok::<(), Box<dyn std::error::Error>>(())
|
|
397
|
+
/// ```
|
|
398
|
+
pub fn sample(&self, c_angle: f64, g_angle: f64) -> f64 {
|
|
399
|
+
crate::symmetry::SymmetryHandler::get_intensity_at(self, c_angle, g_angle)
|
|
400
|
+
}
|
|
364
401
|
}
|
|
@@ -342,4 +342,74 @@ mod tests {
|
|
|
342
342
|
assert!((x - 1.0).abs() < 0.001);
|
|
343
343
|
assert!((y - 0.0).abs() < 0.001);
|
|
344
344
|
}
|
|
345
|
+
|
|
346
|
+
#[test]
|
|
347
|
+
fn test_get_intensity_at_exact_angles() {
|
|
348
|
+
let ldt = Eulumdat {
|
|
349
|
+
symmetry: Symmetry::None,
|
|
350
|
+
c_angles: vec![0.0, 90.0, 180.0, 270.0],
|
|
351
|
+
g_angles: vec![0.0, 45.0, 90.0],
|
|
352
|
+
intensities: vec![
|
|
353
|
+
vec![100.0, 80.0, 50.0], // C0
|
|
354
|
+
vec![90.0, 70.0, 40.0], // C90
|
|
355
|
+
vec![80.0, 60.0, 30.0], // C180
|
|
356
|
+
vec![70.0, 50.0, 20.0], // C270
|
|
357
|
+
],
|
|
358
|
+
..Default::default()
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// Test exact angles
|
|
362
|
+
let i = SymmetryHandler::get_intensity_at(&ldt, 0.0, 0.0);
|
|
363
|
+
assert!((i - 100.0).abs() < 0.001);
|
|
364
|
+
|
|
365
|
+
let i = SymmetryHandler::get_intensity_at(&ldt, 90.0, 45.0);
|
|
366
|
+
assert!((i - 70.0).abs() < 0.001);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
#[test]
|
|
370
|
+
fn test_get_intensity_at_interpolated() {
|
|
371
|
+
let ldt = Eulumdat {
|
|
372
|
+
symmetry: Symmetry::None,
|
|
373
|
+
c_angles: vec![0.0, 90.0],
|
|
374
|
+
g_angles: vec![0.0, 90.0],
|
|
375
|
+
intensities: vec![
|
|
376
|
+
vec![100.0, 0.0], // C0: 100 at nadir, 0 at horizontal
|
|
377
|
+
vec![100.0, 0.0], // C90: same
|
|
378
|
+
],
|
|
379
|
+
..Default::default()
|
|
380
|
+
};
|
|
381
|
+
|
|
382
|
+
// Interpolate at G=45 should give ~50 (midpoint)
|
|
383
|
+
let i = SymmetryHandler::get_intensity_at(&ldt, 0.0, 45.0);
|
|
384
|
+
assert!((i - 50.0).abs() < 0.001);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
#[test]
|
|
388
|
+
fn test_sample_method() {
|
|
389
|
+
let ldt = Eulumdat {
|
|
390
|
+
symmetry: Symmetry::BothPlanes,
|
|
391
|
+
c_angles: vec![0.0, 45.0, 90.0],
|
|
392
|
+
g_angles: vec![0.0, 30.0, 60.0, 90.0],
|
|
393
|
+
intensities: vec![
|
|
394
|
+
vec![100.0, 90.0, 70.0, 40.0], // C0
|
|
395
|
+
vec![95.0, 85.0, 65.0, 35.0], // C45
|
|
396
|
+
vec![90.0, 80.0, 60.0, 30.0], // C90
|
|
397
|
+
],
|
|
398
|
+
..Default::default()
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// Test the sample() convenience method
|
|
402
|
+
let i = ldt.sample(0.0, 0.0);
|
|
403
|
+
assert!((i - 100.0).abs() < 0.001);
|
|
404
|
+
|
|
405
|
+
// Test symmetry - C180 should mirror C0
|
|
406
|
+
let i_c0 = ldt.sample(0.0, 30.0);
|
|
407
|
+
let i_c180 = ldt.sample(180.0, 30.0);
|
|
408
|
+
assert!((i_c0 - i_c180).abs() < 0.001);
|
|
409
|
+
|
|
410
|
+
// Test symmetry - C270 should mirror C90
|
|
411
|
+
let i_c90 = ldt.sample(90.0, 60.0);
|
|
412
|
+
let i_c270 = ldt.sample(270.0, 60.0);
|
|
413
|
+
assert!((i_c90 - i_c270).abs() < 0.001);
|
|
414
|
+
}
|
|
345
415
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "eulumdat-py"
|
|
3
|
-
version.workspace
|
|
4
|
-
edition
|
|
5
|
-
license
|
|
6
|
-
repository
|
|
3
|
+
version = "0.2.2" # Must be explicit for maturin (workspace inheritance not supported)
|
|
4
|
+
edition = "2021"
|
|
5
|
+
license = "MIT OR Apache-2.0"
|
|
6
|
+
repository = "https://github.com/holg/eulumdat-rs"
|
|
7
7
|
description = "Python bindings for eulumdat photometric file parsing library"
|
|
8
8
|
readme = "README.md"
|
|
9
9
|
|
|
@@ -12,5 +12,5 @@ name = "eulumdat"
|
|
|
12
12
|
crate-type = ["cdylib"]
|
|
13
13
|
|
|
14
14
|
[dependencies]
|
|
15
|
-
eulumdat = { path = "../eulumdat" }
|
|
15
|
+
eulumdat = { path = "../eulumdat", version = "0.2.2" }
|
|
16
16
|
pyo3 = { version = "0.27", features = ["extension-module"] }
|
|
@@ -720,6 +720,39 @@ impl Eulumdat {
|
|
|
720
720
|
self.inner.get_intensity(c_index, g_index)
|
|
721
721
|
}
|
|
722
722
|
|
|
723
|
+
/// Sample intensity at any C and G angle using bilinear interpolation.
|
|
724
|
+
///
|
|
725
|
+
/// This method handles symmetry automatically - you can query any angle
|
|
726
|
+
/// in the full 0-360° C range and 0-180° G range regardless of stored symmetry.
|
|
727
|
+
///
|
|
728
|
+
/// Args:
|
|
729
|
+
/// c_angle: C-plane angle in degrees (will be normalized to 0-360)
|
|
730
|
+
/// g_angle: Gamma angle in degrees (will be clamped to 0-180)
|
|
731
|
+
///
|
|
732
|
+
/// Returns:
|
|
733
|
+
/// Intensity in cd/klm at the specified angle
|
|
734
|
+
fn sample(&self, c_angle: f64, g_angle: f64) -> f64 {
|
|
735
|
+
self.inner.sample(c_angle, g_angle)
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
/// Sample normalized intensity (0.0 to 1.0) at any C and G angle.
|
|
739
|
+
///
|
|
740
|
+
/// Returns intensity relative to maximum intensity, useful for visualization.
|
|
741
|
+
///
|
|
742
|
+
/// Args:
|
|
743
|
+
/// c_angle: C-plane angle in degrees
|
|
744
|
+
/// g_angle: Gamma angle in degrees
|
|
745
|
+
///
|
|
746
|
+
/// Returns:
|
|
747
|
+
/// Normalized intensity (0.0 to 1.0)
|
|
748
|
+
fn sample_normalized(&self, c_angle: f64, g_angle: f64) -> f64 {
|
|
749
|
+
let max = self.inner.max_intensity();
|
|
750
|
+
if max <= 0.0 {
|
|
751
|
+
return 0.0;
|
|
752
|
+
}
|
|
753
|
+
self.inner.sample(c_angle, g_angle) / max
|
|
754
|
+
}
|
|
755
|
+
|
|
723
756
|
// === Diagram Generation ===
|
|
724
757
|
|
|
725
758
|
/// Generate a polar diagram SVG.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|