1use super::{Plot, PlotError, safe_cstring, validate_data_lengths};
4use crate::{StemsFlags, sys};
5
6pub struct StemPlot<'a> {
8 label: &'a str,
9 x_data: &'a [f64],
10 y_data: &'a [f64],
11 y_ref: f64,
12 flags: StemsFlags,
13 offset: i32,
14 stride: i32,
15}
16
17impl<'a> StemPlot<'a> {
18 pub fn new(label: &'a str, x_data: &'a [f64], y_data: &'a [f64]) -> Self {
20 Self {
21 label,
22 x_data,
23 y_data,
24 y_ref: 0.0, flags: StemsFlags::NONE,
26 offset: 0,
27 stride: std::mem::size_of::<f64>() as i32,
28 }
29 }
30
31 pub fn with_y_ref(mut self, y_ref: f64) -> Self {
34 self.y_ref = y_ref;
35 self
36 }
37
38 pub fn with_flags(mut self, flags: StemsFlags) -> Self {
40 self.flags = flags;
41 self
42 }
43
44 pub fn with_offset(mut self, offset: i32) -> Self {
46 self.offset = offset;
47 self
48 }
49
50 pub fn with_stride(mut self, stride: i32) -> Self {
52 self.stride = stride;
53 self
54 }
55
56 pub fn validate(&self) -> Result<(), PlotError> {
58 validate_data_lengths(self.x_data, self.y_data)
59 }
60}
61
62impl<'a> Plot for StemPlot<'a> {
63 fn plot(&self) {
64 if self.validate().is_err() {
65 return;
66 }
67
68 let label_cstr = safe_cstring(self.label);
69
70 unsafe {
71 sys::ImPlot_PlotStems_doublePtrdoublePtr(
72 label_cstr.as_ptr(),
73 self.x_data.as_ptr(),
74 self.y_data.as_ptr(),
75 self.x_data.len() as i32,
76 self.y_ref,
77 self.flags.bits() as i32,
78 self.offset,
79 self.stride,
80 );
81 }
82 }
83
84 fn label(&self) -> &str {
85 self.label
86 }
87}
88
89pub struct SimpleStemPlot<'a> {
91 label: &'a str,
92 values: &'a [f64],
93 y_ref: f64,
94 x_scale: f64,
95 x_start: f64,
96}
97
98impl<'a> SimpleStemPlot<'a> {
99 pub fn new(label: &'a str, values: &'a [f64]) -> Self {
101 Self {
102 label,
103 values,
104 y_ref: 0.0,
105 x_scale: 1.0,
106 x_start: 0.0,
107 }
108 }
109
110 pub fn with_y_ref(mut self, y_ref: f64) -> Self {
112 self.y_ref = y_ref;
113 self
114 }
115
116 pub fn with_x_scale(mut self, scale: f64) -> Self {
118 self.x_scale = scale;
119 self
120 }
121
122 pub fn with_x_start(mut self, start: f64) -> Self {
124 self.x_start = start;
125 self
126 }
127}
128
129impl<'a> Plot for SimpleStemPlot<'a> {
130 fn plot(&self) {
131 if self.values.is_empty() {
132 return;
133 }
134
135 let label_cstr = safe_cstring(self.label);
136
137 let x_data: Vec<f64> = (0..self.values.len())
139 .map(|i| self.x_start + i as f64 * self.x_scale)
140 .collect();
141
142 unsafe {
143 sys::ImPlot_PlotStems_doublePtrdoublePtr(
144 label_cstr.as_ptr(),
145 x_data.as_ptr(),
146 self.values.as_ptr(),
147 self.values.len() as i32,
148 self.y_ref,
149 0, 0,
151 std::mem::size_of::<f64>() as i32,
152 );
153 }
154 }
155
156 fn label(&self) -> &str {
157 self.label
158 }
159}
160
161impl<'ui> crate::PlotUi<'ui> {
163 pub fn stem_plot(&self, label: &str, x_data: &[f64], y_data: &[f64]) -> Result<(), PlotError> {
165 let plot = StemPlot::new(label, x_data, y_data);
166 plot.validate()?;
167 plot.plot();
168 Ok(())
169 }
170
171 pub fn stem_plot_with_ref(
173 &self,
174 label: &str,
175 x_data: &[f64],
176 y_data: &[f64],
177 y_ref: f64,
178 ) -> Result<(), PlotError> {
179 let plot = StemPlot::new(label, x_data, y_data).with_y_ref(y_ref);
180 plot.validate()?;
181 plot.plot();
182 Ok(())
183 }
184
185 pub fn simple_stem_plot(&self, label: &str, values: &[f64]) -> Result<(), PlotError> {
187 if values.is_empty() {
188 return Err(PlotError::EmptyData);
189 }
190 let plot = SimpleStemPlot::new(label, values);
191 plot.plot();
192 Ok(())
193 }
194
195 pub fn simple_stem_plot_with_ref(
197 &self,
198 label: &str,
199 values: &[f64],
200 y_ref: f64,
201 ) -> Result<(), PlotError> {
202 if values.is_empty() {
203 return Err(PlotError::EmptyData);
204 }
205 let plot = SimpleStemPlot::new(label, values).with_y_ref(y_ref);
206 plot.plot();
207 Ok(())
208 }
209}
210
211#[cfg(test)]
212mod tests {
213 use super::*;
214
215 #[test]
216 fn test_stem_plot_creation() {
217 let x_data = [1.0, 2.0, 3.0, 4.0];
218 let y_data = [1.0, 4.0, 2.0, 3.0];
219
220 let plot = StemPlot::new("test", &x_data, &y_data);
221 assert_eq!(plot.label(), "test");
222 assert!(plot.validate().is_ok());
223 }
224
225 #[test]
226 fn test_stem_plot_validation() {
227 let x_data = [1.0, 2.0, 3.0];
228 let y_data = [1.0, 4.0]; let plot = StemPlot::new("test", &x_data, &y_data);
231 assert!(plot.validate().is_err());
232 }
233
234 #[test]
235 fn test_simple_stem_plot() {
236 let values = [1.0, 2.0, 3.0, 4.0];
237 let plot = SimpleStemPlot::new("test", &values);
238 assert_eq!(plot.label(), "test");
239 }
240
241 #[test]
242 fn test_stem_plot_with_ref() {
243 let x_data = [1.0, 2.0, 3.0, 4.0];
244 let y_data = [1.0, 4.0, 2.0, 3.0];
245
246 let plot = StemPlot::new("test", &x_data, &y_data).with_y_ref(1.0);
247 assert_eq!(plot.y_ref, 1.0);
248 assert!(plot.validate().is_ok());
249 }
250}