mirror of https://codeberg.org/topola/topola.git
Implement routing *into* dots
This commit is contained in:
parent
cf6460a3db
commit
dfcfc99413
148
src/layout.rs
148
src/layout.rs
|
|
@ -30,7 +30,8 @@ impl Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn route_around(&mut self, from: DotIndex, around: DotIndex, cw: bool, width: f64) -> DotIndex {
|
pub fn route_around(&mut self, from: DotIndex, around: DotIndex, cw: bool, width: f64) -> DotIndex {
|
||||||
let maybe_bend = self.mesh.bend(from);
|
let from_circle = self.head_guidecircle(from, width);
|
||||||
|
let around_circle = self.mesh.weight(Index::Dot(around)).as_dot().unwrap().circle;
|
||||||
|
|
||||||
let conditions = Conditions {
|
let conditions = Conditions {
|
||||||
lower_net: None,
|
lower_net: None,
|
||||||
|
|
@ -39,56 +40,109 @@ impl Layout {
|
||||||
zone: None,
|
zone: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let from_circle = match maybe_bend {
|
let to_circle = self.circle_shell(around_circle, width + 5.0, conditions);
|
||||||
Some(bend) => {
|
|
||||||
let from_around = self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().around;
|
let maybe_bend = self.mesh.bend(from);
|
||||||
let circle = self.mesh.weight(Index::Dot(from_around)).as_dot().unwrap().circle;
|
let from_cw = match maybe_bend {
|
||||||
self.guidecircle(circle, width + 5.0, conditions)
|
Some(bend) => Some(self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().cw),
|
||||||
}
|
None => None,
|
||||||
None => Circle {
|
|
||||||
pos: self.mesh.weight(Index::Dot(from)).as_dot().unwrap().circle.pos,
|
|
||||||
r: 0.0,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
let around_circle = self.mesh.weight(Index::Dot(around)).as_dot().unwrap().circle;
|
|
||||||
|
|
||||||
let to_circle = self.guidecircle(around_circle, width + 5.0, conditions);
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw));
|
||||||
let tg_pt_pairs = math::tangent_points(from_circle, to_circle);
|
|
||||||
|
|
||||||
for tg_pt_pair in tg_pt_pairs {
|
|
||||||
if let Some(bend) = maybe_bend {
|
|
||||||
let start_cross = math::cross_product(tg_pt_pair.0, tg_pt_pair.1, from_circle.pos);
|
|
||||||
|
|
||||||
if (self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().cw && start_cross <= 0.0)
|
|
||||||
|| (!self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().cw && start_cross >= 0.0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let stop_cross = math::cross_product(tg_pt_pair.0, tg_pt_pair.1, to_circle.pos);
|
|
||||||
|
|
||||||
if (cw && stop_cross <= 0.0) || (!cw && stop_cross >= 0.0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if maybe_bend.is_some() {
|
if maybe_bend.is_some() {
|
||||||
self.stretch_dangling_bend(from, tg_pt_pair.0);
|
self.stretch_head_bend(from, tangent_points.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.route_seg_bend(from, around, tg_pt_pair.1, cw, width);
|
self.route_seg_bend(from, around, tangent_points.1, cw, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable!();
|
pub fn route_to(&mut self, from: DotIndex, to: DotIndex, width: f64) -> DotIndex {
|
||||||
|
let from_circle = self.head_guidecircle(from, width);
|
||||||
|
|
||||||
|
let conditions = Conditions {
|
||||||
|
lower_net: None,
|
||||||
|
higher_net: None,
|
||||||
|
layer: None,
|
||||||
|
zone: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let to_circle = Circle {
|
||||||
|
pos: self.mesh.weight(Index::Dot(to)).as_dot().unwrap().circle.pos,
|
||||||
|
r: 0.0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let maybe_bend = self.mesh.bend(from);
|
||||||
|
let from_cw = match maybe_bend {
|
||||||
|
Some(bend) => Some(self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().cw),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None);
|
||||||
|
|
||||||
|
if maybe_bend.is_some() {
|
||||||
|
self.stretch_head_bend(from, tangent_points.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn guidecircle(&self, circle: Circle, width: f64, conditions: Conditions) -> Circle {
|
self.add_seg(from, to, width);
|
||||||
|
to
|
||||||
|
}
|
||||||
|
|
||||||
|
fn route_seg_bend(&mut self, from: DotIndex, around: DotIndex, to: Point, cw: bool, width: f64) -> DotIndex {
|
||||||
|
let bend_from = self.route_seg(from, to, width);
|
||||||
|
let bend_to = self.add_dot(*self.mesh.primitive(Index::Dot(bend_from)).weight.as_dot().unwrap());
|
||||||
|
let from_primitive = self.mesh.primitive(Index::Dot(from));
|
||||||
|
let net = from_primitive.weight.as_dot().unwrap().net;
|
||||||
|
|
||||||
|
let bend = self.mesh.add_bend(bend_from, bend_to, BendWeight {net, around, cw});
|
||||||
|
bend_to
|
||||||
|
}
|
||||||
|
|
||||||
|
fn route_seg(&mut self, from: DotIndex, to: Point, width: f64) -> DotIndex {
|
||||||
|
let from_primitive = self.mesh.primitive(Index::Dot(from));
|
||||||
|
let net = from_primitive.weight.as_dot().unwrap().net;
|
||||||
|
|
||||||
|
assert!(width <= from_primitive.weight.as_dot().unwrap().circle.r * 2.0);
|
||||||
|
|
||||||
|
let to_index = self.mesh.add_dot(DotWeight {
|
||||||
|
net,
|
||||||
|
circle: Circle {pos: to, r: width / 2.0},
|
||||||
|
});
|
||||||
|
self.mesh.add_seg(from, to_index, SegWeight {net, width});
|
||||||
|
to_index
|
||||||
|
}
|
||||||
|
|
||||||
|
fn head_guidecircle(&self, head: DotIndex, width: f64) -> Circle {
|
||||||
|
let maybe_bend = self.mesh.bend(head);
|
||||||
|
|
||||||
|
let conditions = Conditions {
|
||||||
|
lower_net: None,
|
||||||
|
higher_net: None,
|
||||||
|
layer: None,
|
||||||
|
zone: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
match maybe_bend {
|
||||||
|
Some(bend) => {
|
||||||
|
let head_around = self.mesh.weight(Index::Bend(bend)).as_bend().unwrap().around;
|
||||||
|
let circle = self.mesh.weight(Index::Dot(head_around)).as_dot().unwrap().circle;
|
||||||
|
self.circle_shell(circle, width + 5.0, conditions)
|
||||||
|
},
|
||||||
|
None => Circle {
|
||||||
|
pos: self.mesh.weight(Index::Dot(head)).as_dot().unwrap().circle.pos,
|
||||||
|
r: 0.0,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn circle_shell(&self, circle: Circle, width: f64, conditions: Conditions) -> Circle {
|
||||||
Circle {
|
Circle {
|
||||||
pos: circle.pos,
|
pos: circle.pos,
|
||||||
r: circle.r + width + self.rules.ruleset(conditions).clearance.min,
|
r: circle.r + width + self.rules.ruleset(conditions).clearance.min,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stretch_dangling_bend(&mut self, dot: DotIndex, to: Point) {
|
fn stretch_head_bend(&mut self, dot: DotIndex, to: Point) {
|
||||||
let bend = self.mesh.bend(dot).unwrap();
|
let bend = self.mesh.bend(dot).unwrap();
|
||||||
let dot_weight = *self.mesh.weight(Index::Dot(dot)).as_dot().unwrap();
|
let dot_weight = *self.mesh.weight(Index::Dot(dot)).as_dot().unwrap();
|
||||||
let bend_weight = *self.mesh.weight(Index::Bend(bend)).as_bend().unwrap();
|
let bend_weight = *self.mesh.weight(Index::Bend(bend)).as_bend().unwrap();
|
||||||
|
|
@ -111,30 +165,6 @@ impl Layout {
|
||||||
self.mesh.add_bend(*fixed_dot.as_dot().unwrap(), new_dot, bend_weight);
|
self.mesh.add_bend(*fixed_dot.as_dot().unwrap(), new_dot, bend_weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn route_seg_bend(&mut self, from: DotIndex, around: DotIndex, to: Point, cw: bool, width: f64) -> DotIndex {
|
|
||||||
let bend_from = self.route_seg(from, to, width);
|
|
||||||
let bend_to = self.add_dot(*self.mesh.primitive(Index::Dot(bend_from)).weight.as_dot().unwrap());
|
|
||||||
let from_primitive = self.mesh.primitive(Index::Dot(from));
|
|
||||||
let net = from_primitive.weight.as_dot().unwrap().net;
|
|
||||||
|
|
||||||
let bend = self.mesh.add_bend(bend_from, bend_to, BendWeight {net, around, cw});
|
|
||||||
bend_to
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn route_seg(&mut self, from: DotIndex, to: Point, width: f64) -> DotIndex {
|
|
||||||
let from_primitive = self.mesh.primitive(Index::Dot(from));
|
|
||||||
let net = from_primitive.weight.as_dot().unwrap().net;
|
|
||||||
|
|
||||||
assert!(width <= from_primitive.weight.as_dot().unwrap().circle.r * 2.0);
|
|
||||||
|
|
||||||
let to_index = self.mesh.add_dot(DotWeight {
|
|
||||||
net,
|
|
||||||
circle: Circle {pos: to, r: width / 2.0},
|
|
||||||
});
|
|
||||||
self.mesh.add_seg(from, to_index, SegWeight {net, width});
|
|
||||||
to_index
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
||||||
self.mesh.add_dot(weight)
|
self.mesh.add_dot(weight)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ fn main() {
|
||||||
let index5 = layout.route_around(index4, index3, false, 5.0);
|
let index5 = layout.route_around(index4, index3, false, 5.0);
|
||||||
|
|
||||||
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
|
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
|
||||||
let index7 = layout.route_around(index5, index6, false, 5.0);
|
let index7 = layout.route_to(index5, index6, 5.0);
|
||||||
|
|
||||||
'running: loop {
|
'running: loop {
|
||||||
i = (i + 1) % 255;
|
i = (i + 1) % 255;
|
||||||
|
|
@ -113,6 +113,7 @@ fn main() {
|
||||||
angle2.to_degrees() as i16,
|
angle2.to_degrees() as i16,
|
||||||
Color::RGB(200, 52, 52));
|
Color::RGB(200, 52, 52));
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
42
src/math.rs
42
src/math.rs
|
|
@ -23,7 +23,7 @@ impl Sub for Circle {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tangent(center: Point, r1: f64, r2: f64) -> Line {
|
fn _tangent(center: Point, r1: f64, r2: f64) -> Line {
|
||||||
let epsilon = 1e-9;
|
let epsilon = 1e-9;
|
||||||
let dr = r2 - r1;
|
let dr = r2 - r1;
|
||||||
let norm = center.x() * center.x() + center.y() * center.y();
|
let norm = center.x() * center.x() + center.y() * center.y();
|
||||||
|
|
@ -42,12 +42,12 @@ fn tangent(center: Point, r1: f64, r2: f64) -> Line {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tangents(circle1: Circle, circle2: Circle) -> [Line; 4] {
|
fn _tangents(circle1: Circle, circle2: Circle) -> [Line; 4] {
|
||||||
let mut tgs: [Line; 4] = [
|
let mut tgs: [Line; 4] = [
|
||||||
tangent((circle2 - circle1).pos, -circle1.r, -circle2.r),
|
_tangent((circle2 - circle1).pos, -circle1.r, -circle2.r),
|
||||||
tangent((circle2 - circle1).pos, -circle1.r, circle2.r),
|
_tangent((circle2 - circle1).pos, -circle1.r, circle2.r),
|
||||||
tangent((circle2 - circle1).pos, circle1.r, -circle2.r),
|
_tangent((circle2 - circle1).pos, circle1.r, -circle2.r),
|
||||||
tangent((circle2 - circle1).pos, circle1.r, circle2.r),
|
_tangent((circle2 - circle1).pos, circle1.r, circle2.r),
|
||||||
];
|
];
|
||||||
|
|
||||||
for tg in tgs.iter_mut() {
|
for tg in tgs.iter_mut() {
|
||||||
|
|
@ -64,8 +64,8 @@ fn cast_point_to_line(pt: Point, line: Line) -> Point {
|
||||||
).into();
|
).into();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tangent_points(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] {
|
pub fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] {
|
||||||
let tgs = tangents(circle1, circle2);
|
let tgs = _tangents(circle1, circle2);
|
||||||
|
|
||||||
[
|
[
|
||||||
(cast_point_to_line(circle1.pos, tgs[0]), cast_point_to_line(circle2.pos, tgs[0])),
|
(cast_point_to_line(circle1.pos, tgs[0]), cast_point_to_line(circle2.pos, tgs[0])),
|
||||||
|
|
@ -75,6 +75,32 @@ pub fn tangent_points(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tangent_point_pair(circle1: Circle, cw1: Option<bool>, circle2: Circle, cw2: Option<bool>) -> (Point, Point) {
|
||||||
|
let tangent_point_pairs = tangent_point_pairs(circle1, circle2);
|
||||||
|
|
||||||
|
for tangent_point_pair in tangent_point_pairs {
|
||||||
|
if let Some(cw1) = cw1 {
|
||||||
|
let cross1 = cross_product(tangent_point_pair.0, tangent_point_pair.1, circle1.pos);
|
||||||
|
|
||||||
|
if (cw1 && cross1 <= 0.0) || (!cw1 && cross1 >= 0.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(cw2) = cw2 {
|
||||||
|
let cross2 = cross_product(tangent_point_pair.0, tangent_point_pair.1, circle2.pos);
|
||||||
|
|
||||||
|
if (cw2 && cross2 <= 0.0) || (!cw2 && cross2 >= 0.0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tangent_point_pair;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cross_product(start: Point, stop: Point, reference: Point) -> f64 {
|
pub fn cross_product(start: Point, stop: Point, reference: Point) -> f64 {
|
||||||
let dx1 = stop.x() - start.x();
|
let dx1 = stop.x() - start.x();
|
||||||
let dy1 = stop.y() - start.y();
|
let dy1 = stop.y() - start.y();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue