plot: Use f32 instead of f64 (#1052)

## Break Change
- Convert all `f64` parameters to `f32`.

Since the GPUI geometry module uses f32 for rendering, we are also
switching to f32. This helps avoid many as operators and unnecessary
conversions.
This commit is contained in:
Floyd Wang 2025-07-08 16:24:59 +08:00 committed by GitHub
parent 8bf66443b2
commit 3b759cd448
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 121 additions and 133 deletions

View file

@ -164,7 +164,7 @@ impl Render for ChartStory {
.child(chart_container( .child(chart_container(
"Pie Chart", "Pie Chart",
PieChart::new(self.monthly_devices.clone()) PieChart::new(self.monthly_devices.clone())
.value(|d| d.desktop) .value(|d| d.desktop as f32)
.outer_radius(100.) .outer_radius(100.)
.color(move |d| d.color(color)), .color(move |d| d.color(color)),
true, true,
@ -173,7 +173,7 @@ impl Render for ChartStory {
.child(chart_container( .child(chart_container(
"Pie Chart - Donut", "Pie Chart - Donut",
PieChart::new(self.monthly_devices.clone()) PieChart::new(self.monthly_devices.clone())
.value(|d| d.desktop) .value(|d| d.desktop as f32)
.outer_radius(100.) .outer_radius(100.)
.inner_radius(60.) .inner_radius(60.)
.color(move |d| d.color(color)), .color(move |d| d.color(color)),
@ -183,7 +183,7 @@ impl Render for ChartStory {
.child(chart_container( .child(chart_container(
"Pie Chart - Pad Angle", "Pie Chart - Pad Angle",
PieChart::new(self.monthly_devices.clone()) PieChart::new(self.monthly_devices.clone())
.value(|d| d.desktop) .value(|d| d.desktop as f32)
.outer_radius(100.) .outer_radius(100.)
.inner_radius(60.) .inner_radius(60.)
.pad_angle(4. / 100.) .pad_angle(4. / 100.)

View file

@ -94,8 +94,8 @@ where
return; return;
} }
let width = bounds.size.width.to_f64(); let width = bounds.size.width.0;
let height = bounds.size.height.to_f64() - AXIS_GAP; let height = bounds.size.height.0 - AXIS_GAP;
// X scale // X scale
let x = ScalePoint::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width]); let x = ScalePoint::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width]);
@ -134,7 +134,7 @@ where
// Draw grid // Draw grid
Grid::new() Grid::new()
.y((0..=3).map(|i| height * i as f64 / 4.0).collect()) .y((0..=3).map(|i| height * i as f32 / 4.0).collect())
.stroke(cx.theme().border) .stroke(cx.theme().border)
.dash_array(&[px(4.), px(2.)]) .dash_array(&[px(4.), px(2.)])
.paint(&bounds, window); .paint(&bounds, window);

View file

@ -90,8 +90,8 @@ where
return; return;
}; };
let width = bounds.size.width.to_f64(); let width = bounds.size.width.0;
let height = bounds.size.height.to_f64() - AXIS_GAP; let height = bounds.size.height.0 - AXIS_GAP;
// X scale // X scale
let x = ScaleBand::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width]) let x = ScaleBand::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width])
@ -133,7 +133,7 @@ where
// Draw grid // Draw grid
Grid::new() Grid::new()
.y((0..=3).map(|i| height * i as f64 / 4.0).collect()) .y((0..=3).map(|i| height * i as f32 / 4.0).collect())
.stroke(cx.theme().border) .stroke(cx.theme().border)
.dash_array(&[px(4.), px(2.)]) .dash_array(&[px(4.), px(2.)])
.paint(&bounds, window); .paint(&bounds, window);

View file

@ -85,8 +85,8 @@ where
return; return;
}; };
let width = bounds.size.width.to_f64(); let width = bounds.size.width.0;
let height = bounds.size.height.to_f64() - AXIS_GAP; let height = bounds.size.height.0 - AXIS_GAP;
// X scale // X scale
let x = ScalePoint::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width]); let x = ScalePoint::new(self.data.iter().map(|v| x_fn(v)).collect(), vec![0., width]);
@ -126,7 +126,7 @@ where
// Draw grid // Draw grid
Grid::new() Grid::new()
.y((0..=3).map(|i| height * i as f64 / 4.0).collect()) .y((0..=3).map(|i| height * i as f32 / 4.0).collect())
.stroke(cx.theme().border) .stroke(cx.theme().border)
.dash_array(&[px(4.), px(2.)]) .dash_array(&[px(4.), px(2.)])
.paint(&bounds, window); .paint(&bounds, window);

View file

@ -15,10 +15,10 @@ use crate::{
#[derive(IntoPlot)] #[derive(IntoPlot)]
pub struct PieChart<T: 'static> { pub struct PieChart<T: 'static> {
data: Vec<T>, data: Vec<T>,
inner_radius: f64, inner_radius: f32,
outer_radius: f64, outer_radius: f32,
pad_angle: f64, pad_angle: f32,
value: Option<Rc<dyn Fn(&T) -> f64>>, value: Option<Rc<dyn Fn(&T) -> f32>>,
color: Option<Rc<dyn Fn(&T) -> Hsla>>, color: Option<Rc<dyn Fn(&T) -> Hsla>>,
} }
@ -37,22 +37,22 @@ impl<T> PieChart<T> {
} }
} }
pub fn inner_radius(mut self, inner_radius: f64) -> Self { pub fn inner_radius(mut self, inner_radius: f32) -> Self {
self.inner_radius = inner_radius; self.inner_radius = inner_radius;
self self
} }
pub fn outer_radius(mut self, outer_radius: f64) -> Self { pub fn outer_radius(mut self, outer_radius: f32) -> Self {
self.outer_radius = outer_radius; self.outer_radius = outer_radius;
self self
} }
pub fn pad_angle(mut self, pad_angle: f64) -> Self { pub fn pad_angle(mut self, pad_angle: f32) -> Self {
self.pad_angle = pad_angle; self.pad_angle = pad_angle;
self self
} }
pub fn value(mut self, value: impl Fn(&T) -> f64 + 'static) -> Self { pub fn value(mut self, value: impl Fn(&T) -> f32 + 'static) -> Self {
self.value = Some(Rc::new(value)); self.value = Some(Rc::new(value));
self self
} }
@ -73,7 +73,7 @@ impl<T> Plot for PieChart<T> {
}; };
let outer_radius = if self.outer_radius.is_zero() { let outer_radius = if self.outer_radius.is_zero() {
bounds.size.height.to_f64() * 0.4 bounds.size.height.0 * 0.4
} else { } else {
self.outer_radius self.outer_radius
}; };

View file

@ -5,7 +5,7 @@ use gpui::{
use super::{label::Label, label::Text, label::TEXT_GAP, label::TEXT_SIZE, origin_point}; use super::{label::Label, label::Text, label::TEXT_GAP, label::TEXT_SIZE, origin_point};
pub const AXIS_GAP: f64 = 18.; pub const AXIS_GAP: f32 = 18.;
pub struct AxisText { pub struct AxisText {
pub text: SharedString, pub text: SharedString,
@ -75,7 +75,7 @@ impl Axis {
.into_iter() .into_iter()
.map(|t| Text { .map(|t| Text {
text: t.text, text: t.text,
origin: point(t.tick, x + px((TEXT_GAP * 3.) as f32)), origin: point(t.tick, x + px(TEXT_GAP * 3.)),
color: t.color, color: t.color,
font_size: t.font_size, font_size: t.font_size,
font_weight: FontWeight::NORMAL, font_weight: FontWeight::NORMAL,
@ -105,7 +105,7 @@ impl Axis {
.into_iter() .into_iter()
.map(|t| Text { .map(|t| Text {
text: t.text, text: t.text,
origin: point(y + px(TEXT_GAP as f32), t.tick), origin: point(y + px(TEXT_GAP), t.tick),
color: t.color, color: t.color,
font_size: t.font_size, font_size: t.font_size,
font_weight: FontWeight::NORMAL, font_weight: FontWeight::NORMAL,

View file

@ -7,9 +7,9 @@ use gpui::{
use super::origin_point; use super::origin_point;
pub const TEXT_SIZE: f64 = 10.; pub const TEXT_SIZE: f32 = 10.;
pub const TEXT_GAP: f64 = 2.; pub const TEXT_GAP: f32 = 2.;
pub const TEXT_HEIGHT: f64 = TEXT_SIZE + TEXT_GAP; pub const TEXT_HEIGHT: f32 = TEXT_SIZE + TEXT_GAP;
pub struct Text { pub struct Text {
pub text: SharedString, pub text: SharedString,

View file

@ -35,15 +35,15 @@ where
pub fn polygon<T>(points: &[Point<T>], bounds: &Bounds<Pixels>) -> Option<Path<Pixels>> pub fn polygon<T>(points: &[Point<T>], bounds: &Bounds<Pixels>) -> Option<Path<Pixels>>
where where
T: Default + Clone + Copy + Debug + Into<f64> + PartialEq, T: Default + Clone + Copy + Debug + Into<f32> + PartialEq,
{ {
let mut path = PathBuilder::stroke(px(1.)); let mut path = PathBuilder::stroke(px(1.));
let points = &points let points = &points
.iter() .iter()
.map(|p| { .map(|p| {
point( point(
px((p.x.into() + bounds.origin.x.to_f64()) as f32), px(p.x.into() + bounds.origin.x.0),
px((p.y.into() + bounds.origin.y.to_f64()) as f32), px(p.y.into() + bounds.origin.y.0),
) )
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();

View file

@ -10,8 +10,8 @@ pub(crate) use sealed::Sealed;
pub trait Scale<T> { pub trait Scale<T> {
/// Get the tick of the scale. /// Get the tick of the scale.
fn tick(&self, value: &T) -> Option<f64>; fn tick(&self, value: &T) -> Option<f32>;
/// Get the least index of the scale. /// Get the least index of the scale.
fn least_index(&self, tick: f64) -> usize; fn least_index(&self, tick: f32) -> usize;
} }

View file

@ -8,15 +8,15 @@ use super::Scale;
#[derive(Clone)] #[derive(Clone)]
pub struct ScaleBand<T> { pub struct ScaleBand<T> {
domain: Vec<T>, domain: Vec<T>,
range_diff: f64, range_diff: f32,
avg_width: f64, avg_width: f32,
padding_inner: f64, padding_inner: f32,
padding_outer: f64, padding_outer: f32,
} }
impl<T> ScaleBand<T> { impl<T> ScaleBand<T> {
pub fn new(domain: Vec<T>, range: Vec<f64>) -> Self { pub fn new(domain: Vec<T>, range: Vec<f32>) -> Self {
let len = domain.len() as f64; let len = domain.len() as f32;
let range_diff = range let range_diff = range
.iter() .iter()
.minmax() .minmax()
@ -33,18 +33,18 @@ impl<T> ScaleBand<T> {
} }
/// Get the width of the band. /// Get the width of the band.
pub fn band_width(&self) -> f64 { pub fn band_width(&self) -> f32 {
(self.avg_width * (1. - self.padding_inner)).min(30.) (self.avg_width * (1. - self.padding_inner)).min(30.)
} }
/// Set the padding inner of the band. /// Set the padding inner of the band.
pub fn padding_inner(mut self, padding_inner: f64) -> Self { pub fn padding_inner(mut self, padding_inner: f32) -> Self {
self.padding_inner = padding_inner; self.padding_inner = padding_inner;
self self
} }
/// Set the padding outer of the band. /// Set the padding outer of the band.
pub fn padding_outer(mut self, padding_outer: f64) -> Self { pub fn padding_outer(mut self, padding_outer: f32) -> Self {
self.padding_outer = padding_outer; self.padding_outer = padding_outer;
self self
} }
@ -54,7 +54,7 @@ impl<T> Scale<T> for ScaleBand<T>
where where
T: PartialEq, T: PartialEq,
{ {
fn tick(&self, value: &T) -> Option<f64> { fn tick(&self, value: &T) -> Option<f32> {
let index = self.domain.iter().position(|v| v == value)?; let index = self.domain.iter().position(|v| v == value)?;
let domain_len = self.domain.len(); let domain_len = self.domain.len();
@ -63,13 +63,13 @@ where
return Some((self.range_diff - self.band_width()) / 2.); return Some((self.range_diff - self.band_width()) / 2.);
} }
let ratio = 1. + self.padding_inner / (self.domain.len() - 1) as f64; let ratio = 1. + self.padding_inner / (self.domain.len() - 1) as f32;
let padding_outer_width = self.avg_width * self.padding_outer; let padding_outer_width = self.avg_width * self.padding_outer;
let avg_width = (self.range_diff - padding_outer_width * 2.) / self.domain.len() as f64; let avg_width = (self.range_diff - padding_outer_width * 2.) / self.domain.len() as f32;
Some(index as f64 * avg_width * ratio + padding_outer_width) Some(index as f32 * avg_width * ratio + padding_outer_width)
} }
fn least_index(&self, tick: f64) -> usize { fn least_index(&self, tick: f32) -> usize {
let index = (tick / self.avg_width).round() as usize; let index = (tick / self.avg_width).round() as usize;
index.min(self.domain.len().saturating_sub(1)) index.min(self.domain.len().saturating_sub(1))
} }

View file

@ -10,15 +10,15 @@ pub struct ScaleLinear<T> {
domain_len: usize, domain_len: usize,
domain_min: T, domain_min: T,
domain_diff: T, domain_diff: T,
range_min: f64, range_min: f32,
range_diff: f64, range_diff: f32,
} }
impl<T> ScaleLinear<T> impl<T> ScaleLinear<T>
where where
T: Copy + PartialOrd + Num + ToPrimitive + Sealed, T: Copy + PartialOrd + Num + ToPrimitive + Sealed,
{ {
pub fn new(domain: Vec<T>, range: Vec<f64>) -> Self { pub fn new(domain: Vec<T>, range: Vec<f32>) -> Self {
let (domain_min, domain_max) = domain let (domain_min, domain_max) = domain
.iter() .iter()
.minmax() .minmax()
@ -45,17 +45,17 @@ impl<T> Scale<T> for ScaleLinear<T>
where where
T: Copy + PartialOrd + Num + ToPrimitive + Sealed, T: Copy + PartialOrd + Num + ToPrimitive + Sealed,
{ {
fn tick(&self, value: &T) -> Option<f64> { fn tick(&self, value: &T) -> Option<f32> {
if self.domain_diff.is_zero() { if self.domain_diff.is_zero() {
return None; return None;
} }
let ratio = ((*value - self.domain_min) / self.domain_diff).to_f64()?; let ratio = ((*value - self.domain_min) / self.domain_diff).to_f32()?;
Some((1. - ratio) * self.range_diff + self.range_min) Some((1. - ratio) * self.range_diff + self.range_min)
} }
fn least_index(&self, tick: f64) -> usize { fn least_index(&self, tick: f32) -> usize {
let index = (tick / self.range_diff).round() as usize; let index = (tick / self.range_diff).round() as usize;
index.min(self.domain_len.saturating_sub(1)) index.min(self.domain_len.saturating_sub(1))
} }

View file

@ -8,14 +8,14 @@ use super::Scale;
#[derive(Clone)] #[derive(Clone)]
pub struct ScalePoint<T> { pub struct ScalePoint<T> {
domain: Vec<T>, domain: Vec<T>,
range_tick: f64, range_tick: f32,
} }
impl<T> ScalePoint<T> impl<T> ScalePoint<T>
where where
T: PartialEq, T: PartialEq,
{ {
pub fn new(domain: Vec<T>, range: Vec<f64>) -> Self { pub fn new(domain: Vec<T>, range: Vec<f32>) -> Self {
let len = domain.len(); let len = domain.len();
let range_tick = if len.is_zero() { let range_tick = if len.is_zero() {
0. 0.
@ -26,7 +26,7 @@ where
.into_option() .into_option()
.map_or(0., |(min, max)| max - min); .map_or(0., |(min, max)| max - min);
range_diff / (len - 1) as f64 range_diff / (len - 1) as f32
}; };
Self { domain, range_tick } Self { domain, range_tick }
@ -37,12 +37,12 @@ impl<T> Scale<T> for ScalePoint<T>
where where
T: PartialEq, T: PartialEq,
{ {
fn tick(&self, value: &T) -> Option<f64> { fn tick(&self, value: &T) -> Option<f32> {
let index = self.domain.iter().position(|v| v == value)?; let index = self.domain.iter().position(|v| v == value)?;
Some(index as f64 * self.range_tick) Some(index as f32 * self.range_tick)
} }
fn least_index(&self, tick: f64) -> usize { fn least_index(&self, tick: f32) -> usize {
let index = (tick / self.range_tick).round() as usize; let index = (tick / self.range_tick).round() as usize;
index.min(self.domain.len().saturating_sub(1)) index.min(self.domain.len().saturating_sub(1))
} }

View file

@ -1,19 +1,19 @@
// @reference: https://d3js.org/d3-shape/arc // @reference: https://d3js.org/d3-shape/arc
use std::{f64::consts::PI, fmt::Debug}; use std::{f32::consts::PI, fmt::Debug};
use gpui::{point, px, Bounds, Hsla, Path, PathBuilder, Pixels, Point, Window}; use gpui::{point, px, Bounds, Hsla, Path, PathBuilder, Pixels, Point, Window};
const EPSILON: f64 = 1e-12; const EPSILON: f32 = 1e-12;
const HALF_PI: f64 = PI / 2.; const HALF_PI: f32 = PI / 2.;
pub struct ArcData<'a, T> { pub struct ArcData<'a, T> {
pub data: &'a T, pub data: &'a T,
pub index: usize, pub index: usize,
pub value: f64, pub value: f32,
pub start_angle: f64, pub start_angle: f32,
pub end_angle: f64, pub end_angle: f32,
pub pad_angle: f64, pub pad_angle: f32,
} }
impl<T> Debug for ArcData<'_, T> { impl<T> Debug for ArcData<'_, T> {
@ -27,8 +27,8 @@ impl<T> Debug for ArcData<'_, T> {
} }
pub struct Arc { pub struct Arc {
inner_radius: f64, inner_radius: f32,
outer_radius: f64, outer_radius: f32,
} }
impl Default for Arc { impl Default for Arc {
@ -46,19 +46,19 @@ impl Arc {
} }
/// Set the inner radius of the Arc. /// Set the inner radius of the Arc.
pub fn inner_radius(mut self, inner_radius: f64) -> Self { pub fn inner_radius(mut self, inner_radius: f32) -> Self {
self.inner_radius = inner_radius; self.inner_radius = inner_radius;
self self
} }
/// Set the outer radius of the Arc. /// Set the outer radius of the Arc.
pub fn outer_radius(mut self, outer_radius: f64) -> Self { pub fn outer_radius(mut self, outer_radius: f32) -> Self {
self.outer_radius = outer_radius; self.outer_radius = outer_radius;
self self
} }
/// Get the centroid of the Arc. /// Get the centroid of the Arc.
pub fn centroid<T>(&self, arc: &ArcData<T>) -> Point<f64> { pub fn centroid<T>(&self, arc: &ArcData<T>) -> Point<f32> {
let start_angle = arc.start_angle - HALF_PI; let start_angle = arc.start_angle - HALF_PI;
let end_angle = arc.end_angle - HALF_PI; let end_angle = arc.end_angle - HALF_PI;
let r = (self.inner_radius + self.outer_radius) / 2.; let r = (self.inner_radius + self.outer_radius) / 2.;
@ -75,8 +75,8 @@ impl Arc {
let r1 = self.outer_radius.max(0.); let r1 = self.outer_radius.max(0.);
// Calculate the center point. // Calculate the center point.
let center_x = bounds.origin.x.to_f64() + bounds.size.width.to_f64() / 2.; let center_x = bounds.origin.x.0 + bounds.size.width.0 / 2.;
let center_y = bounds.origin.y.to_f64() + bounds.size.height.to_f64() / 2.; let center_y = bounds.origin.y.0 + bounds.size.height.0 / 2.;
// Angle difference. // Angle difference.
let da = end_angle - start_angle; let da = end_angle - start_angle;
@ -123,38 +123,38 @@ impl Arc {
let mut builder = PathBuilder::fill(); let mut builder = PathBuilder::fill();
// Move to the start point of the outer arc. // Move to the start point of the outer arc.
builder.move_to(point(px(x01 as f32), px(y01 as f32))); builder.move_to(point(px(x01), px(y01)));
// Draw the outer arc. // Draw the outer arc.
let large_arc = (a1_outer - a0_outer).abs() > PI; let large_arc = (a1_outer - a0_outer).abs() > PI;
builder.arc_to( builder.arc_to(
point(px(r1 as f32), px(r1 as f32)), point(px(r1), px(r1)),
px(0.), px(0.),
large_arc, large_arc,
true, true,
point(px(x11 as f32), px(y11 as f32)), point(px(x11), px(y11)),
); );
if r0 > EPSILON { if r0 > EPSILON {
// End point of the inner arc. // End point of the inner arc.
let x10 = center_x + r0 * a1_inner.cos(); let x10 = center_x + r0 * a1_inner.cos();
let y10 = center_y + r0 * a1_inner.sin(); let y10 = center_y + r0 * a1_inner.sin();
builder.line_to(point(px(x10 as f32), px(y10 as f32))); builder.line_to(point(px(x10), px(y10)));
// Draw the inner arc. // Draw the inner arc.
let x00 = center_x + r0 * a0_inner.cos(); let x00 = center_x + r0 * a0_inner.cos();
let y00 = center_y + r0 * a0_inner.sin(); let y00 = center_y + r0 * a0_inner.sin();
let large_arc_inner = (a1_inner - a0_inner).abs() > PI; let large_arc_inner = (a1_inner - a0_inner).abs() > PI;
builder.arc_to( builder.arc_to(
point(px(r0 as f32), px(r0 as f32)), point(px(r0), px(r0)),
px(0.), px(0.),
large_arc_inner, large_arc_inner,
false, false,
point(px(x00 as f32), px(y00 as f32)), point(px(x00), px(y00)),
); );
} else { } else {
// If there is no inner radius, draw a line to the center. // If there is no inner radius, draw a line to the center.
builder.line_to(point(px(center_x as f32), px(center_y as f32))); builder.line_to(point(px(center_x), px(center_y)));
} }
builder.build().ok() builder.build().ok()

View file

@ -7,9 +7,9 @@ use crate::plot::{origin_point, StrokeStyle};
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub struct Area<T> { pub struct Area<T> {
data: Vec<T>, data: Vec<T>,
x: Box<dyn Fn(&T) -> Option<f64>>, x: Box<dyn Fn(&T) -> Option<f32>>,
y0: Option<f64>, y0: Option<f32>,
y1: Box<dyn Fn(&T) -> Option<f64>>, y1: Box<dyn Fn(&T) -> Option<f32>>,
fill: Background, fill: Background,
stroke: Background, stroke: Background,
stroke_style: StrokeStyle, stroke_style: StrokeStyle,
@ -46,14 +46,14 @@ impl<T> Area<T> {
/// Set the x of the Area. /// Set the x of the Area.
pub fn x<F>(mut self, x: F) -> Self pub fn x<F>(mut self, x: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.x = Box::new(x); self.x = Box::new(x);
self self
} }
/// Set the y0 of the Area. /// Set the y0 of the Area.
pub fn y0(mut self, y0: f64) -> Self { pub fn y0(mut self, y0: f32) -> Self {
self.y0 = Some(y0); self.y0 = Some(y0);
self self
} }
@ -61,7 +61,7 @@ impl<T> Area<T> {
/// Set the y1 of the Area. /// Set the y1 of the Area.
pub fn y1<F>(mut self, y1: F) -> Self pub fn y1<F>(mut self, y1: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.y1 = Box::new(y1); self.y1 = Box::new(y1);
self self
@ -97,7 +97,7 @@ impl<T> Area<T> {
let y_tick = (self.y1)(v); let y_tick = (self.y1)(v);
if let (Some(x), Some(y)) = (x_tick, y_tick) { if let (Some(x), Some(y)) = (x_tick, y_tick) {
let pos = origin_point(px(x as f32), px(y as f32), origin); let pos = origin_point(px(x), px(y), origin);
points.push(pos); points.push(pos);
} }
@ -150,8 +150,8 @@ impl<T> Area<T> {
if let Some(last) = self.data.last() { if let Some(last) = self.data.last() {
let x_tick = (self.x)(last); let x_tick = (self.x)(last);
if let (Some(x), Some(y)) = (x_tick, self.y0) { if let (Some(x), Some(y)) = (x_tick, self.y0) {
area_builder.line_to(origin_point(px(x as f32), px(y as f32), bounds.origin)); area_builder.line_to(origin_point(px(x), px(y), bounds.origin));
area_builder.line_to(origin_point(px(0.), px(y as f32), bounds.origin)); area_builder.line_to(origin_point(px(0.), px(y), bounds.origin));
area_builder.close(); area_builder.close();
} }
} }

View file

@ -8,10 +8,10 @@ use crate::plot::{
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub struct Bar<T> { pub struct Bar<T> {
data: Vec<T>, data: Vec<T>,
x: Box<dyn Fn(&T) -> Option<f64>>, x: Box<dyn Fn(&T) -> Option<f32>>,
band_width: f64, band_width: f32,
y0: f64, y0: f32,
y1: Box<dyn Fn(&T) -> Option<f64>>, y1: Box<dyn Fn(&T) -> Option<f32>>,
fill: Box<dyn Fn(&T) -> Hsla>, fill: Box<dyn Fn(&T) -> Hsla>,
label: Option<Box<dyn Fn(&T, Point<Pixels>) -> Text>>, label: Option<Box<dyn Fn(&T, Point<Pixels>) -> Text>>,
} }
@ -47,20 +47,20 @@ impl<T> Bar<T> {
/// Set the x of the Bar. /// Set the x of the Bar.
pub fn x<F>(mut self, x: F) -> Self pub fn x<F>(mut self, x: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.x = Box::new(x); self.x = Box::new(x);
self self
} }
/// Set the band width of the Bar. /// Set the band width of the Bar.
pub fn band_width(mut self, band_width: f64) -> Self { pub fn band_width(mut self, band_width: f32) -> Self {
self.band_width = band_width; self.band_width = band_width;
self self
} }
/// Set the y0 of the Bar. /// Set the y0 of the Bar.
pub fn y0(mut self, y0: f64) -> Self { pub fn y0(mut self, y0: f32) -> Self {
self.y0 = y0; self.y0 = y0;
self self
} }
@ -68,7 +68,7 @@ impl<T> Bar<T> {
/// Set the y1 of the Bar. /// Set the y1 of the Bar.
pub fn y1<F>(mut self, y: F) -> Self pub fn y1<F>(mut self, y: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.y1 = Box::new(y); self.y1 = Box::new(y);
self self
@ -106,21 +106,13 @@ impl<T> Bar<T> {
let is_negative = y_tick > self.y0; let is_negative = y_tick > self.y0;
let (p1, p2) = if is_negative { let (p1, p2) = if is_negative {
( (
origin_point(px(x_tick as f32), px(self.y0 as f32), origin), origin_point(px(x_tick), px(self.y0), origin),
origin_point( origin_point(px(x_tick + self.band_width), px(y_tick), origin),
px((x_tick + self.band_width) as f32),
px(y_tick as f32),
origin,
),
) )
} else { } else {
( (
origin_point(px(x_tick as f32), px(y_tick as f32), origin), origin_point(px(x_tick), px(y_tick), origin),
origin_point( origin_point(px(x_tick + self.band_width), px(self.y0), origin),
px((x_tick + self.band_width) as f32),
px(self.y0 as f32),
origin,
),
) )
}; };
@ -132,11 +124,11 @@ impl<T> Bar<T> {
labels.push(label( labels.push(label(
v, v,
point( point(
px((x_tick + self.band_width / 2.) as f32), px(x_tick + self.band_width / 2.),
if is_negative { if is_negative {
px((y_tick + TEXT_GAP) as f32) px(y_tick + TEXT_GAP)
} else { } else {
px((y_tick - TEXT_HEIGHT) as f32) px(y_tick - TEXT_HEIGHT)
}, },
), ),
)); ));

View file

@ -10,8 +10,8 @@ use crate::plot::{origin_point, StrokeStyle};
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub struct Line<T> { pub struct Line<T> {
data: Vec<T>, data: Vec<T>,
x: Box<dyn Fn(&T) -> Option<f64>>, x: Box<dyn Fn(&T) -> Option<f32>>,
y: Box<dyn Fn(&T) -> Option<f64>>, y: Box<dyn Fn(&T) -> Option<f32>>,
stroke: Background, stroke: Background,
stroke_width: Pixels, stroke_width: Pixels,
stroke_style: StrokeStyle, stroke_style: StrokeStyle,
@ -55,7 +55,7 @@ impl<T> Line<T> {
/// Set the x of the Line. /// Set the x of the Line.
pub fn x<F>(mut self, x: F) -> Self pub fn x<F>(mut self, x: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.x = Box::new(x); self.x = Box::new(x);
self self
@ -64,7 +64,7 @@ impl<T> Line<T> {
/// Set the y of the Line. /// Set the y of the Line.
pub fn y<F>(mut self, y: F) -> Self pub fn y<F>(mut self, y: F) -> Self
where where
F: Fn(&T) -> Option<f64> + 'static, F: Fn(&T) -> Option<f32> + 'static,
{ {
self.y = Box::new(y); self.y = Box::new(y);
self self
@ -135,15 +135,11 @@ impl<T> Line<T> {
let y_tick = (self.y)(v); let y_tick = (self.y)(v);
if let (Some(x), Some(y)) = (x_tick, y_tick) { if let (Some(x), Some(y)) = (x_tick, y_tick) {
let pos = origin_point(px(x as f32), px(y as f32), origin); let pos = origin_point(px(x), px(y), origin);
if self.dot { if self.dot {
let dot_radius = self.dot_size.to_f64() / 2.; let dot_radius = self.dot_size.0 / 2.;
let dot_pos = origin_point( let dot_pos = origin_point(px(x - dot_radius), px(y - dot_radius), origin);
px((x - dot_radius) as f32),
px((y - dot_radius) as f32),
origin,
);
paint_dots.push(self.paint_dot(dot_pos)); paint_dots.push(self.paint_dot(dot_pos));
} }

View file

@ -1,15 +1,15 @@
// @reference: https://d3js.org/d3-shape/pie // @reference: https://d3js.org/d3-shape/pie
use std::f64::consts::TAU; use std::f32::consts::TAU;
use super::arc::ArcData; use super::arc::ArcData;
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
pub struct Pie<T> { pub struct Pie<T> {
value: Box<dyn Fn(&T) -> Option<f64>>, value: Box<dyn Fn(&T) -> Option<f32>>,
start_angle: f64, start_angle: f32,
end_angle: f64, end_angle: f32,
pad_angle: f64, pad_angle: f32,
} }
impl<T> Default for Pie<T> { impl<T> Default for Pie<T> {
@ -31,26 +31,26 @@ impl<T> Pie<T> {
/// Set the value of the Pie. /// Set the value of the Pie.
pub fn value<F>(mut self, value: F) -> Self pub fn value<F>(mut self, value: F) -> Self
where where
F: 'static + Fn(&T) -> Option<f64>, F: 'static + Fn(&T) -> Option<f32>,
{ {
self.value = Box::new(value); self.value = Box::new(value);
self self
} }
/// Set the start angle of the Pie. /// Set the start angle of the Pie.
pub fn start_angle(mut self, start_angle: f64) -> Self { pub fn start_angle(mut self, start_angle: f32) -> Self {
self.start_angle = start_angle; self.start_angle = start_angle;
self self
} }
/// Set the end angle of the Pie. /// Set the end angle of the Pie.
pub fn end_angle(mut self, end_angle: f64) -> Self { pub fn end_angle(mut self, end_angle: f32) -> Self {
self.end_angle = end_angle; self.end_angle = end_angle;
self self
} }
/// Set the pad angle of the Pie. /// Set the pad angle of the Pie.
pub fn pad_angle(mut self, pad_angle: f64) -> Self { pub fn pad_angle(mut self, pad_angle: f32) -> Self {
self.pad_angle = pad_angle; self.pad_angle = pad_angle;
self self
} }

View file

@ -19,8 +19,8 @@ impl CrossLine {
} }
} }
pub fn height(mut self, height: f64) -> Self { pub fn height(mut self, height: f32) -> Self {
self.height = Some(height as f32); self.height = Some(height);
self self
} }
} }