mirror of https://codeberg.org/topola/topola.git
layout: fix misalignment of shifted bends
This commit is contained in:
parent
850941715e
commit
7fdf90b126
|
|
@ -17,6 +17,8 @@ use crate::{
|
|||
|
||||
use petgraph::stable_graph::NodeIndex;
|
||||
|
||||
use super::geometry::SetOffset;
|
||||
|
||||
#[enum_dispatch(GetNodeIndex, MakePrimitive)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum BendIndex {
|
||||
|
|
@ -45,7 +47,7 @@ impl TryFrom<GeometryIndex> for BendIndex {
|
|||
}
|
||||
}
|
||||
|
||||
#[enum_dispatch(GetOffset, GetWidth)]
|
||||
#[enum_dispatch(GetOffset, SetOffset, GetWidth)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum BendWeight {
|
||||
Fixed(FixedBendWeight),
|
||||
|
|
@ -91,6 +93,12 @@ impl GetOffset for FixedBendWeight {
|
|||
}
|
||||
}
|
||||
|
||||
impl SetOffset for FixedBendWeight {
|
||||
fn set_offset(&mut self, offset: f64) {
|
||||
self.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
impl GetWidth for FixedBendWeight {
|
||||
fn width(&self) -> f64 {
|
||||
self.width
|
||||
|
|
@ -110,6 +118,12 @@ impl GetOffset for LooseBendWeight {
|
|||
}
|
||||
}
|
||||
|
||||
impl SetOffset for LooseBendWeight {
|
||||
fn set_offset(&mut self, offset: f64) {
|
||||
self.offset = offset
|
||||
}
|
||||
}
|
||||
|
||||
impl GetWidth for LooseBendWeight {
|
||||
fn width(&self) -> f64 {
|
||||
self.width
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@ pub trait GetOffset {
|
|||
fn offset(&self) -> f64;
|
||||
}
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait SetOffset {
|
||||
fn set_offset(&mut self, offset: f64);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum GeometryLabel {
|
||||
Connection,
|
||||
|
|
@ -48,7 +53,7 @@ pub enum GeometryLabel {
|
|||
|
||||
pub trait DotWeightTrait<GW>: GetPos + SetPos + GetWidth + Into<GW> + Copy {}
|
||||
pub trait SegWeightTrait<GW>: GetWidth + Into<GW> + Copy {}
|
||||
pub trait BendWeightTrait<GW>: GetOffset + GetWidth + Into<GW> + Copy {}
|
||||
pub trait BendWeightTrait<GW>: GetOffset + SetOffset + GetWidth + Into<GW> + Copy {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Geometry<
|
||||
|
|
@ -152,7 +157,13 @@ impl<
|
|||
pub fn move_dot(&mut self, dot: DI, to: Point) {
|
||||
let mut weight = self.dot_weight(dot);
|
||||
weight.set_pos(to);
|
||||
*self.graph.node_weight_mut(dot.node_index()).unwrap() = weight.into()
|
||||
*self.graph.node_weight_mut(dot.node_index()).unwrap() = weight.into();
|
||||
}
|
||||
|
||||
pub fn shift_bend(&mut self, bend: BI, offset: f64) {
|
||||
let mut weight = self.bend_weight(bend);
|
||||
weight.set_offset(offset);
|
||||
*self.graph.node_weight_mut(bend.node_index()).unwrap() = weight.into();
|
||||
}
|
||||
|
||||
pub fn flip_bend(&mut self, bend: BI) {
|
||||
|
|
|
|||
|
|
@ -159,15 +159,49 @@ impl<
|
|||
}
|
||||
}
|
||||
|
||||
pub fn shift_bend(&mut self, bend: BI, offset: f64) {
|
||||
let mut rail = bend;
|
||||
|
||||
while let Some(outer) = self.geometry.outer(rail) {
|
||||
self.rtree.remove(&self.make_bend_bbox(outer));
|
||||
rail = outer;
|
||||
}
|
||||
|
||||
self.rtree.remove(&self.make_bend_bbox(bend));
|
||||
self.geometry.shift_bend(bend, offset);
|
||||
self.rtree.insert(self.make_bend_bbox(bend));
|
||||
|
||||
rail = bend;
|
||||
|
||||
while let Some(outer) = self.geometry.outer(rail) {
|
||||
self.rtree.insert(self.make_bend_bbox(outer));
|
||||
rail = outer;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flip_bend(&mut self, bend: BI) {
|
||||
// Does not affect the bbox because it covers the whole guidecircle.
|
||||
self.geometry.flip_bend(bend);
|
||||
}
|
||||
|
||||
pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) {
|
||||
let mut rail = bend;
|
||||
|
||||
while let Some(outer) = self.geometry.outer(rail) {
|
||||
self.rtree.remove(&self.make_bend_bbox(outer));
|
||||
rail = outer;
|
||||
}
|
||||
|
||||
self.rtree.remove(&self.make_bend_bbox(bend));
|
||||
self.geometry.reattach_bend(bend, maybe_new_inner);
|
||||
self.rtree.insert(self.make_bend_bbox(bend));
|
||||
|
||||
rail = bend;
|
||||
|
||||
while let Some(outer) = self.geometry.outer(rail) {
|
||||
self.rtree.insert(self.make_bend_bbox(outer));
|
||||
rail = outer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ use crate::graph::{GenericIndex, GetNodeIndex};
|
|||
use crate::layout::bend::BendIndex;
|
||||
use crate::layout::dot::DotWeight;
|
||||
use crate::layout::geometry::{
|
||||
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, GetWidth, SegWeightTrait,
|
||||
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetOffset, GetPos, GetWidth,
|
||||
SegWeightTrait,
|
||||
};
|
||||
use crate::layout::guide::Guide;
|
||||
use crate::layout::rules::{Conditions, GetConditions};
|
||||
|
|
@ -436,6 +437,12 @@ impl<R: RulesTrait> Layout<R> {
|
|||
self.primitive(rail).width(),
|
||||
)?
|
||||
.end_point();
|
||||
let offset = guide.head_around_bend_offset(
|
||||
&from_head.into(),
|
||||
inner.into(),
|
||||
self.primitive(rail).width(),
|
||||
);
|
||||
|
||||
self.move_dot_infringably(
|
||||
joints.0.into(),
|
||||
from,
|
||||
|
|
@ -446,6 +453,14 @@ impl<R: RulesTrait> Layout<R> {
|
|||
to,
|
||||
&self.inner_bow_and_outer_bows(rail),
|
||||
)?;
|
||||
|
||||
self.shift_bend_infringably(
|
||||
rail.into(),
|
||||
offset,
|
||||
&self.inner_bow_and_outer_bows(rail),
|
||||
)?;
|
||||
|
||||
// Update offsets in case the rule conditions changed.
|
||||
} else {
|
||||
let core = rail_primitive.core();
|
||||
let from = guide
|
||||
|
|
@ -464,6 +479,12 @@ impl<R: RulesTrait> Layout<R> {
|
|||
self.primitive(rail).width(),
|
||||
)?
|
||||
.end_point();
|
||||
let offset = guide.head_around_dot_offset(
|
||||
&from_head.into(),
|
||||
core.into(),
|
||||
self.primitive(rail).width(),
|
||||
);
|
||||
|
||||
self.move_dot_infringably(
|
||||
joints.0.into(),
|
||||
from,
|
||||
|
|
@ -474,6 +495,12 @@ impl<R: RulesTrait> Layout<R> {
|
|||
to,
|
||||
&self.inner_bow_and_outer_bows(rail),
|
||||
)?;
|
||||
|
||||
self.shift_bend_infringably(
|
||||
rail.into(),
|
||||
offset,
|
||||
&self.inner_bow_and_outer_bows(rail),
|
||||
)?;
|
||||
}
|
||||
|
||||
maybe_rail = self.primitive(rail).outer();
|
||||
|
|
@ -834,6 +861,30 @@ impl<R: RulesTrait> Layout<R> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
|
||||
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
|
||||
fn shift_bend_infringably(
|
||||
&mut self,
|
||||
bend: BendIndex,
|
||||
offset: f64,
|
||||
infringables: &[GeometryIndex],
|
||||
) -> Result<(), Infringement> {
|
||||
let old_offset = self
|
||||
.geometry_with_rtree
|
||||
.geometry()
|
||||
.bend_weight(bend)
|
||||
.offset();
|
||||
self.geometry_with_rtree.shift_bend(bend, offset);
|
||||
|
||||
if let Some(infringement) = self.detect_infringement_except(bend.into(), infringables) {
|
||||
// Restore original state.
|
||||
self.geometry_with_rtree.shift_bend(bend, old_offset);
|
||||
return Err(infringement);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
|
||||
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
|
||||
fn detect_infringement_except(
|
||||
|
|
|
|||
|
|
@ -243,10 +243,10 @@ fn main() -> Result<(), anyhow::Error> {
|
|||
let _i = 0;
|
||||
let mut router = Router::new(SimpleRules {
|
||||
net_clearances: HashMap::from([
|
||||
((1, 2), 5.0),
|
||||
((2, 1), 5.0),
|
||||
((2, 3), 10.0),
|
||||
((3, 2), 10.0),
|
||||
((1, 2), 8.0),
|
||||
((2, 1), 8.0),
|
||||
((2, 3), 3.0),
|
||||
((3, 2), 3.0),
|
||||
((3, 4), 15.0),
|
||||
((4, 3), 15.0),
|
||||
]),
|
||||
|
|
|
|||
Loading…
Reference in New Issue