overlay: separately triangulate each net

The way this is done is ineffective of course and we'll have to optimize
it later.
This commit is contained in:
Mikolaj Wielgus 2024-04-24 03:01:50 +02:00
parent d1ae0ec9c6
commit 6f9015106d
3 changed files with 67 additions and 24 deletions

View File

@ -32,7 +32,7 @@ use crate::{
pub type NodeIndex = GenericNode<PrimitiveIndex, GenericIndex<ZoneWeight>>;
pub struct Layout<R: RulesTrait> {
drawing: Drawing<ZoneWeight, R>, // Shouldn't be public, but is for now because `Draw` needs it.
drawing: Drawing<ZoneWeight, R>,
connectivity: StableDiGraph<ConnectivityWeight, ConnectivityLabel, usize>,
}

View File

@ -24,7 +24,7 @@ pub trait MakePolyShape {
) -> PolyShape;
}
#[enum_dispatch(GetLayer, MakePolyShape)]
#[enum_dispatch(GetLayer, GetMaybeNet, MakePolyShape)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ZoneWeight {
Solid(SolidZoneWeight),

View File

@ -1,8 +1,10 @@
use std::collections::HashMap;
use enum_dispatch::enum_dispatch;
use geo::Point;
use petgraph::{
data::FromElements,
stable_graph::{NodeIndex, StableUnGraph},
data::{Element, FromElements},
stable_graph::{NodeIndex, StableGraph, StableUnGraph},
unionfind::UnionFind,
visit::{self, EdgeRef, IntoEdgeReferences, NodeIndexable},
};
@ -11,7 +13,7 @@ use spade::{HasPosition, InsertionError, Point2};
use crate::{
drawing::{
dot::FixedDotIndex,
graph::{MakePrimitive, PrimitiveIndex},
graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex},
primitive::MakePrimitiveShape,
rules::RulesTrait,
},
@ -56,21 +58,40 @@ pub struct Ratsnest {
impl Ratsnest {
pub fn new(layout: &Layout<impl RulesTrait>) -> Result<Self, InsertionError> {
let mut unionfind = UnionFind::new(layout.drawing().geometry().graph().node_bound());
for edge in layout.drawing().geometry().graph().edge_references() {
unionfind.union(edge.source(), edge.target());
}
let mut this = Self {
graph: StableUnGraph::default(),
};
let mut triangulation =
Triangulation::new(layout.drawing().geometry().graph().node_bound());
let mut triangulations = HashMap::new();
for node in layout.drawing().primitive_nodes() {
match node {
PrimitiveIndex::FixedDot(dot) => {
if layout.compounds(dot).next().is_none() {
triangulation.add_vertex(VertexWeight {
vertex: RatsnestVertexIndex::FixedDot(dot),
pos: node.primitive(layout.drawing()).shape().center(),
})?;
if let Some(net) = layout.drawing().primitive(dot).maybe_net() {
if !triangulations.contains_key(&net) {
triangulations.insert(
net,
Triangulation::new(
layout.drawing().geometry().graph().node_bound(),
),
);
}
triangulations
.get_mut(&net)
.unwrap()
.add_vertex(VertexWeight {
vertex: RatsnestVertexIndex::FixedDot(dot),
pos: node.primitive(layout.drawing()).shape().center(),
})?;
}
}
}
_ => (),
@ -78,22 +99,44 @@ impl Ratsnest {
}
for zone in layout.zones() {
triangulation.add_vertex(VertexWeight {
vertex: RatsnestVertexIndex::Zone(zone),
pos: layout
.compound_weight(zone)
.shape(&layout.drawing(), zone)
.center(),
})?
if let Some(net) = layout.drawing().compound_weight(zone).maybe_net() {
if !triangulations.contains_key(&net) {
triangulations.insert(
net,
Triangulation::new(layout.drawing().geometry().graph().node_bound()),
);
}
triangulations
.get_mut(&net)
.unwrap()
.add_vertex(VertexWeight {
vertex: RatsnestVertexIndex::Zone(zone),
pos: layout
.compound_weight(zone)
.shape(&layout.drawing(), zone)
.center(),
})?
}
}
this.graph =
StableUnGraph::from_elements(petgraph::algo::min_spanning_tree(&triangulation));
for (net, triangulation) in triangulations {
let mut map = Vec::new();
let mut unionfind = UnionFind::new(layout.drawing().geometry().graph().node_bound());
for edge in layout.drawing().geometry().graph().edge_references() {
unionfind.union(edge.source(), edge.target());
for element in petgraph::algo::min_spanning_tree(&triangulation) {
match element {
Element::Node { weight } => {
map.push(this.graph.add_node(weight));
}
Element::Edge {
source,
target,
weight,
} => {
this.graph.add_edge(map[source], map[target], weight);
}
}
}
}
this.graph.retain_edges(|g, i| {