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:
parent
8bf66443b2
commit
3b759cd448
18 changed files with 121 additions and 133 deletions
|
|
@ -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.)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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<_>>();
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
|
||||||
|
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue