From 9835e2ae736235810b4ea1c162ca5e65c547e770 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 18 May 2024 04:49:50 +0200 Subject: Merging upstream version 1.71.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/plotters/examples/3d-plot.rs | 62 +++ vendor/plotters/examples/3d-plot2.rs | 56 +++ vendor/plotters/examples/README.md | 19 + vendor/plotters/examples/animation.rs | 65 ++++ vendor/plotters/examples/area-chart.rs | 54 +++ vendor/plotters/examples/blit-bitmap.rs | 45 +++ vendor/plotters/examples/boxplot.rs | 229 +++++++++++ vendor/plotters/examples/chart.rs | 94 +++++ vendor/plotters/examples/console.rs | 200 ++++++++++ vendor/plotters/examples/customized_coord.rs | 54 +++ vendor/plotters/examples/errorbar.rs | 98 +++++ vendor/plotters/examples/full_palette.rs | 548 +++++++++++++++++++++++++++ vendor/plotters/examples/histogram.rs | 43 +++ vendor/plotters/examples/mandelbrot.rs | 71 ++++ vendor/plotters/examples/matshow.rs | 62 +++ vendor/plotters/examples/nested_coord.rs | 47 +++ vendor/plotters/examples/normal-dist.rs | 66 ++++ vendor/plotters/examples/normal-dist2.rs | 83 ++++ vendor/plotters/examples/pie.rs | 25 ++ vendor/plotters/examples/relative_size.rs | 57 +++ vendor/plotters/examples/sierpinski.rs | 43 +++ vendor/plotters/examples/slc-temp.rs | 174 +++++++++ vendor/plotters/examples/snowflake.rs | 57 +++ vendor/plotters/examples/stock.rs | 79 ++++ vendor/plotters/examples/tick_control.rs | 89 +++++ vendor/plotters/examples/two-scales.rs | 60 +++ 26 files changed, 2480 insertions(+) create mode 100644 vendor/plotters/examples/3d-plot.rs create mode 100644 vendor/plotters/examples/3d-plot2.rs create mode 100644 vendor/plotters/examples/README.md create mode 100644 vendor/plotters/examples/animation.rs create mode 100644 vendor/plotters/examples/area-chart.rs create mode 100644 vendor/plotters/examples/blit-bitmap.rs create mode 100644 vendor/plotters/examples/boxplot.rs create mode 100644 vendor/plotters/examples/chart.rs create mode 100644 vendor/plotters/examples/console.rs create mode 100644 vendor/plotters/examples/customized_coord.rs create mode 100644 vendor/plotters/examples/errorbar.rs create mode 100644 vendor/plotters/examples/full_palette.rs create mode 100644 vendor/plotters/examples/histogram.rs create mode 100644 vendor/plotters/examples/mandelbrot.rs create mode 100644 vendor/plotters/examples/matshow.rs create mode 100644 vendor/plotters/examples/nested_coord.rs create mode 100644 vendor/plotters/examples/normal-dist.rs create mode 100644 vendor/plotters/examples/normal-dist2.rs create mode 100644 vendor/plotters/examples/pie.rs create mode 100644 vendor/plotters/examples/relative_size.rs create mode 100644 vendor/plotters/examples/sierpinski.rs create mode 100644 vendor/plotters/examples/slc-temp.rs create mode 100644 vendor/plotters/examples/snowflake.rs create mode 100644 vendor/plotters/examples/stock.rs create mode 100644 vendor/plotters/examples/tick_control.rs create mode 100644 vendor/plotters/examples/two-scales.rs (limited to 'vendor/plotters/examples') diff --git a/vendor/plotters/examples/3d-plot.rs b/vendor/plotters/examples/3d-plot.rs new file mode 100644 index 000000000..af40cc29e --- /dev/null +++ b/vendor/plotters/examples/3d-plot.rs @@ -0,0 +1,62 @@ +use plotters::prelude::*; +const OUT_FILE_NAME: &'static str = "plotters-doc-data/3d-plot.svg"; +fn main() -> Result<(), Box> { + let area = SVGBackend::new(OUT_FILE_NAME, (1024, 760)).into_drawing_area(); + + area.fill(&WHITE)?; + + let x_axis = (-3.0..3.0).step(0.1); + let z_axis = (-3.0..3.0).step(0.1); + + let mut chart = ChartBuilder::on(&area) + .caption(format!("3D Plot Test"), ("sans", 20)) + .build_cartesian_3d(x_axis.clone(), -3.0..3.0, z_axis.clone())?; + + chart.with_projection(|mut pb| { + pb.yaw = 0.5; + pb.scale = 0.9; + pb.into_matrix() + }); + + chart + .configure_axes() + .light_grid_style(BLACK.mix(0.15)) + .max_light_lines(3) + .draw()?; + + chart + .draw_series( + SurfaceSeries::xoz( + (-30..30).map(|f| f as f64 / 10.0), + (-30..30).map(|f| f as f64 / 10.0), + |x, z| (x * x + z * z).cos(), + ) + .style(BLUE.mix(0.2).filled()), + )? + .label("Surface") + .legend(|(x, y)| Rectangle::new([(x + 5, y - 5), (x + 15, y + 5)], BLUE.mix(0.5).filled())); + + chart + .draw_series(LineSeries::new( + (-100..100) + .map(|y| y as f64 / 40.0) + .map(|y| ((y * 10.0).sin(), y, (y * 10.0).cos())), + &BLACK, + ))? + .label("Line") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLACK)); + + chart + .configure_series_labels() + .border_style(&BLACK) + .draw()?; + + // To avoid the IO failure being ignored silently, we manually call the present function + area.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/3d-plot2.rs b/vendor/plotters/examples/3d-plot2.rs new file mode 100644 index 000000000..0b5ca2131 --- /dev/null +++ b/vendor/plotters/examples/3d-plot2.rs @@ -0,0 +1,56 @@ +use plotters::prelude::*; +fn pdf(x: f64, y: f64) -> f64 { + const SDX: f64 = 0.1; + const SDY: f64 = 0.1; + const A: f64 = 5.0; + let x = x as f64 / 10.0; + let y = y as f64 / 10.0; + A * (-x * x / 2.0 / SDX / SDX - y * y / 2.0 / SDY / SDY).exp() +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/3d-plot2.gif"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::gif(OUT_FILE_NAME, (600, 400), 100)?.into_drawing_area(); + + for pitch in 0..157 { + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("2D Gaussian PDF", ("sans-serif", 20)) + .build_cartesian_3d(-3.0..3.0, 0.0..6.0, -3.0..3.0)?; + chart.with_projection(|mut p| { + p.pitch = 1.57 - (1.57 - pitch as f64 / 50.0).abs(); + p.scale = 0.7; + p.into_matrix() // build the projection matrix + }); + + chart + .configure_axes() + .light_grid_style(BLACK.mix(0.15)) + .max_light_lines(3) + .draw()?; + + chart.draw_series( + SurfaceSeries::xoz( + (-15..=15).map(|x| x as f64 / 5.0), + (-15..=15).map(|x| x as f64 / 5.0), + pdf, + ) + .style_func(&|&v| { + (&HSLColor(240.0 / 360.0 - 240.0 / 360.0 * v / 5.0, 1.0, 0.7)).into() + }), + )?; + + root.present()?; + } + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/README.md b/vendor/plotters/examples/README.md new file mode 100644 index 000000000..b6dd1666a --- /dev/null +++ b/vendor/plotters/examples/README.md @@ -0,0 +1,19 @@ +# plotters examples + +* The example projects have been moved to independent git repository under plotters-rs organization, please check the [Example Project](#example-project) section for the links. + +To run any example, from within the repo, run `cargo run --example ` where `` is the name of the file without the `.rs` extension. + +All the examples assumes the directory [plotters-doc-data](https://github.com/38/plotters-doc-data) exists, otherwise those example crashs. + +The output of these example files are used to generate the [plotters-doc-data](https://github.com/38/plotters-doc-data) repo that populates the sample images in the main README. +We also rely on the output of examples to detect potential layout changes. +For that reason, **they must be run with `cargo` from within the repo, or you must change the output filename in the example code to a directory that exists.** + +The examples that have their own directories and `Cargo.toml` files work differently. They are run the same way you would a standalone project. + +## Example Projects + +- For WebAssembly sample project, check [plotters-wasm-demo](https://github.com/plotters-rs/plotters-wasm-demo) +- For Frame Buffer, Realtime Readering example, check [plotters-minifb-demo](https://github.com/plotters-rs/plotters-minifb-demo) +- For GTK integration, check [plotters-gtk-demo](https://github.com/plotters-rs/plotters-gtk-demo) diff --git a/vendor/plotters/examples/animation.rs b/vendor/plotters/examples/animation.rs new file mode 100644 index 000000000..dab7d451d --- /dev/null +++ b/vendor/plotters/examples/animation.rs @@ -0,0 +1,65 @@ +use plotters::prelude::*; + +fn snowflake_iter(points: &[(f64, f64)]) -> Vec<(f64, f64)> { + let mut ret = vec![]; + for i in 0..points.len() { + let (start, end) = (points[i], points[(i + 1) % points.len()]); + let t = ((end.0 - start.0) / 3.0, (end.1 - start.1) / 3.0); + let s = ( + t.0 * 0.5 - t.1 * (0.75f64).sqrt(), + t.1 * 0.5 + (0.75f64).sqrt() * t.0, + ); + ret.push(start); + ret.push((start.0 + t.0, start.1 + t.1)); + ret.push((start.0 + t.0 + s.0, start.1 + t.1 + s.1)); + ret.push((start.0 + t.0 * 2.0, start.1 + t.1 * 2.0)); + } + ret +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/animation.gif"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::gif(OUT_FILE_NAME, (800, 600), 1_000)?.into_drawing_area(); + + for i in 0..8 { + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption( + format!("Koch's Snowflake (n_iter = {})", i), + ("sans-serif", 50), + ) + .build_cartesian_2d(-2.0..2.0, -1.5..1.5)?; + + let mut snowflake_vertices = { + let mut current: Vec<(f64, f64)> = vec![ + (0.0, 1.0), + ((3.0f64).sqrt() / 2.0, -0.5), + (-(3.0f64).sqrt() / 2.0, -0.5), + ]; + for _ in 0..i { + current = snowflake_iter(¤t[..]); + } + current + }; + + chart.draw_series(std::iter::once(Polygon::new( + snowflake_vertices.clone(), + &RED.mix(0.2), + )))?; + + snowflake_vertices.push(snowflake_vertices[0]); + chart.draw_series(std::iter::once(PathElement::new(snowflake_vertices, &RED)))?; + + root.present()?; + } + + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} + +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/area-chart.rs b/vendor/plotters/examples/area-chart.rs new file mode 100644 index 000000000..5b1a7a5a5 --- /dev/null +++ b/vendor/plotters/examples/area-chart.rs @@ -0,0 +1,54 @@ +use plotters::prelude::*; + +use rand::SeedableRng; +use rand_distr::{Distribution, Normal}; +use rand_xorshift::XorShiftRng; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/area-chart.png"; +fn main() -> Result<(), Box> { + let data: Vec<_> = { + let norm_dist = Normal::new(500.0, 100.0).unwrap(); + let mut x_rand = XorShiftRng::from_seed(*b"MyFragileSeed123"); + let x_iter = norm_dist.sample_iter(&mut x_rand); + x_iter + .filter(|x| *x < 1500.0) + .take(100) + .zip(0..) + .map(|(x, b)| x + (b as f64).powf(1.2)) + .collect() + }; + + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .set_label_area_size(LabelAreaPosition::Left, 60) + .set_label_area_size(LabelAreaPosition::Bottom, 60) + .caption("Area Chart Demo", ("sans-serif", 40)) + .build_cartesian_2d(0..(data.len() - 1), 0.0..1500.0)?; + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .draw()?; + + chart.draw_series( + AreaSeries::new( + (0..).zip(data.iter()).map(|(x, y)| (x, *y)), + 0.0, + &RED.mix(0.2), + ) + .border_style(&RED), + )?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/blit-bitmap.rs b/vendor/plotters/examples/blit-bitmap.rs new file mode 100644 index 000000000..990b25645 --- /dev/null +++ b/vendor/plotters/examples/blit-bitmap.rs @@ -0,0 +1,45 @@ +use plotters::prelude::*; + +use image::{imageops::FilterType, ImageFormat}; + +use std::fs::File; +use std::io::BufReader; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/blit-bitmap.png"; + +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("Bitmap Example", ("sans-serif", 30)) + .margin(5) + .set_label_area_size(LabelAreaPosition::Left, 40) + .set_label_area_size(LabelAreaPosition::Bottom, 40) + .build_cartesian_2d(0.0..1.0, 0.0..1.0)?; + + chart.configure_mesh().disable_mesh().draw()?; + + let (w, h) = chart.plotting_area().dim_in_pixel(); + let image = image::load( + BufReader::new( + File::open("plotters-doc-data/cat.png").map_err(|e| { + eprintln!("Unable to open file plotters-doc-data.png, please make sure you have clone this repo with --recursive"); + e + })?), + ImageFormat::Png, + )? + .resize_exact(w - w / 10, h - h / 10, FilterType::Nearest); + + let elem: BitMapElement<_> = ((0.05, 0.95), image).into(); + + chart.draw_series(std::iter::once(elem))?; + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/boxplot.rs b/vendor/plotters/examples/boxplot.rs new file mode 100644 index 000000000..6e46db40a --- /dev/null +++ b/vendor/plotters/examples/boxplot.rs @@ -0,0 +1,229 @@ +use itertools::Itertools; +use plotters::data::fitting_range; +use plotters::prelude::*; +use std::collections::BTreeMap; +use std::collections::HashMap; +use std::env; +use std::fs; +use std::io::{self, prelude::*, BufReader}; + +fn read_data(reader: BR) -> HashMap<(String, String), Vec> { + let mut ds = HashMap::new(); + for l in reader.lines() { + let line = l.unwrap(); + let tuple: Vec<&str> = line.split('\t').collect(); + if tuple.len() == 3 { + let key = (String::from(tuple[0]), String::from(tuple[1])); + let entry = ds.entry(key).or_insert_with(Vec::new); + entry.push(tuple[2].parse::().unwrap()); + } + } + ds +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/boxplot.svg"; +fn main() -> Result<(), Box> { + let root = SVGBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + root.fill(&WHITE)?; + + let root = root.margin(5, 5, 5, 5); + + let (upper, lower) = root.split_vertically(512); + + let args: Vec = env::args().collect(); + + let ds = if args.len() < 2 { + read_data(io::Cursor::new(get_data())) + } else { + let file = fs::File::open(&args[1])?; + read_data(BufReader::new(file)) + }; + let dataset: Vec<(String, String, Quartiles)> = ds + .iter() + .map(|(k, v)| (k.0.clone(), k.1.clone(), Quartiles::new(&v))) + .collect(); + + let host_list: Vec<_> = dataset + .iter() + .unique_by(|x| x.0.clone()) + .sorted_by(|a, b| b.2.median().partial_cmp(&a.2.median()).unwrap()) + .map(|x| x.0.clone()) + .collect(); + + let mut colors = (0..).map(Palette99::pick); + let mut offsets = (-12..).step_by(24); + let mut series = BTreeMap::new(); + for x in dataset.iter() { + let entry = series + .entry(x.1.clone()) + .or_insert_with(|| (Vec::new(), colors.next().unwrap(), offsets.next().unwrap())); + entry.0.push((x.0.clone(), &x.2)); + } + + let values: Vec = dataset + .iter() + .map(|x| x.2.values().to_vec()) + .flatten() + .collect(); + let values_range = fitting_range(values.iter()); + + let mut chart = ChartBuilder::on(&upper) + .x_label_area_size(40) + .y_label_area_size(80) + .caption("Ping Boxplot", ("sans-serif", 20)) + .build_cartesian_2d( + values_range.start - 1.0..values_range.end + 1.0, + host_list[..].into_segmented(), + )?; + + chart + .configure_mesh() + .x_desc("Ping, ms") + .y_desc("Host") + .y_labels(host_list.len()) + .light_line_style(&WHITE) + .draw()?; + + for (label, (values, style, offset)) in &series { + chart + .draw_series(values.iter().map(|x| { + Boxplot::new_horizontal(SegmentValue::CenterOf(&x.0), &x.1) + .width(20) + .whisker_width(0.5) + .style(style) + .offset(*offset) + }))? + .label(label) + .legend(move |(x, y)| Rectangle::new([(x, y - 6), (x + 12, y + 6)], style.filled())); + } + chart + .configure_series_labels() + .position(SeriesLabelPosition::UpperRight) + .background_style(WHITE.filled()) + .border_style(&BLACK.mix(0.5)) + .legend_area_size(22) + .draw()?; + + let drawing_areas = lower.split_evenly((1, 2)); + let (left, right) = (&drawing_areas[0], &drawing_areas[1]); + + let quartiles_a = Quartiles::new(&[ + 6.0, 7.0, 15.9, 36.9, 39.0, 40.0, 41.0, 42.0, 43.0, 47.0, 49.0, + ]); + let quartiles_b = Quartiles::new(&[16.0, 17.0, 50.0, 60.0, 40.2, 41.3, 42.7, 43.3, 47.0]); + + let ab_axis = ["a", "b"]; + + let values_range = fitting_range( + quartiles_a + .values() + .iter() + .chain(quartiles_b.values().iter()), + ); + let mut chart = ChartBuilder::on(&left) + .x_label_area_size(40) + .y_label_area_size(40) + .caption("Vertical Boxplot", ("sans-serif", 20)) + .build_cartesian_2d( + ab_axis[..].into_segmented(), + values_range.start - 10.0..values_range.end + 10.0, + )?; + + chart.configure_mesh().light_line_style(&WHITE).draw()?; + chart.draw_series(vec![ + Boxplot::new_vertical(SegmentValue::CenterOf(&"a"), &quartiles_a), + Boxplot::new_vertical(SegmentValue::CenterOf(&"b"), &quartiles_b), + ])?; + + let mut chart = ChartBuilder::on(&right) + .x_label_area_size(40) + .y_label_area_size(40) + .caption("Horizontal Boxplot", ("sans-serif", 20)) + .build_cartesian_2d(-30f32..90f32, 0..3)?; + + chart.configure_mesh().light_line_style(&WHITE).draw()?; + chart.draw_series(vec![ + Boxplot::new_horizontal(1, &quartiles_a), + Boxplot::new_horizontal(2, &Quartiles::new(&[30])), + ])?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} + +fn get_data() -> String { + String::from( + " + 1.1.1.1 wireless 41.6 + 1.1.1.1 wireless 32.5 + 1.1.1.1 wireless 33.1 + 1.1.1.1 wireless 32.3 + 1.1.1.1 wireless 36.7 + 1.1.1.1 wireless 32.0 + 1.1.1.1 wireless 33.1 + 1.1.1.1 wireless 32.0 + 1.1.1.1 wireless 32.9 + 1.1.1.1 wireless 32.7 + 1.1.1.1 wireless 34.5 + 1.1.1.1 wireless 36.5 + 1.1.1.1 wireless 31.9 + 1.1.1.1 wireless 33.7 + 1.1.1.1 wireless 32.6 + 1.1.1.1 wireless 35.1 + 8.8.8.8 wireless 42.3 + 8.8.8.8 wireless 32.9 + 8.8.8.8 wireless 32.9 + 8.8.8.8 wireless 34.3 + 8.8.8.8 wireless 32.0 + 8.8.8.8 wireless 33.3 + 8.8.8.8 wireless 31.5 + 8.8.8.8 wireless 33.1 + 8.8.8.8 wireless 33.2 + 8.8.8.8 wireless 35.9 + 8.8.8.8 wireless 42.3 + 8.8.8.8 wireless 34.1 + 8.8.8.8 wireless 34.2 + 8.8.8.8 wireless 34.2 + 8.8.8.8 wireless 32.4 + 8.8.8.8 wireless 33.0 + 1.1.1.1 wired 31.8 + 1.1.1.1 wired 28.6 + 1.1.1.1 wired 29.4 + 1.1.1.1 wired 28.8 + 1.1.1.1 wired 28.2 + 1.1.1.1 wired 28.8 + 1.1.1.1 wired 28.4 + 1.1.1.1 wired 28.6 + 1.1.1.1 wired 28.3 + 1.1.1.1 wired 28.5 + 1.1.1.1 wired 28.5 + 1.1.1.1 wired 28.5 + 1.1.1.1 wired 28.4 + 1.1.1.1 wired 28.6 + 1.1.1.1 wired 28.4 + 1.1.1.1 wired 28.9 + 8.8.8.8 wired 33.3 + 8.8.8.8 wired 28.4 + 8.8.8.8 wired 28.7 + 8.8.8.8 wired 29.1 + 8.8.8.8 wired 29.6 + 8.8.8.8 wired 28.9 + 8.8.8.8 wired 28.6 + 8.8.8.8 wired 29.3 + 8.8.8.8 wired 28.6 + 8.8.8.8 wired 29.1 + 8.8.8.8 wired 28.7 + 8.8.8.8 wired 28.3 + 8.8.8.8 wired 28.3 + 8.8.8.8 wired 28.6 + 8.8.8.8 wired 29.4 + 8.8.8.8 wired 33.1 +", + ) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/chart.rs b/vendor/plotters/examples/chart.rs new file mode 100644 index 000000000..acdddc3c1 --- /dev/null +++ b/vendor/plotters/examples/chart.rs @@ -0,0 +1,94 @@ +use plotters::prelude::*; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/sample.png"; +fn main() -> Result<(), Box> { + let root_area = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root_area.fill(&WHITE)?; + + let root_area = root_area.titled("Image Title", ("sans-serif", 60))?; + + let (upper, lower) = root_area.split_vertically(512); + + let x_axis = (-3.4f32..3.4).step(0.1); + + let mut cc = ChartBuilder::on(&upper) + .margin(5) + .set_all_label_area_size(50) + .caption("Sine and Cosine", ("sans-serif", 40)) + .build_cartesian_2d(-3.4f32..3.4, -1.2f32..1.2f32)?; + + cc.configure_mesh() + .x_labels(20) + .y_labels(10) + .disable_mesh() + .x_label_formatter(&|v| format!("{:.1}", v)) + .y_label_formatter(&|v| format!("{:.1}", v)) + .draw()?; + + cc.draw_series(LineSeries::new(x_axis.values().map(|x| (x, x.sin())), &RED))? + .label("Sine") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + + cc.draw_series(LineSeries::new( + x_axis.values().map(|x| (x, x.cos())), + &BLUE, + ))? + .label("Cosine") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + + cc.configure_series_labels().border_style(&BLACK).draw()?; + + /* + // It's possible to use a existing pointing element + cc.draw_series(PointSeries::<_, _, Circle<_>>::new( + (-3.0f32..2.1f32).step(1.0).values().map(|x| (x, x.sin())), + 5, + Into::::into(&RGBColor(255,0,0)).filled(), + ))?;*/ + + // Otherwise you can use a function to construct your pointing element yourself + cc.draw_series(PointSeries::of_element( + (-3.0f32..2.1f32).step(1.0).values().map(|x| (x, x.sin())), + 5, + ShapeStyle::from(&RED).filled(), + &|coord, size, style| { + EmptyElement::at(coord) + + Circle::new((0, 0), size, style) + + Text::new(format!("{:?}", coord), (0, 15), ("sans-serif", 15)) + }, + ))?; + + let drawing_areas = lower.split_evenly((1, 2)); + + for (drawing_area, idx) in drawing_areas.iter().zip(1..) { + let mut cc = ChartBuilder::on(&drawing_area) + .x_label_area_size(30) + .y_label_area_size(30) + .margin_right(20) + .caption(format!("y = x^{}", 1 + 2 * idx), ("sans-serif", 40)) + .build_cartesian_2d(-1f32..1f32, -1f32..1f32)?; + cc.configure_mesh() + .x_labels(5) + .y_labels(3) + .max_light_lines(4) + .draw()?; + + cc.draw_series(LineSeries::new( + (-1f32..1f32) + .step(0.01) + .values() + .map(|x| (x, x.powf(idx as f32 * 2.0 + 1.0))), + &BLUE, + ))?; + } + + // To avoid the IO failure being ignored silently, we manually call the present function + root_area.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/console.rs b/vendor/plotters/examples/console.rs new file mode 100644 index 000000000..feba0956b --- /dev/null +++ b/vendor/plotters/examples/console.rs @@ -0,0 +1,200 @@ +use plotters::prelude::*; +use plotters::style::text_anchor::{HPos, VPos}; +use plotters_backend::{ + BackendColor, BackendStyle, BackendTextStyle, DrawingBackend, DrawingErrorKind, +}; +use std::error::Error; + +#[derive(Copy, Clone)] +enum PixelState { + Empty, + HLine, + VLine, + Cross, + Pixel, + Text(char), + Circle(bool), +} + +impl PixelState { + fn to_char(self) -> char { + match self { + Self::Empty => ' ', + Self::HLine => '-', + Self::VLine => '|', + Self::Cross => '+', + Self::Pixel => '.', + Self::Text(c) => c, + Self::Circle(filled) => { + if filled { + '@' + } else { + 'O' + } + } + } + } + + fn update(&mut self, new_state: PixelState) { + let next_state = match (*self, new_state) { + (Self::HLine, Self::VLine) => Self::Cross, + (Self::VLine, Self::HLine) => Self::Cross, + (_, Self::Circle(what)) => Self::Circle(what), + (Self::Circle(what), _) => Self::Circle(what), + (_, Self::Pixel) => Self::Pixel, + (Self::Pixel, _) => Self::Pixel, + (_, new) => new, + }; + + *self = next_state; + } +} + +pub struct TextDrawingBackend(Vec); + +impl DrawingBackend for TextDrawingBackend { + type ErrorType = std::io::Error; + + fn get_size(&self) -> (u32, u32) { + (100, 30) + } + + fn ensure_prepared(&mut self) -> Result<(), DrawingErrorKind> { + Ok(()) + } + + fn present(&mut self) -> Result<(), DrawingErrorKind> { + for r in 0..30 { + let mut buf = String::new(); + for c in 0..100 { + buf.push(self.0[r * 100 + c].to_char()); + } + println!("{}", buf); + } + + Ok(()) + } + + fn draw_pixel( + &mut self, + pos: (i32, i32), + color: BackendColor, + ) -> Result<(), DrawingErrorKind> { + if color.alpha > 0.3 { + self.0[(pos.1 * 100 + pos.0) as usize].update(PixelState::Pixel); + } + Ok(()) + } + + fn draw_line( + &mut self, + from: (i32, i32), + to: (i32, i32), + style: &S, + ) -> Result<(), DrawingErrorKind> { + if from.0 == to.0 { + let x = from.0; + let y0 = from.1.min(to.1); + let y1 = from.1.max(to.1); + for y in y0..y1 { + self.0[(y * 100 + x) as usize].update(PixelState::VLine); + } + return Ok(()); + } + + if from.1 == to.1 { + let y = from.1; + let x0 = from.0.min(to.0); + let x1 = from.0.max(to.0); + for x in x0..x1 { + self.0[(y * 100 + x) as usize].update(PixelState::HLine); + } + return Ok(()); + } + + plotters_backend::rasterizer::draw_line(self, from, to, style) + } + + fn estimate_text_size( + &self, + text: &str, + _: &S, + ) -> Result<(u32, u32), DrawingErrorKind> { + Ok((text.len() as u32, 1)) + } + + fn draw_text( + &mut self, + text: &str, + style: &S, + pos: (i32, i32), + ) -> Result<(), DrawingErrorKind> { + let (width, height) = self.estimate_text_size(text, style)?; + let (width, height) = (width as i32, height as i32); + let dx = match style.anchor().h_pos { + HPos::Left => 0, + HPos::Right => -width, + HPos::Center => -width / 2, + }; + let dy = match style.anchor().v_pos { + VPos::Top => 0, + VPos::Center => -height / 2, + VPos::Bottom => -height, + }; + let offset = (pos.1 + dy).max(0) * 100 + (pos.0 + dx).max(0); + for (idx, chr) in (offset..).zip(text.chars()) { + self.0[idx as usize].update(PixelState::Text(chr)); + } + Ok(()) + } +} + +fn draw_chart( + b: DrawingArea, +) -> Result<(), Box> +where + DB::ErrorType: 'static, +{ + let mut chart = ChartBuilder::on(&b) + .margin(1) + .caption("Sine and Cosine", ("sans-serif", (10).percent_height())) + .set_label_area_size(LabelAreaPosition::Left, (5i32).percent_width()) + .set_label_area_size(LabelAreaPosition::Bottom, (10i32).percent_height()) + .build_cartesian_2d(-std::f64::consts::PI..std::f64::consts::PI, -1.2..1.2)?; + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .draw()?; + + chart.draw_series(LineSeries::new( + (-314..314).map(|x| x as f64 / 100.0).map(|x| (x, x.sin())), + &RED, + ))?; + + chart.draw_series(LineSeries::new( + (-314..314).map(|x| x as f64 / 100.0).map(|x| (x, x.cos())), + &RED, + ))?; + + b.present()?; + + Ok(()) +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/console-example.png"; +fn main() -> Result<(), Box> { + draw_chart(TextDrawingBackend(vec![PixelState::Empty; 5000]).into_drawing_area())?; + let b = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + b.fill(&WHITE)?; + draw_chart(b)?; + + println!("Image result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/customized_coord.rs b/vendor/plotters/examples/customized_coord.rs new file mode 100644 index 000000000..cb3a18f03 --- /dev/null +++ b/vendor/plotters/examples/customized_coord.rs @@ -0,0 +1,54 @@ +use plotters::{ + coord::ranged1d::{KeyPointHint, NoDefaultFormatting, ValueFormatter}, + prelude::*, +}; +const OUT_FILE_NAME: &'static str = "plotters-doc-data/customized_coord.svg"; + +struct CustomizedX(u32); + +impl Ranged for CustomizedX { + type ValueType = u32; + type FormatOption = NoDefaultFormatting; + fn map(&self, value: &Self::ValueType, limit: (i32, i32)) -> i32 { + let size = limit.1 - limit.0; + ((*value as f64 / self.0 as f64) * size as f64) as i32 + limit.0 + } + + fn range(&self) -> std::ops::Range { + 0..self.0 + } + + fn key_points(&self, hint: Hint) -> Vec { + if hint.max_num_points() < (self.0 as usize) { + return vec![]; + } + + (0..self.0).collect() + } +} + +impl ValueFormatter for CustomizedX { + fn format_ext(&self, value: &u32) -> String { + format!("{} of {}", value, self.0) + } +} + +fn main() -> Result<(), Box> { + let area = SVGBackend::new(OUT_FILE_NAME, (1024, 760)).into_drawing_area(); + area.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&area) + .set_all_label_area_size(50) + .build_cartesian_2d(CustomizedX(7), 0.0..10.0)?; + + chart.configure_mesh().draw()?; + + area.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} + +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/errorbar.rs b/vendor/plotters/examples/errorbar.rs new file mode 100644 index 000000000..75c5dbea0 --- /dev/null +++ b/vendor/plotters/examples/errorbar.rs @@ -0,0 +1,98 @@ +use plotters::prelude::*; + +use rand::SeedableRng; +use rand_distr::{Distribution, Normal}; +use rand_xorshift::XorShiftRng; + +use itertools::Itertools; + +use num_traits::sign::Signed; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/errorbar.png"; +fn main() -> Result<(), Box> { + let data = generate_random_data(); + let down_sampled = down_sample(&data[..]); + + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("Linear Function with Noise", ("sans-serif", 60)) + .margin(10) + .set_label_area_size(LabelAreaPosition::Left, 40) + .set_label_area_size(LabelAreaPosition::Bottom, 40) + .build_cartesian_2d(-10f64..10f64, -10f64..10f64)?; + + chart.configure_mesh().draw()?; + + chart + .draw_series(LineSeries::new(data, &GREEN.mix(0.3)))? + .label("Raw Data") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &GREEN)); + + chart.draw_series(LineSeries::new( + down_sampled.iter().map(|(x, _, y, _)| (*x, *y)), + &BLUE, + ))?; + + chart + .draw_series( + down_sampled.iter().map(|(x, yl, ym, yh)| { + ErrorBar::new_vertical(*x, *yl, *ym, *yh, BLUE.filled(), 20) + }), + )? + .label("Down-sampled") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + + chart + .configure_series_labels() + .background_style(WHITE.filled()) + .draw()?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} + +fn generate_random_data() -> Vec<(f64, f64)> { + let norm_dist = Normal::new(0.0, 1.0).unwrap(); + let mut x_rand = XorShiftRng::from_seed(*b"MyFragileSeed123"); + let x_iter = norm_dist.sample_iter(&mut x_rand); + x_iter + .take(20000) + .filter(|x| x.abs() <= 4.0) + .zip(-10000..10000) + .map(|(yn, x)| { + ( + x as f64 / 1000.0, + x as f64 / 1000.0 + yn * x as f64 / 10000.0, + ) + }) + .collect() +} + +fn down_sample(data: &[(f64, f64)]) -> Vec<(f64, f64, f64, f64)> { + let down_sampled: Vec<_> = data + .iter() + .group_by(|x| (x.0 * 1.0).round() / 1.0) + .into_iter() + .map(|(x, g)| { + let mut g: Vec<_> = g.map(|(_, y)| *y).collect(); + g.sort_by(|a, b| a.partial_cmp(b).unwrap()); + ( + x, + g[0], + g.iter().sum::() / g.len() as f64, + g[g.len() - 1], + ) + }) + .collect(); + down_sampled +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/full_palette.rs b/vendor/plotters/examples/full_palette.rs new file mode 100644 index 000000000..dbd0d4290 --- /dev/null +++ b/vendor/plotters/examples/full_palette.rs @@ -0,0 +1,548 @@ +use plotters::prelude::*; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/full_palette.png"; + +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (2000, 850)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("Demonstration of full_palette Colors", ("sans-serif", 50)) + .build_cartesian_2d(-0.5f32..19f32, -1f32..15f32)?; + + use full_palette::*; + let colors = [ + [ + RED, RED_50, RED_100, RED_200, RED_300, RED_400, RED_500, RED_600, RED_700, RED_800, + RED_900, RED_A100, RED_A200, RED_A400, RED_A700, + ], + [ + PINK, PINK_50, PINK_100, PINK_200, PINK_300, PINK_400, PINK_500, PINK_600, PINK_700, + PINK_800, PINK_900, PINK_A100, PINK_A200, PINK_A400, PINK_A700, + ], + [ + PURPLE, + PURPLE_50, + PURPLE_100, + PURPLE_200, + PURPLE_300, + PURPLE_400, + PURPLE_500, + PURPLE_600, + PURPLE_700, + PURPLE_800, + PURPLE_900, + PURPLE_A100, + PURPLE_A200, + PURPLE_A400, + PURPLE_A700, + ], + [ + DEEPPURPLE, + DEEPPURPLE_50, + DEEPPURPLE_100, + DEEPPURPLE_200, + DEEPPURPLE_300, + DEEPPURPLE_400, + DEEPPURPLE_500, + DEEPPURPLE_600, + DEEPPURPLE_700, + DEEPPURPLE_800, + DEEPPURPLE_900, + DEEPPURPLE_A100, + DEEPPURPLE_A200, + DEEPPURPLE_A400, + DEEPPURPLE_A700, + ], + [ + INDIGO, + INDIGO_50, + INDIGO_100, + INDIGO_200, + INDIGO_300, + INDIGO_400, + INDIGO_500, + INDIGO_600, + INDIGO_700, + INDIGO_800, + INDIGO_900, + INDIGO_A100, + INDIGO_A200, + INDIGO_A400, + INDIGO_A700, + ], + [ + BLUE, BLUE_50, BLUE_100, BLUE_200, BLUE_300, BLUE_400, BLUE_500, BLUE_600, BLUE_700, + BLUE_800, BLUE_900, BLUE_A100, BLUE_A200, BLUE_A400, BLUE_A700, + ], + [ + LIGHTBLUE, + LIGHTBLUE_50, + LIGHTBLUE_100, + LIGHTBLUE_200, + LIGHTBLUE_300, + LIGHTBLUE_400, + LIGHTBLUE_500, + LIGHTBLUE_600, + LIGHTBLUE_700, + LIGHTBLUE_800, + LIGHTBLUE_900, + LIGHTBLUE_A100, + LIGHTBLUE_A200, + LIGHTBLUE_A400, + LIGHTBLUE_A700, + ], + [ + CYAN, CYAN_50, CYAN_100, CYAN_200, CYAN_300, CYAN_400, CYAN_500, CYAN_600, CYAN_700, + CYAN_800, CYAN_900, CYAN_A100, CYAN_A200, CYAN_A400, CYAN_A700, + ], + [ + TEAL, TEAL_50, TEAL_100, TEAL_200, TEAL_300, TEAL_400, TEAL_500, TEAL_600, TEAL_700, + TEAL_800, TEAL_900, TEAL_A100, TEAL_A200, TEAL_A400, TEAL_A700, + ], + [ + GREEN, GREEN_50, GREEN_100, GREEN_200, GREEN_300, GREEN_400, GREEN_500, GREEN_600, + GREEN_700, GREEN_800, GREEN_900, GREEN_A100, GREEN_A200, GREEN_A400, GREEN_A700, + ], + [ + LIGHTGREEN, + LIGHTGREEN_50, + LIGHTGREEN_100, + LIGHTGREEN_200, + LIGHTGREEN_300, + LIGHTGREEN_400, + LIGHTGREEN_500, + LIGHTGREEN_600, + LIGHTGREEN_700, + LIGHTGREEN_800, + LIGHTGREEN_900, + LIGHTGREEN_A100, + LIGHTGREEN_A200, + LIGHTGREEN_A400, + LIGHTGREEN_A700, + ], + [ + LIME, LIME_50, LIME_100, LIME_200, LIME_300, LIME_400, LIME_500, LIME_600, LIME_700, + LIME_800, LIME_900, LIME_A100, LIME_A200, LIME_A400, LIME_A700, + ], + [ + YELLOW, + YELLOW_50, + YELLOW_100, + YELLOW_200, + YELLOW_300, + YELLOW_400, + YELLOW_500, + YELLOW_600, + YELLOW_700, + YELLOW_800, + YELLOW_900, + YELLOW_A100, + YELLOW_A200, + YELLOW_A400, + YELLOW_A700, + ], + [ + AMBER, AMBER_50, AMBER_100, AMBER_200, AMBER_300, AMBER_400, AMBER_500, AMBER_600, + AMBER_700, AMBER_800, AMBER_900, AMBER_A100, AMBER_A200, AMBER_A400, AMBER_A700, + ], + [ + ORANGE, + ORANGE_50, + ORANGE_100, + ORANGE_200, + ORANGE_300, + ORANGE_400, + ORANGE_500, + ORANGE_600, + ORANGE_700, + ORANGE_800, + ORANGE_900, + ORANGE_A100, + ORANGE_A200, + ORANGE_A400, + ORANGE_A700, + ], + [ + DEEPORANGE, + DEEPORANGE_50, + DEEPORANGE_100, + DEEPORANGE_200, + DEEPORANGE_300, + DEEPORANGE_400, + DEEPORANGE_500, + DEEPORANGE_600, + DEEPORANGE_700, + DEEPORANGE_800, + DEEPORANGE_900, + DEEPORANGE_A100, + DEEPORANGE_A200, + DEEPORANGE_A400, + DEEPORANGE_A700, + ], + [ + BROWN, BROWN_50, BROWN_100, BROWN_200, BROWN_300, BROWN_400, BROWN_500, BROWN_600, + BROWN_700, BROWN_800, BROWN_900, BROWN_A100, BROWN_A200, BROWN_A400, BROWN_A700, + ], + [ + GREY, GREY_50, GREY_100, GREY_200, GREY_300, GREY_400, GREY_500, GREY_600, GREY_700, + GREY_800, GREY_900, GREY_A100, GREY_A200, GREY_A400, GREY_A700, + ], + [ + BLUEGREY, + BLUEGREY_50, + BLUEGREY_100, + BLUEGREY_200, + BLUEGREY_300, + BLUEGREY_400, + BLUEGREY_500, + BLUEGREY_600, + BLUEGREY_700, + BLUEGREY_800, + BLUEGREY_900, + BLUEGREY_A100, + BLUEGREY_A200, + BLUEGREY_A400, + BLUEGREY_A700, + ], + ]; + let color_names = [ + [ + "RED", "RED_50", "RED_100", "RED_200", "RED_300", "RED_400", "RED_500", "RED_600", + "RED_700", "RED_800", "RED_900", "RED_A100", "RED_A200", "RED_A400", "RED_A700", + ], + [ + "PINK", + "PINK_50", + "PINK_100", + "PINK_200", + "PINK_300", + "PINK_400", + "PINK_500", + "PINK_600", + "PINK_700", + "PINK_800", + "PINK_900", + "PINK_A100", + "PINK_A200", + "PINK_A400", + "PINK_A700", + ], + [ + "PURPLE", + "PURPLE_50", + "PURPLE_100", + "PURPLE_200", + "PURPLE_300", + "PURPLE_400", + "PURPLE_500", + "PURPLE_600", + "PURPLE_700", + "PURPLE_800", + "PURPLE_900", + "PURPLE_A100", + "PURPLE_A200", + "PURPLE_A400", + "PURPLE_A700", + ], + [ + "DEEPPURPLE", + "DEEPPURPLE_50", + "DEEPPURPLE_100", + "DEEPPURPLE_200", + "DEEPPURPLE_300", + "DEEPPURPLE_400", + "DEEPPURPLE_500", + "DEEPPURPLE_600", + "DEEPPURPLE_700", + "DEEPPURPLE_800", + "DEEPPURPLE_900", + "DEEPPURPLE_A100", + "DEEPPURPLE_A200", + "DEEPPURPLE_A400", + "DEEPPURPLE_A700", + ], + [ + "INDIGO", + "INDIGO_50", + "INDIGO_100", + "INDIGO_200", + "INDIGO_300", + "INDIGO_400", + "INDIGO_500", + "INDIGO_600", + "INDIGO_700", + "INDIGO_800", + "INDIGO_900", + "INDIGO_A100", + "INDIGO_A200", + "INDIGO_A400", + "INDIGO_A700", + ], + [ + "BLUE", + "BLUE_50", + "BLUE_100", + "BLUE_200", + "BLUE_300", + "BLUE_400", + "BLUE_500", + "BLUE_600", + "BLUE_700", + "BLUE_800", + "BLUE_900", + "BLUE_A100", + "BLUE_A200", + "BLUE_A400", + "BLUE_A700", + ], + [ + "LIGHTBLUE", + "LIGHTBLUE_50", + "LIGHTBLUE_100", + "LIGHTBLUE_200", + "LIGHTBLUE_300", + "LIGHTBLUE_400", + "LIGHTBLUE_500", + "LIGHTBLUE_600", + "LIGHTBLUE_700", + "LIGHTBLUE_800", + "LIGHTBLUE_900", + "LIGHTBLUE_A100", + "LIGHTBLUE_A200", + "LIGHTBLUE_A400", + "LIGHTBLUE_A700", + ], + [ + "CYAN", + "CYAN_50", + "CYAN_100", + "CYAN_200", + "CYAN_300", + "CYAN_400", + "CYAN_500", + "CYAN_600", + "CYAN_700", + "CYAN_800", + "CYAN_900", + "CYAN_A100", + "CYAN_A200", + "CYAN_A400", + "CYAN_A700", + ], + [ + "TEAL", + "TEAL_50", + "TEAL_100", + "TEAL_200", + "TEAL_300", + "TEAL_400", + "TEAL_500", + "TEAL_600", + "TEAL_700", + "TEAL_800", + "TEAL_900", + "TEAL_A100", + "TEAL_A200", + "TEAL_A400", + "TEAL_A700", + ], + [ + "GREEN", + "GREEN_50", + "GREEN_100", + "GREEN_200", + "GREEN_300", + "GREEN_400", + "GREEN_500", + "GREEN_600", + "GREEN_700", + "GREEN_800", + "GREEN_900", + "GREEN_A100", + "GREEN_A200", + "GREEN_A400", + "GREEN_A700", + ], + [ + "LIGHTGREEN", + "LIGHTGREEN_50", + "LIGHTGREEN_100", + "LIGHTGREEN_200", + "LIGHTGREEN_300", + "LIGHTGREEN_400", + "LIGHTGREEN_500", + "LIGHTGREEN_600", + "LIGHTGREEN_700", + "LIGHTGREEN_800", + "LIGHTGREEN_900", + "LIGHTGREEN_A100", + "LIGHTGREEN_A200", + "LIGHTGREEN_A400", + "LIGHTGREEN_A700", + ], + [ + "LIME", + "LIME_50", + "LIME_100", + "LIME_200", + "LIME_300", + "LIME_400", + "LIME_500", + "LIME_600", + "LIME_700", + "LIME_800", + "LIME_900", + "LIME_A100", + "LIME_A200", + "LIME_A400", + "LIME_A700", + ], + [ + "YELLOW", + "YELLOW_50", + "YELLOW_100", + "YELLOW_200", + "YELLOW_300", + "YELLOW_400", + "YELLOW_500", + "YELLOW_600", + "YELLOW_700", + "YELLOW_800", + "YELLOW_900", + "YELLOW_A100", + "YELLOW_A200", + "YELLOW_A400", + "YELLOW_A700", + ], + [ + "AMBER", + "AMBER_50", + "AMBER_100", + "AMBER_200", + "AMBER_300", + "AMBER_400", + "AMBER_500", + "AMBER_600", + "AMBER_700", + "AMBER_800", + "AMBER_900", + "AMBER_A100", + "AMBER_A200", + "AMBER_A400", + "AMBER_A700", + ], + [ + "ORANGE", + "ORANGE_50", + "ORANGE_100", + "ORANGE_200", + "ORANGE_300", + "ORANGE_400", + "ORANGE_500", + "ORANGE_600", + "ORANGE_700", + "ORANGE_800", + "ORANGE_900", + "ORANGE_A100", + "ORANGE_A200", + "ORANGE_A400", + "ORANGE_A700", + ], + [ + "DEEPORANGE", + "DEEPORANGE_50", + "DEEPORANGE_100", + "DEEPORANGE_200", + "DEEPORANGE_300", + "DEEPORANGE_400", + "DEEPORANGE_500", + "DEEPORANGE_600", + "DEEPORANGE_700", + "DEEPORANGE_800", + "DEEPORANGE_900", + "DEEPORANGE_A100", + "DEEPORANGE_A200", + "DEEPORANGE_A400", + "DEEPORANGE_A700", + ], + [ + "BROWN", + "BROWN_50", + "BROWN_100", + "BROWN_200", + "BROWN_300", + "BROWN_400", + "BROWN_500", + "BROWN_600", + "BROWN_700", + "BROWN_800", + "BROWN_900", + "BROWN_A100", + "BROWN_A200", + "BROWN_A400", + "BROWN_A700", + ], + [ + "GREY", + "GREY_50", + "GREY_100", + "GREY_200", + "GREY_300", + "GREY_400", + "GREY_500", + "GREY_600", + "GREY_700", + "GREY_800", + "GREY_900", + "GREY_A100", + "GREY_A200", + "GREY_A400", + "GREY_A700", + ], + [ + "BLUEGREY", + "BLUEGREY_50", + "BLUEGREY_100", + "BLUEGREY_200", + "BLUEGREY_300", + "BLUEGREY_400", + "BLUEGREY_500", + "BLUEGREY_600", + "BLUEGREY_700", + "BLUEGREY_800", + "BLUEGREY_900", + "BLUEGREY_A100", + "BLUEGREY_A200", + "BLUEGREY_A400", + "BLUEGREY_A700", + ], + ]; + + use plotters::style::text_anchor::*; + let centered = Pos::new(HPos::Center, VPos::Top); + let label_style = TextStyle::from(("monospace", 14.0).into_font()).pos(centered); + + for (col, colors) in colors.iter().enumerate() { + chart.draw_series(colors.iter().zip(color_names[col].iter()).enumerate().map( + |(row, (color, &name))| { + let row = row as f32; + let col = col as f32; + EmptyElement::at((col, row)) + + Circle::new((0, 0), 15, color.filled()) + + Text::new(name, (0, 16), &label_style) + }, + ))?; + } + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/histogram.rs b/vendor/plotters/examples/histogram.rs new file mode 100644 index 000000000..5cda05dbe --- /dev/null +++ b/vendor/plotters/examples/histogram.rs @@ -0,0 +1,43 @@ +use plotters::prelude::*; +const OUT_FILE_NAME: &'static str = "plotters-doc-data/histogram.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (640, 480)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .x_label_area_size(35) + .y_label_area_size(40) + .margin(5) + .caption("Histogram Test", ("sans-serif", 50.0)) + .build_cartesian_2d((0u32..10u32).into_segmented(), 0u32..10u32)?; + + chart + .configure_mesh() + .disable_x_mesh() + .bold_line_style(&WHITE.mix(0.3)) + .y_desc("Count") + .x_desc("Bucket") + .axis_desc_style(("sans-serif", 15)) + .draw()?; + + let data = [ + 0u32, 1, 1, 1, 4, 2, 5, 7, 8, 6, 4, 2, 1, 8, 3, 3, 3, 4, 4, 3, 3, 3, + ]; + + chart.draw_series( + Histogram::vertical(&chart) + .style(RED.mix(0.5).filled()) + .data(data.iter().map(|x: &u32| (*x, 1))), + )?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/mandelbrot.rs b/vendor/plotters/examples/mandelbrot.rs new file mode 100644 index 000000000..413c319c6 --- /dev/null +++ b/vendor/plotters/examples/mandelbrot.rs @@ -0,0 +1,71 @@ +use plotters::prelude::*; +use std::ops::Range; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/mandelbrot.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (800, 600)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(20) + .x_label_area_size(10) + .y_label_area_size(10) + .build_cartesian_2d(-2.1f64..0.6f64, -1.2f64..1.2f64)?; + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .draw()?; + + let plotting_area = chart.plotting_area(); + + let range = plotting_area.get_pixel_range(); + + let (pw, ph) = (range.0.end - range.0.start, range.1.end - range.1.start); + let (xr, yr) = (chart.x_range(), chart.y_range()); + + for (x, y, c) in mandelbrot_set(xr, yr, (pw as usize, ph as usize), 100) { + if c != 100 { + plotting_area.draw_pixel((x, y), &HSLColor(c as f64 / 100.0, 1.0, 0.5))?; + } else { + plotting_area.draw_pixel((x, y), &BLACK)?; + } + } + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} + +fn mandelbrot_set( + real: Range, + complex: Range, + samples: (usize, usize), + max_iter: usize, +) -> impl Iterator { + let step = ( + (real.end - real.start) / samples.0 as f64, + (complex.end - complex.start) / samples.1 as f64, + ); + return (0..(samples.0 * samples.1)).map(move |k| { + let c = ( + real.start + step.0 * (k % samples.0) as f64, + complex.start + step.1 * (k / samples.0) as f64, + ); + let mut z = (0.0, 0.0); + let mut cnt = 0; + while cnt < max_iter && z.0 * z.0 + z.1 * z.1 <= 1e10 { + z = (z.0 * z.0 - z.1 * z.1 + c.0, 2.0 * z.0 * z.1 + c.1); + cnt += 1; + } + return (c.0, c.1, cnt); + }); +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/matshow.rs b/vendor/plotters/examples/matshow.rs new file mode 100644 index 000000000..30c71a745 --- /dev/null +++ b/vendor/plotters/examples/matshow.rs @@ -0,0 +1,62 @@ +use plotters::prelude::*; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/matshow.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("Matshow Example", ("sans-serif", 80)) + .margin(5) + .top_x_label_area_size(40) + .y_label_area_size(40) + .build_cartesian_2d(0i32..15i32, 15i32..0i32)?; + + chart + .configure_mesh() + .x_labels(15) + .y_labels(15) + .max_light_lines(4) + .x_label_offset(35) + .y_label_offset(25) + .disable_x_mesh() + .disable_y_mesh() + .label_style(("sans-serif", 20)) + .draw()?; + + let mut matrix = [[0; 15]; 15]; + + for i in 0..15 { + matrix[i][i] = i + 4; + } + + chart.draw_series( + matrix + .iter() + .zip(0..) + .map(|(l, y)| l.iter().zip(0..).map(move |(v, x)| (x as i32, y as i32, v))) + .flatten() + .map(|(x, y, v)| { + Rectangle::new( + [(x, y), (x + 1, y + 1)], + HSLColor( + 240.0 / 360.0 - 240.0 / 360.0 * (*v as f64 / 20.0), + 0.7, + 0.1 + 0.4 * *v as f64 / 20.0, + ) + .filled(), + ) + }), + )?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/nested_coord.rs b/vendor/plotters/examples/nested_coord.rs new file mode 100644 index 000000000..b70010148 --- /dev/null +++ b/vendor/plotters/examples/nested_coord.rs @@ -0,0 +1,47 @@ +use plotters::prelude::*; +const OUT_FILE_NAME: &'static str = "plotters-doc-data/nested_coord.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (640, 480)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .x_label_area_size(35) + .y_label_area_size(40) + .margin(5) + .caption("Nested Coord", ("sans-serif", 50.0)) + .build_cartesian_2d( + ["Linear", "Quadratic"].nested_coord(|_| 0.0..10.0), + 0.0..10.0, + )?; + + chart + .configure_mesh() + .disable_mesh() + .axis_desc_style(("sans-serif", 15)) + .draw()?; + + chart.draw_series(LineSeries::new( + (0..10) + .map(|x| x as f64 / 1.0) + .map(|x| ((&"Linear", x).into(), x)), + &RED, + ))?; + + chart.draw_series(LineSeries::new( + (0..10) + .map(|x| x as f64 / 1.0) + .map(|x| ((&"Quadratic", x).into(), x * x / 10.0)), + &RED, + ))?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/normal-dist.rs b/vendor/plotters/examples/normal-dist.rs new file mode 100644 index 000000000..be4878630 --- /dev/null +++ b/vendor/plotters/examples/normal-dist.rs @@ -0,0 +1,66 @@ +use plotters::prelude::*; + +use rand::SeedableRng; +use rand_distr::{Distribution, Normal}; +use rand_xorshift::XorShiftRng; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/normal-dist.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let sd = 0.13; + + let random_points: Vec<(f64, f64)> = { + let norm_dist = Normal::new(0.5, sd).unwrap(); + let mut x_rand = XorShiftRng::from_seed(*b"MyFragileSeed123"); + let mut y_rand = XorShiftRng::from_seed(*b"MyFragileSeed321"); + let x_iter = norm_dist.sample_iter(&mut x_rand); + let y_iter = norm_dist.sample_iter(&mut y_rand); + x_iter.zip(y_iter).take(5000).collect() + }; + + let areas = root.split_by_breakpoints([944], [80]); + + let mut x_hist_ctx = ChartBuilder::on(&areas[0]) + .y_label_area_size(40) + .build_cartesian_2d((0.0..1.0).step(0.01).use_round().into_segmented(), 0..250)?; + let mut y_hist_ctx = ChartBuilder::on(&areas[3]) + .x_label_area_size(40) + .build_cartesian_2d(0..250, (0.0..1.0).step(0.01).use_round())?; + let mut scatter_ctx = ChartBuilder::on(&areas[2]) + .x_label_area_size(40) + .y_label_area_size(40) + .build_cartesian_2d(0f64..1f64, 0f64..1f64)?; + scatter_ctx + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .draw()?; + scatter_ctx.draw_series( + random_points + .iter() + .map(|(x, y)| Circle::new((*x, *y), 2, GREEN.filled())), + )?; + let x_hist = Histogram::vertical(&x_hist_ctx) + .style(GREEN.filled()) + .margin(0) + .data(random_points.iter().map(|(x, _)| (*x, 1))); + let y_hist = Histogram::horizontal(&y_hist_ctx) + .style(GREEN.filled()) + .margin(0) + .data(random_points.iter().map(|(_, y)| (*y, 1))); + x_hist_ctx.draw_series(x_hist)?; + y_hist_ctx.draw_series(y_hist)?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/normal-dist2.rs b/vendor/plotters/examples/normal-dist2.rs new file mode 100644 index 000000000..6c84ab3ab --- /dev/null +++ b/vendor/plotters/examples/normal-dist2.rs @@ -0,0 +1,83 @@ +use plotters::prelude::*; + +use rand::SeedableRng; +use rand_distr::{Distribution, Normal}; +use rand_xorshift::XorShiftRng; + +use num_traits::sign::Signed; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/normal-dist2.png"; +fn main() -> Result<(), Box> { + let sd = 0.60; + + let random_points: Vec = { + let norm_dist = Normal::new(0.0, sd).unwrap(); + let mut x_rand = XorShiftRng::from_seed(*b"MyFragileSeed123"); + let x_iter = norm_dist.sample_iter(&mut x_rand); + x_iter.take(5000).filter(|x| x.abs() <= 4.0).collect() + }; + + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(5) + .caption("1D Gaussian Distribution Demo", ("sans-serif", 30)) + .set_label_area_size(LabelAreaPosition::Left, 60) + .set_label_area_size(LabelAreaPosition::Bottom, 60) + .set_label_area_size(LabelAreaPosition::Right, 60) + .build_cartesian_2d(-4f64..4f64, 0f64..0.1)? + .set_secondary_coord( + (-4f64..4f64).step(0.1).use_round().into_segmented(), + 0u32..500u32, + ); + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .y_label_formatter(&|y| format!("{:.0}%", *y * 100.0)) + .y_desc("Percentage") + .draw()?; + + chart.configure_secondary_axes().y_desc("Count").draw()?; + + let actual = Histogram::vertical(chart.borrow_secondary()) + .style(GREEN.filled()) + .margin(3) + .data(random_points.iter().map(|x| (*x, 1))); + + chart + .draw_secondary_series(actual)? + .label("Observed") + .legend(|(x, y)| Rectangle::new([(x, y - 5), (x + 10, y + 5)], GREEN.filled())); + + let pdf = LineSeries::new( + (-400..400).map(|x| x as f64 / 100.0).map(|x| { + ( + x, + (-x * x / 2.0 / sd / sd).exp() / (2.0 * std::f64::consts::PI * sd * sd).sqrt() + * 0.1, + ) + }), + &RED, + ); + + chart + .draw_series(pdf)? + .label("PDF") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], RED.filled())); + + chart.configure_series_labels().draw()?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/pie.rs b/vendor/plotters/examples/pie.rs new file mode 100644 index 000000000..a950c0218 --- /dev/null +++ b/vendor/plotters/examples/pie.rs @@ -0,0 +1,25 @@ +use plotters::{prelude::*, style::full_palette::ORANGE}; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/pie-chart.png"; +fn main() -> Result<(), Box> { + let root_area = BitMapBackend::new(&OUT_FILE_NAME, (950, 700)).into_drawing_area(); + root_area.fill(&WHITE).unwrap(); + let title_style = TextStyle::from(("sans-serif", 30).into_font()).color(&(BLACK)); + root_area.titled("BEST CIRCLES", title_style).unwrap(); + + let dims = root_area.dim_in_pixel(); + let center = (dims.0 as i32 / 2, dims.1 as i32 / 2); + let radius = 300.0; + let sizes = vec![66.0, 33.0]; + let _rgba = RGBAColor(0, 50, 255, 1.0); + let colors = vec![RGBColor(0, 50, 255), CYAN]; + let labels = vec!["Pizza", "Pacman"]; + + let mut pie = Pie::new(¢er, &radius, &sizes, &colors, &labels); + pie.start_angle(66.0); + pie.label_style((("sans-serif", 50).into_font()).color(&(ORANGE))); + pie.percentages((("sans-serif", radius * 0.08).into_font()).color(&BLACK)); + root_area.draw(&pie)?; + + Ok(()) +} diff --git a/vendor/plotters/examples/relative_size.rs b/vendor/plotters/examples/relative_size.rs new file mode 100644 index 000000000..66eaec130 --- /dev/null +++ b/vendor/plotters/examples/relative_size.rs @@ -0,0 +1,57 @@ +use plotters::coord::Shift; +use plotters::prelude::*; + +fn draw_chart(root: &DrawingArea) -> DrawResult<(), B> { + let mut chart = ChartBuilder::on(root) + .caption( + "Relative Size Example", + ("sans-serif", (5).percent_height()), + ) + .x_label_area_size((10).percent_height()) + .y_label_area_size((10).percent_width()) + .margin(5) + .build_cartesian_2d(-5.0..5.0, -1.0..1.0)?; + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .label_style(("sans-serif", (3).percent_height())) + .draw()?; + + chart.draw_series(LineSeries::new( + (0..1000) + .map(|x| x as f64 / 100.0 - 5.0) + .map(|x| (x, x.sin())), + &RED, + ))?; + Ok(()) +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/relative_size.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let (left, right) = root.split_horizontally((70).percent_width()); + + draw_chart(&left)?; + + let (upper, lower) = right.split_vertically(300); + + draw_chart(&upper)?; + draw_chart(&lower)?; + let root = root.shrink((200, 200), (150, 100)); + draw_chart(&root)?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/sierpinski.rs b/vendor/plotters/examples/sierpinski.rs new file mode 100644 index 000000000..b9655bf94 --- /dev/null +++ b/vendor/plotters/examples/sierpinski.rs @@ -0,0 +1,43 @@ +use plotters::coord::Shift; +use plotters::prelude::*; + +pub fn sierpinski_carpet( + depth: u32, + drawing_area: &DrawingArea, +) -> Result<(), Box> { + if depth > 0 { + let sub_areas = drawing_area.split_evenly((3, 3)); + for (idx, sub_area) in (0..).zip(sub_areas.iter()) { + if idx != 4 { + sub_area.fill(&BLUE)?; + sierpinski_carpet(depth - 1, sub_area)?; + } else { + sub_area.fill(&WHITE)?; + } + } + } + Ok(()) +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/sierpinski.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let root = root + .titled("Sierpinski Carpet Demo", ("sans-serif", 60))? + .shrink(((1024 - 700) / 2, 0), (700, 700)); + + sierpinski_carpet(5, &root)?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/slc-temp.rs b/vendor/plotters/examples/slc-temp.rs new file mode 100644 index 000000000..9d6e47313 --- /dev/null +++ b/vendor/plotters/examples/slc-temp.rs @@ -0,0 +1,174 @@ +use plotters::prelude::*; + +use chrono::{TimeZone, Utc}; + +use std::error::Error; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/slc-temp.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .margin(10) + .caption( + "Monthly Average Temperate in Salt Lake City, UT", + ("sans-serif", 40), + ) + .set_label_area_size(LabelAreaPosition::Left, 60) + .set_label_area_size(LabelAreaPosition::Right, 60) + .set_label_area_size(LabelAreaPosition::Bottom, 40) + .build_cartesian_2d( + (Utc.ymd(2010, 1, 1)..Utc.ymd(2018, 12, 1)).monthly(), + 14.0..104.0, + )? + .set_secondary_coord( + (Utc.ymd(2010, 1, 1)..Utc.ymd(2018, 12, 1)).monthly(), + -10.0..40.0, + ); + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .x_labels(30) + .max_light_lines(4) + .y_desc("Average Temp (F)") + .draw()?; + chart + .configure_secondary_axes() + .y_desc("Average Temp (C)") + .draw()?; + + chart.draw_series(LineSeries::new( + DATA.iter().map(|(y, m, t)| (Utc.ymd(*y, *m, 1), *t)), + &BLUE, + ))?; + + chart.draw_series( + DATA.iter() + .map(|(y, m, t)| Circle::new((Utc.ymd(*y, *m, 1), *t), 3, BLUE.filled())), + )?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} + +const DATA: [(i32, u32, f64); 12 * 9] = [ + (2010, 1, 32.4), + (2010, 2, 37.5), + (2010, 3, 44.5), + (2010, 4, 50.3), + (2010, 5, 55.0), + (2010, 6, 70.0), + (2010, 7, 78.7), + (2010, 8, 76.5), + (2010, 9, 68.9), + (2010, 10, 56.3), + (2010, 11, 40.3), + (2010, 12, 36.5), + (2011, 1, 28.8), + (2011, 2, 35.1), + (2011, 3, 45.5), + (2011, 4, 48.9), + (2011, 5, 55.1), + (2011, 6, 68.8), + (2011, 7, 77.9), + (2011, 8, 78.4), + (2011, 9, 68.2), + (2011, 10, 55.0), + (2011, 11, 41.5), + (2011, 12, 31.0), + (2012, 1, 35.6), + (2012, 2, 38.1), + (2012, 3, 49.1), + (2012, 4, 56.1), + (2012, 5, 63.4), + (2012, 6, 73.0), + (2012, 7, 79.0), + (2012, 8, 79.0), + (2012, 9, 68.8), + (2012, 10, 54.9), + (2012, 11, 45.2), + (2012, 12, 34.9), + (2013, 1, 19.7), + (2013, 2, 31.1), + (2013, 3, 46.2), + (2013, 4, 49.8), + (2013, 5, 61.3), + (2013, 6, 73.3), + (2013, 7, 80.3), + (2013, 8, 77.2), + (2013, 9, 68.3), + (2013, 10, 52.0), + (2013, 11, 43.2), + (2013, 12, 25.7), + (2014, 1, 31.5), + (2014, 2, 39.3), + (2014, 3, 46.4), + (2014, 4, 52.5), + (2014, 5, 63.0), + (2014, 6, 71.3), + (2014, 7, 81.0), + (2014, 8, 75.3), + (2014, 9, 70.0), + (2014, 10, 58.6), + (2014, 11, 42.1), + (2014, 12, 38.0), + (2015, 1, 35.3), + (2015, 2, 45.2), + (2015, 3, 50.9), + (2015, 4, 54.3), + (2015, 5, 60.5), + (2015, 6, 77.1), + (2015, 7, 76.2), + (2015, 8, 77.3), + (2015, 9, 70.4), + (2015, 10, 60.6), + (2015, 11, 40.9), + (2015, 12, 32.4), + (2016, 1, 31.5), + (2016, 2, 35.1), + (2016, 3, 49.1), + (2016, 4, 55.1), + (2016, 5, 60.9), + (2016, 6, 76.9), + (2016, 7, 80.0), + (2016, 8, 77.0), + (2016, 9, 67.1), + (2016, 10, 59.1), + (2016, 11, 47.4), + (2016, 12, 31.8), + (2017, 1, 29.4), + (2017, 2, 42.4), + (2017, 3, 51.7), + (2017, 4, 51.7), + (2017, 5, 62.5), + (2017, 6, 74.8), + (2017, 7, 81.3), + (2017, 8, 78.1), + (2017, 9, 65.7), + (2017, 10, 52.5), + (2017, 11, 49.0), + (2017, 12, 34.4), + (2018, 1, 38.1), + (2018, 2, 37.5), + (2018, 3, 45.4), + (2018, 4, 54.6), + (2018, 5, 64.0), + (2018, 6, 74.9), + (2018, 7, 82.5), + (2018, 8, 78.1), + (2018, 9, 71.9), + (2018, 10, 53.2), + (2018, 11, 39.7), + (2018, 12, 33.6), +]; +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/snowflake.rs b/vendor/plotters/examples/snowflake.rs new file mode 100644 index 000000000..6e52f25b6 --- /dev/null +++ b/vendor/plotters/examples/snowflake.rs @@ -0,0 +1,57 @@ +use plotters::prelude::*; + +fn snowflake_iter(points: &[(f64, f64)]) -> Vec<(f64, f64)> { + let mut ret = vec![]; + for i in 0..points.len() { + let (start, end) = (points[i], points[(i + 1) % points.len()]); + let t = ((end.0 - start.0) / 3.0, (end.1 - start.1) / 3.0); + let s = ( + t.0 * 0.5 - t.1 * (0.75f64).sqrt(), + t.1 * 0.5 + (0.75f64).sqrt() * t.0, + ); + ret.push(start); + ret.push((start.0 + t.0, start.1 + t.1)); + ret.push((start.0 + t.0 + s.0, start.1 + t.1 + s.1)); + ret.push((start.0 + t.0 * 2.0, start.1 + t.1 * 2.0)); + } + ret +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/snowflake.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .caption("Koch's Snowflake", ("sans-serif", 50)) + .build_cartesian_2d(-2.0..2.0, -1.5..1.5)?; + + let mut snowflake_vertices = { + let mut current: Vec<(f64, f64)> = vec![ + (0.0, 1.0), + ((3.0f64).sqrt() / 2.0, -0.5), + (-(3.0f64).sqrt() / 2.0, -0.5), + ]; + for _ in 0..6 { + current = snowflake_iter(¤t[..]); + } + current + }; + + chart.draw_series(std::iter::once(Polygon::new( + snowflake_vertices.clone(), + &RED.mix(0.2), + )))?; + snowflake_vertices.push(snowflake_vertices[0]); + chart.draw_series(std::iter::once(PathElement::new(snowflake_vertices, &RED)))?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/stock.rs b/vendor/plotters/examples/stock.rs new file mode 100644 index 000000000..8e9416f6d --- /dev/null +++ b/vendor/plotters/examples/stock.rs @@ -0,0 +1,79 @@ +use chrono::offset::{Local, TimeZone}; +use chrono::{Date, Duration}; +use plotters::prelude::*; +fn parse_time(t: &str) -> Date { + Local + .datetime_from_str(&format!("{} 0:0", t), "%Y-%m-%d %H:%M") + .unwrap() + .date() +} +const OUT_FILE_NAME: &'static str = "plotters-doc-data/stock.png"; +fn main() -> Result<(), Box> { + let data = get_data(); + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + root.fill(&WHITE)?; + + let (to_date, from_date) = ( + parse_time(&data[0].0) + Duration::days(1), + parse_time(&data[29].0) - Duration::days(1), + ); + + let mut chart = ChartBuilder::on(&root) + .x_label_area_size(40) + .y_label_area_size(40) + .caption("MSFT Stock Price", ("sans-serif", 50.0).into_font()) + .build_cartesian_2d(from_date..to_date, 110f32..135f32)?; + + chart.configure_mesh().light_line_style(&WHITE).draw()?; + + chart.draw_series( + data.iter().map(|x| { + CandleStick::new(parse_time(x.0), x.1, x.2, x.3, x.4, GREEN.filled(), RED, 15) + }), + )?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} + +fn get_data() -> Vec<(&'static str, f32, f32, f32, f32)> { + return vec![ + ("2019-04-25", 130.0600, 131.3700, 128.8300, 129.1500), + ("2019-04-24", 125.7900, 125.8500, 124.5200, 125.0100), + ("2019-04-23", 124.1000, 125.5800, 123.8300, 125.4400), + ("2019-04-22", 122.6200, 124.0000, 122.5700, 123.7600), + ("2019-04-18", 122.1900, 123.5200, 121.3018, 123.3700), + ("2019-04-17", 121.2400, 121.8500, 120.5400, 121.7700), + ("2019-04-16", 121.6400, 121.6500, 120.1000, 120.7700), + ("2019-04-15", 120.9400, 121.5800, 120.5700, 121.0500), + ("2019-04-12", 120.6400, 120.9800, 120.3700, 120.9500), + ("2019-04-11", 120.5400, 120.8500, 119.9200, 120.3300), + ("2019-04-10", 119.7600, 120.3500, 119.5400, 120.1900), + ("2019-04-09", 118.6300, 119.5400, 118.5800, 119.2800), + ("2019-04-08", 119.8100, 120.0200, 118.6400, 119.9300), + ("2019-04-05", 119.3900, 120.2300, 119.3700, 119.8900), + ("2019-04-04", 120.1000, 120.2300, 118.3800, 119.3600), + ("2019-04-03", 119.8600, 120.4300, 119.1500, 119.9700), + ("2019-04-02", 119.0600, 119.4800, 118.5200, 119.1900), + ("2019-04-01", 118.9500, 119.1085, 118.1000, 119.0200), + ("2019-03-29", 118.0700, 118.3200, 116.9600, 117.9400), + ("2019-03-28", 117.4400, 117.5800, 116.1300, 116.9300), + ("2019-03-27", 117.8750, 118.2100, 115.5215, 116.7700), + ("2019-03-26", 118.6200, 118.7050, 116.8500, 117.9100), + ("2019-03-25", 116.5600, 118.0100, 116.3224, 117.6600), + ("2019-03-22", 119.5000, 119.5900, 117.0400, 117.0500), + ("2019-03-21", 117.1350, 120.8200, 117.0900, 120.2200), + ("2019-03-20", 117.3900, 118.7500, 116.7100, 117.5200), + ("2019-03-19", 118.0900, 118.4400, 116.9900, 117.6500), + ("2019-03-18", 116.1700, 117.6100, 116.0500, 117.5700), + ("2019-03-15", 115.3400, 117.2500, 114.5900, 115.9100), + ("2019-03-14", 114.5400, 115.2000, 114.3300, 114.5900), + ]; +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/tick_control.rs b/vendor/plotters/examples/tick_control.rs new file mode 100644 index 000000000..b34fc88c1 --- /dev/null +++ b/vendor/plotters/examples/tick_control.rs @@ -0,0 +1,89 @@ +// Data is pulled from https://covid.ourworldindata.org/data/owid-covid-data.json +use plotters::prelude::*; +use std::fs::File; +use std::io::BufReader; + +#[derive(serde_derive::Deserialize)] +struct DailyData { + #[serde(default)] + new_cases: f64, + #[serde(default)] + total_cases: f64, +} + +#[derive(serde_derive::Deserialize)] +struct CountryData { + data: Vec, +} + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/tick_control.svg"; +fn main() -> Result<(), Box> { + let root = SVGBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + root.fill(&WHITE)?; + + let (upper, lower) = root.split_vertically(750); + + lower.titled( + "Data Source: https://covid.ourworldindata.org/data/owid-covid-data.json", + ("sans-serif", 10).into_font().color(&BLACK.mix(0.5)), + )?; + + let mut chart = ChartBuilder::on(&upper) + .caption("World COVID-19 Cases", ("sans-serif", (5).percent_height())) + .set_label_area_size(LabelAreaPosition::Left, (8).percent()) + .set_label_area_size(LabelAreaPosition::Bottom, (4).percent()) + .margin((1).percent()) + .build_cartesian_2d( + (20u32..5000_0000u32) + .log_scale() + .with_key_points(vec![50, 100, 1000, 10000, 100000, 1000000, 10000000]), + (0u32..50_0000u32) + .log_scale() + .with_key_points(vec![10, 50, 100, 1000, 10000, 100000, 200000]), + )?; + + chart + .configure_mesh() + .x_desc("Total Cases") + .y_desc("New Cases") + .draw()?; + + let data: std::collections::HashMap = serde_json::from_reader( + BufReader::new(File::open("plotters-doc-data/covid-data.json")?), + )?; + + for (idx, &series) in ["CHN", "USA", "RUS", "JPN", "DEU", "IND", "OWID_WRL"] + .iter() + .enumerate() + { + let color = Palette99::pick(idx).mix(0.9); + chart + .draw_series(LineSeries::new( + data[series].data.iter().map( + |&DailyData { + new_cases, + total_cases, + .. + }| (total_cases as u32, new_cases as u32), + ), + color.stroke_width(3), + ))? + .label(series) + .legend(move |(x, y)| Rectangle::new([(x, y - 5), (x + 10, y + 5)], color.filled())); + } + + chart + .configure_series_labels() + .border_style(&BLACK) + .draw()?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} diff --git a/vendor/plotters/examples/two-scales.rs b/vendor/plotters/examples/two-scales.rs new file mode 100644 index 000000000..6e1dfa4c2 --- /dev/null +++ b/vendor/plotters/examples/two-scales.rs @@ -0,0 +1,60 @@ +use plotters::prelude::*; + +const OUT_FILE_NAME: &'static str = "plotters-doc-data/twoscale.png"; +fn main() -> Result<(), Box> { + let root = BitMapBackend::new(OUT_FILE_NAME, (1024, 768)).into_drawing_area(); + root.fill(&WHITE)?; + + let mut chart = ChartBuilder::on(&root) + .x_label_area_size(35) + .y_label_area_size(40) + .right_y_label_area_size(40) + .margin(5) + .caption("Dual Y-Axis Example", ("sans-serif", 50.0).into_font()) + .build_cartesian_2d(0f32..10f32, (0.1f32..1e10f32).log_scale())? + .set_secondary_coord(0f32..10f32, -1.0f32..1.0f32); + + chart + .configure_mesh() + .disable_x_mesh() + .disable_y_mesh() + .y_desc("Log Scale") + .y_label_formatter(&|x| format!("{:e}", x)) + .draw()?; + + chart + .configure_secondary_axes() + .y_desc("Linear Scale") + .draw()?; + + chart + .draw_series(LineSeries::new( + (0..=100).map(|x| (x as f32 / 10.0, (1.02f32).powf(x as f32 * x as f32 / 10.0))), + &BLUE, + ))? + .label("y = 1.02^x^2") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE)); + + chart + .draw_secondary_series(LineSeries::new( + (0..=100).map(|x| (x as f32 / 10.0, (x as f32 / 5.0).sin())), + &RED, + ))? + .label("y = sin(2x)") + .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED)); + + chart + .configure_series_labels() + .background_style(&RGBColor(128, 128, 128)) + .draw()?; + + // To avoid the IO failure being ignored silently, we manually call the present function + root.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir"); + println!("Result has been saved to {}", OUT_FILE_NAME); + + Ok(()) +} +#[test] +fn entry_point() { + main().unwrap() +} -- cgit v1.2.3