From 3c03b2dfa15ab4a5351ac5bacea34c202dcdf8c7 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Tue, 2 Jul 2024 23:33:29 +0200 Subject: [PATCH] geometry: create `MeasureLength` trait to measure lengths --- src/geometry/poly.rs | 16 ++++++++++-- src/geometry/primitive.rs | 55 +++++++++++++++++++++------------------ src/geometry/shape.rs | 9 +++++-- src/layout/layout.rs | 5 +++- src/router/router.rs | 5 +++- 5 files changed, 59 insertions(+), 31 deletions(-) diff --git a/src/geometry/poly.rs b/src/geometry/poly.rs index e71c0fc..98caaf0 100644 --- a/src/geometry/poly.rs +++ b/src/geometry/poly.rs @@ -1,12 +1,24 @@ -use geo::{Centroid, Contains, Point, Polygon}; +use geo::{Centroid, Contains, EuclideanLength, Point, Polygon}; -use crate::geometry::shape::ShapeTrait; +use crate::geometry::shape::{MeasureLength, ShapeTrait}; #[derive(Debug, Clone, PartialEq)] pub struct PolyShape { pub polygon: Polygon, } +impl MeasureLength for PolyShape { + fn length(&self) -> f64 { + let mut length = 0.0; + + for line in self.polygon.exterior().lines() { + length += line.euclidean_length(); + } + + length + } +} + impl ShapeTrait for PolyShape { fn center(&self) -> Point { self.polygon.centroid().unwrap() diff --git a/src/geometry/primitive.rs b/src/geometry/primitive.rs index 47cd991..fc402ff 100644 --- a/src/geometry/primitive.rs +++ b/src/geometry/primitive.rs @@ -3,7 +3,7 @@ use geo::{point, polygon, Contains, EuclideanDistance, Intersects, Point, Polygo use rstar::{RTreeObject, AABB}; use crate::{ - geometry::shape::ShapeTrait, + geometry::shape::{MeasureLength, ShapeTrait}, math::{self, Circle}, }; @@ -14,7 +14,6 @@ pub trait PrimitiveShapeTrait: ShapeTrait { fn intersects(&self, other: &PrimitiveShape) -> bool; fn envelope(&self, margin: f64) -> AABB<[f64; 2]>; fn width(&self) -> f64; - fn length(&self) -> f64; fn envelope_3d(&self, margin: f64, layer: usize) -> AABB<[f64; 3]> { let envelope = self.envelope(margin); @@ -37,7 +36,7 @@ pub trait PrimitiveShapeTrait: ShapeTrait { } } -#[enum_dispatch(ShapeTrait, PrimitiveShapeTrait)] +#[enum_dispatch(MeasureLength, ShapeTrait, PrimitiveShapeTrait)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum PrimitiveShape { // Intentionally in different order to reorder `self.intersects(...)` properly. @@ -51,6 +50,12 @@ pub struct DotShape { pub circle: Circle, } +impl MeasureLength for DotShape { + fn length(&self) -> f64 { + 0.0 + } +} + impl ShapeTrait for DotShape { fn center(&self) -> Point { self.circle.pos @@ -122,10 +127,6 @@ impl PrimitiveShapeTrait for DotShape { fn width(&self) -> f64 { self.circle.r * 2.0 } - - fn length(&self) -> f64 { - 0.0 - } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -152,6 +153,12 @@ impl SegShape { } } +impl MeasureLength for SegShape { + fn length(&self) -> f64 { + self.to.euclidean_distance(&self.from) + } +} + impl ShapeTrait for SegShape { fn center(&self) -> Point { (self.from + self.to) / 2.0 @@ -225,10 +232,6 @@ impl PrimitiveShapeTrait for SegShape { fn width(&self) -> f64 { self.width } - - fn length(&self) -> f64 { - self.to.euclidean_distance(&self.from) - } } #[derive(Debug, Clone, Copy, PartialEq)] @@ -267,6 +270,22 @@ impl BendShape { } } +impl MeasureLength for BendShape { + fn length(&self) -> f64 { + // TODO: Not valid for inflated bends, as currently `from` and `to` of these don't lie on + // teir circles. + + // We obtain the angle from the law of cosines and multiply with radius to get the length. + let d = self.to.euclidean_distance(&self.from); + + if d > 0.0 { + (1.0 - d * d / (2.0 * d * d)).acos() + } else { + 0.0 + } + } +} + impl ShapeTrait for BendShape { fn center(&self) -> Point { let sum = (self.from - self.inner_circle.pos) + (self.to - self.inner_circle.pos); @@ -351,20 +370,6 @@ impl PrimitiveShapeTrait for BendShape { fn width(&self) -> f64 { self.width } - - fn length(&self) -> f64 { - // TODO: Not valid for inflated bends, as currently `from` and `to` of these don't lie on - // teir circles. - - // We obtain the angle from the law of cosines and multiply with radius to get the length. - let d = self.to.euclidean_distance(&self.from); - - if d > 0.0 { - (1.0 - d * d / (2.0 * d * d)).acos() - } else { - 0.0 - } - } } impl RTreeObject for PrimitiveShape { diff --git a/src/geometry/shape.rs b/src/geometry/shape.rs index b09311a..79faf39 100644 --- a/src/geometry/shape.rs +++ b/src/geometry/shape.rs @@ -7,12 +7,17 @@ use crate::geometry::{ }; #[enum_dispatch] -pub trait ShapeTrait { +pub trait MeasureLength { + fn length(&self) -> f64; +} + +#[enum_dispatch] +pub trait ShapeTrait: MeasureLength { fn center(&self) -> Point; fn contains_point(&self, p: Point) -> bool; } -#[enum_dispatch(ShapeTrait)] +#[enum_dispatch(MeasureLength, ShapeTrait)] #[derive(Debug, Clone, PartialEq)] pub enum Shape { Dot(DotShape), diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 15ca6a3..3f2efba 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -19,7 +19,10 @@ use crate::{ wraparoundable::WraparoundableIndex, Drawing, Infringement, LayoutException, }, - geometry::{compound::CompoundManagerTrait, primitive::PrimitiveShapeTrait, GenericNode}, + geometry::{ + compound::CompoundManagerTrait, primitive::PrimitiveShapeTrait, shape::MeasureLength, + GenericNode, + }, graph::{GenericIndex, GetPetgraphIndex}, layout::{ via::{Via, ViaWeight}, diff --git a/src/router/router.rs b/src/router/router.rs index 42fda8a..28c90d5 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -11,7 +11,10 @@ use crate::{ primitive::MakePrimitiveShape, rules::RulesTrait, }, - geometry::{primitive::PrimitiveShapeTrait, shape::ShapeTrait}, + geometry::{ + primitive::PrimitiveShapeTrait, + shape::{MeasureLength, ShapeTrait}, + }, graph::GetPetgraphIndex, layout::Layout, router::{