use crate::svg;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Marker {
CircleOpen,
CircleFilled,
SquareOpen,
SquareFilled,
TriangleOpen,
TriangleFilled,
DiamondOpen,
DiamondFilled,
Cross,
Plus,
Asterisk,
Dot,
}
impl Marker {
pub const CYCLE: [Marker; 12] = [
Marker::CircleOpen,
Marker::SquareOpen,
Marker::TriangleOpen,
Marker::DiamondOpen,
Marker::Cross,
Marker::Plus,
Marker::CircleFilled,
Marker::SquareFilled,
Marker::TriangleFilled,
Marker::DiamondFilled,
Marker::Asterisk,
Marker::Dot,
];
pub fn cycle(index: usize) -> Marker {
Self::CYCLE[index % Self::CYCLE.len()]
}
}
pub fn draw(buf: &mut String, marker: Marker, cx: f64, cy: f64, size: f64, stroke_width: f64) {
match marker {
Marker::CircleOpen => {
let attrs = format!(
" fill=\"none\" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::circle(buf, cx, cy, size, &attrs);
}
Marker::CircleFilled => {
svg::circle(buf, cx, cy, size, " fill=\"black\"");
}
Marker::SquareOpen => {
let attrs = format!(
" fill=\"none\" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::rect(buf, cx - size, cy - size, 2.0 * size, 2.0 * size, &attrs);
}
Marker::SquareFilled => {
svg::rect(
buf,
cx - size,
cy - size,
2.0 * size,
2.0 * size,
" fill=\"black\"",
);
}
Marker::TriangleOpen => {
let pts = triangle_points(cx, cy, size);
let attrs = format!(
" fill=\"none\" stroke=\"black\" stroke-width=\"{}\" stroke-linejoin=\"miter\"",
svg::num(stroke_width)
);
svg::polygon(buf, &pts, &attrs);
}
Marker::TriangleFilled => {
let pts = triangle_points(cx, cy, size);
svg::polygon(buf, &pts, " fill=\"black\"");
}
Marker::DiamondOpen => {
let pts = diamond_points(cx, cy, size);
let attrs = format!(
" fill=\"none\" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::polygon(buf, &pts, &attrs);
}
Marker::DiamondFilled => {
let pts = diamond_points(cx, cy, size);
svg::polygon(buf, &pts, " fill=\"black\"");
}
Marker::Cross => {
let attrs = format!(
" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::line(buf, cx - size, cy - size, cx + size, cy + size, &attrs);
svg::line(buf, cx - size, cy + size, cx + size, cy - size, &attrs);
}
Marker::Plus => {
let attrs = format!(
" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::line(buf, cx - size, cy, cx + size, cy, &attrs);
svg::line(buf, cx, cy - size, cx, cy + size, &attrs);
}
Marker::Asterisk => {
let attrs = format!(
" stroke=\"black\" stroke-width=\"{}\"",
svg::num(stroke_width)
);
svg::line(buf, cx - size, cy, cx + size, cy, &attrs);
svg::line(
buf,
cx - size * 0.5,
cy - size * 0.866,
cx + size * 0.5,
cy + size * 0.866,
&attrs,
);
svg::line(
buf,
cx - size * 0.5,
cy + size * 0.866,
cx + size * 0.5,
cy - size * 0.866,
&attrs,
);
}
Marker::Dot => {
svg::circle(buf, cx, cy, 0.8, " fill=\"black\"");
}
}
}
fn triangle_points(cx: f64, cy: f64, s: f64) -> [(f64, f64); 3] {
[
(cx, cy - s),
(cx + s * 0.866, cy + s * 0.5),
(cx - s * 0.866, cy + s * 0.5),
]
}
fn diamond_points(cx: f64, cy: f64, s: f64) -> [(f64, f64); 4] {
[(cx, cy - s), (cx + s, cy), (cx, cy + s), (cx - s, cy)]
}