use crate::graph::Arrow;
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(dead_code)]
pub(crate) struct MarkerEnvelope {
pub length: f64,
pub width: f64,
}
#[allow(dead_code)]
pub(crate) fn marker_envelope(arrow: Arrow) -> Option<MarkerEnvelope> {
match arrow {
Arrow::Normal => Some(MarkerEnvelope {
length: 8.0,
width: 8.0,
}),
Arrow::OpenTriangle => Some(MarkerEnvelope {
length: 9.0,
width: 8.0,
}),
Arrow::Diamond => Some(MarkerEnvelope {
length: 11.0,
width: 12.0,
}),
Arrow::OpenDiamond => Some(MarkerEnvelope {
length: 12.0,
width: 12.0,
}),
Arrow::Circle => Some(MarkerEnvelope {
length: 21.0,
width: 12.0,
}),
Arrow::Cross => Some(MarkerEnvelope {
length: 12.0,
width: 11.0,
}),
Arrow::None => None,
}
}
#[allow(dead_code)]
pub(crate) fn marker_avoidance_distance(arrow: Arrow) -> f64 {
marker_envelope(arrow).map(|e| e.length).unwrap_or(0.0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn marker_envelope_returns_none_for_arrow_none() {
assert_eq!(marker_envelope(Arrow::None), None);
}
#[test]
fn marker_envelope_returns_some_for_every_other_arrow() {
for arrow in [
Arrow::Normal,
Arrow::OpenTriangle,
Arrow::Diamond,
Arrow::OpenDiamond,
Arrow::Circle,
Arrow::Cross,
] {
assert!(
marker_envelope(arrow).is_some(),
"arrow {arrow:?} should have an envelope"
);
}
}
#[test]
fn marker_avoidance_distance_matches_envelope_length() {
for arrow in [
Arrow::Normal,
Arrow::OpenTriangle,
Arrow::Diamond,
Arrow::OpenDiamond,
Arrow::Circle,
Arrow::Cross,
Arrow::None,
] {
let len = marker_envelope(arrow).map(|e| e.length).unwrap_or(0.0);
assert_eq!(
marker_avoidance_distance(arrow),
len,
"arrow {arrow:?}: avoidance and envelope.length must agree"
);
}
}
#[test]
fn diamond_envelope_matches_class_relationships_svg() {
let env = marker_envelope(Arrow::Diamond).expect("diamond has envelope");
assert_eq!(env.length, 11.0);
assert_eq!(env.width, 12.0);
}
#[test]
fn arrowhead_envelope_matches_normal_path_pullback() {
let env = marker_envelope(Arrow::Normal).expect("normal arrow has envelope");
assert_eq!(env.length, 8.0);
assert_eq!(env.width, 8.0);
}
}