#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct AxisLabelConfig {
pub font_size: f32,
pub offset: f32,
pub show_x: bool,
pub show_y: bool,
pub show_z: bool,
pub color_x: [f32; 4],
pub color_y: [f32; 4],
pub color_z: [f32; 4],
}
impl Default for AxisLabelConfig {
fn default() -> Self {
Self {
font_size: 14.0,
offset: 0.15,
show_x: true,
show_y: true,
show_z: true,
color_x: [1.0, 0.2, 0.2, 1.0],
color_y: [0.2, 1.0, 0.2, 1.0],
color_z: [0.2, 0.4, 1.0, 1.0],
}
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct AxisLabelEntry {
pub label: String,
pub world_position: [f32; 3],
pub color: [f32; 4],
}
#[allow(dead_code)]
pub fn new_axis_label_config() -> AxisLabelConfig {
AxisLabelConfig::default()
}
#[allow(dead_code)]
pub fn generate_axis_labels(cfg: &AxisLabelConfig, axis_length: f32) -> Vec<AxisLabelEntry> {
let mut labels = Vec::new();
let l = axis_length + cfg.offset;
if cfg.show_x {
labels.push(AxisLabelEntry {
label: "X".to_string(),
world_position: [l, 0.0, 0.0],
color: cfg.color_x,
});
}
if cfg.show_y {
labels.push(AxisLabelEntry {
label: "Y".to_string(),
world_position: [0.0, l, 0.0],
color: cfg.color_y,
});
}
if cfg.show_z {
labels.push(AxisLabelEntry {
label: "Z".to_string(),
world_position: [0.0, 0.0, l],
color: cfg.color_z,
});
}
labels
}
#[allow(dead_code)]
pub fn al_set_font_size(cfg: &mut AxisLabelConfig, size: f32) {
cfg.font_size = size.max(4.0);
}
#[allow(dead_code)]
pub fn al_toggle_axis(cfg: &mut AxisLabelConfig, axis: u8, visible: bool) {
match axis {
0 => cfg.show_x = visible,
1 => cfg.show_y = visible,
2 => cfg.show_z = visible,
_ => {}
}
}
#[allow(dead_code)]
pub fn al_visible_count(cfg: &AxisLabelConfig) -> usize {
[cfg.show_x, cfg.show_y, cfg.show_z]
.iter()
.filter(|&&v| v)
.count()
}
#[allow(dead_code)]
pub fn al_label_text(axis: u8) -> &'static str {
match axis {
0 => "X",
1 => "Y",
2 => "Z",
_ => "?",
}
}
#[allow(dead_code)]
pub fn axis_label_to_json(cfg: &AxisLabelConfig) -> String {
format!(
r#"{{"font_size":{:.1},"offset":{:.4},"show_x":{},"show_y":{},"show_z":{}}}"#,
cfg.font_size, cfg.offset, cfg.show_x, cfg.show_y, cfg.show_z
)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_default() {
let c = AxisLabelConfig::default();
assert!(c.show_x && c.show_y && c.show_z);
}
#[test]
fn test_generate_all() {
let c = AxisLabelConfig::default();
let labels = generate_axis_labels(&c, 1.0);
assert_eq!(labels.len(), 3);
}
#[test]
fn test_generate_x_only() {
let c = AxisLabelConfig {
show_y: false,
show_z: false,
..Default::default()
};
let labels = generate_axis_labels(&c, 1.0);
assert_eq!(labels.len(), 1);
assert_eq!(labels[0].label, "X");
}
#[test]
fn test_set_font_size_min() {
let mut c = AxisLabelConfig::default();
al_set_font_size(&mut c, -5.0);
assert!(c.font_size >= 4.0);
}
#[test]
fn test_toggle_axis() {
let mut c = AxisLabelConfig::default();
al_toggle_axis(&mut c, 0, false);
assert!(!c.show_x);
}
#[test]
fn test_visible_count() {
let c = AxisLabelConfig::default();
assert_eq!(al_visible_count(&c), 3);
}
#[test]
fn test_visible_count_partial() {
let c = AxisLabelConfig {
show_z: false,
..Default::default()
};
assert_eq!(al_visible_count(&c), 2);
}
#[test]
fn test_label_text() {
assert_eq!(al_label_text(0), "X");
assert_eq!(al_label_text(1), "Y");
assert_eq!(al_label_text(2), "Z");
}
#[test]
fn test_label_position_offset() {
let c = AxisLabelConfig {
offset: 0.5,
..Default::default()
};
let labels = generate_axis_labels(&c, 1.0);
let x_label = &labels[0];
assert!((x_label.world_position[0] - 1.5).abs() < 1e-5);
}
#[test]
fn test_to_json() {
let j = axis_label_to_json(&AxisLabelConfig::default());
assert!(j.contains("font_size"));
assert!(j.contains("show_x"));
}
}