///|
fn validate_pie(
values : Array[Double],
labels : Array[String],
colors : Array[String],
start_angle : Double,
) -> Unit raise @core.DataError {
if values.length() == 0 {
raise @core.DataError::InvalidPie(message="pie requires at least one value")
}
if labels.length() != 0 && labels.length() != values.length() {
raise @core.DataError::InvalidPie(
message="pie labels must match the number of values",
)
}
if colors.length() != 0 && colors.length() != values.length() {
raise @core.DataError::InvalidPie(
message="pie colors must match the number of values",
)
}
if start_angle.is_nan() || start_angle.is_inf() {
raise @core.DataError::InvalidPie(message="pie start_angle must be finite")
}
let mut total = 0.0
for value in values {
if value.is_nan() || value.is_inf() || value < 0.0 {
raise @core.DataError::InvalidPie(
message="pie values must be finite and non-negative",
)
}
total += value
}
if total <= 0.0 {
raise @core.DataError::InvalidPie(
message="pie values must have a positive sum",
)
}
}
///|
fn parse_pie_color(value : String) -> @colors.Rgba raise @core.DataError {
@colors.parse_color(value) catch {
@colors.ColorError::InvalidColor(_)
| @colors.ColorError::ComponentOutOfRange(_)
| @colors.ColorError::InvalidColorMap(_) =>
raise @core.DataError::InvalidPie(message="invalid pie color")
}
}
///|
fn resolve_pie_colors(
axes : Axes,
colors : Array[String],
count : Int32,
) -> Array[String] raise @core.DataError {
let result = Array(capacity=count)
for index in 0.. Array[Double] raise @core.DataError {
self.axes().pie(values, labels~, colors~, start_angle~)
}
///|
/// Draw a pie chart and return the normalized slice fractions.
pub fn Axes::pie(
self : Axes,
values : Array[Double],
labels~ : Array[String] = [],
colors~ : Array[String] = [],
start_angle~ : Double = 0.0,
) -> Array[Double] raise @core.DataError {
validate_pie(values, labels, colors, start_angle)
let resolved_colors = resolve_pie_colors(self, colors, values.length())
let mut total = 0.0
for value in values {
total += value
}
let fractions = Array(capacity=values.length())
for value in values {
fractions.push(value / total)
}
let start = self.state.val.artists.length()
self.push_artist(
Artist::Pie(values.copy(), labels.copy(), resolved_colors, start_angle),
)
self.add_container(ContainerKind::Pie, start, "")
fractions
}