Skip to main content

plotkit_core/charts/
line.rs

1//! Line chart builder methods.
2//!
3//! This module extends [`LineArtist`] with a fluent API for configuring
4//! line chart properties. Since [`Axes::plot`] returns `Result<&mut LineArtist>`,
5//! these builder methods can be chained directly on the return value:
6//!
7//! ```ignore
8//! ax.plot(&x, &y)?
9//!     .color(Color::rgb(0.2, 0.4, 0.8))
10//!     .width(2.0)
11//!     .style(LineStyle::Dashed)
12//!     .label("Series A")
13//!     .alpha(0.9);
14//! ```
15
16use crate::artist::LineArtist;
17use crate::decimate::DecimateMethod;
18use crate::primitives::Color;
19use crate::theme::LineStyle;
20
21impl LineArtist {
22    /// Sets the line color.
23    ///
24    /// Accepts any [`Color`] value, which can be constructed from RGB components,
25    /// hex strings, or named color constants.
26    ///
27    /// # Examples
28    ///
29    /// ```ignore
30    /// artist.color(Color::rgb(1.0, 0.0, 0.0)); // red
31    /// ```
32    pub fn color(&mut self, color: Color) -> &mut Self {
33        self.color = color;
34        self
35    }
36
37    /// Sets the line width in pixels.
38    ///
39    /// A width of `1.0` is the default hairline width. Values below `1.0` may
40    /// produce sub-pixel rendering depending on the backend.
41    ///
42    /// # Examples
43    ///
44    /// ```ignore
45    /// artist.width(2.5);
46    /// ```
47    pub fn width(&mut self, width: f64) -> &mut Self {
48        self.width = width;
49        self
50    }
51
52    /// Sets the line style (solid, dashed, dotted, dash-dot).
53    ///
54    /// The [`LineStyle`] enum defines the available stroke patterns. The default
55    /// is [`LineStyle::Solid`].
56    ///
57    /// # Examples
58    ///
59    /// ```ignore
60    /// artist.style(LineStyle::Dashed);
61    /// ```
62    pub fn style(&mut self, style: LineStyle) -> &mut Self {
63        self.style = style;
64        self
65    }
66
67    /// Sets the legend label for this line.
68    ///
69    /// When a label is set, the line will appear in the legend if one is
70    /// displayed on the axes. Pass an empty string or omit this call to
71    /// exclude the line from the legend.
72    ///
73    /// # Examples
74    ///
75    /// ```ignore
76    /// artist.label("Temperature");
77    /// ```
78    pub fn label(&mut self, label: &str) -> &mut Self {
79        self.label = Some(label.to_string());
80        self
81    }
82
83    /// Sets the opacity (0.0 = fully transparent, 1.0 = fully opaque).
84    ///
85    /// The value is clamped to the `[0.0, 1.0]` range. The default opacity
86    /// is `1.0`.
87    ///
88    /// # Examples
89    ///
90    /// ```ignore
91    /// artist.alpha(0.5); // 50% transparent
92    /// ```
93    pub fn alpha(&mut self, alpha: f64) -> &mut Self {
94        self.alpha = alpha.clamp(0.0, 1.0);
95        self
96    }
97
98    /// Enables LTTB decimation with the given point threshold.
99    ///
100    /// When the data series length exceeds `threshold`, the rendering
101    /// pipeline downsamples the data using the Largest Triangle Three
102    /// Buckets algorithm before drawing. This dramatically improves
103    /// rendering performance for large datasets (100k+ points) with
104    /// negligible visual impact.
105    ///
106    /// # Examples
107    ///
108    /// ```ignore
109    /// ax.plot(&x, &y)?.decimate(1000);
110    /// ```
111    pub fn decimate(&mut self, threshold: usize) -> &mut Self {
112        self.decimate = Some((threshold, DecimateMethod::Lttb));
113        self
114    }
115
116    /// Enables decimation with a specific method and point threshold.
117    ///
118    /// Available methods:
119    /// - [`DecimateMethod::Lttb`] — best visual fidelity (default)
120    /// - [`DecimateMethod::MinMax`] — fastest, preserves peaks/troughs
121    ///
122    /// # Examples
123    ///
124    /// ```ignore
125    /// ax.plot(&x, &y)?.decimate_with(1000, DecimateMethod::MinMax);
126    /// ```
127    pub fn decimate_with(&mut self, threshold: usize, method: DecimateMethod) -> &mut Self {
128        self.decimate = Some((threshold, method));
129        self
130    }
131}