mirror of https://codeberg.org/topola/topola.git
layout: inflate infringement-testing shapes and bboxes
This results in unintentional infringements of linked traces. I'll fix this in subsequent commits by increasing the number of
This commit is contained in:
parent
b66995b30c
commit
d5d2ffd9d8
|
|
@ -7,9 +7,10 @@ use crate::math::{self, Circle};
|
||||||
#[enum_dispatch]
|
#[enum_dispatch]
|
||||||
pub trait ShapeTrait {
|
pub trait ShapeTrait {
|
||||||
fn priority(&self) -> u64;
|
fn priority(&self) -> u64;
|
||||||
|
fn inflate(&self, margin: f64) -> Shape;
|
||||||
fn center(&self) -> Point;
|
fn center(&self) -> Point;
|
||||||
fn intersects(&self, other: &Shape) -> bool;
|
fn intersects(&self, other: &Shape) -> bool;
|
||||||
fn envelope(&self) -> AABB<[f64; 2]>;
|
fn envelope(&self, margin: f64) -> AABB<[f64; 2]>;
|
||||||
fn width(&self) -> f64;
|
fn width(&self) -> f64;
|
||||||
fn length(&self) -> f64;
|
fn length(&self) -> f64;
|
||||||
}
|
}
|
||||||
|
|
@ -33,6 +34,15 @@ impl ShapeTrait for DotShape {
|
||||||
3
|
3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inflate(&self, margin: f64) -> Shape {
|
||||||
|
Shape::Dot(DotShape {
|
||||||
|
c: Circle {
|
||||||
|
pos: self.c.pos,
|
||||||
|
r: self.c.r + margin,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn center(&self) -> Point {
|
fn center(&self) -> Point {
|
||||||
self.c.pos
|
self.c.pos
|
||||||
}
|
}
|
||||||
|
|
@ -63,10 +73,16 @@ impl ShapeTrait for DotShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn envelope(&self) -> AABB<[f64; 2]> {
|
fn envelope(&self, margin: f64) -> AABB<[f64; 2]> {
|
||||||
AABB::from_corners(
|
AABB::from_corners(
|
||||||
[self.c.pos.x() - self.c.r, self.c.pos.y() - self.c.r],
|
[
|
||||||
[self.c.pos.x() + self.c.r, self.c.pos.y() + self.c.r],
|
self.c.pos.x() - self.c.r - margin,
|
||||||
|
self.c.pos.y() - self.c.r - margin,
|
||||||
|
],
|
||||||
|
[
|
||||||
|
self.c.pos.x() + self.c.r + margin,
|
||||||
|
self.c.pos.y() + self.c.r + margin,
|
||||||
|
],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,6 +124,16 @@ impl ShapeTrait for SegShape {
|
||||||
2
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inflate(&self, margin: f64) -> Shape {
|
||||||
|
let mag = (self.to - self.from).euclidean_distance(&point! {x: 0.0, y: 0.0});
|
||||||
|
|
||||||
|
Shape::Seg(SegShape {
|
||||||
|
from: self.from + (self.from - self.to) / mag * margin,
|
||||||
|
to: self.to + (self.to - self.from) / mag * margin,
|
||||||
|
width: self.width + 2.0 * margin,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn center(&self) -> Point {
|
fn center(&self) -> Point {
|
||||||
(self.from + self.to) / 2.0
|
(self.from + self.to) / 2.0
|
||||||
}
|
}
|
||||||
|
|
@ -143,14 +169,20 @@ impl ShapeTrait for SegShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn envelope(&self) -> AABB<[f64; 2]> {
|
fn envelope(&self, margin: f64) -> AABB<[f64; 2]> {
|
||||||
let points: Vec<[f64; 2]> = self
|
let points: Vec<[f64; 2]> = self
|
||||||
.polygon()
|
.polygon()
|
||||||
.exterior()
|
.exterior()
|
||||||
.points()
|
.points()
|
||||||
.map(|p| [p.x(), p.y()])
|
.map(|p| [p.x(), p.y()])
|
||||||
.collect();
|
.collect();
|
||||||
AABB::<[f64; 2]>::from_points(points.iter())
|
|
||||||
|
let aabb = AABB::<[f64; 2]>::from_points(points.iter());
|
||||||
|
|
||||||
|
// Inflate.
|
||||||
|
let lower = [aabb.lower()[0] - margin, aabb.lower()[1] - margin];
|
||||||
|
let upper = [aabb.upper()[0] + margin, aabb.upper()[1] + margin];
|
||||||
|
AABB::<[f64; 2]>::from_corners(lower, upper)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn width(&self) -> f64 {
|
fn width(&self) -> f64 {
|
||||||
|
|
@ -203,6 +235,18 @@ impl ShapeTrait for BendShape {
|
||||||
1
|
1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn inflate(&self, margin: f64) -> Shape {
|
||||||
|
Shape::Bend(BendShape {
|
||||||
|
from: self.from, // TODO: Is not inflated for now.
|
||||||
|
to: self.to, // TODO: Is not inflated for now.
|
||||||
|
c: Circle {
|
||||||
|
pos: self.c.pos,
|
||||||
|
r: self.c.r - margin,
|
||||||
|
},
|
||||||
|
width: self.width + 2.0 * margin,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fn center(&self) -> Point {
|
fn center(&self) -> Point {
|
||||||
let sum = (self.from - self.c.pos) + (self.to - self.c.pos);
|
let sum = (self.from - self.c.pos) + (self.to - self.c.pos);
|
||||||
self.c.pos + (sum / sum.euclidean_distance(&point! {x: 0.0, y: 0.0})) * self.c.r
|
self.c.pos + (sum / sum.euclidean_distance(&point! {x: 0.0, y: 0.0})) * self.c.r
|
||||||
|
|
@ -245,7 +289,7 @@ impl ShapeTrait for BendShape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn envelope(&self) -> AABB<[f64; 2]> {
|
fn envelope(&self, margin: f64) -> AABB<[f64; 2]> {
|
||||||
let halfwidth = self.c.r + self.width;
|
let halfwidth = self.c.r + self.width;
|
||||||
AABB::from_corners(
|
AABB::from_corners(
|
||||||
[self.c.pos.x() - halfwidth, self.c.pos.y() - halfwidth],
|
[self.c.pos.x() - halfwidth, self.c.pos.y() - halfwidth],
|
||||||
|
|
@ -258,6 +302,9 @@ impl ShapeTrait for BendShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn length(&self) -> f64 {
|
fn length(&self) -> f64 {
|
||||||
|
// TODO: Not valid for inflated bends, as currently `from` and `to` of these don't lie on
|
||||||
|
// teir circles.
|
||||||
|
|
||||||
// We obtain the angle from the law of cosines and multiply with radius to get the length.
|
// We obtain the angle from the law of cosines and multiply with radius to get the length.
|
||||||
let d = self.to.euclidean_distance(&self.from);
|
let d = self.to.euclidean_distance(&self.from);
|
||||||
|
|
||||||
|
|
@ -272,6 +319,6 @@ impl ShapeTrait for BendShape {
|
||||||
impl RTreeObject for Shape {
|
impl RTreeObject for Shape {
|
||||||
type Envelope = AABB<[f64; 2]>;
|
type Envelope = AABB<[f64; 2]>;
|
||||||
fn envelope(&self) -> Self::Envelope {
|
fn envelope(&self) -> Self::Envelope {
|
||||||
return ShapeTrait::envelope(self);
|
return ShapeTrait::envelope(self, 0.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -901,20 +901,33 @@ impl<R: RulesTrait> Layout<R> {
|
||||||
node: GeometryIndex,
|
node: GeometryIndex,
|
||||||
except: &[GeometryIndex],
|
except: &[GeometryIndex],
|
||||||
) -> Option<Infringement> {
|
) -> Option<Infringement> {
|
||||||
let shape = node.primitive(self).shape();
|
let limiting_shape = node
|
||||||
|
.primitive(self)
|
||||||
|
.shape()
|
||||||
|
.inflate(self.rules.clearance_net_limit(node.primitive(self).net()));
|
||||||
|
let mut inflated_shape = limiting_shape; // Unused temporary value just for initialization.
|
||||||
|
let conditions = node.primitive(self).conditions();
|
||||||
|
|
||||||
self.geometry_with_rtree
|
self.geometry_with_rtree
|
||||||
.rtree()
|
.rtree()
|
||||||
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
|
.locate_in_envelope_intersecting(&RTreeObject::envelope(&limiting_shape))
|
||||||
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
|
.filter(|wrapper| !self.are_connectable(node, wrapper.data))
|
||||||
.filter(|wrapper| !except.contains(&wrapper.data))
|
.filter(|wrapper| !except.contains(&wrapper.data))
|
||||||
.filter(|wrapper| shape.intersects(wrapper.geom()))
|
.filter(|wrapper| {
|
||||||
|
let infringee_conditions = wrapper.data.primitive(self).conditions();
|
||||||
|
|
||||||
|
inflated_shape = node
|
||||||
|
.primitive(self)
|
||||||
|
.shape()
|
||||||
|
.inflate(self.rules.clearance(&conditions, &infringee_conditions));
|
||||||
|
|
||||||
|
inflated_shape.intersects(wrapper.geom())
|
||||||
|
})
|
||||||
.map(|wrapper| wrapper.data)
|
.map(|wrapper| wrapper.data)
|
||||||
.next()
|
.next()
|
||||||
.and_then(|infringee| Some(Infringement(shape, infringee)))
|
.and_then(|infringee| Some(Infringement(inflated_shape, infringee)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Collision and infringement are the same for now. Change this.
|
|
||||||
#[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_collision(&self, node: GeometryIndex) -> Option<Collision> {
|
fn detect_collision(&self, node: GeometryIndex) -> Option<Collision> {
|
||||||
|
|
|
||||||
|
|
@ -16,10 +16,5 @@ pub struct Conditions {
|
||||||
|
|
||||||
pub trait RulesTrait {
|
pub trait RulesTrait {
|
||||||
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
|
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
|
||||||
/*fn clearance_limit(
|
fn clearance_net_limit(&self, net: i64) -> f64;
|
||||||
&self,
|
|
||||||
layer: String,
|
|
||||||
netclass: String,
|
|
||||||
conditions: &PrimitiveConditions,
|
|
||||||
) -> f64;*/
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
21
src/main.rs
21
src/main.rs
|
|
@ -70,14 +70,17 @@ impl RulesTrait for SimpleRules {
|
||||||
.unwrap_or(&10.0)
|
.unwrap_or(&10.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*fn clearance_limit(
|
fn clearance_net_limit(&self, net: i64) -> f64 {
|
||||||
&self,
|
let mut highest_clearance = 0.0;
|
||||||
_layer: String,
|
|
||||||
_netclass: String,
|
for ((net1, net2), clearance) in self.net_clearances.iter() {
|
||||||
_conditions: &PrimitiveConditions,
|
if *net1 == net || *net2 == net {
|
||||||
) -> f64 {
|
highest_clearance = *clearance;
|
||||||
3.0
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
|
highest_clearance
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clunky enum to work around borrow checker.
|
// Clunky enum to work around borrow checker.
|
||||||
|
|
@ -805,7 +808,7 @@ fn render_shape(canvas: &mut CanvasRenderingContext2D, shape: &Shape, color: Col
|
||||||
canvas.stroke_path(path);
|
canvas.stroke_path(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let envelope = ShapeTrait::envelope(shape);
|
let envelope = ShapeTrait::envelope(shape, 0.0);
|
||||||
// XXX: points represented as arrays can't be conveniently converted to vector types
|
// 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 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);
|
let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue