mirror of https://codeberg.org/topola/topola.git
117 lines
3.4 KiB
Rust
117 lines
3.4 KiB
Rust
use std::collections::HashSet;
|
|
|
|
use geo::Point;
|
|
use rstar::AABB;
|
|
use spade::InsertionError;
|
|
|
|
use topola::{
|
|
autorouter::{ratsnest::Ratsnest, selection::Selection},
|
|
board::{mesadata::MesadataTrait, Board},
|
|
drawing::{
|
|
graph::{GetLayer, MakePrimitive},
|
|
primitive::MakePrimitiveShape,
|
|
},
|
|
geometry::{
|
|
compound::CompoundManagerTrait,
|
|
shape::{Shape, ShapeTrait},
|
|
},
|
|
graph::{GenericIndex, GetNodeIndex},
|
|
layout::{
|
|
via::ViaWeight,
|
|
zone::{MakePolyShape, Zone, ZoneWeight},
|
|
CompoundWeight, Layout, NodeIndex,
|
|
},
|
|
};
|
|
|
|
pub struct Overlay {
|
|
ratsnest: Ratsnest,
|
|
selection: Selection,
|
|
active_layer: usize,
|
|
}
|
|
|
|
impl Overlay {
|
|
pub fn new(board: &Board<impl MesadataTrait>) -> Result<Self, InsertionError> {
|
|
Ok(Self {
|
|
ratsnest: Ratsnest::new(board.layout())?,
|
|
selection: Selection::new(),
|
|
active_layer: 0,
|
|
})
|
|
}
|
|
|
|
pub fn click(&mut self, board: &Board<impl MesadataTrait>, at: Point) {
|
|
let geoms: Vec<_> = board
|
|
.layout()
|
|
.drawing()
|
|
.rtree()
|
|
.locate_in_envelope_intersecting(&AABB::<[f64; 3]>::from_corners(
|
|
[at.x(), at.y(), -f64::INFINITY],
|
|
[at.x(), at.y(), f64::INFINITY],
|
|
))
|
|
.collect();
|
|
|
|
if let Some(geom) = geoms.iter().find(|&&geom| match geom.data {
|
|
NodeIndex::Primitive(primitive) => {
|
|
primitive.primitive(board.layout().drawing()).layer() == self.active_layer
|
|
}
|
|
NodeIndex::Compound(compound) => false,
|
|
}) {
|
|
if self.toggle_selection_if_contains_point(board, geom.data, at) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
for geom in geoms {
|
|
if self.toggle_selection_if_contains_point(board, geom.data, at) {
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
fn toggle_selection_if_contains_point(
|
|
&mut self,
|
|
board: &Board<impl MesadataTrait>,
|
|
node: NodeIndex,
|
|
p: Point,
|
|
) -> bool {
|
|
let shape: Shape = match node {
|
|
NodeIndex::Primitive(primitive) => {
|
|
primitive.primitive(board.layout().drawing()).shape().into()
|
|
}
|
|
NodeIndex::Compound(compound) => {
|
|
match board.layout().drawing().compound_weight(compound) {
|
|
/*CompoundWeight::Zone(zone) => Zone::new(
|
|
GenericIndex::<ZoneWeight>::new(compound.node_index()),
|
|
board.layout(),
|
|
)
|
|
.shape()
|
|
.into(),*/
|
|
CompoundWeight::Zone(weight) => board
|
|
.layout()
|
|
.zone(GenericIndex::<ZoneWeight>::new(compound.node_index()))
|
|
.shape()
|
|
.into(),
|
|
CompoundWeight::Via(weight) => board
|
|
.layout()
|
|
.via(GenericIndex::<ViaWeight>::new(compound.node_index()))
|
|
.shape()
|
|
.into(),
|
|
}
|
|
}
|
|
};
|
|
|
|
if shape.contains_point(p) {
|
|
self.selection.toggle_at_node(board, node);
|
|
return true;
|
|
}
|
|
false
|
|
}
|
|
|
|
pub fn ratsnest(&self) -> &Ratsnest {
|
|
&self.ratsnest
|
|
}
|
|
|
|
pub fn selection(&self) -> &Selection {
|
|
&self.selection
|
|
}
|
|
}
|