From cdcd75eb98007f426bd9af8c0bb2bd76bf0f0863 Mon Sep 17 00:00:00 2001 From: Natan Freeman Date: Wed, 19 Jan 2022 20:38:12 +0200 Subject: [PATCH 1/4] Implements copy trait for ScaleLinear. --- src/scales/linear.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scales/linear.rs b/src/scales/linear.rs index 135d224..02d9edf 100644 --- a/src/scales/linear.rs +++ b/src/scales/linear.rs @@ -1,8 +1,8 @@ -use std::cmp::{max, Ordering}; use crate::scales::{Scale, ScaleType}; +use std::cmp::{max, Ordering}; /// The scale to represent categorical data. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ScaleLinear { /// The domain limits of the dataset that the scale is going to represent. domain: Vec, @@ -151,4 +151,4 @@ impl Scale for ScaleLinear { ticks } -} \ No newline at end of file +} From 7b44044c8b24d83d8a9df86490c99bbee1d8df9b Mon Sep 17 00:00:00 2001 From: Natan Freeman Date: Wed, 19 Jan 2022 20:52:07 +0200 Subject: [PATCH 2/4] Adds ```Clone``` trait to ```ScaleLinear```. --- src/scales/linear.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scales/linear.rs b/src/scales/linear.rs index 135d224..02d9edf 100644 --- a/src/scales/linear.rs +++ b/src/scales/linear.rs @@ -1,8 +1,8 @@ -use std::cmp::{max, Ordering}; use crate::scales::{Scale, ScaleType}; +use std::cmp::{max, Ordering}; /// The scale to represent categorical data. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct ScaleLinear { /// The domain limits of the dataset that the scale is going to represent. domain: Vec, @@ -151,4 +151,4 @@ impl Scale for ScaleLinear { ticks } -} \ No newline at end of file +} From 55c266e9cae9670514a5ee15f1cda8b97fc8ffe7 Mon Sep 17 00:00:00 2001 From: Natan Freeman Date: Fri, 21 Jan 2022 09:15:27 +0200 Subject: [PATCH 3/4] Sets ```x_scale``` to be public. --- src/views/area.rs | 96 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 73 insertions(+), 23 deletions(-) diff --git a/src/views/area.rs b/src/views/area.rs index 1aa3a0b..e3b1a90 100644 --- a/src/views/area.rs +++ b/src/views/area.rs @@ -1,14 +1,14 @@ -use svg::node::Node; -use svg::node::element::Group; -use crate::components::scatter::{ScatterPoint, MarkerType, PointLabelPosition}; use crate::colors::Color; -use crate::Scale; +use crate::components::area::AreaSeries; +use crate::components::legend::{LegendEntry, LegendMarkerType}; +use crate::components::scatter::{MarkerType, PointLabelPosition, ScatterPoint}; +use crate::components::DatumRepresentation; use crate::views::datum::PointDatum; use crate::views::View; -use crate::components::DatumRepresentation; +use crate::Scale; use std::fmt::Display; -use crate::components::legend::{LegendEntry, LegendMarkerType}; -use crate::components::area::AreaSeries; +use svg::node::element::Group; +use svg::node::Node; /// A View that represents data as a scatter plot. pub struct AreaSeriesView<'a, T: Display + Clone, U: Display + Clone> { @@ -17,8 +17,8 @@ pub struct AreaSeriesView<'a, T: Display + Clone, U: Display + Clone> { marker_type: MarkerType, entries: Vec>, colors: Vec, - x_scale: Option<&'a dyn Scale>, - y_scale: Option<&'a dyn Scale>, + pub x_scale: Option<&'a dyn Scale>, + pub y_scale: Option<&'a dyn Scale>, custom_data_label: String, } @@ -85,12 +85,20 @@ impl<'a, T: Display + Clone, U: Display + Clone> AreaSeriesView<'a, T, U> { /// Load and process a dataset of BarDatum points. pub fn load_data(mut self, data: &Vec>) -> Result { match self.x_scale { - Some(_) => {}, - _ => return Err("Please provide a scale for the X dimension before loading data".to_string()), + Some(_) => {} + _ => { + return Err( + "Please provide a scale for the X dimension before loading data".to_string(), + ) + } } match self.y_scale { - Some(_) => {}, - _ => return Err("Please provide a scale for the Y dimension before loading data".to_string()), + Some(_) => {} + _ => { + return Err( + "Please provide a scale for the Y dimension before loading data".to_string(), + ) + } } // Compute corresponding offsets to apply in case there is a non-zero bandwidth. @@ -109,11 +117,25 @@ impl<'a, T: Display + Clone, U: Display + Clone> AreaSeriesView<'a, T, U> { } }; - let mut points = data.iter().map(|datum| { - let scaled_x = self.x_scale.unwrap().scale(&datum.get_x()); - let scaled_y = self.y_scale.unwrap().scale(&datum.get_y()); - ScatterPoint::new(scaled_x + x_bandwidth_offset, scaled_y + y_bandwidth_offset, self.marker_type, 5, datum.get_x(), datum.get_y(), self.label_position, self.labels_visible, true, self.colors[0].as_hex()) - }).collect::>>(); + let mut points = data + .iter() + .map(|datum| { + let scaled_x = self.x_scale.unwrap().scale(&datum.get_x()); + let scaled_y = self.y_scale.unwrap().scale(&datum.get_y()); + ScatterPoint::new( + scaled_x + x_bandwidth_offset, + scaled_y + y_bandwidth_offset, + self.marker_type, + 5, + datum.get_x(), + datum.get_y(), + self.label_position, + self.labels_visible, + true, + self.colors[0].as_hex(), + ) + }) + .collect::>>(); let y_origin = { if self.y_scale.unwrap().is_range_reversed() { @@ -124,10 +146,33 @@ impl<'a, T: Display + Clone, U: Display + Clone> AreaSeriesView<'a, T, U> { }; let first = data.first().unwrap(); let last = data.last().unwrap(); - points.push(ScatterPoint::new(self.x_scale.unwrap().scale(&last.get_x()) + x_bandwidth_offset, y_origin, self.marker_type, 5, data[0].get_x(), data[0].get_y(), self.label_position, false, false, "#fff".to_string())); - points.push(ScatterPoint::new(self.x_scale.unwrap().scale(&first.get_x()) + x_bandwidth_offset, y_origin, self.marker_type, 5, data[0].get_x(), data[0].get_y(), self.label_position, false, false, "#fff".to_string())); - - self.entries.push(AreaSeries::new(points, self.colors[0].as_hex())); + points.push(ScatterPoint::new( + self.x_scale.unwrap().scale(&last.get_x()) + x_bandwidth_offset, + y_origin, + self.marker_type, + 5, + data[0].get_x(), + data[0].get_y(), + self.label_position, + false, + false, + "#fff".to_string(), + )); + points.push(ScatterPoint::new( + self.x_scale.unwrap().scale(&first.get_x()) + x_bandwidth_offset, + y_origin, + self.marker_type, + 5, + data[0].get_x(), + data[0].get_y(), + self.label_position, + false, + false, + "#fff".to_string(), + )); + + self.entries + .push(AreaSeries::new(points, self.colors[0].as_hex())); Ok(self) } @@ -153,7 +198,12 @@ impl<'a, T: Display + Clone, U: Display + Clone> View<'a> for AreaSeriesView<'a, // Area series currently does not support multiple keys per dataset, // hence when displaying a legend, it will display the custom data label // as the legend label. - entries.push(LegendEntry::new(LegendMarkerType::Square, self.colors[0].as_hex(), String::from("none"), self.custom_data_label.clone())); + entries.push(LegendEntry::new( + LegendMarkerType::Square, + self.colors[0].as_hex(), + String::from("none"), + self.custom_data_label.clone(), + )); entries } From 91c1af750718437672f68aee2a4115fbe5ac3bad Mon Sep 17 00:00:00 2001 From: Natan Freeman Date: Fri, 21 Jan 2022 09:21:34 +0200 Subject: [PATCH 4/4] Sets ```ScaleLinear``` privet fields to be public. --- src/scales/linear.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/scales/linear.rs b/src/scales/linear.rs index 02d9edf..9459160 100644 --- a/src/scales/linear.rs +++ b/src/scales/linear.rs @@ -5,11 +5,11 @@ use std::cmp::{max, Ordering}; #[derive(Debug, Clone)] pub struct ScaleLinear { /// The domain limits of the dataset that the scale is going to represent. - domain: Vec, + pub domain: Vec, /// The range limits of the drawable area on the chart. - range: Vec, + pub range: Vec, /// The amount of ticks to display. - tick_count: usize, + pub tick_count: usize, } impl ScaleLinear {