///|
/// A collection of marker paths with per-point styles.
///
/// This is the data model used by the collection form of scatter. Colors are
/// CSS-compatible strings and sizes are marker areas; a size of `s` is
/// rendered with radius `sqrt(s)` in SVG display units.
pub struct PathCollection {
points : Array[@core.Point]
styles : Array[@core.Style]
}
///|
fn[T] collection_values(
values : Array[T],
count : Int32,
default : T,
) -> Array[T] {
if count == 0 {
[]
} else if values.length() == 0 {
let result = Array(capacity=count)
for _ in 0.. PathCollection raise @core.DataError {
let count = points.length()
if count != 0 &&
colors.length() != 0 &&
colors.length() != 1 &&
colors.length() != count {
raise @core.DataError::LengthMismatch(
expected=count,
actual=colors.length(),
)
}
if count != 0 &&
sizes.length() != 0 &&
sizes.length() != 1 &&
sizes.length() != count {
raise @core.DataError::LengthMismatch(expected=count, actual=sizes.length())
}
for size in sizes {
if size.is_nan() || size.is_inf() || size < 0.0 {
raise @core.DataError::InvalidCollection(
message="marker sizes must be finite and non-negative",
)
}
}
let resolved_colors = collection_values(colors, count, "#ff7f0e")
let resolved_sizes = collection_values(sizes, count, 12.25)
let styles = Array(capacity=count)
for i in 0.. Array[@core.Point] {
self.points.copy()
}
///|
/// Return a copy of the per-point styles.
pub fn PathCollection::styles(self : PathCollection) -> Array[@core.Style] {
self.styles.copy()
}
///|
/// Return the number of markers in this collection.
pub fn PathCollection::length(self : PathCollection) -> Int32 {
self.points.length()
}
///|
/// Copy a collection for the owning figure's value semantics.
fn copy_path_collection(collection : PathCollection) -> PathCollection {
{ points: collection.points.copy(), styles: collection.styles.copy(), }
}
///|
/// Add a per-point marker collection to the default axes.
pub fn Figure::scatter_collection(
self : Figure,
points : Array[@core.Point],
colors~ : Array[String] = [],
sizes~ : Array[Double] = [],
label~ : String = "",
) -> PathCollection raise @core.DataError {
self.axes().scatter_collection(points, colors~, sizes~, label~)
}
///|
/// Add a per-point marker collection to this axes.
pub fn Axes::scatter_collection(
self : Axes,
points : Array[@core.Point],
colors~ : Array[String] = [],
sizes~ : Array[Double] = [],
label~ : String = "",
) -> PathCollection raise @core.DataError {
let collection = path_collection(points, colors~, sizes~)
self.push_artist(Artist::PathCollection(collection))
let legend_color = if colors.length() == 0 { "#ff7f0e" } else { colors[0] }
self.add_auto_legend(label, legend_color, LegendKind::Marker)
collection
}