From 177b8cb231bfa3b8e38d8ca7bcaa383b6edafffe Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Tue, 17 Oct 2023 05:17:07 +0000 Subject: [PATCH] guide: Return Err(...) instead of panicking --- src/draw.rs | 10 +++++----- src/guide.rs | 23 ++++++++++++++--------- src/math.rs | 40 +++++++++++++++++++++------------------- 3 files changed, 40 insertions(+), 33 deletions(-) diff --git a/src/draw.rs b/src/draw.rs index 9d6cfaa..bebb524 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -76,7 +76,7 @@ impl<'a> Draw<'a> { fn finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { let tangent = self .guide(&Default::default()) - .head_into_dot_segment(&head, into, width); + .head_into_dot_segment(&head, into, width)?; let head = self.extend_head(head, tangent.start_point())?; let net = self.layout.primitive(head.dot()).weight().net; @@ -98,7 +98,7 @@ impl<'a> Draw<'a> { let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); let tangent = self .guide(&Default::default()) - .head_around_bend_segment(&head, into_bend, to_cw, width); + .head_around_bend_segment(&head, into_bend, to_cw, width)?; let head = self.extend_head(head, tangent.start_point())?; let _to_head = self.extend_head(to_head, tangent.end_point())?; @@ -119,7 +119,7 @@ impl<'a> Draw<'a> { ) -> Result { let mut tangents = self .guide(&Default::default()) - .head_around_dot_segments(&head, around, width); + .head_around_dot_segments(&head, around, width)?; let mut dirs = [true, false]; if tangents.1.euclidean_length() < tangents.0.euclidean_length() { @@ -154,7 +154,7 @@ impl<'a> Draw<'a> { ) -> Result { let mut tangents = self .guide(&Default::default()) - .head_around_bend_segments(&head, around, width); + .head_around_bend_segments(&head, around, width)?; let mut dirs = [true, false]; if tangents.1.euclidean_length() < tangents.0.euclidean_length() { @@ -206,7 +206,7 @@ impl<'a> Draw<'a> { let alternate_tangent = self .guide(&Default::default()) - .head_around_dot_segment(&prev_head, around, cw, 5.0); + .head_around_dot_segment(&prev_head, around, cw, 5.0)?; let segbend_dot_pos = self.layout.primitive(head.segbend.dot).weight().circle.pos; diff --git a/src/guide.rs b/src/guide.rs index 7200521..4fad7b8 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -23,7 +23,12 @@ impl<'a, 'b> Guide<'a, 'b> { } } - pub fn head_into_dot_segment(&self, head: &Head, into: DotIndex, width: f64) -> Line { + pub fn head_into_dot_segment( + &self, + head: &Head, + into: DotIndex, + width: f64, + ) -> Result { let from_circle = self.head_circle(head, width); let to_circle = Circle { pos: self.layout.primitive(into).weight().circle.pos, @@ -39,14 +44,14 @@ impl<'a, 'b> Guide<'a, 'b> { head: &Head, around: DotIndex, width: f64, - ) -> (Line, Line) { + ) -> Result<(Line, Line), ()> { let from_circle = self.head_circle(head, width); let to_circle = self.dot_circle(around, width); let from_cw = self.head_cw(head); let tangents: Vec = - math::tangent_segments(from_circle, from_cw, to_circle, None).collect(); - (tangents[0], tangents[1]) + math::tangent_segments(from_circle, from_cw, to_circle, None)?.collect(); + Ok((tangents[0], tangents[1])) } pub fn head_around_dot_segment( @@ -55,7 +60,7 @@ impl<'a, 'b> Guide<'a, 'b> { around: DotIndex, cw: bool, width: f64, - ) -> Line { + ) -> Result { let from_circle = self.head_circle(head, width); let to_circle = self.dot_circle(around, width); @@ -68,14 +73,14 @@ impl<'a, 'b> Guide<'a, 'b> { head: &Head, around: BendIndex, width: f64, - ) -> (Line, Line) { + ) -> Result<(Line, Line), ()> { let from_circle = self.head_circle(head, width); let to_circle = self.bend_circle(around, width); let from_cw = self.head_cw(head); let tangents: Vec = - math::tangent_segments(from_circle, from_cw, to_circle, None).collect(); - (tangents[0], tangents[1]) + math::tangent_segments(from_circle, from_cw, to_circle, None)?.collect(); + Ok((tangents[0], tangents[1])) } pub fn head_around_bend_segment( @@ -84,7 +89,7 @@ impl<'a, 'b> Guide<'a, 'b> { around: BendIndex, cw: bool, width: f64, - ) -> Line { + ) -> Result { let from_circle = self.head_circle(head, width); let to_circle = self.bend_circle(around, width); diff --git a/src/math.rs b/src/math.rs index caee5c9..07534a3 100644 --- a/src/math.rs +++ b/src/math.rs @@ -25,38 +25,38 @@ impl Sub for Circle { } } -fn _tangent(center: Point, r1: f64, r2: f64) -> CanonicalLine { +fn _tangent(center: Point, r1: f64, r2: f64) -> Result { let epsilon = 1e-9; let dr = r2 - r1; let norm = center.x() * center.x() + center.y() * center.y(); let discriminant = norm - dr * dr; if discriminant < -epsilon { - panic!(); + return Err(()); } let sqrt_discriminant = f64::sqrt(f64::abs(discriminant)); - CanonicalLine { + Ok(CanonicalLine { a: (center.x() * dr + center.y() * sqrt_discriminant) / norm, b: (center.y() * dr - center.x() * sqrt_discriminant) / norm, c: r1, - } + }) } -fn _tangents(circle1: Circle, circle2: Circle) -> [CanonicalLine; 4] { +fn _tangents(circle1: Circle, circle2: Circle) -> Result<[CanonicalLine; 4], ()> { let mut tgs: [CanonicalLine; 4] = [ - _tangent((circle2 - circle1).pos, -circle1.r, -circle2.r), - _tangent((circle2 - circle1).pos, -circle1.r, circle2.r), - _tangent((circle2 - circle1).pos, circle1.r, -circle2.r), - _tangent((circle2 - circle1).pos, circle1.r, circle2.r), + _tangent((circle2 - circle1).pos, -circle1.r, -circle2.r)?, + _tangent((circle2 - circle1).pos, -circle1.r, circle2.r)?, + _tangent((circle2 - circle1).pos, circle1.r, -circle2.r)?, + _tangent((circle2 - circle1).pos, circle1.r, circle2.r)?, ]; for tg in tgs.iter_mut() { tg.c -= tg.a * circle1.pos.x() + tg.b * circle1.pos.y(); } - return tgs; + Ok(tgs) } fn cast_point_to_canonical_line(pt: Point, line: CanonicalLine) -> Point { @@ -69,10 +69,10 @@ fn cast_point_to_canonical_line(pt: Point, line: CanonicalLine) -> Point { .into(); } -fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] { - let tgs = _tangents(circle1, circle2); +fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> Result<[(Point, Point); 4], ()> { + let tgs = _tangents(circle1, circle2)?; - [ + Ok([ ( cast_point_to_canonical_line(circle1.pos, tgs[0]), cast_point_to_canonical_line(circle2.pos, tgs[0]), @@ -89,7 +89,7 @@ fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] cast_point_to_canonical_line(circle1.pos, tgs[3]), cast_point_to_canonical_line(circle2.pos, tgs[3]), ), - ] + ]) } pub fn tangent_segments( @@ -97,8 +97,8 @@ pub fn tangent_segments( cw1: Option, circle2: Circle, cw2: Option, -) -> impl Iterator { - tangent_point_pairs(circle1, circle2) +) -> Result, ()> { + Ok(tangent_point_pairs(circle1, circle2)? .into_iter() .filter_map(move |tangent_point_pair| { if let Some(cw1) = cw1 { @@ -120,7 +120,7 @@ pub fn tangent_segments( } Some(Line::new(tangent_point_pair.0, tangent_point_pair.1)) - }) + })) } pub fn tangent_segment( @@ -128,8 +128,10 @@ pub fn tangent_segment( cw1: Option, circle2: Circle, cw2: Option, -) -> Line { - tangent_segments(circle1, cw1, circle2, cw2).next().unwrap() +) -> Result { + Ok(tangent_segments(circle1, cw1, circle2, cw2)? + .next() + .unwrap()) } pub fn intersect_circles(circle1: &Circle, circle2: &Circle) -> Vec {