Skip to main content

dear_implot/plots/
inf_lines.rs

1//! Infinite lines plot implementation
2
3use super::{Plot, PlotError, PlotItemStyle, plot_spec_with_style, with_plot_str_or_empty};
4use crate::{InfLinesFlags, ItemFlags, sys};
5
6/// Builder for infinite lines plots
7pub struct InfLinesPlot<'a> {
8    label: &'a str,
9    positions: &'a [f64],
10    style: PlotItemStyle,
11    flags: InfLinesFlags,
12    item_flags: ItemFlags,
13    offset: i32,
14    stride: i32,
15}
16
17impl<'a> super::PlotItemStyled for InfLinesPlot<'a> {
18    fn style_mut(&mut self) -> &mut PlotItemStyle {
19        &mut self.style
20    }
21}
22
23impl<'a> InfLinesPlot<'a> {
24    /// Create a new infinite lines plot with the given label and positions (vertical by default)
25    pub fn new(label: &'a str, positions: &'a [f64]) -> Self {
26        Self {
27            label,
28            positions,
29            style: PlotItemStyle::default(),
30            flags: InfLinesFlags::NONE,
31            item_flags: ItemFlags::NONE,
32            offset: 0,
33            stride: std::mem::size_of::<f64>() as i32,
34        }
35    }
36
37    /// Make lines horizontal instead of vertical
38    pub fn horizontal(mut self) -> Self {
39        self.flags |= InfLinesFlags::HORIZONTAL;
40        self
41    }
42
43    /// Set common item flags for this plot item (applies to all plot types)
44    pub fn with_item_flags(mut self, flags: ItemFlags) -> Self {
45        self.item_flags = flags;
46        self
47    }
48
49    /// Set data offset for partial plotting
50    pub fn with_offset(mut self, offset: i32) -> Self {
51        self.offset = offset;
52        self
53    }
54
55    /// Set data stride for non-contiguous data
56    pub fn with_stride(mut self, stride: i32) -> Self {
57        self.stride = stride;
58        self
59    }
60
61    /// Validate the plot data
62    pub fn validate(&self) -> Result<(), PlotError> {
63        if self.positions.is_empty() {
64            return Err(PlotError::EmptyData);
65        }
66        Ok(())
67    }
68}
69
70impl<'a> Plot for InfLinesPlot<'a> {
71    fn plot(&self) {
72        if self.validate().is_err() {
73            return;
74        }
75        let Ok(count) = i32::try_from(self.positions.len()) else {
76            return;
77        };
78        with_plot_str_or_empty(self.label, |label_ptr| unsafe {
79            let spec = plot_spec_with_style(
80                self.style,
81                self.flags.bits() | self.item_flags.bits(),
82                self.offset,
83                self.stride,
84            );
85            sys::ImPlot_PlotInfLines_doublePtr(label_ptr, self.positions.as_ptr(), count, spec);
86        })
87    }
88
89    fn label(&self) -> &str {
90        self.label
91    }
92}
93
94/// Convenience functions for quick inf-lines plotting
95impl<'ui> crate::PlotUi<'ui> {
96    /// Plot vertical infinite lines at given x positions
97    pub fn inf_lines_vertical(&self, label: &str, xs: &[f64]) -> Result<(), PlotError> {
98        let plot = InfLinesPlot::new(label, xs);
99        plot.validate()?;
100        plot.plot();
101        Ok(())
102    }
103
104    /// Plot horizontal infinite lines at given y positions
105    pub fn inf_lines_horizontal(&self, label: &str, ys: &[f64]) -> Result<(), PlotError> {
106        let plot = InfLinesPlot::new(label, ys).horizontal();
107        plot.validate()?;
108        plot.plot();
109        Ok(())
110    }
111}