geometry: create `MeasureLength` trait to measure lengths

This commit is contained in:
Mikolaj Wielgus 2024-07-02 23:33:29 +02:00
parent 27d1c9e712
commit 3c03b2dfa1
5 changed files with 59 additions and 31 deletions

View File

@ -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)] #[derive(Debug, Clone, PartialEq)]
pub struct PolyShape { pub struct PolyShape {
pub polygon: Polygon, 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 { impl ShapeTrait for PolyShape {
fn center(&self) -> Point { fn center(&self) -> Point {
self.polygon.centroid().unwrap() self.polygon.centroid().unwrap()

View File

@ -3,7 +3,7 @@ use geo::{point, polygon, Contains, EuclideanDistance, Intersects, Point, Polygo
use rstar::{RTreeObject, AABB}; use rstar::{RTreeObject, AABB};
use crate::{ use crate::{
geometry::shape::ShapeTrait, geometry::shape::{MeasureLength, ShapeTrait},
math::{self, Circle}, math::{self, Circle},
}; };
@ -14,7 +14,6 @@ pub trait PrimitiveShapeTrait: ShapeTrait {
fn intersects(&self, other: &PrimitiveShape) -> bool; fn intersects(&self, other: &PrimitiveShape) -> bool;
fn envelope(&self, margin: f64) -> AABB<[f64; 2]>; fn envelope(&self, margin: f64) -> AABB<[f64; 2]>;
fn width(&self) -> f64; fn width(&self) -> f64;
fn length(&self) -> f64;
fn envelope_3d(&self, margin: f64, layer: usize) -> AABB<[f64; 3]> { fn envelope_3d(&self, margin: f64, layer: usize) -> AABB<[f64; 3]> {
let envelope = self.envelope(margin); 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)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum PrimitiveShape { pub enum PrimitiveShape {
// Intentionally in different order to reorder `self.intersects(...)` properly. // Intentionally in different order to reorder `self.intersects(...)` properly.
@ -51,6 +50,12 @@ pub struct DotShape {
pub circle: Circle, pub circle: Circle,
} }
impl MeasureLength for DotShape {
fn length(&self) -> f64 {
0.0
}
}
impl ShapeTrait for DotShape { impl ShapeTrait for DotShape {
fn center(&self) -> Point { fn center(&self) -> Point {
self.circle.pos self.circle.pos
@ -122,10 +127,6 @@ impl PrimitiveShapeTrait for DotShape {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.circle.r * 2.0 self.circle.r * 2.0
} }
fn length(&self) -> f64 {
0.0
}
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[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 { impl ShapeTrait for SegShape {
fn center(&self) -> Point { fn center(&self) -> Point {
(self.from + self.to) / 2.0 (self.from + self.to) / 2.0
@ -225,10 +232,6 @@ impl PrimitiveShapeTrait for SegShape {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.width self.width
} }
fn length(&self) -> f64 {
self.to.euclidean_distance(&self.from)
}
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[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 { impl ShapeTrait for BendShape {
fn center(&self) -> Point { fn center(&self) -> Point {
let sum = (self.from - self.inner_circle.pos) + (self.to - self.inner_circle.pos); 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 { fn width(&self) -> f64 {
self.width 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 { impl RTreeObject for PrimitiveShape {

View File

@ -7,12 +7,17 @@ use crate::geometry::{
}; };
#[enum_dispatch] #[enum_dispatch]
pub trait ShapeTrait { pub trait MeasureLength {
fn length(&self) -> f64;
}
#[enum_dispatch]
pub trait ShapeTrait: MeasureLength {
fn center(&self) -> Point; fn center(&self) -> Point;
fn contains_point(&self, p: Point) -> bool; fn contains_point(&self, p: Point) -> bool;
} }
#[enum_dispatch(ShapeTrait)] #[enum_dispatch(MeasureLength, ShapeTrait)]
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum Shape { pub enum Shape {
Dot(DotShape), Dot(DotShape),

View File

@ -19,7 +19,10 @@ use crate::{
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
Drawing, Infringement, LayoutException, Drawing, Infringement, LayoutException,
}, },
geometry::{compound::CompoundManagerTrait, primitive::PrimitiveShapeTrait, GenericNode}, geometry::{
compound::CompoundManagerTrait, primitive::PrimitiveShapeTrait, shape::MeasureLength,
GenericNode,
},
graph::{GenericIndex, GetPetgraphIndex}, graph::{GenericIndex, GetPetgraphIndex},
layout::{ layout::{
via::{Via, ViaWeight}, via::{Via, ViaWeight},

View File

@ -11,7 +11,10 @@ use crate::{
primitive::MakePrimitiveShape, primitive::MakePrimitiveShape,
rules::RulesTrait, rules::RulesTrait,
}, },
geometry::{primitive::PrimitiveShapeTrait, shape::ShapeTrait}, geometry::{
primitive::PrimitiveShapeTrait,
shape::{MeasureLength, ShapeTrait},
},
graph::GetPetgraphIndex, graph::GetPetgraphIndex,
layout::Layout, layout::Layout,
router::{ router::{