use crate::{
math::{Matrix2d, Scalar},
triangulation, types,
types::{Color, Radius, Resolution},
DrawState, Graphics,
};
#[derive(Copy, Clone)]
pub enum Shape {
Square,
Round,
RoundWithResolution(Resolution),
Bevel,
}
impl Shape {
fn resolution(&self) -> u32 {
use Shape::*;
match self {
Square => 2,
Bevel => 3,
Round => 64,
RoundWithResolution(n) => *n,
}
}
}
#[derive(Copy, Clone)]
pub struct Line {
pub color: Color,
pub radius: Radius,
pub shape: Shape,
}
impl Line {
pub fn new(color: Color, radius: Radius) -> Line {
Line {
color,
radius,
shape: Shape::Square,
}
}
pub fn new_round(color: Color, radius: Radius) -> Line {
Line {
color,
radius,
shape: Shape::Round,
}
}
pub fn color(mut self, value: Color) -> Self {
self.color = value;
self
}
pub fn radius(mut self, value: Radius) -> Self {
self.radius = value;
self
}
pub fn width(mut self, value: types::Width) -> Self {
self.radius = 0.5 * value;
self
}
pub fn shape(mut self, value: Shape) -> Self {
self.shape = value;
self
}
#[inline(always)]
pub fn draw_from_to<P: Into<types::Vec2d>, G>(
&self,
from: P,
to: P,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
G: Graphics,
{
let from: types::Vec2d = from.into();
let to: types::Vec2d = to.into();
g.line(
self,
[from[0], from[1], to[0], to[1]],
draw_state,
transform,
);
}
#[inline(always)]
pub fn draw<L: Into<types::Line>, G>(
&self,
line: L,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
G: Graphics,
{
g.line(self, line, draw_state, transform);
}
pub fn draw_tri<L: Into<types::Line>, G>(
&self,
line: L,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
G: Graphics,
{
let line = line.into();
g.tri_list(draw_state, &self.color, |f| {
triangulation::with_round_border_line_tri_list(
self.shape.resolution(),
transform,
line,
self.radius,
|vertices| f(vertices),
)
});
}
pub fn draw_arrow<L: Into<types::Line>, G>(
&self,
line: L,
head_size: Scalar,
draw_state: &DrawState,
transform: Matrix2d,
g: &mut G,
) where
G: Graphics,
{
use crate::Transformed;
let line = line.into();
self.draw(line, draw_state, transform, g);
let diff = [line[2] - line[0], line[3] - line[1]];
let arrow_head = transform.trans(line[2], line[3]).orient(diff[0], diff[1]);
self.draw([-head_size, head_size, 0.0, 0.0], draw_state, arrow_head, g);
self.draw(
[-head_size, -head_size, 0.0, 0.0],
draw_state,
arrow_head,
g,
);
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_line() {
use crate::Colored;
let _line = Line::new([0.0; 4], 3.0)
.color([1.0; 4])
.radius(3.0)
.shape(Shape::Round)
.hue_deg(1.0);
}
}