microcad_core/
render.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Render trait.
5
6use cgmath::InnerSpace;
7
8use crate::*;
9
10/// A trait renders something.
11pub trait Render<T> {
12    /// The render function.
13    fn render(&self, resolution: &RenderResolution) -> T;
14}
15
16/// Render resolution when rendering things to polygons or meshes.
17#[derive(Debug, Clone)]
18pub struct RenderResolution {
19    /// Linear resolution in millimeters (Default = 0.1mm)
20    pub linear: Scalar,
21}
22
23impl RenderResolution {
24    /// Create new render resolution.
25    pub fn new(linear: Scalar) -> Self {
26        Self { linear }
27    }
28
29    /// Coarse render resolution of 1.0mm.
30    pub fn coarse() -> Self {
31        Self { linear: 1.0 }
32    }
33
34    /// Get the number segments for a circle as power of 2.
35    ///
36    /// The minimal number of segments is 4, the maximum number of segments is 1024.
37    pub fn circular_segments(&self, radius: Scalar) -> u32 {
38        let n = (radius / self.linear * std::f64::consts::PI * 0.5).max(3.0);
39        2_u32.pow(n.log2().ceil() as u32).clamp(4, 1024)
40    }
41}
42
43impl std::ops::Mul<Mat3> for RenderResolution {
44    type Output = RenderResolution;
45
46    fn mul(self, rhs: Mat3) -> Self::Output {
47        let scale = (rhs.x.magnitude() * rhs.y.magnitude()).sqrt();
48        Self {
49            linear: self.linear / scale,
50        }
51    }
52}
53
54impl std::ops::Mul<Mat4> for RenderResolution {
55    type Output = RenderResolution;
56
57    fn mul(self, rhs: Mat4) -> Self::Output {
58        let scale = (rhs.x.magnitude() * rhs.y.magnitude() * rhs.z.magnitude()).powf(1.0 / 3.0);
59        Self {
60            linear: self.linear / scale,
61        }
62    }
63}
64
65impl Default for RenderResolution {
66    fn default() -> Self {
67        RenderResolution { linear: 0.1 }
68    }
69}
70
71impl std::fmt::Display for RenderResolution {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        write!(f, "@{}mm", self.linear)
74    }
75}
76
77impl std::hash::Hash for RenderResolution {
78    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
79        bytemuck::bytes_of(&self.linear).hash(state);
80    }
81}