use concinnity_core::gfx::lines::Line;
const SOLID_FRACTION: f32 = 0.25;
const WIDTH_PX: f32 = 2.0;
const MIN_EXTENT: f32 = 50.0;
const UNLIMITED_EXTENT: f32 = 200.0;
const AXIS_COLORS: [[f32; 3]; 3] = [[0.90, 0.10, 0.12], [0.16, 0.75, 0.22], [0.16, 0.35, 0.95]];
const AXES: [[f32; 3]; 3] = [[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]];
pub(crate) fn push_lines(out: &mut Vec<Line>, view_distance: Option<f32>) {
let extent = view_distance.unwrap_or(UNLIMITED_EXTENT).max(MIN_EXTENT);
let solid = extent * SOLID_FRACTION;
for (axis, rgb) in AXES.iter().zip(AXIS_COLORS) {
let at = |d: f32| [axis[0] * d, axis[1] * d, axis[2] * d];
let color = |a: f32| [rgb[0], rgb[1], rgb[2], a];
out.push(Line {
start: [0.0; 3],
end: at(solid),
start_color: color(1.0),
end_color: color(1.0),
width_px: WIDTH_PX,
});
out.push(Line {
start: at(solid),
end: at(extent),
start_color: color(1.0),
end_color: color(0.0),
width_px: WIDTH_PX,
});
}
}
#[cfg(test)]
mod tests {
use super::*;
fn lines(view_distance: f32) -> Vec<Line> {
let mut out = Vec::new();
push_lines(&mut out, Some(view_distance));
out
}
#[test]
fn one_solid_and_one_fading_run_per_axis() {
let l = lines(200.0);
assert_eq!(l.len(), 6);
for pair in l.chunks(2) {
assert_eq!(pair[0].start_color[3], 1.0);
assert_eq!(pair[0].end_color[3], 1.0);
assert_eq!(pair[0].end, pair[1].start, "the runs meet");
assert_eq!(pair[1].end_color[3], 0.0);
}
}
#[test]
fn every_run_leaves_the_origin_in_its_positive_direction() {
let l = lines(200.0);
assert_eq!(l[0].start, [0.0; 3]);
let ends = [l[1].end, l[3].end, l[5].end];
for (i, end) in ends.iter().enumerate() {
assert!(end[i] > 0.0, "axis {i} runs positive: {end:?}");
for (j, v) in end.iter().enumerate() {
if j != i {
assert_eq!(*v, 0.0, "axis {i} stays on its own axis");
}
}
}
}
#[test]
fn the_run_reaches_the_view_distance() {
assert_eq!(lines(500.0)[1].end[0], 500.0);
assert_eq!(lines(1.0)[1].end[0], MIN_EXTENT);
let mut unlimited = Vec::new();
push_lines(&mut unlimited, None);
assert_eq!(unlimited[1].end[0], UNLIMITED_EXTENT);
}
#[test]
fn both_runs_of_an_axis_share_its_color() {
let l = lines(200.0);
for (pair, rgb) in l.chunks(2).zip(AXIS_COLORS) {
assert_eq!(pair[0].start_color[..3], rgb);
assert_eq!(pair[1].start_color[..3], rgb);
}
}
#[test]
fn each_axis_reads_as_its_gizmo_hue() {
for (axis, rgb) in AXIS_COLORS.iter().enumerate() {
let others: f32 = rgb
.iter()
.enumerate()
.filter(|(i, _)| *i != axis)
.map(|(_, c)| *c)
.fold(0.0, f32::max);
assert!(rgb[axis] > others * 2.0, "axis {axis} hue is {rgb:?}");
}
}
}