1mod axes;
4#[path = "plot.rs"]
5mod builder;
6mod canvas;
7mod raster;
8mod style;
9mod text;
10
11pub use axes::Axes;
12pub use builder::{DEFAULT_SIZE, Plot};
13pub use canvas::Canvas;
14pub use style::{LineStyle, MarkerStyle};
15
16use crate::Image;
17
18pub fn scatter_plot(
20 points: &[(f64, f64)],
21 xlim: (f64, f64),
22 ylim: (f64, f64),
23 width: usize,
24 height: usize,
25) -> Image {
26 scatter_plot_with_size(points, xlim, ylim, width, height, 1)
27}
28
29pub fn scatter_plot_with_size(
31 points: &[(f64, f64)],
32 xlim: (f64, f64),
33 ylim: (f64, f64),
34 width: usize,
35 height: usize,
36 size: usize,
37) -> Image {
38 scatter_plot_with_size_and_inset(
39 points,
40 xlim,
41 ylim,
42 width,
43 height,
44 size,
45 default_inset(width),
46 default_inset(height),
47 )
48}
49
50#[allow(clippy::too_many_arguments)]
52pub fn scatter_plot_with_size_and_inset(
53 points: &[(f64, f64)],
54 xlim: (f64, f64),
55 ylim: (f64, f64),
56 width: usize,
57 height: usize,
58 size: usize,
59 inset_x: usize,
60 inset_y: usize,
61) -> Image {
62 let mut canvas = Canvas::with_inset(
63 width,
64 height,
65 Axes::from_limits(xlim, ylim),
66 inset_x,
67 inset_y,
68 );
69 canvas.render();
70 canvas.scatter(points, size);
71 canvas.into_image()
72}
73
74pub fn line_plot(
76 points: &[(f64, f64)],
77 xlim: (f64, f64),
78 ylim: (f64, f64),
79 width: usize,
80 height: usize,
81) -> Image {
82 line_plot_with_width(points, xlim, ylim, width, height, 1)
83}
84
85pub fn line_plot_with_width(
87 points: &[(f64, f64)],
88 xlim: (f64, f64),
89 ylim: (f64, f64),
90 width: usize,
91 height: usize,
92 line_width: usize,
93) -> Image {
94 line_plot_with_width_and_inset(
95 points,
96 xlim,
97 ylim,
98 width,
99 height,
100 line_width,
101 default_inset(width),
102 default_inset(height),
103 )
104}
105
106#[allow(clippy::too_many_arguments)]
108pub fn line_plot_with_width_and_inset(
109 points: &[(f64, f64)],
110 xlim: (f64, f64),
111 ylim: (f64, f64),
112 width: usize,
113 height: usize,
114 line_width: usize,
115 inset_x: usize,
116 inset_y: usize,
117) -> Image {
118 let mut canvas = Canvas::with_inset(
119 width,
120 height,
121 Axes::from_limits(xlim, ylim),
122 inset_x,
123 inset_y,
124 );
125 canvas.render();
126 canvas.plot(points, line_width);
127 canvas.into_image()
128}
129
130fn default_inset(size: usize) -> usize {
131 size / 16
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use crate::Pixel;
138
139 #[test]
140 fn convenience_plots_respect_insets() {
141 let scatter = scatter_plot_with_size_and_inset(
142 &[(0.0, 0.0)],
143 (0.0, 1.0),
144 (0.0, 1.0),
145 11,
146 11,
147 1,
148 2,
149 3,
150 );
151 assert_eq!(scatter.get_pixel(2, 7), Some(&Pixel::rgb(255, 0, 0)));
152 assert_eq!(scatter.get_pixel(0, 10), Some(&Pixel::WHITE));
153
154 let line = line_plot_with_width_and_inset(
155 &[(0.0, 0.0), (1.0, 1.0)],
156 (0.0, 1.0),
157 (0.0, 1.0),
158 11,
159 11,
160 1,
161 2,
162 3,
163 );
164 assert_eq!(line.get_pixel(5, 5), Some(&Pixel::rgb(0, 0, 255)));
165 assert_eq!(line.get_pixel(0, 10), Some(&Pixel::WHITE));
166 }
167
168 #[test]
169 fn line_width_and_marker_size_are_configurable() {
170 let line = line_plot_with_width(&[(0.0, 0.5), (1.0, 0.5)], (0.0, 1.0), (0.0, 1.0), 9, 9, 3);
171 for y in 3..=5 {
172 assert_eq!(line.get_pixel(4, y), Some(&Pixel::rgb(0, 0, 255)));
173 }
174
175 let scatter = scatter_plot_with_size(&[(0.5, 0.5)], (0.0, 1.0), (0.0, 1.0), 5, 5, 3);
176 assert_eq!(scatter.get_pixel(2, 2), Some(&Pixel::rgb(255, 0, 0)));
177 }
178
179 #[test]
180 fn axes_fall_back_to_center_when_zero_is_outside_limits() {
181 let image = scatter_plot(&[], (1.0, 2.0), (1.0, 2.0), 7, 7);
182 assert_eq!(image.get_pixel(3, 3), Some(&Pixel::BLACK));
183 }
184}