mirror of https://codeberg.org/topola/topola.git
refactor(specctra/design): Place fillet circles, netless for now
This commit is contained in:
parent
4a057d3499
commit
521bb0598a
|
|
@ -105,6 +105,8 @@ impl Ratsnest {
|
|||
|
||||
for node in layout.drawing().layer_primitive_nodes(layer) {
|
||||
if let PrimitiveIndex::FixedDot(dot) = node {
|
||||
// Dots that are parts of polys are ignored because ratlines
|
||||
// should only go to their centerpoints.
|
||||
if layout.drawing().compounds(dot).next().is_none() {
|
||||
handle_rvw(
|
||||
layout.drawing().primitive(dot).maybe_net(),
|
||||
|
|
|
|||
|
|
@ -4,9 +4,11 @@
|
|||
|
||||
use std::ops::Sub;
|
||||
|
||||
use geo::{point, Distance, Euclidean, Line, Point};
|
||||
use geo::{point, Distance, Euclidean, Length, Line, Point};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::math;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
|
||||
pub struct Circle {
|
||||
pub pos: Point,
|
||||
|
|
@ -129,3 +131,36 @@ pub fn intersect_circle_segment(circle: &Circle, segment: &Line) -> Vec<Point> {
|
|||
|
||||
v
|
||||
}
|
||||
|
||||
/// Find the filleting circle of line segments `segment1` and `segment2`.
|
||||
pub fn fillet_circle(segment1: &Line, segment2: &Line) -> Circle {
|
||||
// Turn segment1 delta vector counterclockwisely by 90 degrees.
|
||||
let diameter_ray = Line::new(
|
||||
segment1.end_point(),
|
||||
point! {x: segment1.end_point().x() - segment1.delta().y, y: segment1.end_point().y() + segment1.delta().x},
|
||||
);
|
||||
|
||||
// Radius is the distance from the diameter line to segment2.start_point().
|
||||
let radius = (diameter_ray.delta().y * segment2.start_point().x()
|
||||
- diameter_ray.delta().x * segment2.start_point().y()
|
||||
+ diameter_ray.end_point().x() * diameter_ray.start_point().y()
|
||||
- diameter_ray.end_point().y() * diameter_ray.start_point().x())
|
||||
.abs()
|
||||
/ diameter_ray.length::<Euclidean>();
|
||||
|
||||
let center =
|
||||
if math::perp_dot_product(Point::from(segment1.delta()), Point::from(segment2.delta()))
|
||||
>= 0.0
|
||||
{
|
||||
segment1.end_point()
|
||||
+ (diameter_ray.delta() / diameter_ray.length::<Euclidean>() * radius).into()
|
||||
} else {
|
||||
segment1.end_point()
|
||||
- (diameter_ray.delta() / diameter_ray.length::<Euclidean>() * radius).into()
|
||||
};
|
||||
|
||||
Circle {
|
||||
pos: center,
|
||||
r: radius,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
|
||||
use std::collections::{btree_map::Entry as BTreeMapEntry, BTreeMap};
|
||||
|
||||
use geo::{Point, Rotate};
|
||||
use geo::{Euclidean, Length, Line, Point, Rotate};
|
||||
use itertools::Itertools;
|
||||
use specctra_core::math::PointWithRotation;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -22,7 +23,7 @@ use crate::{
|
|||
},
|
||||
geometry::{primitive::PrimitiveShape, GetLayer, GetWidth},
|
||||
layout::{poly::SolidPolyWeight, Layout},
|
||||
math::Circle,
|
||||
math::{self, Circle},
|
||||
specctra::{
|
||||
mesadata::SpecctraMesadata,
|
||||
read::ListTokenizer,
|
||||
|
|
@ -733,6 +734,78 @@ impl SpecctraDesign {
|
|||
maybe_pin,
|
||||
&nodes[..],
|
||||
);
|
||||
|
||||
Self::add_polygon_fillet_circles(
|
||||
recorder, board, place, pin, coords, width, layer, maybe_net, None, flip,
|
||||
);
|
||||
}
|
||||
|
||||
fn add_polygon_fillet_circles(
|
||||
recorder: &mut BoardEdit,
|
||||
board: &mut Board<SpecctraMesadata>,
|
||||
place: PointWithRotation,
|
||||
pin: PointWithRotation,
|
||||
coords: &[structure::Point],
|
||||
_width: f64,
|
||||
layer: usize,
|
||||
maybe_net: Option<usize>,
|
||||
_maybe_pin: Option<String>,
|
||||
flip: bool,
|
||||
) {
|
||||
let MIN_FIRST_CHAIN_ELEMENT_LENGTH = 100.0;
|
||||
let mut maybe_first_chain_segment = None;
|
||||
|
||||
let first_pos = Self::pos(place, pin, coords[0].x, coords[0].y, flip);
|
||||
let last_pos = Self::pos(
|
||||
place,
|
||||
pin,
|
||||
coords.last().unwrap().x,
|
||||
coords.last().unwrap().y,
|
||||
flip,
|
||||
);
|
||||
|
||||
let last_first_segment = Line::new(last_pos, first_pos);
|
||||
|
||||
if last_first_segment.length::<Euclidean>() >= MIN_FIRST_CHAIN_ELEMENT_LENGTH {
|
||||
maybe_first_chain_segment = Some((Line::new(last_pos, first_pos), 0));
|
||||
}
|
||||
|
||||
for (index, coord_triple) in coords
|
||||
.iter()
|
||||
.circular_tuple_windows::<(_, _, _)>()
|
||||
.enumerate()
|
||||
{
|
||||
let curr_pos0 = Self::pos(place, pin, coord_triple.0.x, coord_triple.0.y, flip);
|
||||
let curr_pos1 = Self::pos(place, pin, coord_triple.1.x, coord_triple.1.y, flip);
|
||||
let curr_pos2 = Self::pos(place, pin, coord_triple.2.x, coord_triple.2.y, flip);
|
||||
let curr_segment01 = Line::new(curr_pos0, curr_pos1);
|
||||
let curr_segment12 = Line::new(curr_pos1, curr_pos2);
|
||||
|
||||
if math::angle_between(curr_segment01.delta().into(), curr_segment12.delta().into())
|
||||
.abs()
|
||||
> 30.0_f64.to_radians()
|
||||
|| curr_segment12.length::<Euclidean>() >= MIN_FIRST_CHAIN_ELEMENT_LENGTH
|
||||
{
|
||||
if let Some((first_chain_segment, first_chain_index)) = maybe_first_chain_segment {
|
||||
if index - first_chain_index >= 3 {
|
||||
let circle = math::fillet_circle(&first_chain_segment, &curr_segment12);
|
||||
|
||||
board.add_fixed_dot_infringably(
|
||||
recorder,
|
||||
FixedDotWeight(GeneralDotWeight {
|
||||
circle,
|
||||
layer,
|
||||
maybe_net: None, // TODO.
|
||||
//maybe_net,
|
||||
}),
|
||||
None,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
maybe_first_chain_segment = Some((Line::new(curr_pos1, curr_pos2), index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn pos(place: PointWithRotation, pin: PointWithRotation, x: f64, y: f64, flip: bool) -> Point {
|
||||
|
|
|
|||
Loading…
Reference in New Issue