topola/src/geometry/shape.rs

54 lines
1.4 KiB
Rust

// SPDX-FileCopyrightText: 2024 Topola contributors
//
// SPDX-License-Identifier: MIT
use enum_dispatch::enum_dispatch;
use geo::{Point, Polygon};
use rstar::AABB;
use crate::geometry::primitive::{BendShape, DotShape, PrimitiveShape, SegShape};
#[enum_dispatch]
pub trait MeasureLength {
fn length(&self) -> f64;
}
#[enum_dispatch]
pub trait AccessShape: MeasureLength {
fn center(&self) -> Point;
fn contains_point(&self, p: Point) -> bool;
fn bbox_without_margin(&self) -> AABB<[f64; 2]>;
fn bbox(&self, margin: f64) -> AABB<[f64; 2]> {
let aabb = self.bbox_without_margin();
AABB::<[f64; 2]>::from_corners(
[aabb.lower()[0] - margin, aabb.lower()[1] - margin],
[aabb.upper()[0] + margin, aabb.upper()[1] + margin],
)
}
fn intersects_with_bbox(&self, bbox: &AABB<[f64; 2]>) -> bool {
use rstar::Envelope;
bbox.intersection_area(&self.bbox_without_margin()) > 0.0
}
}
#[enum_dispatch(MeasureLength, AccessShape)]
#[derive(Debug, Clone, PartialEq)]
pub enum Shape {
Dot(DotShape),
Seg(SegShape),
Bend(BendShape),
Poly(Polygon),
}
impl From<PrimitiveShape> for Shape {
fn from(primitive: PrimitiveShape) -> Self {
match primitive {
PrimitiveShape::Dot(dot) => Shape::Dot(dot),
PrimitiveShape::Seg(seg) => Shape::Seg(seg),
PrimitiveShape::Bend(bend) => Shape::Bend(bend),
}
}
}