Add polygon insertion

This commit is contained in:
Mikolaj Wielgus 2026-03-10 13:13:38 +01:00
parent f4a8bee711
commit c927ad281f
5 changed files with 120 additions and 12 deletions

View File

@ -6,7 +6,8 @@ use derive_getters::{Dissolve, Getters};
use undoredo::{ApplyDelta, Delta, FlushDelta};
use crate::layout::{
Arc, ArcId, Joint, JointId, Layout, LayoutHalfDelta, Segment, SegmentId, Via, ViaId,
Arc, ArcId, Joint, JointId, Layout, LayoutHalfDelta, Polygon, PolygonId, Segment, SegmentId,
Via, ViaId,
};
struct Layer {
@ -41,6 +42,10 @@ impl Board {
pub fn add_via(&mut self, via: Via) -> ViaId {
self.layout.add_via(via)
}
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
self.layout.add_polygon(polygon)
}
}
#[derive(Clone, Debug, Dissolve)]

View File

@ -12,7 +12,7 @@ use undoredo::{ApplyDelta, Delta, FlushDelta, Recorder};
pub struct JointId(usize);
impl JointId {
/// Wrap a vertex index in a newtype struct.
/// Wrap a joint index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
@ -36,7 +36,7 @@ pub struct Joint {
pub struct SegmentId(usize);
impl SegmentId {
/// Wrap a vertex index in a newtype struct.
/// Wrap a segment index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
@ -60,7 +60,7 @@ pub struct Segment {
pub struct ArcId(usize);
impl ArcId {
/// Wrap a vertex index in a newtype struct.
/// Wrap an arc index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
@ -85,7 +85,7 @@ pub struct Arc {
pub struct ViaId(usize);
impl ViaId {
/// Wrap a vertex index in a newtype struct.
/// Wrap a via index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
@ -105,6 +105,29 @@ pub struct Via {
pub radius: u64,
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PolygonId(usize);
impl PolygonId {
/// Wrap a polygon index in a newtype struct.
#[inline]
pub fn new(id: usize) -> Self {
Self(id)
}
/// Returns the underlying index.
#[inline]
pub fn id(self) -> usize {
self.0
}
}
#[derive(Clone, Debug)]
pub struct Polygon {
pub vertices: Vec<[i64; 2]>,
pub layer: usize,
}
#[derive(Clone, Debug, Getters)]
pub struct Layout {
boundary: Vec<[i64; 2]>,
@ -113,6 +136,7 @@ pub struct Layout {
segments: Recorder<StableVec<Segment>>,
arcs: Recorder<StableVec<Arc>>,
vias: Recorder<StableVec<Via>>,
polygons: Recorder<StableVec<Polygon>>,
}
impl Layout {
@ -124,6 +148,7 @@ impl Layout {
segments: Recorder::new(StableVec::new()),
arcs: Recorder::new(StableVec::new()),
vias: Recorder::new(StableVec::new()),
polygons: Recorder::new(StableVec::new()),
}
}
@ -142,6 +167,10 @@ impl Layout {
pub fn add_via(&mut self, via: Via) -> ViaId {
ViaId::new(self.vias.push(via))
}
pub fn add_polygon(&mut self, polygon: Polygon) -> PolygonId {
PolygonId::new(self.polygons.push(polygon))
}
}
#[derive(Clone, Debug, Dissolve)]
@ -150,6 +179,7 @@ pub struct LayoutHalfDelta {
segments: BTreeMap<usize, Segment>,
arcs: BTreeMap<usize, Arc>,
vias: BTreeMap<usize, Via>,
polygons: BTreeMap<usize, Polygon>,
}
impl ApplyDelta<LayoutHalfDelta> for Layout {
@ -167,6 +197,9 @@ impl ApplyDelta<LayoutHalfDelta> for Layout {
let vias_delta = Delta::with_removed_inserted(removed.vias, inserted.vias);
self.vias.apply_delta(&vias_delta);
let polygons_delta = Delta::with_removed_inserted(removed.polygons, inserted.polygons);
self.polygons.apply_delta(&polygons_delta);
}
}
@ -176,6 +209,7 @@ impl FlushDelta<LayoutHalfDelta> for Layout {
let (removed_segments, inserted_segments) = self.segments.flush_delta().dissolve();
let (removed_arcs, inserted_arcs) = self.arcs.flush_delta().dissolve();
let (removed_vias, inserted_vias) = self.vias.flush_delta().dissolve();
let (removed_polygons, inserted_polygons) = self.polygons.flush_delta().dissolve();
Delta::with_removed_inserted(
LayoutHalfDelta {
@ -183,12 +217,14 @@ impl FlushDelta<LayoutHalfDelta> for Layout {
segments: removed_segments,
arcs: removed_arcs,
vias: removed_vias,
polygons: removed_polygons,
},
LayoutHalfDelta {
joints: inserted_joints,
segments: inserted_segments,
arcs: inserted_arcs,
vias: inserted_vias,
polygons: inserted_polygons,
},
)
}

40
topola/src/math.rs Normal file
View File

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2026 Topola contributors
//
// SPDX-License-Identifier: MIT OR Apache-2.0
use derive_more::{Add, Constructor, From, Into, Sub};
#[derive(Add, Clone, Constructor, Copy, Debug, From, Into, Sub)]
pub struct Vector2<T> {
pub x: T,
pub y: T,
}
macro_rules! impl_rotate_around_point {
($t:ty) => {
impl Vector2<$t> {
pub fn rotate_around_point(&mut self, angle: $t, origin: Vector2<$t>) -> Self {
let sin = angle.sin();
let cos = angle.cos();
let tx = self.x - origin.x;
let ty = self.y - origin.y;
let rx = tx * cos - ty * sin;
let ry = tx * sin + ty * cos;
self.x = rx + origin.x;
self.y = ry + origin.y;
*self
}
pub fn rotate_around_point_degrees(&mut self, angle: $t, origin: Vector2<$t>) -> Self {
self.rotate_around_point(angle.to_radians(), origin)
}
}
};
}
impl_rotate_around_point!(f32);
impl_rotate_around_point!(f64);

View File

@ -7,7 +7,7 @@ use derive_getters::Getters;
use crate::{
Board,
layout::{Arc, ArcId, Joint, JointId, Segment, SegmentId, Via, ViaId},
layout::{Arc, ArcId, Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId},
};
#[derive(Clone, Debug, Getters)]
@ -123,4 +123,9 @@ impl NavmesherBoard {
// TODO: Insert into navmesh.
self.board.add_via(via)
}
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
// TODO: Insert into navmesh.
self.board.add_polygon(polygon)
}
}

View File

@ -47,6 +47,7 @@ impl Board {
&mut board,
place.point_with_rotation(),
pin.point_with_rotation(),
0,
(circle.diameter / 2.0) as u64,
false,
),
@ -64,31 +65,52 @@ impl Board {
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
layer: usize,
radius: u64,
flip: bool,
) {
let pos = Self::pos(place, pin, 0.0, 0.0, flip);
board.add_joint(Joint {
position: [pos.x, pos.y],
layer: 0,
position: Self::pos(place, pin, 0.0, 0.0, flip),
layer,
radius,
});
}
/*pub fn place_rect(
board: &mut Board,
place: PointWithRotation,
pin: PointWithRotation,
x1: f64,
y1: f64,
x2: f64,
y2: f64,
layer: usize,
flip: bool,
) {
board.add_polygon(Polygon {
vertices: [
Self::pos(place, pin, x1, y1, flip),
Self::pos(place, pin, x2, y1, flip),
Self::pos(place, pin, x2, y2, flip),
Self::pos(place, pin, x1, y2, flip),
],
layer,
})
}*/
fn pos(
place: PointWithRotation,
pin: PointWithRotation,
x: f64,
y: f64,
flip: bool,
) -> Vector2<i64> {
) -> [i64; 2] {
let pos = (Vector2::new(x, y) + Vector2::new(pin.pos.x(), pin.pos.y()))
.rotate_around_point_degrees(pin.rot, Vector2::new(pin.pos.x(), pin.pos.y()));
let pos = (Vector2::new(place.pos.x(), place.pos.y())
+ flip.then_some(Vector2::new(-pos.x, pos.y)).unwrap_or(pos))
.rotate_around_point_degrees(place.rot, Vector2::new(place.pos.x(), place.pos.y()));
Vector2::new(pos.x as i64, pos.y as i64)
[pos.x as i64, pos.y as i64]
}
}