ui: one symbol-unit helper for the window, ui.render and headless renders (#285)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
jyvikoandClaude Opus 5.5 authored and Irakli Kourtis committed 2026-10-15 10:17:28 -04:00
1 parent b377c882d6
commit 1f36693c8f
6 files changed
+66 -17

No files matched your search

+14
View File
@@ -198,6 +198,15 @@ pub fn symbol_unit(length_per_pixel: f64, size: f64) -> Option<f64> {
(unit.is_finite() && unit > 0.0).then_some(unit)
}
/// The symbol unit for symbols `size_pt` points across in a view `height_px` pixels high at
/// `pixels_per_point` (1 for a headless image, the display's scale for the desktop), seen with
/// `cam`: the one helper the desktop, `ui.render` and headless renders share, so a render at
/// device resolution matches the window. A scale that is not a positive number counts as 1.
pub fn unit_for(cam: &crate::Camera, height_px: f64, size_pt: f64, pixels_per_point: f64) -> Option<f64> {
let ppp = if pixels_per_point.is_finite() && pixels_per_point > 0.0 { pixels_per_point } else { 1.0 };
symbol_unit(cam.length_per_pixel(height_px)? * ppp, size_pt)
}
/// A symbol unit rounded to a quarter of a doubling (within 9 %), and the step it is: a viewer
/// rebuilds its symbols only when zooming changes the step.
pub fn quantise_unit(unit: f64) -> Option<(i32, f64)> {
@@ -1414,6 +1423,11 @@ mod tests {
assert_eq!(symbol_unit(1.0, 1e9), Some(SIZE_RANGE.1));
assert_eq!(symbol_unit(1.0, f64::NAN), Some(DEFAULT_SIZE));
assert_eq!(symbol_unit(f64::INFINITY, 10.0), None);
// A view at twice the pixels per point has the same unit as at one (#285).
let cam = crate::Camera::default();
assert_eq!(unit_for(&cam, 1600.0, DEFAULT_SIZE, 2.0), unit_for(&cam, 800.0, DEFAULT_SIZE, 1.0));
assert_eq!(unit_for(&cam, 800.0, DEFAULT_SIZE, f64::NAN), unit_for(&cam, 800.0, DEFAULT_SIZE, 1.0));
assert_eq!(unit_for(&cam, 0.0, DEFAULT_SIZE, 1.0), None);
assert_eq!(Camera::default().length_per_pixel(0.0), None);
// Units round to a quarter of a doubling.
let (k, q) = quantise_unit(1.1).unwrap();
+14
View File
@@ -76,6 +76,20 @@ impl Scene {
self.labels.extend(other.labels);
self.on_top.extend(other.on_top);
}
/// Line widths and point sizes (given in points) in pixels at `pixels_per_point`, as the GPU
/// viewport draws them: a CPU render at device resolution then matches the window.
pub fn scale_marks(&mut self, pixels_per_point: f64) {
if !(pixels_per_point.is_finite() && pixels_per_point > 0.0) {
return;
}
for l in self.lines.iter_mut().chain(self.on_top.iter_mut()) {
l.width *= pixels_per_point;
}
for p in &mut self.points {
p.size *= pixels_per_point;
}
}
}
/// The lit colour of a surface with normal `n` seen along `view_dir` (toward the eye). The GPU