mirror of https://codeberg.org/topola/topola.git
126 lines
3.5 KiB
Rust
126 lines
3.5 KiB
Rust
// SPDX-FileCopyrightText: 2024 Topola contributors
|
|
//
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
use core::{cmp, hash};
|
|
use enum_dispatch::enum_dispatch;
|
|
use petgraph::stable_graph::NodeIndex;
|
|
|
|
use crate::{
|
|
geometry::shape::MeasureLength,
|
|
graph::{GetPetgraphIndex, MakeRef},
|
|
};
|
|
|
|
use super::{
|
|
graph::MakePrimitive,
|
|
loose::{GetPrevNextLoose, LooseIndex},
|
|
primitive::MakePrimitiveShape,
|
|
rules::AccessRules,
|
|
seg::{LoneLooseSegIndex, SeqLooseSegIndex},
|
|
Drawing,
|
|
};
|
|
|
|
#[derive(Clone, Copy, Debug)]
|
|
pub struct BandUid(pub BandTermsegIndex, pub BandTermsegIndex);
|
|
|
|
impl BandUid {
|
|
pub fn new(first_seg1: BandTermsegIndex, first_seg2: BandTermsegIndex) -> Self {
|
|
if first_seg1.petgraph_index() <= first_seg2.petgraph_index() {
|
|
BandUid(first_seg1, first_seg2)
|
|
} else {
|
|
BandUid(first_seg2, first_seg1)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PartialEq for BandUid {
|
|
fn eq(&self, other: &Self) -> bool {
|
|
self.0.petgraph_index() == other.0.petgraph_index()
|
|
&& self.1.petgraph_index() == other.1.petgraph_index()
|
|
}
|
|
}
|
|
|
|
impl Eq for BandUid {}
|
|
|
|
impl hash::Hash for BandUid {
|
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
|
self.0.petgraph_index().hash(state);
|
|
self.1.petgraph_index().hash(state);
|
|
}
|
|
}
|
|
|
|
impl cmp::PartialOrd for BandUid {
|
|
fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
|
|
Some(self.cmp(other))
|
|
}
|
|
}
|
|
|
|
impl cmp::Ord for BandUid {
|
|
fn cmp(&self, other: &Self) -> cmp::Ordering {
|
|
use cmp::Ordering as O;
|
|
match self.0.petgraph_index().cmp(&other.0.petgraph_index()) {
|
|
O::Less => O::Less,
|
|
O::Greater => O::Greater,
|
|
O::Equal => self.1.petgraph_index().cmp(&other.1.petgraph_index()),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[enum_dispatch(GetPetgraphIndex)]
|
|
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
|
pub enum BandTermsegIndex {
|
|
Straight(LoneLooseSegIndex),
|
|
Bended(SeqLooseSegIndex),
|
|
}
|
|
|
|
impl From<BandTermsegIndex> for LooseIndex {
|
|
fn from(terminating_seg: BandTermsegIndex) -> Self {
|
|
match terminating_seg {
|
|
BandTermsegIndex::Straight(seg) => LooseIndex::LoneSeg(seg),
|
|
BandTermsegIndex::Bended(seg) => LooseIndex::SeqSeg(seg),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, CW, R> MakeRef<'a, BandRef<'a, CW, R>, Drawing<CW, R>> for BandTermsegIndex {
|
|
fn ref_(&self, drawing: &'a Drawing<CW, R>) -> BandRef<'a, CW, R> {
|
|
BandRef::new(*self, drawing)
|
|
}
|
|
}
|
|
|
|
pub struct BandRef<'a, CW, R> {
|
|
first_seg: BandTermsegIndex,
|
|
drawing: &'a Drawing<CW, R>,
|
|
}
|
|
|
|
impl<'a, CW, R> BandRef<'a, CW, R> {
|
|
pub fn new(first_seg: BandTermsegIndex, drawing: &'a Drawing<CW, R>) -> BandRef<'a, CW, R> {
|
|
Self { first_seg, drawing }
|
|
}
|
|
}
|
|
|
|
impl<'a, CW: Copy, R: AccessRules> MeasureLength for BandRef<'a, CW, R> {
|
|
fn length(&self) -> f64 {
|
|
match self.first_seg {
|
|
BandTermsegIndex::Straight(seg) => {
|
|
self.drawing.geometry().seg_shape(seg.into()).length()
|
|
}
|
|
BandTermsegIndex::Bended(first_loose_seg) => {
|
|
let mut maybe_loose: Option<LooseIndex> = Some(first_loose_seg.into());
|
|
let mut prev = None;
|
|
let mut length = 0.0;
|
|
|
|
while let Some(loose) = maybe_loose {
|
|
length += loose.primitive(self.drawing).shape().length();
|
|
|
|
let prev_prev = prev;
|
|
prev = maybe_loose;
|
|
maybe_loose = self.drawing.loose(loose).next_loose(prev_prev);
|
|
}
|
|
|
|
length
|
|
}
|
|
}
|
|
}
|
|
}
|