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 petgraph::stable_graph::NodeIndex;
|
||||||
|
|
||||||
|
use super::geometry::SetOffset;
|
||||||
|
|
||||||
#[enum_dispatch(GetNodeIndex, MakePrimitive)]
|
#[enum_dispatch(GetNodeIndex, MakePrimitive)]
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum BendIndex {
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum BendWeight {
|
pub enum BendWeight {
|
||||||
Fixed(FixedBendWeight),
|
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 {
|
impl GetWidth for FixedBendWeight {
|
||||||
fn width(&self) -> f64 {
|
fn width(&self) -> f64 {
|
||||||
self.width
|
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 {
|
impl GetWidth for LooseBendWeight {
|
||||||
fn width(&self) -> f64 {
|
fn width(&self) -> f64 {
|
||||||
self.width
|
self.width
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,11 @@ pub trait GetOffset {
|
||||||
fn offset(&self) -> f64;
|
fn offset(&self) -> f64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[enum_dispatch]
|
||||||
|
pub trait SetOffset {
|
||||||
|
fn set_offset(&mut self, offset: f64);
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum GeometryLabel {
|
pub enum GeometryLabel {
|
||||||
Connection,
|
Connection,
|
||||||
|
|
@ -48,7 +53,7 @@ pub enum GeometryLabel {
|
||||||
|
|
||||||
pub trait DotWeightTrait<GW>: GetPos + SetPos + GetWidth + Into<GW> + Copy {}
|
pub trait DotWeightTrait<GW>: GetPos + SetPos + GetWidth + Into<GW> + Copy {}
|
||||||
pub trait SegWeightTrait<GW>: 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)]
|
#[derive(Debug)]
|
||||||
pub struct Geometry<
|
pub struct Geometry<
|
||||||
|
|
@ -152,7 +157,13 @@ impl<
|
||||||
pub fn move_dot(&mut self, dot: DI, to: Point) {
|
pub fn move_dot(&mut self, dot: DI, to: Point) {
|
||||||
let mut weight = self.dot_weight(dot);
|
let mut weight = self.dot_weight(dot);
|
||||||
weight.set_pos(to);
|
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) {
|
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) {
|
pub fn flip_bend(&mut self, bend: BI) {
|
||||||
// Does not affect the bbox because it covers the whole guidecircle.
|
// Does not affect the bbox because it covers the whole guidecircle.
|
||||||
self.geometry.flip_bend(bend);
|
self.geometry.flip_bend(bend);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reattach_bend(&mut self, bend: BI, maybe_new_inner: Option<BI>) {
|
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.rtree.remove(&self.make_bend_bbox(bend));
|
||||||
self.geometry.reattach_bend(bend, maybe_new_inner);
|
self.geometry.reattach_bend(bend, maybe_new_inner);
|
||||||
self.rtree.insert(self.make_bend_bbox(bend));
|
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::bend::BendIndex;
|
||||||
use crate::layout::dot::DotWeight;
|
use crate::layout::dot::DotWeight;
|
||||||
use crate::layout::geometry::{
|
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::guide::Guide;
|
||||||
use crate::layout::rules::{Conditions, GetConditions};
|
use crate::layout::rules::{Conditions, GetConditions};
|
||||||
|
|
@ -436,6 +437,12 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
self.primitive(rail).width(),
|
self.primitive(rail).width(),
|
||||||
)?
|
)?
|
||||||
.end_point();
|
.end_point();
|
||||||
|
let offset = guide.head_around_bend_offset(
|
||||||
|
&from_head.into(),
|
||||||
|
inner.into(),
|
||||||
|
self.primitive(rail).width(),
|
||||||
|
);
|
||||||
|
|
||||||
self.move_dot_infringably(
|
self.move_dot_infringably(
|
||||||
joints.0.into(),
|
joints.0.into(),
|
||||||
from,
|
from,
|
||||||
|
|
@ -446,6 +453,14 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
to,
|
to,
|
||||||
&self.inner_bow_and_outer_bows(rail),
|
&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 {
|
} else {
|
||||||
let core = rail_primitive.core();
|
let core = rail_primitive.core();
|
||||||
let from = guide
|
let from = guide
|
||||||
|
|
@ -464,6 +479,12 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
self.primitive(rail).width(),
|
self.primitive(rail).width(),
|
||||||
)?
|
)?
|
||||||
.end_point();
|
.end_point();
|
||||||
|
let offset = guide.head_around_dot_offset(
|
||||||
|
&from_head.into(),
|
||||||
|
core.into(),
|
||||||
|
self.primitive(rail).width(),
|
||||||
|
);
|
||||||
|
|
||||||
self.move_dot_infringably(
|
self.move_dot_infringably(
|
||||||
joints.0.into(),
|
joints.0.into(),
|
||||||
from,
|
from,
|
||||||
|
|
@ -474,6 +495,12 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
to,
|
to,
|
||||||
&self.inner_bow_and_outer_bows(rail),
|
&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();
|
maybe_rail = self.primitive(rail).outer();
|
||||||
|
|
@ -834,6 +861,30 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
Ok(())
|
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().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()))]
|
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
|
||||||
fn detect_infringement_except(
|
fn detect_infringement_except(
|
||||||
|
|
|
||||||
|
|
@ -243,10 +243,10 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
let _i = 0;
|
let _i = 0;
|
||||||
let mut router = Router::new(SimpleRules {
|
let mut router = Router::new(SimpleRules {
|
||||||
net_clearances: HashMap::from([
|
net_clearances: HashMap::from([
|
||||||
((1, 2), 5.0),
|
((1, 2), 8.0),
|
||||||
((2, 1), 5.0),
|
((2, 1), 8.0),
|
||||||
((2, 3), 10.0),
|
((2, 3), 3.0),
|
||||||
((3, 2), 10.0),
|
((3, 2), 3.0),
|
||||||
((3, 4), 15.0),
|
((3, 4), 15.0),
|
||||||
((4, 3), 15.0),
|
((4, 3), 15.0),
|
||||||
]),
|
]),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue