dear_implot3d/plots/
mod.rs

1//! Modular plot types for ImPlot3D
2//!
3//! Builder-oriented API mirroring dear-implot's `plots` module.
4
5pub mod image;
6pub mod line;
7pub mod mesh;
8pub mod quads;
9pub mod scatter;
10pub mod surface;
11pub mod triangles;
12
13pub use image::*;
14pub use line::*;
15pub use mesh::*;
16pub use quads::*;
17pub use scatter::*;
18pub use surface::*;
19pub use triangles::*;
20
21/// Errors that can occur during 3D plotting
22#[derive(Debug, Clone, PartialEq)]
23pub enum Plot3DError {
24    EmptyData,
25    DataLengthMismatch {
26        a: usize,
27        b: usize,
28        what: &'static str,
29    },
30    NotMultipleOf {
31        len: usize,
32        k: usize,
33        what: &'static str,
34    },
35    GridSizeMismatch {
36        x_count: usize,
37        y_count: usize,
38        z_len: usize,
39    },
40    StringConversion(&'static str),
41}
42
43impl std::fmt::Display for Plot3DError {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        match self {
46            Plot3DError::EmptyData => write!(f, "data is empty"),
47            Plot3DError::DataLengthMismatch { a, b, what } => {
48                write!(f, "length mismatch for {}: {} vs {}", what, a, b)
49            }
50            Plot3DError::NotMultipleOf { len, k, what } => {
51                write!(f, "length of {} = {} is not multiple of {}", what, len, k)
52            }
53            Plot3DError::GridSizeMismatch {
54                x_count,
55                y_count,
56                z_len,
57            } => write!(
58                f,
59                "grid mismatch: x={} y={} => expected z_len={}, got {}",
60                x_count,
61                y_count,
62                x_count * y_count,
63                z_len
64            ),
65            Plot3DError::StringConversion(what) => write!(f, "string conversion error: {}", what),
66        }
67    }
68}
69
70impl std::error::Error for Plot3DError {}
71
72/// Common trait for 3D plot elements
73pub trait Plot3D {
74    fn label(&self) -> &str;
75    fn try_plot(&self, ui: &crate::Plot3DUi<'_>) -> Result<(), Plot3DError>;
76    fn plot(&self, ui: &crate::Plot3DUi<'_>) {
77        let _ = self.try_plot(ui);
78    }
79}
80
81#[inline]
82pub fn validate_nonempty<T>(a: &[T]) -> Result<(), Plot3DError> {
83    if a.is_empty() {
84        Err(Plot3DError::EmptyData)
85    } else {
86        Ok(())
87    }
88}
89
90#[inline]
91pub fn validate_lengths<T, U>(a: &[T], b: &[U], what: &'static str) -> Result<(), Plot3DError> {
92    if a.len() != b.len() {
93        Err(Plot3DError::DataLengthMismatch {
94            a: a.len(),
95            b: b.len(),
96            what,
97        })
98    } else {
99        Ok(())
100    }
101}
102
103#[inline]
104pub fn validate_multiple(len: usize, k: usize, what: &'static str) -> Result<(), Plot3DError> {
105    if len % k != 0 {
106        Err(Plot3DError::NotMultipleOf { len, k, what })
107    } else {
108        Ok(())
109    }
110}