layout: implement almost working reworked squeezing-under

I've temporarily removed collision/infringement detection in
`.move_dot()` because it was a lot of effort to get it right. We'll deal
with this later.

There's a panic due to mesh edges not being generated properly from
loose bends. But this commit is already very large, so I'm going to fix
this in the next one.

There's also some nomenclature changes.
This commit is contained in:
Mikolaj Wielgus 2023-12-19 02:22:55 +00:00
parent 5e3248014c
commit 84d5f9c49e
12 changed files with 612 additions and 472 deletions

View File

@ -8,7 +8,7 @@ use crate::{
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive,
WraparoundableIndex, WraparoundableIndex,
}, },
guide::Guide, guide::{Guide, Head, HeadTrait, SegbendHead},
layout::Layout, layout::Layout,
math::Circle, math::Circle,
primitive::{GetOtherEnd, GetWeight}, primitive::{GetOtherEnd, GetWeight},
@ -16,52 +16,6 @@ use crate::{
segbend::Segbend, segbend::Segbend,
}; };
#[enum_dispatch]
pub trait HeadTrait {
fn dot(&self) -> DotIndex;
fn band(&self) -> usize;
}
#[enum_dispatch(HeadTrait)]
#[derive(Debug, Clone, Copy)]
pub enum Head {
Bare(BareHead),
Segbend(SegbendHead),
}
#[derive(Debug, Clone, Copy)]
pub struct BareHead {
pub dot: FixedDotIndex,
pub band: usize,
}
impl HeadTrait for BareHead {
fn dot(&self) -> DotIndex {
self.dot.into()
}
fn band(&self) -> usize {
self.band
}
}
#[derive(Debug, Clone, Copy)]
pub struct SegbendHead {
pub dot: LooseDotIndex,
pub segbend: Segbend,
pub band: usize,
}
impl HeadTrait for SegbendHead {
fn dot(&self) -> DotIndex {
self.dot.into()
}
fn band(&self) -> usize {
self.band
}
}
pub struct Draw<'a> { pub struct Draw<'a> {
layout: &'a mut Layout, layout: &'a mut Layout,
rules: &'a Rules, rules: &'a Rules,
@ -73,7 +27,7 @@ impl<'a> Draw<'a> {
} }
pub fn start(&mut self, from: LooseDotIndex) -> Head { pub fn start(&mut self, from: LooseDotIndex) -> Head {
self.segbend_head(from).into() self.guide(&Default::default()).segbend_head(from).into()
} }
#[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 1))]
@ -111,7 +65,7 @@ impl<'a> Draw<'a> {
into: LooseDotIndex, into: LooseDotIndex,
width: f64, width: f64,
) -> Result<(), ()> { ) -> Result<(), ()> {
let to_head = self.segbend_head(into); let to_head = self.guide(&Default::default()).segbend_head(into);
let to_cw = self let to_cw = self
.guide(&Default::default()) .guide(&Default::default())
.head_cw(&to_head.into()) .head_cw(&to_head.into())
@ -244,7 +198,7 @@ impl<'a> Draw<'a> {
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
let segbend = self.layout.add_segbend( let segbend = self.layout.insert_segbend(
head.dot(), head.dot(),
around, around,
LooseDotWeight { LooseDotWeight {
@ -280,51 +234,7 @@ impl<'a> Draw<'a> {
self.layout.remove_interior(&head.segbend); self.layout.remove_interior(&head.segbend);
self.layout.remove(head.dot().into()); self.layout.remove(head.dot().into());
Some(self.head(prev_dot, band)) Some(self.guide(&Default::default()).head(prev_dot, band))
}
#[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))]
pub fn update_bow(&mut self, _bend: LooseBendIndex) {
/*let cw = self.layout.primitive(bend).weight().cw;
let ends = self.layout.primitive(bend).ends();
let from_head = self.rear_head(ends.0);
let to_head = self.rear_head(ends.1);
let from = self
.guide(&Default::default())
.head_around_bend_segment(&from_head, inner, cw, 3.0);
let to = self
.guide(&Default::default())
.head_around_bend_segment(&from_head, inner, cw, 3.0);
self.layout.reposition_bend(bend, from, to);*/
}
fn head(&self, dot: DotIndex, band: usize) -> Head {
match dot {
DotIndex::Fixed(loose) => BareHead { dot: loose, band }.into(),
DotIndex::Loose(fixed) => self.segbend_head(fixed).into(),
}
}
fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead {
SegbendHead {
dot,
segbend: self.layout.segbend(dot),
band: self.layout.primitive(dot).weight().band(),
}
}
fn rear_head(&self, dot: LooseDotIndex) -> Head {
self.head(
self.rear(self.segbend_head(dot)),
self.layout.primitive(dot).weight().band(),
)
}
fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout
.primitive(head.segbend.seg)
.other_end(head.segbend.dot.into())
} }
fn guide(&'a self, conditions: &'a Conditions) -> Guide { fn guide(&'a self, conditions: &'a Conditions) -> Guide {

View File

@ -11,14 +11,6 @@ use crate::{
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
}; };
pub trait Interior<T> {
fn interior(&self) -> Vec<T>;
}
pub trait GetEnds<F, T> {
fn ends(&self) -> (F, T);
}
#[enum_dispatch] #[enum_dispatch]
pub trait Retag { pub trait Retag {
fn retag(&self, index: NodeIndex<usize>) -> Index; fn retag(&self, index: NodeIndex<usize>) -> Index;
@ -176,14 +168,23 @@ impl From<BendIndex> for WraparoundableIndex {
} }
} }
#[enum_dispatch(GetNodeIndex, MakePrimitive, GetWraparound)] #[enum_dispatch(GetNodeIndex, MakePrimitive)]
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum WraparoundableIndex { pub enum WraparoundableIndex {
FixedDot(FixedDotIndex),
FixedBend(FixedBendIndex), FixedBend(FixedBendIndex),
LooseBend(LooseBendIndex), LooseBend(LooseBendIndex),
FixedDot(FixedDotIndex),
} }
impl From<WraparoundableIndex> for Index {
fn from(wraparoundable: WraparoundableIndex) -> Self {
match wraparoundable {
WraparoundableIndex::FixedDot(dot) => Index::FixedDot(dot),
WraparoundableIndex::FixedBend(bend) => Index::FixedBend(bend),
WraparoundableIndex::LooseBend(bend) => Index::LooseBend(bend),
}
}
}
pub trait DotWeight: GetWidth + Into<Weight> + Copy {} pub trait DotWeight: GetWidth + Into<Weight> + Copy {}
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]

View File

@ -1,15 +1,62 @@
use enum_dispatch::enum_dispatch;
use geo::Line; use geo::Line;
use crate::{ use crate::{
draw::{Head, HeadTrait}, graph::{BendIndex, DotIndex, FixedDotIndex, GetBand, LooseDotIndex, MakePrimitive},
graph::{BendIndex, DotIndex, FixedDotIndex, MakePrimitive},
layout::Layout, layout::Layout,
math::{self, Circle}, math::{self, Circle},
primitive::{GetCore, GetInnerOuter, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetOtherEnd, GetWeight, MakeShape},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
segbend::Segbend,
shape::{Shape, ShapeTrait}, shape::{Shape, ShapeTrait},
}; };
#[enum_dispatch]
pub trait HeadTrait {
fn dot(&self) -> DotIndex;
fn band(&self) -> usize;
}
#[enum_dispatch(HeadTrait)]
#[derive(Debug, Clone, Copy)]
pub enum Head {
Bare(BareHead),
Segbend(SegbendHead),
}
#[derive(Debug, Clone, Copy)]
pub struct BareHead {
pub dot: FixedDotIndex,
pub band: usize,
}
impl HeadTrait for BareHead {
fn dot(&self) -> DotIndex {
self.dot.into()
}
fn band(&self) -> usize {
self.band
}
}
#[derive(Debug, Clone, Copy)]
pub struct SegbendHead {
pub dot: LooseDotIndex,
pub segbend: Segbend,
pub band: usize,
}
impl HeadTrait for SegbendHead {
fn dot(&self) -> DotIndex {
self.dot.into()
}
fn band(&self) -> usize {
self.band
}
}
pub struct Guide<'a, 'b> { pub struct Guide<'a, 'b> {
layout: &'a Layout, layout: &'a Layout,
rules: &'a Rules, rules: &'a Rules,
@ -149,7 +196,35 @@ impl<'a, 'b> Guide<'a, 'b> {
let shape = dot.primitive(self.layout).shape(); let shape = dot.primitive(self.layout).shape();
Circle { Circle {
pos: shape.center(), pos: shape.center(),
r: shape.width() / 2.0 + width + self.rules.ruleset(self.conditions).clearance.min, r: shape.width() / 2.0 + width + 0.0,
} }
} }
pub fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead {
SegbendHead {
dot,
segbend: self.layout.segbend(dot),
band: self.layout.primitive(dot).weight().band(),
}
}
pub fn rear_head(&self, dot: LooseDotIndex) -> Head {
self.head(
self.rear(self.segbend_head(dot)),
self.layout.primitive(dot).weight().band(),
)
}
pub fn head(&self, dot: DotIndex, band: usize) -> Head {
match dot {
DotIndex::Fixed(fixed) => BareHead { dot: fixed, band }.into(),
DotIndex::Loose(loose) => self.segbend_head(loose).into(),
}
}
fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout
.primitive(head.segbend.seg)
.other_end(head.segbend.dot.into())
}
} }

View File

@ -9,11 +9,15 @@ use slab::Slab;
use crate::graph::{ use crate::graph::{
BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex, BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex,
FixedSegWeight, GenericIndex, GetNodeIndex, Index, Interior, Label, LooseBendIndex, FixedSegWeight, GenericIndex, GetNet, GetNodeIndex, Index, Label, LooseBendIndex,
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive,
Retag, SegWeight, Weight, WraparoundableIndex, Retag, SegWeight, Weight, WraparoundableIndex,
}; };
use crate::primitive::{GenericPrimitive, GetConnectable, GetWeight, MakeShape}; use crate::guide::Guide;
use crate::primitive::{
GenericPrimitive, GetConnectable, GetCore, GetEnds, GetFirstRail, GetInnerOuter, GetInterior,
GetOtherEnd, GetWeight, GetWraparound, MakeShape,
};
use crate::segbend::Segbend; use crate::segbend::Segbend;
use crate::shape::{Shape, ShapeTrait}; use crate::shape::{Shape, ShapeTrait};
@ -44,7 +48,7 @@ impl Layout {
} }
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))]
pub fn remove_interior(&mut self, path: &impl Interior<Index>) { pub fn remove_interior(&mut self, path: &impl GetInterior<Index>) {
for index in path for index in path
.interior() .interior()
.into_iter() .into_iter()
@ -67,6 +71,14 @@ impl Layout {
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))]
pub fn remove(&mut self, index: Index) { pub fn remove(&mut self, index: Index) {
// Removing a loose bend affects its outer bends.
if let Index::LooseBend(bend) = index {
if let Some(outer) = self.primitive(bend).outer() {
self.reattach_bend(outer, self.primitive(bend).inner());
self.update_this_and_outward_bows(outer).unwrap(); // Must never fail.
}
}
// Unnecessary retag. It should be possible to elide it. // Unnecessary retag. It should be possible to elide it.
let weight = *self.graph.node_weight(index.node_index()).unwrap(); let weight = *self.graph.node_weight(index.node_index()).unwrap();
@ -78,27 +90,30 @@ impl Layout {
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, ()> { pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, ()> {
self.add_dot(weight) self.add_dot_infringably(weight, &[])
} }
// TODO: Remove. /*#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_loose_dot(&mut self, weight: LooseDotWeight) -> Result<LooseDotIndex, ()> { fn add_loose_dot(&mut self, weight: LooseDotWeight) -> Result<LooseDotIndex, ()> {
self.add_dot(weight) self.add_dot_infringably(weight, &[])
} }*/
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
fn add_dot<W: DotWeight>(&mut self, weight: W) -> Result<GenericIndex<W>, ()> fn add_dot_infringably<W: DotWeight>(
&mut self,
weight: W,
infringables: &[Index],
) -> Result<GenericIndex<W>, ()>
where where
GenericIndex<W>: Into<Index> + Copy, GenericIndex<W>: Into<Index> + Copy,
{ {
let dot = GenericIndex::<W>::new(self.graph.add_node(weight.into())); let dot = GenericIndex::<W>::new(self.graph.add_node(weight.into()));
self.insert_into_rtree(dot.into()); self.insert_into_rtree(dot.into());
self.fail_and_remove_if_collides_except(dot.into(), &[])?; self.fail_and_remove_if_infringes_except(dot.into(), infringables)?;
Ok(dot) Ok(dot)
} }
@ -113,7 +128,253 @@ impl Layout {
to: FixedDotIndex, to: FixedDotIndex,
weight: FixedSegWeight, weight: FixedSegWeight,
) -> Result<FixedSegIndex, ()> { ) -> Result<FixedSegIndex, ()> {
self.add_seg(from, to, weight) self.add_seg_infringably(from, to, weight, &[])
}
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() >= old(self.graph.edge_count() + 5))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
pub fn insert_segbend(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: LooseSegWeight,
bend_weight: LooseBendWeight,
) -> Result<Segbend, ()> {
let maybe_wraparound = match around {
WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(),
WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(),
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
};
let mut infringables = self.this_and_wraparound_bow(around);
if let Some(wraparound) = maybe_wraparound {
infringables.append(&mut self.outer_bows(wraparound));
}
let segbend = self.add_segbend_infringably(
from,
around,
dot_weight,
seg_weight,
bend_weight,
&infringables,
)?;
if let Some(wraparound) = maybe_wraparound {
self.reattach_bend(wraparound, Some(segbend.bend));
}
if let Some(outer) = self.primitive(segbend.bend).outer() {
self.update_this_and_outward_bows(outer);
}
// Segs must not cross.
if let Some(..) = self.detect_collision(segbend.seg.into()) {
let end = self.primitive(segbend.bend).other_end(segbend.dot);
self.remove_interior(&segbend);
self.remove(end.into());
return Err(());
}
Ok(segbend)
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn inner_and_outer_bows(&self, bend: LooseBendIndex) -> Vec<Index> {
let bend_primitive = self.primitive(bend);
let mut v = vec![];
if let Some(inner) = bend_primitive.inner() {
v.append(&mut self.bow(inner.into()));
} else {
let core = bend_primitive.core();
v.push(core.into());
}
if let Some(outer) = bend_primitive.outer() {
v.append(&mut self.bow(outer.into()));
}
v
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn this_and_wraparound_bow(&self, around: WraparoundableIndex) -> Vec<Index> {
match around {
WraparoundableIndex::FixedDot(dot) => {
let mut v = vec![around.into()];
if let Some(first_rail) = self.primitive(dot).first_rail() {
v.append(&mut self.bow(first_rail));
}
v
}
WraparoundableIndex::FixedBend(bend) => {
let mut v = vec![around.into()];
if let Some(first_rail) = self.primitive(bend).first_rail() {
v.append(&mut self.bow(first_rail));
}
v
}
WraparoundableIndex::LooseBend(bend) => {
let mut v = self.bow(bend);
if let Some(outer) = self.primitive(bend).outer() {
v.append(&mut self.bow(outer));
}
v
}
}
}
// XXX: Move this to primitives?
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn bow(&self, bend: LooseBendIndex) -> Vec<Index> {
let mut bow: Vec<Index> = vec![];
bow.push(bend.into());
let ends = self.primitive(bend).ends();
bow.push(ends.0.into());
bow.push(ends.1.into());
if let Some(seg0) = self.primitive(ends.0).seg() {
bow.push(seg0.into());
}
if let Some(seg1) = self.primitive(ends.1).seg() {
bow.push(seg1.into());
}
bow
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn outer_bows(&self, bend: LooseBendIndex) -> Vec<Index> {
let mut outer_bows = vec![];
let mut rail = bend;
while let Some(outer) = self.primitive(rail).outer() {
let primitive = self.primitive(outer);
outer_bows.push(outer.into());
let ends = primitive.ends();
outer_bows.push(ends.0.into());
outer_bows.push(ends.1.into());
outer_bows.push(self.primitive(ends.0).seg().unwrap().into());
outer_bows.push(self.primitive(ends.1).seg().unwrap().into());
rail = outer;
}
outer_bows
/*let mut outer_bows = vec![];
// XXX: Ugly all-same match.
let mut maybe_rail = match around {
WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(),
WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(),
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
};
while let Some(rail) = maybe_rail {
let primitive = self.primitive(rail);
outer_bows.push(rail.into());
let ends = primitive.ends();
outer_bows.push(ends.0.into());
outer_bows.push(ends.1.into());
outer_bows.push(self.primitive(ends.0).seg().unwrap().into());
maybe_rail = primitive.outer();
}
outer_bows*/
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count())
|| self.graph.edge_count() == old(self.graph.edge_count() - 1)
|| self.graph.edge_count() == old(self.graph.edge_count() + 1))]
fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option<LooseBendIndex>) {
self.remove_from_rtree(bend.into());
if let Some(old_inner_edge) = self
.graph
.edges_directed(bend.node_index(), Incoming)
.filter(|edge| *edge.weight() == Label::Outer)
.next()
{
self.graph.remove_edge(old_inner_edge.id());
}
if let Some(new_inner) = maybe_new_inner {
self.graph
.add_edge(new_inner.node_index(), bend.node_index(), Label::Outer);
}
self.insert_into_rtree(bend.into());
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn update_this_and_outward_bows(&mut self, around: LooseBendIndex) -> Result<(), ()> {
let mut maybe_rail = Some(around);
while let Some(rail) = maybe_rail {
let primitive = self.primitive(rail);
let cw = primitive.weight().cw;
let ends = primitive.ends();
let rules = Default::default();
let conditions = Default::default();
let guide = Guide::new(self, &rules, &conditions);
let from_head = guide.rear_head(ends.1);
let to_head = guide.rear_head(ends.0);
if let Some(inner) = primitive.inner() {
let from = guide
.head_around_bend_segment(&from_head.into(), inner.into(), !cw, 6.0)?
.end_point();
let to = guide
.head_around_bend_segment(&to_head.into(), inner.into(), cw, 6.0)?
.end_point();
self.move_dot(ends.0, from)?;
self.move_dot(ends.1, to)?;
} else {
let core = primitive.core();
let from = guide
.head_around_dot_segment(&from_head.into(), core.into(), !cw, 6.0)?
.end_point();
let to = guide
.head_around_dot_segment(&to_head.into(), core.into(), cw, 6.0)?
.end_point();
self.move_dot(ends.0, from)?;
self.move_dot(ends.1, to)?;
}
/*let from = guide
.head_around_bend_segment(&from_head.into(), rail.into(), !cw, 0.0)?
.end_point();
let to = guide
.head_around_bend_segment(&to_head.into(), rail.into(), cw, 0.0)?
.end_point();
self.move_dot(ends.0, from)?;
self.move_dot(ends.1, to)?;*/
maybe_rail = self.primitive(rail).outer();
}
Ok(())
} }
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))]
@ -128,17 +389,44 @@ impl Layout {
seg_weight: LooseSegWeight, seg_weight: LooseSegWeight,
bend_weight: LooseBendWeight, bend_weight: LooseBendWeight,
) -> Result<Segbend, ()> { ) -> Result<Segbend, ()> {
let seg_to = self.add_loose_dot(dot_weight)?; self.add_segbend_infringably(
let seg = self.add_loose_seg(from, seg_to, seg_weight).map_err(|_| { from,
self.remove(seg_to.into()); around,
})?; dot_weight,
seg_weight,
bend_weight,
&self.this_and_wraparound_bow(around),
)
}
let bend_to = self.add_loose_dot(dot_weight).map_err(|_| { #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))]
self.remove(seg.into()); #[debug_ensures(ret.is_ok() -> self.graph.edge_count() >= old(self.graph.edge_count() + 5))]
self.remove(seg_to.into()); #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
})?; #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_segbend_infringably(
&mut self,
from: DotIndex,
around: WraparoundableIndex,
dot_weight: LooseDotWeight,
seg_weight: LooseSegWeight,
bend_weight: LooseBendWeight,
infringables: &[Index],
) -> Result<Segbend, ()> {
let seg_to = self.add_dot_infringably(dot_weight, infringables)?;
let seg = self
.add_seg_infringably(from, seg_to, seg_weight, infringables)
.map_err(|_| {
self.remove(seg_to.into());
})?;
let bend_to = self
.add_dot_infringably(dot_weight, infringables)
.map_err(|_| {
self.remove(seg.into());
self.remove(seg_to.into());
})?;
let bend = self let bend = self
.add_loose_bend(seg_to, bend_to, around, bend_weight) .add_loose_bend_infringably(seg_to, bend_to, around, bend_weight, infringables)
.map_err(|_| { .map_err(|_| {
self.remove(bend_to.into()); self.remove(bend_to.into());
self.remove(seg.into()); self.remove(seg.into());
@ -162,18 +450,19 @@ impl Layout {
to: LooseDotIndex, to: LooseDotIndex,
weight: LooseSegWeight, weight: LooseSegWeight,
) -> Result<LooseSegIndex, ()> { ) -> Result<LooseSegIndex, ()> {
self.add_seg(from, to, weight) self.add_seg_infringably(from, to, weight, &[])
} }
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 2))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 2))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_seg<W: SegWeight>( fn add_seg_infringably<W: SegWeight>(
&mut self, &mut self,
from: impl GetNodeIndex, from: impl GetNodeIndex,
to: impl GetNodeIndex, to: impl GetNodeIndex,
weight: W, weight: W,
infringables: &[Index],
) -> Result<GenericIndex<W>, ()> ) -> Result<GenericIndex<W>, ()>
where where
GenericIndex<W>: Into<Index> + Copy, GenericIndex<W>: Into<Index> + Copy,
@ -186,7 +475,7 @@ impl Layout {
.add_edge(seg.node_index(), to.node_index(), Label::Adjacent); .add_edge(seg.node_index(), to.node_index(), Label::Adjacent);
self.insert_into_rtree(seg.into()); self.insert_into_rtree(seg.into());
self.fail_and_remove_if_collides_except(seg.into(), &[])?; self.fail_and_remove_if_infringes_except(seg.into(), infringables)?;
Ok(seg) Ok(seg)
} }
@ -208,21 +497,43 @@ impl Layout {
}*/ }*/
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3) || self.graph.edge_count() == old(self.graph.edge_count() + 4))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3)
|| self.graph.edge_count() == old(self.graph.edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_loose_bend( fn add_loose_bend_infringably(
&mut self, &mut self,
from: LooseDotIndex, from: LooseDotIndex,
to: LooseDotIndex, to: LooseDotIndex,
around: WraparoundableIndex, around: WraparoundableIndex,
weight: LooseBendWeight, weight: LooseBendWeight,
infringables: &[Index],
) -> Result<LooseBendIndex, ()> { ) -> Result<LooseBendIndex, ()> {
// It makes no sense to wrap something around or under one of its connectables.
if self.bands[weight.band].net == around.primitive(self).net() {
return Err(());
}
//
if let Some(wraparound) = match around {
WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(),
WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(),
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
} {
if self.bands[weight.band].net == wraparound.primitive(self).net() {
return Err(());
}
}
match around { match around {
WraparoundableIndex::FixedDot(core) => self.add_core_bend(from, to, core, weight), WraparoundableIndex::FixedDot(core) => {
WraparoundableIndex::FixedBend(around) => self.add_outer_bend(from, to, around, weight), self.add_core_bend_infringably(from, to, core, weight, infringables)
WraparoundableIndex::LooseBend(around) => self.add_outer_bend(from, to, around, weight), }
_ => unreachable!(), WraparoundableIndex::FixedBend(around) => {
self.add_outer_bend_infringably(from, to, around, weight, infringables)
}
WraparoundableIndex::LooseBend(around) => {
self.add_outer_bend_infringably(from, to, around, weight, infringables)
}
} }
} }
@ -230,12 +541,13 @@ impl Layout {
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_core_bend<W: BendWeight>( fn add_core_bend_infringably<W: BendWeight>(
&mut self, &mut self,
from: impl GetNodeIndex, from: impl GetNodeIndex,
to: impl GetNodeIndex, to: impl GetNodeIndex,
core: FixedDotIndex, core: FixedDotIndex,
weight: W, weight: W,
infringables: &[Index],
) -> Result<LooseBendIndex, ()> ) -> Result<LooseBendIndex, ()>
where where
GenericIndex<W>: Into<Index> + Copy, GenericIndex<W>: Into<Index> + Copy,
@ -250,7 +562,7 @@ impl Layout {
.add_edge(bend.node_index(), core.node_index(), Label::Core); .add_edge(bend.node_index(), core.node_index(), Label::Core);
self.insert_into_rtree(bend.into()); self.insert_into_rtree(bend.into());
self.fail_and_remove_if_collides_except(bend.into(), &[core.into()])?; self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend) Ok(bend)
} }
@ -258,12 +570,13 @@ impl Layout {
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 4))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_outer_bend<W: BendWeight>( fn add_outer_bend_infringably<W: BendWeight>(
&mut self, &mut self,
from: impl GetNodeIndex, from: impl GetNodeIndex,
to: impl GetNodeIndex, to: impl GetNodeIndex,
inner: impl GetNodeIndex, inner: impl GetNodeIndex,
weight: W, weight: W,
infringables: &[Index],
) -> Result<LooseBendIndex, ()> { ) -> Result<LooseBendIndex, ()> {
let core = *self let core = *self
.graph .graph
@ -293,34 +606,10 @@ impl Layout {
.add_edge(inner.node_index(), bend.node_index(), Label::Outer); .add_edge(inner.node_index(), bend.node_index(), Label::Outer);
self.insert_into_rtree(bend.into()); self.insert_into_rtree(bend.into());
self.fail_and_remove_if_collides_except(bend.into(), &[core.into()])?; self.fail_and_remove_if_infringes_except(bend.into(), infringables)?;
Ok(bend) Ok(bend)
} }
pub fn reposition_bend(&mut self, _bend: LooseBendIndex, _from: Point, _to: Point) {
// TODO.
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count())
|| self.graph.edge_count() == old(self.graph.edge_count() + 1))]
pub fn reattach_bend(&mut self, bend: LooseBendIndex, inner: LooseBendIndex) {
self.remove_from_rtree(bend.into());
if let Some(old_inner_edge) = self
.graph
.edges_directed(bend.node_index(), Incoming)
.filter(|edge| *edge.weight() == Label::Outer)
.next()
{
self.graph.remove_edge(old_inner_edge.id());
}
self.graph
.add_edge(inner.node_index(), bend.node_index(), Label::Outer);
self.insert_into_rtree(bend.into());
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
pub fn flip_bend(&mut self, bend: FixedBendIndex) { pub fn flip_bend(&mut self, bend: FixedBendIndex) {
@ -346,12 +635,12 @@ impl Layout {
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))]
fn fail_and_remove_if_collides_except( fn fail_and_remove_if_infringes_except(
&mut self, &mut self,
index: Index, index: Index,
except: &[Index], except: &[Index],
) -> Result<(), ()> { ) -> Result<(), ()> {
if let Some(..) = self.detect_collision_except(index, except) { if let Some(..) = self.detect_infringement_except(index, except) {
self.remove(index); self.remove(index);
return Err(()); return Err(());
} }
@ -382,9 +671,31 @@ impl Layout {
#[debug_invariant(self.test_envelopes())] #[debug_invariant(self.test_envelopes())]
impl Layout { impl Layout {
pub fn move_dot(&mut self, dot: LooseDotIndex, to: Point) -> Result<(), ()> {
self.move_dot_infringably(
dot,
to,
&self.inner_and_outer_bows(self.primitive(dot).bend()),
)
//let bend_primitive = self.primitive(self.primitive(dot).bend());
/*if let Some(inner) = bend_primitive.inner() {
} else {
let core = bend_primitive.core();
//let v = vec![];
//self.move_dot_infringably(dot, to, &self.this_and_wraparound_bow(core.into()))
}*/
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
pub fn move_dot(&mut self, dot: LooseDotIndex, to: Point) -> Result<(), ()> { pub fn move_dot_infringably(
&mut self,
dot: LooseDotIndex,
to: Point,
infringables: &[Index],
) -> Result<(), ()> {
self.primitive(dot) self.primitive(dot)
.seg() .seg()
.map(|seg| self.remove_from_rtree(seg.into())); .map(|seg| self.remove_from_rtree(seg.into()));
@ -397,23 +708,23 @@ impl Layout {
dot_weight.circle.pos = to; dot_weight.circle.pos = to;
*self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(dot_weight); *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(dot_weight);
if let Some(..) = self.detect_collision_except(dot.into(), &[]) { /*if let Some(..) = dbg!(self.detect_infringement_except(dot.into(), infringables)) {
// Restore original state. // Restore original state.
*self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(old_weight); *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(old_weight);
self.insert_into_rtree(dot.into()); self.insert_into_rtree(dot.into());
self.insert_into_rtree(self.primitive(dot).bend().into());
self.primitive(dot) self.primitive(dot)
.seg() .seg()
.map(|seg| self.remove_from_rtree(seg.into())); .map(|seg| self.insert_into_rtree(seg.into()));
self.insert_into_rtree(self.primitive(dot).bend().into());
return Err(()); return Err(());
} }*/
self.insert_into_rtree(dot.into()); self.insert_into_rtree(dot.into());
self.insert_into_rtree(self.primitive(dot).bend().into());
self.primitive(dot) self.primitive(dot)
.seg() .seg()
.map(|seg| self.remove_from_rtree(seg.into())); .map(|seg| self.insert_into_rtree(seg.into()));
self.insert_into_rtree(self.primitive(dot).bend().into());
Ok(()) Ok(())
} }
@ -422,7 +733,7 @@ impl Layout {
GenericPrimitive::new(index, self) GenericPrimitive::new(index, self)
} }
fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option<Index> { fn detect_infringement_except(&self, index: Index, except: &[Index]) -> Option<Index> {
let shape = index.primitive(self).shape(); let shape = index.primitive(self).shape();
self.rtree self.rtree
@ -437,6 +748,21 @@ impl Layout {
.next() .next()
} }
// TODO: Collision and infringement are the same for now. Change this.
fn detect_collision(&self, index: Index) -> Option<Index> {
let shape = index.primitive(self).shape();
self.rtree
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| {
let other_index = wrapper.data;
!index.primitive(self).connectable(other_index)
})
.filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data)
.next()
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))]
fn insert_into_rtree(&mut self, index: Index) { fn insert_into_rtree(&mut self, index: Index) {

View File

@ -34,12 +34,12 @@ use router::RouterObserver;
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
use sdl2::video::{Window, GLProfile}; use sdl2::video::{GLProfile, Window};
use sdl2::EventPump; use sdl2::EventPump;
use shape::{Shape, ShapeTrait}; use shape::{Shape, ShapeTrait};
use pathfinder_canvas::{ArcDirection, ColorU, FillRule};
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D}; use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
use pathfinder_canvas::{ColorU, FillRule, ArcDirection};
use pathfinder_geometry::rect::RectF; use pathfinder_geometry::rect::RectF;
use pathfinder_geometry::vector::{vec2f, vec2i}; use pathfinder_geometry::vector::{vec2f, vec2i};
use pathfinder_gl::{GLDevice, GLVersion}; use pathfinder_gl::{GLDevice, GLVersion};
@ -63,6 +63,15 @@ enum RouterOrLayout<'a> {
Layout(&'a Layout), Layout(&'a Layout),
} }
struct EmptyRouterObserver;
impl RouterObserver for EmptyRouterObserver {
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {}
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {}
fn on_probe(&mut self, tracer: &Tracer, trace: &Trace, _edge: MeshEdgeReference) {}
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
}
struct DebugRouterObserver<'a> { struct DebugRouterObserver<'a> {
event_pump: &'a mut sdl2::EventPump, event_pump: &'a mut sdl2::EventPump,
window: &'a Window, window: &'a Window,
@ -74,10 +83,15 @@ impl<'a> DebugRouterObserver<'a> {
pub fn new( pub fn new(
event_pump: &'a mut sdl2::EventPump, event_pump: &'a mut sdl2::EventPump,
window: &'a Window, window: &'a Window,
renderer: &'a mut Renderer<GLDevice>, renderer: &'a mut Renderer<GLDevice>,
font_context: &'a CanvasFontContext, font_context: &'a CanvasFontContext,
) -> Self { ) -> Self {
Self { event_pump, window, renderer, font_context } Self {
event_pump,
window,
renderer,
font_context,
}
} }
} }
@ -93,7 +107,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
20, 40,
); );
} }
@ -110,7 +124,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&path, &path,
5, 10,
); );
} }
@ -125,7 +139,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
None, None,
Some(tracer.mesh.clone()), Some(tracer.mesh.clone()),
&trace.path, &trace.path,
5, 10,
); );
} }
@ -181,7 +195,7 @@ fn main() {
let _i = 0; let _i = 0;
let mut router = Router::new(); let mut router = Router::new();
let dot1 = router let dot_start = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: 1, net: 1,
@ -192,10 +206,10 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot2 = router let dot_start2 = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: 5, net: 3,
circle: Circle { circle: Circle {
pos: (100.5, 500.5).into(), pos: (100.5, 500.5).into(),
r: 8.0, r: 8.0,
@ -203,6 +217,17 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot_start3 = router
.layout
.add_fixed_dot(FixedDotWeight {
net: 4,
circle: Circle {
pos: (160.5, 430.5).into(),
r: 8.0,
},
})
.unwrap();
let dot_end = router let dot_end = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
@ -217,7 +242,7 @@ fn main() {
let dot_end2 = router let dot_end2 = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: 5, net: 3,
circle: Circle { circle: Circle {
pos: (500.5, 150.5).into(), pos: (500.5, 150.5).into(),
r: 8.0, r: 8.0,
@ -225,6 +250,17 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot_end3 = router
.layout
.add_fixed_dot(FixedDotWeight {
net: 4,
circle: Circle {
pos: (350.5, 200.5).into(),
r: 8.0,
},
})
.unwrap();
let dot1_1 = router let dot1_1 = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
@ -411,7 +447,7 @@ fn main() {
&mut event_pump, &mut event_pump,
&mut canvas, &mut canvas,
RouterOrLayout::Router(&mut router), RouterOrLayout::Router(&mut router),
Some(dot1), Some(dot_start),
Some(dot_end), Some(dot_end),
None, None,
&[], &[],
@ -419,9 +455,10 @@ fn main() {
);*/ );*/
let _ = router.enroute( let _ = router.enroute(
dot1, dot_start,
dot_end, dot_end,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
); );
render_times( render_times(
@ -441,7 +478,7 @@ fn main() {
&mut event_pump, &mut event_pump,
&mut canvas, &mut canvas,
RouterOrLayout::Router(&mut router), RouterOrLayout::Router(&mut router),
Some(dot2), Some(dot_start2),
Some(dot_end), Some(dot_end),
None, None,
&[], &[],
@ -449,8 +486,28 @@ fn main() {
);*/ );*/
let _ = router.enroute( let _ = router.enroute(
dot2, dot_start2,
dot_end2, dot_end2,
&mut EmptyRouterObserver,
//&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
);
render_times(
&mut event_pump,
&window,
&mut renderer,
&font_context,
RouterOrLayout::Layout(&router.layout),
None,
None,
None,
&[],
-1,
);
let _ = router.enroute(
dot_start3,
dot_end3,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
); );
@ -510,7 +567,12 @@ fn render_times(
.reroute( .reroute(
from, from,
point! {x: state.x() as f64, y: state.y() as f64}, point! {x: state.x() as f64, y: state.y() as f64},
&mut DebugRouterObserver::new(event_pump, window, renderer, font_context), &mut DebugRouterObserver::new(
event_pump,
window,
renderer,
font_context,
),
) )
.ok(); .ok();
} else { } else {
@ -534,25 +596,18 @@ fn render_times(
Shape::Dot(dot) => { Shape::Dot(dot) => {
let mut path = Path2D::new(); let mut path = Path2D::new();
path.ellipse( path.ellipse(
vec2f( vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
dot.c.pos.x() as f32,
dot.c.pos.y() as f32
),
dot.c.r as f32, dot.c.r as f32,
0.0, 0.0, std::f32::consts::TAU 0.0,
0.0,
std::f32::consts::TAU,
); );
canvas.fill_path(path, FillRule::Winding); canvas.fill_path(path, FillRule::Winding);
} }
Shape::Seg(seg) => { Shape::Seg(seg) => {
let mut path = Path2D::new(); let mut path = Path2D::new();
path.move_to(vec2f( path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32));
seg.from.x() as f32, path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32));
seg.from.y() as f32
));
path.line_to(vec2f(
seg.to.x() as f32,
seg.to.y() as f32
));
canvas.set_line_width(seg.width as f32); canvas.set_line_width(seg.width as f32);
canvas.stroke_path(path); canvas.stroke_path(path);
} }
@ -565,14 +620,11 @@ fn render_times(
let mut path = Path2D::new(); let mut path = Path2D::new();
path.arc( path.arc(
vec2f( vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
bend.c.pos.x() as f32,
bend.c.pos.y() as f32
),
bend.circle().r as f32, bend.circle().r as f32,
angle1 as f32, angle1 as f32,
angle2 as f32, angle2 as f32,
ArcDirection::CW ArcDirection::CW,
); );
canvas.set_line_width(bend.width as f32); canvas.set_line_width(bend.width as f32);
canvas.stroke_path(path); canvas.stroke_path(path);
@ -584,7 +636,7 @@ fn render_times(
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32); let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
canvas.set_line_width(1.0); canvas.set_line_width(1.0);
canvas.set_stroke_style(ColorU::new(100, 100, 100, 255)); canvas.set_stroke_style(ColorU::new(100, 100, 100, 255));
canvas.stroke_rect(RectF::new(topleft, bottomright-topleft)); canvas.stroke_rect(RectF::new(topleft, bottomright - topleft));
} }
if let Some(ref mesh) = mesh { if let Some(ref mesh) = mesh {
@ -599,14 +651,8 @@ fn render_times(
}; };
let mut path = Path2D::new(); let mut path = Path2D::new();
path.move_to(vec2f( path.move_to(vec2f(start_point.x() as f32, start_point.y() as f32));
start_point.x() as f32, path.line_to(vec2f(end_point.x() as f32, end_point.y() as f32));
start_point.y() as f32
));
path.line_to(vec2f(
end_point.x() as f32,
end_point.y() as f32
));
canvas.set_stroke_style(color); canvas.set_stroke_style(color);
canvas.set_line_width(1.0); canvas.set_line_width(1.0);
canvas.stroke_path(path); canvas.stroke_path(path);
@ -614,9 +660,11 @@ fn render_times(
} }
//}); //});
let mut scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), let mut scene = SceneProxy::from_scene(
renderer.mode().level, canvas.into_canvas().into_scene(),
RayonExecutor); renderer.mode().level,
RayonExecutor,
);
scene.build_and_render(renderer, BuildOptions::default()); scene.build_and_render(renderer, BuildOptions::default());
window.gl_swap_window(); window.gl_swap_window();

View File

@ -200,6 +200,7 @@ impl<'a> visit::IntoEdges for &'a Mesh {
fn edges(self, node: Self::NodeId) -> Self::Edges { fn edges(self, node: Self::NodeId) -> Self::Edges {
Box::new( Box::new(
self.triangulation self.triangulation
// FIXME: node has to be converted to triangulation vertex (?)
.edges(node) .edges(node)
.flat_map(move |edge| edges(&self.triangulation, edge)), .flat_map(move |edge| edges(&self.triangulation, edge)),
) )

View File

@ -6,9 +6,9 @@ use petgraph::Direction::{Incoming, Outgoing};
use crate::graph::{ use crate::graph::{
DotIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, GenericIndex, DotIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, GenericIndex,
GetBand, GetEnds, GetNet, GetNodeIndex, GetOffset, GetWidth, Index, Interior, Label, GetBand, GetNet, GetNodeIndex, GetOffset, GetWidth, Index, Label, LooseBendIndex,
LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive,
MakePrimitive, Retag, Weight, Retag, Weight,
}; };
use crate::layout::Layout; use crate::layout::Layout;
use crate::math::{self, Circle}; use crate::math::{self, Circle};
@ -39,6 +39,10 @@ pub trait MakeShape {
fn shape(&self) -> Shape; fn shape(&self) -> Shape;
} }
pub trait GetInterior<T> {
fn interior(&self) -> Vec<T>;
}
pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T> { pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T> {
fn other_end(&self, end: F) -> F { fn other_end(&self, end: F) -> F {
let ends = self.ends(); let ends = self.ends();
@ -50,6 +54,10 @@ pub trait GetOtherEnd<F: GetNodeIndex, T: GetNodeIndex + Into<F>>: GetEnds<F, T>
} }
} }
pub trait GetEnds<F, T> {
fn ends(&self) -> (F, T);
}
pub trait GetWraparound: GetLayout + GetNodeIndex { pub trait GetWraparound: GetLayout + GetNodeIndex {
fn wraparound(&self) -> Option<LooseBendIndex>; fn wraparound(&self) -> Option<LooseBendIndex>;
} }
@ -59,12 +67,6 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
self.layout() self.layout()
.graph .graph
.neighbors_directed(self.node_index(), Incoming) .neighbors_directed(self.node_index(), Incoming)
.filter(|ni| {
self.layout()
.graph
.find_edge(self.node_index(), *ni)
.is_some()
})
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.layout() self.layout()
@ -72,7 +74,7 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex {
.edge_weight( .edge_weight(
self.layout() self.layout()
.graph .graph
.find_edge(self.node_index(), *ni) .find_edge(*ni, self.node_index())
.unwrap() .unwrap()
) )
.unwrap(), .unwrap(),
@ -249,7 +251,7 @@ impl<'a, W> GenericPrimitive<'a, W> {
} }
} }
impl<'a, W> Interior<Index> for GenericPrimitive<'a, W> { impl<'a, W> GetInterior<Index> for GenericPrimitive<'a, W> {
fn interior(&self) -> Vec<Index> { fn interior(&self) -> Vec<Index> {
vec![self.tagged_weight().retag(self.index.node_index())] vec![self.tagged_weight().retag(self.index.node_index())]
} }
@ -288,9 +290,7 @@ impl<'a> MakeShape for FixedDot<'a> {
}) })
} }
} }
impl<'a> GetFirstRail for FixedDot<'a> {} impl<'a> GetFirstRail for FixedDot<'a> {}
impl<'a> GetWraparound for FixedDot<'a> { impl<'a> GetWraparound for FixedDot<'a> {
fn wraparound(&self) -> Option<LooseBendIndex> { fn wraparound(&self) -> Option<LooseBendIndex> {
self.first_rail() self.first_rail()
@ -557,5 +557,6 @@ impl<'a> GetWraparound for LooseBend<'a> {
self.outer() self.outer()
} }
} }
impl<'a> GetCore for LooseBend<'a> {} impl<'a> GetCore for LooseBend<'a> {}
impl<'a> GetInnerOuter for LooseBend<'a> {} impl<'a> GetInnerOuter for LooseBend<'a> {}

View File

@ -112,148 +112,10 @@ impl Router {
_to: Point, _to: Point,
_observer: &mut impl RouterObserver, _observer: &mut impl RouterObserver,
) -> Result<Mesh, InsertionError> { ) -> Result<Mesh, InsertionError> {
/*let to_dot = if let Some(band) = self.layout.next_band(from) {
let to_dot = band.ends().1;
self.layout.remove_interior(&band);
self.layout.move_dot(to_dot, to);
to_dot
} else {
let from_weight = self.layout.primitive(from).weight();
self.layout
.add_fixed_dot(FixedDotWeight {
net: from_weight.net,
circle: Circle { pos: to, r: 2.0 },
})
.unwrap() // TODO.
};
self.enroute(from, to_dot, observer)*/
Ok(Mesh::new(&self.layout)) Ok(Mesh::new(&self.layout))
} }
/*pub fn squeeze_around_dot(
&mut self,
head: Head,
around: FixedDotIndex,
cw: bool,
width: f64,
) -> Result<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw().segbend_around_dot(head, around, cw, width)?;
self.layout
.reattach_bend(outer, head.segbend.as_ref().unwrap().bend);
self.reroute_outward(outer)?;
Ok(head)
}
pub fn squeeze_around_bend(
&mut self,
head: Head,
around: FixedBendIndex,
cw: bool,
width: f64,
) -> Result<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw().segbend_around_bend(head, around, cw, width)?;
self.layout
.reattach_bend(outer, head.segbend.as_ref().unwrap().bend);
self.reroute_outward(outer)?;
Ok(head)
}
fn reroute_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> {
let mut bows: Vec<Bow> = vec![];
let cw = self.layout.primitive(bend).weight().cw;
let mut cur_bend = bend;
loop {
bows.push(self.layout.bow(cur_bend));
cur_bend = match self.layout.primitive(cur_bend).outer() {
Some(new_bend) => new_bend,
None => break,
}
}
let core = self.layout.primitive(bend).core().unwrap();
let mut maybe_inner = self.layout.primitive(bend).inner();
for bow in &bows {
self.layout.remove_interior(bow);
}
for bow in &bows {
let ends = bow.ends();
let mut head = self.draw().start(ends.0);
let width = 5.0;
if let Some(inner) = maybe_inner {
head = self.draw().segbend_around_bend(head, inner, cw, width)?;
} else {
head = self.draw().segbend_around_dot(head, core, cw, width)?;
}
maybe_inner = head.segbend.as_ref().map(|segbend| segbend.bend);
self.draw().finish(head, ends.1, width)?;
self.relax_band(maybe_inner.unwrap());
}
Ok(())
}
fn relax_band(&mut self, bend: FixedBendIndex) {
let mut prev_bend = bend;
while let Some(cur_bend) = self.layout.primitive(prev_bend).find_prev_akin() {
if self.layout.primitive(cur_bend).cross_product() >= 0. {
self.release_bow(cur_bend);
}
prev_bend = cur_bend;
}
let mut prev_bend = bend;
while let Some(cur_bend) = self.layout.primitive(prev_bend).find_next_akin() {
if self.layout.primitive(cur_bend).cross_product() >= 0. {
self.release_bow(cur_bend);
}
prev_bend = cur_bend;
}
}
fn release_bow(&mut self, bend: FixedBendIndex) {
let bow = self.layout.bow(bend);
let ends = bow.ends();
self.layout.remove_interior(&bow);
let head = self.draw().start(ends.0);
let _ = self.draw().finish(head, ends.1, 5.0);
}
pub fn move_dot(&mut self, dot: FixedDotIndex, to: Point) -> Result<(), ()> {
self.layout.move_dot(dot, to)?;
if let Some(outer) = self.layout.primitive(dot).outer() {
self.reroute_outward(outer)?;
}
Ok(())
}*/
pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer { pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer {
Tracer::new(&mut self.layout, &self.rules, mesh) Tracer::new(&mut self.layout, &self.rules, mesh)
} }
/*pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {
self.mesh.edge_references().map(|edge| {
(
self.mesh.position(edge.source()),
self.mesh.position(edge.target()),
)
})
}*/
} }

View File

@ -19,6 +19,7 @@ impl Conditions {
} }
} }
#[derive(Debug, Default, Clone)]
pub struct Rules { pub struct Rules {
rulesets: [Option<HashMap<Conditions, Ruleset>>; 16], rulesets: [Option<HashMap<Conditions, Ruleset>>; 16],
} }
@ -55,6 +56,7 @@ impl Rules {
} }
} }
#[derive(Debug, Default, Clone)]
pub struct Ruleset { pub struct Ruleset {
pub length: Rule, pub length: Rule,
pub clearance: Rule, pub clearance: Rule,
@ -69,6 +71,7 @@ impl Ruleset {
} }
} }
#[derive(Debug, Default, Clone)]
pub struct Rule { pub struct Rule {
pub min: f64, pub min: f64,
pub opt: Option<f64>, pub opt: Option<f64>,

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
graph::{GetEnds, Index, Interior, LooseBendIndex, LooseDotIndex, LooseSegIndex}, graph::{Index, LooseBendIndex, LooseDotIndex, LooseSegIndex},
layout::Layout, layout::Layout,
primitive::{GetOtherEnd, LooseBend, LooseDot}, primitive::{GetEnds, GetInterior, GetOtherEnd, LooseBend, LooseDot},
}; };
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -20,7 +20,7 @@ impl Segbend {
} }
} }
impl Interior<Index> for Segbend { impl GetInterior<Index> for Segbend {
fn interior(&self) -> Vec<Index> { fn interior(&self) -> Vec<Index> {
vec![self.bend.into(), self.dot.into(), self.seg.into()] vec![self.bend.into(), self.dot.into(), self.seg.into()]
} }

View File

@ -1,11 +1,12 @@
use contracts::debug_ensures; use contracts::debug_ensures;
use crate::{ use crate::{
draw::{BareHead, Draw, Head, SegbendHead}, draw::Draw,
graph::{FixedDotIndex, GetNet, LooseBendIndex}, graph::{FixedDotIndex, GetNet, LooseBendIndex},
guide::{BareHead, Head, SegbendHead},
layout::{Band, Layout}, layout::{Band, Layout},
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
primitive::{GetFirstRail, GetInnerOuter}, primitive::{GetInnerOuter, GetWraparound},
rules::Rules, rules::Rules,
}; };
@ -109,12 +110,6 @@ impl<'a> Tracer<'a> {
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
let head = self.draw().segbend_around_dot(head, around.into(), width)?; let head = self.draw().segbend_around_dot(head, around.into(), width)?;
if let Some(first_rail) = self.layout.primitive(around).first_rail() {
self.layout.reattach_bend(first_rail, head.segbend.bend);
self.update_outward(head.segbend.bend);
}
Ok(head) Ok(head)
} }
@ -124,98 +119,13 @@ impl<'a> Tracer<'a> {
around: LooseBendIndex, around: LooseBendIndex,
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
let maybe_outer = self.layout.primitive(around).outer();
let head = self let head = self
.draw() .draw()
.segbend_around_bend(head, around.into(), width)?; .segbend_around_bend(head, around.into(), width)?;
if let Some(outer) = maybe_outer {
self.layout.reattach_bend(outer, head.segbend.bend);
self.update_outward(head.segbend.bend);
}
Ok(head) Ok(head)
} }
fn update_outward(&mut self, bend: LooseBendIndex) {
let mut rail = bend;
while let Some(outer) = self.layout.primitive(rail).outer() {
self.draw().update_bow(bend);
rail = outer;
}
}
/*fn redraw_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> {
let mut bows: Vec<Bow> = vec![];
let mut cur_bend = bend;
loop {
bows.push(self.layout.bow(cur_bend));
cur_bend = match self.layout.primitive(cur_bend).outer() {
Some(new_bend) => new_bend,
None => break,
}
}
let core = self.layout.primitive(bend).core().unwrap();
let mut maybe_inner = self.layout.primitive(bend).inner();
for bow in &bows {
self.layout.remove_interior(bow);
}
for bow in &bows {
let ends = bow.ends();
let head = self.draw().start(ends.0);
let width = 5.0;
let segbend_head = if let Some(inner) = maybe_inner {
self.draw().segbend_around_bend(head, inner.into(), width)?
} else {
self.draw().segbend_around_dot(head, core.into(), width)?
};
maybe_inner = Some(segbend_head.segbend.bend);
self.draw().finish(head, ends.1, width)?;
//self.relax_band(maybe_inner.unwrap());
}
Ok(())
}*/
/*fn relax_band(&mut self, bend: FixedBendIndex) {
let mut prev_bend = bend;
while let Some(cur_bend) = self.layout.primitive(prev_bend).prev_bend() {
if self.layout.primitive(cur_bend).cross_product() >= 0. {
self.release_bow(cur_bend);
}
prev_bend = cur_bend;
}
let mut prev_bend = bend;
while let Some(cur_bend) = self.layout.primitive(prev_bend).next_bend() {
if self.layout.primitive(cur_bend).cross_product() >= 0. {
self.release_bow(cur_bend);
}
prev_bend = cur_bend;
}
}*/
/*fn release_bow(&mut self, bend: FixedBendIndex) {
let bow = self.layout.bow(bend);
let ends = bow.ends();
self.layout.remove_interior(&bow);
let head = self.draw().start(ends.0);
let _ = self.draw().finish(head, ends.1, 5.0);
}*/
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() - 1))] #[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() - 1))]
#[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))] #[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))]
pub fn undo_step(&mut self, trace: &mut Trace) -> Result<(), ()> { pub fn undo_step(&mut self, trace: &mut Trace) -> Result<(), ()> {

View File

@ -143,8 +143,11 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<
} }
} }
impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>> impl<
visit::IntoEdges for &'a Triangulation<I, W> 'a,
I: Copy + PartialEq + GetNodeIndex + std::fmt::Debug,
W: GetVertexIndex<I> + HasPosition<Scalar = f64>,
> visit::IntoEdges for &'a Triangulation<I, W>
{ {
type Edges = Box<dyn Iterator<Item = TriangulationEdgeReference<I>> + 'a>; type Edges = Box<dyn Iterator<Item = TriangulationEdgeReference<I>> + 'a>;