loam_egui/
bivector_matrix.rs1use egui::{Grid, Label, Response, RichText, Ui};
2use loam_math::{Bivector4, Plane4};
3
4pub fn bivector_matrix(ui: &mut Ui, b: &Bivector4) -> Response {
6 Grid::new("loam_egui_bivector_matrix")
7 .num_columns(5)
8 .spacing([8.0, 2.0])
9 .show(ui, |ui| {
10 ui.label("");
11 for axis in AXIS {
12 ui.add(Label::new(RichText::new(axis).monospace().weak()));
13 }
14 ui.end_row();
15 for (row, row_axis) in AXIS.iter().enumerate() {
16 ui.add(Label::new(RichText::new(*row_axis).monospace().weak()));
17 for col in 0..4 {
18 let text = cell_text(b, row, col);
19 ui.add(Label::new(RichText::new(text).monospace()));
20 }
21 ui.end_row();
22 }
23 })
24 .response
25}
26
27const AXIS: [&str; 4] = ["x", "y", "z", "w"];
28
29pub fn cell_text(b: &Bivector4, row: usize, col: usize) -> String {
30 if row == col {
31 "0".to_string()
32 } else if row < col {
33 format!("{:>+5.1}", upper_pair(b, row, col).to_degrees())
34 } else {
35 format!("{:>+5.1}", -upper_pair(b, col, row).to_degrees())
36 }
37}
38
39fn upper_pair(b: &Bivector4, row: usize, col: usize) -> f32 {
40 let plane = match (row, col) {
41 (0, 1) => Plane4::Xy,
42 (0, 2) => Plane4::Xz,
43 (0, 3) => Plane4::Xw,
44 (1, 2) => Plane4::Yz,
45 (1, 3) => Plane4::Yw,
46 (2, 3) => Plane4::Zw,
47 _ => unreachable!("upper_pair expects row < col, got ({row}, {col})"),
48 };
49 b.component(plane)
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 fn pure(plane: Plane4) -> Bivector4 {
57 let mut b = Bivector4::ZERO;
58 b.set_component(plane, 1.0);
59 b
60 }
61
62 #[test]
63 fn cell_text_each_basis_plane_lights_correct_cell() {
64 let cases = [
65 (Plane4::Xy, (0, 1)),
66 (Plane4::Xz, (0, 2)),
67 (Plane4::Xw, (0, 3)),
68 (Plane4::Yz, (1, 2)),
69 (Plane4::Yw, (1, 3)),
70 (Plane4::Zw, (2, 3)),
71 ];
72 for (plane, (row, col)) in cases {
73 let b = pure(plane);
74 assert_eq!(
75 cell_text(&b, row, col),
76 "+57.3",
77 "plane {plane:?} should populate ({row}, {col})",
78 );
79 assert_eq!(
80 cell_text(&b, col, row),
81 "-57.3",
82 "plane {plane:?} mirror ({col}, {row}) should be negated",
83 );
84 }
85 }
86}