1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
use serde::{Deserialize, Serialize};
/// An abstract chart with information about what to render and where to render
/// it.
///
/// All coordinates in an abstract chart are normalized to run from 0.0 to 1.0,
/// so (0, 0) is the origin of the chart (typically rendered bottom left), while
/// (1, 0) is the end of the X axis and (0, 1) is the end of the Y axis.
///
/// The generic argument `S` refers to the type of the series from which shapes
/// will be generated, while the type `P` refers to the type for individual data
/// points. When generating charts from timeseries data, these will be
/// [Timeseries](crate::fiberplane::Timeseries) and
/// [Metric](crate::fiberplane::Metric), respectively.
#[derive(Default, Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct MondrianChart<S, P> {
pub x_axis: Axis,
pub y_axis: Axis,
pub shape_lists: Vec<ShapeList<S, P>>,
}
/// Defines the range of values that are displayed along a given axis.
#[derive(Debug, Default, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Axis {
/// The value to display at the chart origin.
pub min_value: f64,
/// The value to display at the end of the axis.
pub max_value: f64,
/// Optional suggestion of where to draw ticks based on the detected bucket
/// intervals.
///
/// Ticks are expressed as values between `minValue` and `maxValue`.
pub tick_suggestions: Option<Vec<f64>>,
}
impl Axis {
/// Extends the range of the axis with the given interval.
///
/// The range of the interval is divided among ends of the axis. This can be
/// used to extend the axis with enough space to display the bars for the
/// first and last buckets displayed on a bar chart.
#[must_use]
pub fn extend_with_interval(mut self, interval: f64) -> Self {
let half_interval = 0.5 * interval;
self.min_value -= half_interval;
self.max_value += half_interval;
self
}
/// Extends the range of the axis with the given value.
///
/// If the given value is outside the range of the axis, the range is
/// extended to include the value. Otherwise, nothing happens.
#[must_use]
pub fn extend_with_value(mut self, value: f64) -> Self {
if value < self.min_value {
self.min_value = value;
} else if value > self.max_value {
self.max_value = value;
}
self
}
}
/// List of shapes that belongs together.
///
/// These are usually rendered in the same color and would correspond to a
/// single legend item, conceptually.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ShapeList<S, P> {
/// All the shapes to represent data points within the series.
///
/// This list may be empty if no relevant data points were found in the
/// series data.
pub shapes: Vec<Shape<P>>,
/// The original source this shape list was generated from.
///
/// This would be the type of series data the chart was generated from, such
/// as [Timeseries](crate::fiberplane::Timeseries).
pub source: S,
}
/// An abstract shape used to visualize data points.
#[derive(Deserialize, Serialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum Shape<P> {
Area(Area<P>),
Line(Line<P>),
Point(Point<P>),
Rectangle(Rectangle<P>),
}
/// An area to be drawn between two lines that share their X coordinates.
///
/// Area points move from left to right.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Area<P> {
pub points: Vec<AreaPoint<P>>,
// Optional boolean that allows for overriding the area_gradient_shown property on the ShapeOptions per individual Line
pub area_gradient_shown: Option<bool>,
}
/// A single data point in an area shape.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct AreaPoint<P> {
/// X coordinate between 0.0 and 1.0.
pub x: f64,
/// Y coordinate between 0.0 and 1.0 for the bottom of the area.
pub y_min: f64,
/// Y coordinate between 0.0 and 1.0 for the top of the area.
pub y_max: f64,
/// The source this point was generated from.
///
/// This would be a [Metric](crate::fiberplane::Metric) if the chart was
/// generated from [Timeseries](crate::fiberplane::Timeseries).
pub source: P,
}
/// A line to be drawn between two or more points.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Line<P> {
pub points: Vec<Point<P>>,
// Optional boolean that allows for overriding the area_gradient_shown property on the ShapeOptions per individual Line
pub area_gradient_shown: Option<bool>,
}
/// A single point in the chart.
///
/// Points can be rendered independently as a dot, or can be used to draw lines
/// between them.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Point<P> {
/// X coordinate of the point's center, between 0.0 and 1.0.
pub x: f64,
/// Y coordinate of the point's center, between 0.0 and 1.0.
pub y: f64,
/// The source this point was generated from.
///
/// This would be a [Metric](crate::fiberplane::Metric) if the chart was
/// generated from [Timeseries](crate::fiberplane::Timeseries).
pub source: P,
}
/// A rectangle to be rendered inside the chart.
#[derive(Deserialize, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Rectangle<P> {
/// X coordinate of the bottom left corner, between 0.0 and 1.0.
pub x: f64,
/// Y coordinate of the bottom left corner, between 0.0 and 1.0.
pub y: f64,
/// Width of the rectangle, between 0.0 and 1.0.
pub width: f64,
/// Width of the rectangle, between 0.0 and 1.0.
pub height: f64,
/// The source this rectangle was generated from.
///
/// This would be a [Metric](crate::fiberplane::Metric) if the chart was
/// generated from [Timeseries](crate::fiberplane::Timeseries).
pub source: P,
}