mirror of https://codeberg.org/topola/topola.git
layout,main: display attempted shapes that caused probe to fail
This commit is contained in:
parent
da8af817bf
commit
81e316397f
|
|
@ -31,7 +31,7 @@ pub enum LayoutException {
|
||||||
NoTangents(NoTangents),
|
NoTangents(NoTangents),
|
||||||
Infringement(Infringement),
|
Infringement(Infringement),
|
||||||
Collision(Collision),
|
Collision(Collision),
|
||||||
AreConnected(AreConnected),
|
IsConnected(IsConnected),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<NoTangents> for LayoutException {
|
impl From<NoTangents> for LayoutException {
|
||||||
|
|
@ -52,20 +52,20 @@ impl From<Collision> for LayoutException {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<AreConnected> for LayoutException {
|
impl From<IsConnected> for LayoutException {
|
||||||
fn from(err: AreConnected) -> Self {
|
fn from(err: IsConnected) -> Self {
|
||||||
LayoutException::AreConnected(err)
|
LayoutException::IsConnected(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Infringement(pub Index, pub Index);
|
pub struct Infringement(pub Shape, pub Index);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Collision(pub Index, pub Index);
|
pub struct Collision(pub Shape, pub Index);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct AreConnected(pub Weight, pub Index);
|
pub struct IsConnected(pub i64, pub Index);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct Band {
|
pub struct Band {
|
||||||
|
|
@ -562,9 +562,11 @@ impl Layout {
|
||||||
infringables: &[Index],
|
infringables: &[Index],
|
||||||
) -> Result<LooseBendIndex, LayoutException> {
|
) -> Result<LooseBendIndex, LayoutException> {
|
||||||
// It makes no sense to wrap something around or under one of its connectables.
|
// It makes no sense to wrap something around or under one of its connectables.
|
||||||
if self.bands[weight.band].net == around.primitive(self).net() {
|
let net = self.bands[weight.band].net;
|
||||||
return Err(LayoutException::AreConnected(AreConnected(
|
//
|
||||||
weight.into(),
|
if net == around.primitive(self).net() {
|
||||||
|
return Err(LayoutException::IsConnected(IsConnected(
|
||||||
|
net,
|
||||||
around.into(),
|
around.into(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -574,9 +576,9 @@ impl Layout {
|
||||||
WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(),
|
WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(),
|
||||||
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
|
WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(),
|
||||||
} {
|
} {
|
||||||
if self.bands[weight.band].net == wraparound.primitive(self).net() {
|
if net == wraparound.primitive(self).net() {
|
||||||
return Err(LayoutException::AreConnected(AreConnected(
|
return Err(LayoutException::IsConnected(IsConnected(
|
||||||
weight.into(),
|
net,
|
||||||
wraparound.into(),
|
wraparound.into(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -799,7 +801,7 @@ impl Layout {
|
||||||
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
||||||
.map(|wrapper| wrapper.data)
|
.map(|wrapper| wrapper.data)
|
||||||
.next()
|
.next()
|
||||||
.and_then(|infringee| Some(Infringement(index, infringee)))
|
.and_then(|infringee| Some(Infringement(shape, infringee)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Collision and infringement are the same for now. Change this.
|
// TODO: Collision and infringement are the same for now. Change this.
|
||||||
|
|
@ -815,7 +817,7 @@ impl Layout {
|
||||||
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
||||||
.map(|wrapper| wrapper.data)
|
.map(|wrapper| wrapper.data)
|
||||||
.next()
|
.next()
|
||||||
.and_then(|collidee| Some(Collision(index, collidee)))
|
.and_then(|collidee| Some(Collision(shape, collidee)))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
|
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
|
||||||
|
|
|
||||||
132
src/main.rs
132
src/main.rs
|
|
@ -39,7 +39,7 @@ 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::{ArcDirection, CanvasRenderingContext2D, ColorU, FillRule};
|
||||||
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
|
use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D};
|
||||||
use pathfinder_geometry::rect::RectF;
|
use pathfinder_geometry::rect::RectF;
|
||||||
use pathfinder_geometry::vector::{vec2f, vec2i};
|
use pathfinder_geometry::vector::{vec2f, vec2i};
|
||||||
|
|
@ -116,6 +116,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&trace.path,
|
&trace.path,
|
||||||
&[],
|
&[],
|
||||||
|
&[],
|
||||||
40,
|
40,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -134,6 +135,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&path,
|
&path,
|
||||||
&[],
|
&[],
|
||||||
|
&[],
|
||||||
10,
|
10,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -145,15 +147,13 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
_edge: MeshEdgeReference,
|
_edge: MeshEdgeReference,
|
||||||
result: Result<(), DrawException>,
|
result: Result<(), DrawException>,
|
||||||
) {
|
) {
|
||||||
let highlight = match result {
|
let (ghosts, highlighteds, delay) = match result {
|
||||||
Err(DrawException::CannotWrapAround(
|
Err(DrawException::CannotWrapAround(
|
||||||
..,
|
..,
|
||||||
LayoutException::Infringement(Infringement(.., infringee1)),
|
LayoutException::Infringement(Infringement(shape1, infringee1)),
|
||||||
LayoutException::Infringement(Infringement(.., infringee2)),
|
LayoutException::Infringement(Infringement(shape2, infringee2)),
|
||||||
)) => {
|
)) => (vec![shape1, shape2], vec![infringee1, infringee2], 30),
|
||||||
vec![infringee1, infringee2]
|
_ => (vec![], vec![], 10),
|
||||||
}
|
|
||||||
_ => vec![],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render_times(
|
render_times(
|
||||||
|
|
@ -166,8 +166,9 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||||
None,
|
None,
|
||||||
Some(tracer.mesh.clone()),
|
Some(tracer.mesh.clone()),
|
||||||
&trace.path,
|
&trace.path,
|
||||||
&highlight,
|
&ghosts,
|
||||||
10,
|
&highlighteds,
|
||||||
|
delay,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -500,6 +501,7 @@ fn main() {
|
||||||
None,
|
None,
|
||||||
&[],
|
&[],
|
||||||
&[],
|
&[],
|
||||||
|
&[],
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -532,6 +534,7 @@ fn main() {
|
||||||
None,
|
None,
|
||||||
&[],
|
&[],
|
||||||
&[],
|
&[],
|
||||||
|
&[],
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
@ -552,6 +555,7 @@ fn main() {
|
||||||
None,
|
None,
|
||||||
&[],
|
&[],
|
||||||
&[],
|
&[],
|
||||||
|
&[],
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -566,7 +570,8 @@ fn render_times(
|
||||||
follower: Option<LooseDotIndex>,
|
follower: Option<LooseDotIndex>,
|
||||||
mut mesh: Option<Mesh>,
|
mut mesh: Option<Mesh>,
|
||||||
path: &[VertexIndex],
|
path: &[VertexIndex],
|
||||||
highlight: &[Index],
|
ghosts: &[Shape],
|
||||||
|
highlighteds: &[Index],
|
||||||
times: i64,
|
times: i64,
|
||||||
) {
|
) {
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
|
|
@ -621,62 +626,18 @@ fn render_times(
|
||||||
|
|
||||||
//let result = panic::catch_unwind(|| {
|
//let result = panic::catch_unwind(|| {
|
||||||
for node in layout.nodes() {
|
for node in layout.nodes() {
|
||||||
let color = if highlight.contains(&node) {
|
let color = if highlighteds.contains(&node) {
|
||||||
ColorU::new(255, 100, 100, 255)
|
ColorU::new(255, 100, 100, 255)
|
||||||
} else {
|
} else {
|
||||||
ColorU::new(200, 52, 52, 255)
|
ColorU::new(200, 52, 52, 255)
|
||||||
};
|
};
|
||||||
|
|
||||||
canvas.set_stroke_style(color);
|
|
||||||
canvas.set_fill_style(color);
|
|
||||||
|
|
||||||
let shape = node.primitive(layout).shape();
|
let shape = node.primitive(layout).shape();
|
||||||
|
render_shape(&mut canvas, &shape, color);
|
||||||
|
}
|
||||||
|
|
||||||
match shape {
|
for ghost in ghosts {
|
||||||
Shape::Dot(dot) => {
|
render_shape(&mut canvas, &ghost, ColorU::new(75, 75, 150, 255));
|
||||||
let mut path = Path2D::new();
|
|
||||||
path.ellipse(
|
|
||||||
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
|
|
||||||
dot.c.r as f32,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
std::f32::consts::TAU,
|
|
||||||
);
|
|
||||||
canvas.fill_path(path, FillRule::Winding);
|
|
||||||
}
|
|
||||||
Shape::Seg(seg) => {
|
|
||||||
let mut path = Path2D::new();
|
|
||||||
path.move_to(vec2f(seg.from.x() 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.stroke_path(path);
|
|
||||||
}
|
|
||||||
Shape::Bend(bend) => {
|
|
||||||
let delta1 = bend.from - bend.c.pos;
|
|
||||||
let delta2 = bend.to - bend.c.pos;
|
|
||||||
|
|
||||||
let angle1 = delta1.y().atan2(delta1.x());
|
|
||||||
let angle2 = delta2.y().atan2(delta2.x());
|
|
||||||
|
|
||||||
let mut path = Path2D::new();
|
|
||||||
path.arc(
|
|
||||||
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
|
|
||||||
bend.circle().r as f32,
|
|
||||||
angle1 as f32,
|
|
||||||
angle2 as f32,
|
|
||||||
ArcDirection::CW,
|
|
||||||
);
|
|
||||||
canvas.set_line_width(bend.width as f32);
|
|
||||||
canvas.stroke_path(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let envelope = ShapeTrait::envelope(&shape);
|
|
||||||
// XXX: points represented as arrays can't be conveniently converted to vector types
|
|
||||||
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
|
|
||||||
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
|
|
||||||
canvas.set_line_width(1.0);
|
|
||||||
canvas.set_stroke_style(ColorU::new(100, 100, 100, 255));
|
|
||||||
canvas.stroke_rect(RectF::new(topleft, bottomright - topleft));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mesh) = mesh {
|
if let Some(ref mesh) = mesh {
|
||||||
|
|
@ -723,3 +684,54 @@ fn render_times(
|
||||||
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
|
::std::thread::sleep(Duration::new(0, 1_000_000_000u32 / 60));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_shape(canvas: &mut CanvasRenderingContext2D, shape: &Shape, color: ColorU) {
|
||||||
|
canvas.set_stroke_style(color);
|
||||||
|
canvas.set_fill_style(color);
|
||||||
|
|
||||||
|
match shape {
|
||||||
|
Shape::Dot(dot) => {
|
||||||
|
let mut path = Path2D::new();
|
||||||
|
path.ellipse(
|
||||||
|
vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32),
|
||||||
|
dot.c.r as f32,
|
||||||
|
0.0,
|
||||||
|
0.0,
|
||||||
|
std::f32::consts::TAU,
|
||||||
|
);
|
||||||
|
canvas.fill_path(path, FillRule::Winding);
|
||||||
|
}
|
||||||
|
Shape::Seg(seg) => {
|
||||||
|
let mut path = Path2D::new();
|
||||||
|
path.move_to(vec2f(seg.from.x() 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.stroke_path(path);
|
||||||
|
}
|
||||||
|
Shape::Bend(bend) => {
|
||||||
|
let delta1 = bend.from - bend.c.pos;
|
||||||
|
let delta2 = bend.to - bend.c.pos;
|
||||||
|
|
||||||
|
let angle1 = delta1.y().atan2(delta1.x());
|
||||||
|
let angle2 = delta2.y().atan2(delta2.x());
|
||||||
|
|
||||||
|
let mut path = Path2D::new();
|
||||||
|
path.arc(
|
||||||
|
vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32),
|
||||||
|
bend.circle().r as f32,
|
||||||
|
angle1 as f32,
|
||||||
|
angle2 as f32,
|
||||||
|
ArcDirection::CW,
|
||||||
|
);
|
||||||
|
canvas.set_line_width(bend.width as f32);
|
||||||
|
canvas.stroke_path(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let envelope = ShapeTrait::envelope(shape);
|
||||||
|
// XXX: points represented as arrays can't be conveniently converted to vector types
|
||||||
|
let topleft = vec2f(envelope.lower()[0] as f32, envelope.lower()[1] as f32);
|
||||||
|
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
|
||||||
|
canvas.set_line_width(1.0);
|
||||||
|
canvas.set_stroke_style(ColorU::new(100, 100, 100, 255));
|
||||||
|
canvas.stroke_rect(RectF::new(topleft, bottomright - topleft));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue