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)]
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()

View File

@ -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 {

View File

@ -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),

View File

@ -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},

View File

@ -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::{