Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/scales/linear.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
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<f32>,
pub domain: Vec<f32>,
/// The range limits of the drawable area on the chart.
range: Vec<isize>,
pub range: Vec<isize>,
/// The amount of ticks to display.
tick_count: usize,
pub tick_count: usize,
}

impl ScaleLinear {
Expand Down Expand Up @@ -151,4 +151,4 @@ impl Scale<f32> for ScaleLinear {

ticks
}
}
}
96 changes: 73 additions & 23 deletions src/views/area.rs
Original file line number Diff line number Diff line change
@@ -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> {
Expand All @@ -17,8 +17,8 @@ pub struct AreaSeriesView<'a, T: Display + Clone, U: Display + Clone> {
marker_type: MarkerType,
entries: Vec<AreaSeries<T, U>>,
colors: Vec<Color>,
x_scale: Option<&'a dyn Scale<T>>,
y_scale: Option<&'a dyn Scale<U>>,
pub x_scale: Option<&'a dyn Scale<T>>,
pub y_scale: Option<&'a dyn Scale<U>>,
custom_data_label: String,
}

Expand Down Expand Up @@ -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<impl PointDatum<T, U>>) -> Result<Self, String> {
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.
Expand All @@ -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::<Vec<ScatterPoint<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::<Vec<ScatterPoint<T, U>>>();

let y_origin = {
if self.y_scale.unwrap().is_range_reversed() {
Expand All @@ -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)
}
Expand All @@ -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
}
Expand Down