mirror of https://codeberg.org/topola/topola.git
feat(layout): implement extraction of band-between-nodes information
This commit is contained in:
parent
3c3c1d9b42
commit
e7b120e8ed
|
|
@ -62,13 +62,7 @@ impl<'a> ResolvedSelector<'a> {
|
||||||
let (layer, loose) = match node {
|
let (layer, loose) = match node {
|
||||||
NodeIndex::Primitive(primitive) => (
|
NodeIndex::Primitive(primitive) => (
|
||||||
primitive.primitive(board.layout().drawing()).layer(),
|
primitive.primitive(board.layout().drawing()).layer(),
|
||||||
match primitive {
|
primitive.try_into().ok(),
|
||||||
PrimitiveIndex::LooseDot(dot) => Some(dot.into()),
|
|
||||||
PrimitiveIndex::LoneLooseSeg(seg) => Some(seg.into()),
|
|
||||||
PrimitiveIndex::SeqLooseSeg(seg) => Some(seg.into()),
|
|
||||||
PrimitiveIndex::LooseBend(bend) => Some(bend.into()),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
NodeIndex::Compound(compound) => {
|
NodeIndex::Compound(compound) => {
|
||||||
match board.layout().drawing().compound_weight(compound) {
|
match board.layout().drawing().compound_weight(compound) {
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,19 @@ impl From<LooseIndex> for PrimitiveIndex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<PrimitiveIndex> for LooseIndex {
|
||||||
|
type Error = ();
|
||||||
|
fn try_from(primitive: PrimitiveIndex) -> Result<LooseIndex, ()> {
|
||||||
|
match primitive {
|
||||||
|
PrimitiveIndex::LooseDot(dot) => Ok(dot.into()),
|
||||||
|
PrimitiveIndex::LoneLooseSeg(seg) => Ok(seg.into()),
|
||||||
|
PrimitiveIndex::SeqLooseSeg(seg) => Ok(seg.into()),
|
||||||
|
PrimitiveIndex::LooseBend(bend) => Ok(bend.into()),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[enum_dispatch(GetPrevNextLoose, GetDrawing, GetPetgraphIndex)]
|
#[enum_dispatch(GetPrevNextLoose, GetDrawing, GetPetgraphIndex)]
|
||||||
pub enum Loose<'a, CW: Copy, R: AccessRules> {
|
pub enum Loose<'a, CW: Copy, R: AccessRules> {
|
||||||
Dot(LooseDot<'a, CW, R>),
|
Dot(LooseDot<'a, CW, R>),
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use rstar::AABB;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
drawing::{
|
drawing::{
|
||||||
band::BandTermsegIndex,
|
band::{BandTermsegIndex, BandUid},
|
||||||
bend::{BendIndex, BendWeight, LooseBendWeight},
|
bend::{BendIndex, BendWeight, LooseBendWeight},
|
||||||
dot::{
|
dot::{
|
||||||
DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, GeneralDotWeight, LooseDotIndex,
|
DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, GeneralDotWeight, LooseDotIndex,
|
||||||
|
|
@ -18,15 +18,21 @@ use crate::{
|
||||||
},
|
},
|
||||||
gear::GearIndex,
|
gear::GearIndex,
|
||||||
graph::{GetMaybeNet, IsInLayer, MakePrimitive, PrimitiveIndex, PrimitiveWeight},
|
graph::{GetMaybeNet, IsInLayer, MakePrimitive, PrimitiveIndex, PrimitiveWeight},
|
||||||
|
loose::LooseIndex,
|
||||||
primitive::MakePrimitiveShape,
|
primitive::MakePrimitiveShape,
|
||||||
rules::AccessRules,
|
rules::AccessRules,
|
||||||
seg::{
|
seg::{
|
||||||
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
|
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
|
||||||
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
|
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
|
||||||
},
|
},
|
||||||
Cane, Drawing, DrawingEdit, DrawingException, Infringement,
|
Cane, Collect, Drawing, DrawingEdit, DrawingException, Infringement,
|
||||||
|
},
|
||||||
|
geometry::{
|
||||||
|
edit::ApplyGeometryEdit,
|
||||||
|
primitive::{AccessPrimitiveShape, PrimitiveShape, SegShape},
|
||||||
|
shape::{AccessShape, Shape},
|
||||||
|
GenericNode,
|
||||||
},
|
},
|
||||||
geometry::{edit::ApplyGeometryEdit, shape::Shape, GenericNode},
|
|
||||||
graph::{GenericIndex, GetPetgraphIndex},
|
graph::{GenericIndex, GetPetgraphIndex},
|
||||||
layout::{
|
layout::{
|
||||||
poly::{MakePolygon, Poly, PolyWeight},
|
poly::{MakePolygon, Poly, PolyWeight},
|
||||||
|
|
@ -367,6 +373,68 @@ impl<R: AccessRules> Layout<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Finds all bands on `layer` between `left` and `right`
|
||||||
|
/// (usually assuming `left` and `right` are neighbors in a Delaunay triangulation)
|
||||||
|
/// and returns them ordered from `left` to `right`.
|
||||||
|
pub fn bands_between_nodes(
|
||||||
|
&self,
|
||||||
|
layer: usize,
|
||||||
|
left: NodeIndex,
|
||||||
|
right: NodeIndex,
|
||||||
|
) -> Vec<BandUid> {
|
||||||
|
assert_ne!(left, right);
|
||||||
|
let left_pos = self.node_shape(left).center();
|
||||||
|
let right_pos = self.node_shape(right).center();
|
||||||
|
let delta = right_pos - left_pos;
|
||||||
|
let delta_len = delta.y().hypot(delta.x());
|
||||||
|
let fake_seg = PrimitiveShape::Seg(SegShape {
|
||||||
|
from: left_pos,
|
||||||
|
to: right_pos,
|
||||||
|
// TODO: being able to use a zero-width segshape here would be optimal
|
||||||
|
// check if that works
|
||||||
|
width: f64::EPSILON,
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut bands: Vec<_> = self
|
||||||
|
.drawing
|
||||||
|
.rtree()
|
||||||
|
.locate_in_envelope_intersecting(&{
|
||||||
|
let aabb_init = AABB::from_corners(
|
||||||
|
[left_pos.x(), left_pos.y()],
|
||||||
|
[right_pos.x(), right_pos.y()],
|
||||||
|
);
|
||||||
|
AABB::from_corners(
|
||||||
|
[aabb_init.lower()[0], aabb_init.lower()[1], layer as f64],
|
||||||
|
[aabb_init.upper()[0], aabb_init.upper()[1], layer as f64],
|
||||||
|
)
|
||||||
|
})
|
||||||
|
// TODO: handle non-loose entries (bends, segs)
|
||||||
|
.filter_map(|geom| match geom.data {
|
||||||
|
NodeIndex::Primitive(prim) => LooseIndex::try_from(prim).ok(),
|
||||||
|
NodeIndex::Compound(_) => None,
|
||||||
|
})
|
||||||
|
.map(|loose| {
|
||||||
|
let prim: PrimitiveIndex = loose.into();
|
||||||
|
let shape = prim.primitive(&self.drawing).shape();
|
||||||
|
(prim, loose, shape)
|
||||||
|
})
|
||||||
|
.filter(|(_, _, shape)| shape.intersects(&fake_seg))
|
||||||
|
.map(|(_, loose, shape)| {
|
||||||
|
let band_uid = self.drawing.loose_band_uid(loose);
|
||||||
|
// TODO: check that the resulting order is correct
|
||||||
|
let location = crate::math::dot_product(delta, shape.center()) / delta_len;
|
||||||
|
(location, band_uid)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
bands.sort_by(|a, b| f64::total_cmp(&a.0, &b.0));
|
||||||
|
|
||||||
|
// TODO: handle "loops" of bands, or multiple primitives from the band crossing the segment
|
||||||
|
// both in the case of "edge" of a primitive/loose, and in case the band actually goes into a segment
|
||||||
|
// and then again out of it.
|
||||||
|
|
||||||
|
bands.into_iter().map(|(_, band_uid)| band_uid).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn rules(&self) -> &R {
|
pub fn rules(&self) -> &R {
|
||||||
self.drawing.rules()
|
self.drawing.rules()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue