Change `Shape` from struct to enum

It's more readable to use a match rather than an odd if condition.
This commit is contained in:
Mikolaj Wielgus 2023-08-08 02:28:41 +02:00
parent 9bfd035ed7
commit 14c3acb633
4 changed files with 93 additions and 74 deletions

View File

@ -286,7 +286,7 @@ impl Layout {
let mut layer = bend; let mut layer = bend;
while let Some(inner) = self.mesh.primitive(layer).inner() { while let Some(inner) = self.mesh.primitive(layer).inner() {
r += 5.0 + self.mesh.primitive(inner).shape().width; r += 5.0 + self.mesh.primitive(inner).shape().width();
layer = inner; layer = inner;
} }

View File

@ -18,6 +18,7 @@ mod math;
use std::panic; use std::panic;
use std::time::Duration; use std::time::Duration;
use geo::EuclideanDistance;
use graph::{TaggedIndex, Tag}; use graph::{TaggedIndex, Tag};
use sdl2::EventPump; use sdl2::EventPump;
use sdl2::pixels::Color; use sdl2::pixels::Color;
@ -26,6 +27,7 @@ use sdl2::keyboard::Keycode;
use sdl2::gfx::primitives::DrawRenderer; use sdl2::gfx::primitives::DrawRenderer;
use sdl2::render::Canvas; use sdl2::render::Canvas;
use sdl2::video::Window; use sdl2::video::Window;
use shape::Shape;
use crate::layout::Layout; use crate::layout::Layout;
use crate::graph::DotWeight; use crate::graph::DotWeight;
@ -205,44 +207,49 @@ fn render_times(event_pump: &mut EventPump, canvas: &mut Canvas<Window>, layout:
let result = panic::catch_unwind(|| { let result = panic::catch_unwind(|| {
for shape in layout.shapes() { for shape in layout.shapes() {
if let Some(center) = shape.center { match shape {
let circle = shape.circle().unwrap(); Shape::Dot(dot) => {
let delta1 = shape.from - circle.pos; let _ = canvas.filled_circle(dot.c.pos.x() as i16,
let delta2 = shape.to - circle.pos; dot.c.pos.y() as i16,
dot.c.r as i16,
Color::RGB(200, 52, 52));
},
Shape::Seg(seg) => {
let _ = canvas.thick_line(seg.from.x() as i16,
seg.from.y() as i16,
seg.to.x() as i16,
seg.to.y() as i16,
seg.width as u8,
Color::RGB(200, 52, 52));
},
Shape::Bend(bend) => {
let delta1 = bend.from - bend.center;
let delta2 = bend.to - bend.center;
let r = bend.from.euclidean_distance(&bend.center);
let mut angle1 = delta1.y().atan2(delta1.x()); let mut angle1 = delta1.y().atan2(delta1.x());
let mut angle2 = delta2.y().atan2(delta2.x()); let mut angle2 = delta2.y().atan2(delta2.x());
for d in -2..3 { for d in -2..3 {
let _ = canvas.arc( let _ = canvas.arc(
//around_circle.pos.x() as i16, //around_circle.pos.x() as i16,
//around_circle.pos.y() as i16, //around_circle.pos.y() as i16,
circle.pos.x() as i16, bend.center.x() as i16,
circle.pos.y() as i16, bend.center.y() as i16,
//(shape.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16, //(shape.around_weight.unwrap().circle.r + 10.0 + (d as f64)) as i16,
(circle.r + (d as f64)) as i16, (r + (d as f64)) as i16,
angle1.to_degrees() as i16, angle1.to_degrees() as i16,
angle2.to_degrees() as i16, angle2.to_degrees() as i16,
Color::RGB(200, 52, 52)); Color::RGB(200, 52, 52));
} }
} else if shape.from != shape.to { },
let _ = canvas.thick_line(shape.from.x() as i16,
shape.from.y() as i16,
shape.to.x() as i16,
shape.to.y() as i16,
shape.width as u8,
Color::RGB(200, 52, 52));
} else {
let _ = canvas.filled_circle(shape.from.x() as i16,
shape.from.y() as i16,
(shape.width / 2.0) as i16,
Color::RGB(200, 52, 52));
} }
/*let envelope = shape.envelope(); /*let envelope = shape.envelope();
let _ = canvas.rectangle(envelope.lower()[0] as i16, let _ = canvas.rectangle(envelope.lower()[0] as i16,
envelope.lower()[1] as i16, envelope.lower()[1] as i16,
envelope.upper()[0] as i16, envelope.upper()[0] as i16,
envelope.upper()[1] as i16, envelope.upper()[1] as i16,
Color::RGB(100, 100, 100));*/ Color::RGB(100, 100, 100));*/
} }
}); });

View File

@ -5,7 +5,7 @@ use petgraph::stable_graph::StableDiGraph;
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label}; use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
use crate::math; use crate::math;
use crate::shape::Shape; use crate::shape::{Shape, DotShape, SegShape, BendShape};
#[derive(Debug)] #[derive(Debug)]
pub struct Primitive<'a, Weight> { pub struct Primitive<'a, Weight> {
@ -20,35 +20,31 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn shape(&self) -> Shape { pub fn shape(&self) -> Shape {
match self.tagged_weight() { match self.tagged_weight() {
TaggedWeight::Dot(dot) => Shape { TaggedWeight::Dot(dot) => Shape::Dot(DotShape {
width: dot.circle.r * 2.0, c: dot.circle,
from: dot.circle.pos, }),
to: dot.circle.pos,
center: None,
},
TaggedWeight::Seg(seg) => { TaggedWeight::Seg(seg) => {
let ends = self.ends(); let ends = self.ends();
Shape { Shape::Seg(SegShape {
width: seg.width,
from: self.primitive(ends[0]).weight().circle.pos, from: self.primitive(ends[0]).weight().circle.pos,
to: self.primitive(ends[1]).weight().circle.pos, to: self.primitive(ends[1]).weight().circle.pos,
center: None, width: seg.width,
} })
} },
TaggedWeight::Bend(bend) => { TaggedWeight::Bend(bend) => {
let ends = self.ends(); let ends = self.ends();
let mut shape = Shape { let mut bend_shape = BendShape {
width: self.primitive(ends[0]).weight().circle.r * 2.0,
from: self.primitive(ends[0]).weight().circle.pos, from: self.primitive(ends[0]).weight().circle.pos,
to: self.primitive(ends[1]).weight().circle.pos, to: self.primitive(ends[1]).weight().circle.pos,
center: Some(self.primitive(self.core().unwrap()).weight().circle.pos), center: self.primitive(self.core().unwrap()).weight().circle.pos,
width: self.primitive(ends[0]).weight().circle.r * 2.0,
}; };
if bend.cw { if bend.cw {
swap(&mut shape.from, &mut shape.to); swap(&mut bend_shape.from, &mut bend_shape.to);
} }
shape Shape::Bend(bend_shape)
} },
} }
} }

View File

@ -5,40 +5,56 @@ use crate::graph::{TaggedWeight, DotWeight};
use crate::math::Circle; use crate::math::Circle;
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub struct Shape { pub struct DotShape {
pub width: f64, pub c: Circle,
}
#[derive(Debug, PartialEq)]
pub struct SegShape {
pub from: Point, pub from: Point,
pub to: Point, pub to: Point,
pub center: Option<Point>, pub width: f64,
}
#[derive(Debug, PartialEq)]
pub struct BendShape {
pub from: Point,
pub to: Point,
pub center: Point,
pub width: f64,
}
#[derive(Debug, PartialEq)]
pub enum Shape {
Dot(DotShape),
Seg(SegShape),
Bend(BendShape),
} }
impl Shape { impl Shape {
pub fn new(width: f64, from: Point, to: Point, center: Option<Point>) -> Self {
Shape {width, from, to, center}
}
pub fn envelope(&self) -> AABB<[f64; 2]> { pub fn envelope(&self) -> AABB<[f64; 2]> {
if self.from == self.to { match self {
AABB::from_corners( Shape::Dot(dot) =>
[self.from.x() - self.width, self.from.y() - self.width], AABB::from_corners(
[self.from.x() + self.width, self.from.y() + self.width] [dot.c.pos.x() - dot.c.r, dot.c.pos.y() - dot.c.r],
) [dot.c.pos.x() + dot.c.r, dot.c.pos.y() + dot.c.r],
} else { ),
// TODO: Take widths into account. Shape::Seg(seg) =>
AABB::<[f64; 2]>::from_points(&[[self.from.x(), self.from.y()], AABB::<[f64; 2]>::from_points(&[[seg.from.x(), seg.from.y()],
[self.to.x(), self.to.y()]]) [seg.to.x(), seg.to.y()]]),
Shape::Bend(bend) =>
AABB::<[f64; 2]>::from_points(&[[bend.from.x() - bend.width,
bend.from.y() - bend.width],
[bend.to.x() + bend.width,
bend.to.y() + bend.width]]),
} }
} }
pub fn circle(&self) -> Option<Circle> { pub fn width(&self) -> f64 {
if let Some(center) = self.center { match self {
let r = self.from.euclidean_distance(&center); Shape::Dot(dot) => dot.c.r * 2.0,
Some(Circle { Shape::Seg(seg) => seg.width,
pos: center, Shape::Bend(bend) => bend.width,
r,
})
} else {
None
} }
} }
} }