mirror of https://codeberg.org/topola/topola.git
refactor: merge CanonicalLine and HomogeneousLine into NormalLine
(they represent the exact same object, modulo sign of offset)
This commit is contained in:
parent
5c91235761
commit
41468d51c3
|
|
@ -39,7 +39,7 @@ use crate::{
|
|||
poly::{MakePolygon, Poly, PolyWeight},
|
||||
via::{Via, ViaWeight},
|
||||
},
|
||||
math::{HomogeneousLine, LineIntersection},
|
||||
math::{LineIntersection, NormalLine},
|
||||
};
|
||||
|
||||
/// Represents a weight for various compounds
|
||||
|
|
@ -388,7 +388,7 @@ impl<R: AccessRules> Layout<R> {
|
|||
to: right_pos.into(),
|
||||
width: f64::EPSILON * 16.0,
|
||||
};
|
||||
let mut orig_hline = HomogeneousLine::from(ltr_line);
|
||||
let mut orig_hline = NormalLine::from(ltr_line);
|
||||
orig_hline.make_normal_unit();
|
||||
let orig_hline = orig_hline;
|
||||
let location_denom = orig_hline.segment_interval(<r_line);
|
||||
|
|
@ -422,7 +422,7 @@ impl<R: AccessRules> Layout<R> {
|
|||
let band_uid = self.drawing.loose_band_uid(loose);
|
||||
let loose_hline = orig_hline.orthogonal_through(&match shape {
|
||||
PrimitiveShape::Seg(seg) => {
|
||||
let seg_hline = HomogeneousLine::from(seg.middle_line());
|
||||
let seg_hline = NormalLine::from(seg.middle_line());
|
||||
match orig_hline.intersects(&seg_hline) {
|
||||
LineIntersection::Empty => return None,
|
||||
LineIntersection::Overlapping => shape.center(),
|
||||
|
|
|
|||
|
|
@ -16,15 +16,15 @@ pub enum LineIntersection {
|
|||
Point(Point),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct HomogeneousLine<T> {
|
||||
// x0*x + y0*y = offset
|
||||
pub x: T,
|
||||
pub y: T,
|
||||
pub offset: T,
|
||||
/// A line in normal form: `x0*y + y0*y + offset = 0`
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct NormalLine {
|
||||
pub x: f64,
|
||||
pub y: f64,
|
||||
pub offset: f64,
|
||||
}
|
||||
|
||||
impl From<Line> for HomogeneousLine<f64> {
|
||||
impl From<Line> for NormalLine {
|
||||
fn from(l: Line) -> Self {
|
||||
// the normal vector is perpendicular to the line
|
||||
let normal = geo::point! {
|
||||
|
|
@ -34,14 +34,14 @@ impl From<Line> for HomogeneousLine<f64> {
|
|||
Self {
|
||||
x: normal.0.x,
|
||||
y: normal.0.y,
|
||||
offset: perp_dot_product(l.end.into(), l.start.into()),
|
||||
offset: -perp_dot_product(l.end.into(), l.start.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl HomogeneousLine<f64> {
|
||||
impl NormalLine {
|
||||
pub fn evaluate_at(&self, pt: Point) -> f64 {
|
||||
self.x * pt.x() + self.y * pt.y() - self.offset
|
||||
self.x * pt.x() + self.y * pt.y() + self.offset
|
||||
}
|
||||
|
||||
pub fn angle(&self) -> f64 {
|
||||
|
|
@ -53,6 +53,7 @@ impl HomogeneousLine<f64> {
|
|||
if normal_len > (f64::EPSILON * 16.0) {
|
||||
self.x /= normal_len;
|
||||
self.y /= normal_len;
|
||||
self.offset /= normal_len;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -63,8 +64,8 @@ impl HomogeneousLine<f64> {
|
|||
let apt = geo::point! { x: a.x, y: a.y };
|
||||
let bpt = geo::point! { x: b.x, y: b.y };
|
||||
let det = perp_dot_product(apt, bpt);
|
||||
let rpx = b.y * a.offset - a.y * b.offset;
|
||||
let rpy = -b.x * a.offset + a.x * b.offset;
|
||||
let rpx = -b.y * a.offset + a.y * b.offset;
|
||||
let rpy = b.x * a.offset - a.x * b.offset;
|
||||
|
||||
if det.abs() > ALMOST_ZERO {
|
||||
LineIntersection::Point(geo::point! { x: rpx, y: rpy } / det)
|
||||
|
|
@ -83,7 +84,7 @@ impl HomogeneousLine<f64> {
|
|||
// recover the original parallel vector
|
||||
x: -self.y,
|
||||
y: self.x,
|
||||
offset: self.x * pt.0.y - self.y * pt.0.x,
|
||||
offset: -self.x * pt.0.y + self.y * pt.0.x,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,20 +6,13 @@ use geo::{geometry::Point, Line};
|
|||
use specctra_core::math::Circle;
|
||||
use thiserror::Error;
|
||||
|
||||
use super::seq_perp_dot_product;
|
||||
use super::{seq_perp_dot_product, NormalLine};
|
||||
|
||||
#[derive(Error, Debug, Clone, Copy, PartialEq)]
|
||||
#[error("no tangents for {0:?} and {1:?}")] // TODO add real error message
|
||||
pub struct NoTangents(pub Circle, pub Circle);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct CanonicalLine {
|
||||
pub a: f64,
|
||||
pub b: f64,
|
||||
pub c: f64,
|
||||
}
|
||||
|
||||
fn _tangent(center: Point, r1: f64, r2: f64) -> Result<CanonicalLine, ()> {
|
||||
fn _tangent(center: Point, r1: f64, r2: f64) -> Result<NormalLine, ()> {
|
||||
let epsilon = 1e-9;
|
||||
let dr = r2 - r1;
|
||||
let norm = center.x() * center.x() + center.y() * center.y();
|
||||
|
|
@ -31,15 +24,15 @@ fn _tangent(center: Point, r1: f64, r2: f64) -> Result<CanonicalLine, ()> {
|
|||
|
||||
let sqrt_discriminant = f64::sqrt(f64::abs(discriminant));
|
||||
|
||||
Ok(CanonicalLine {
|
||||
a: (center.x() * dr + center.y() * sqrt_discriminant) / norm,
|
||||
b: (center.y() * dr - center.x() * sqrt_discriminant) / norm,
|
||||
c: r1,
|
||||
Ok(NormalLine {
|
||||
x: (center.x() * dr + center.y() * sqrt_discriminant) / norm,
|
||||
y: (center.y() * dr - center.x() * sqrt_discriminant) / norm,
|
||||
offset: r1,
|
||||
})
|
||||
}
|
||||
|
||||
fn _tangents(circle1: Circle, circle2: Circle) -> Result<[CanonicalLine; 4], ()> {
|
||||
let mut tgs: [CanonicalLine; 4] = [
|
||||
fn _tangents(circle1: Circle, circle2: Circle) -> Result<[NormalLine; 4], ()> {
|
||||
let mut tgs: [NormalLine; 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)?,
|
||||
|
|
@ -47,18 +40,18 @@ fn _tangents(circle1: Circle, circle2: Circle) -> Result<[CanonicalLine; 4], ()>
|
|||
];
|
||||
|
||||
for tg in tgs.iter_mut() {
|
||||
tg.c -= tg.a * circle1.pos.x() + tg.b * circle1.pos.y();
|
||||
tg.offset -= tg.x * circle1.pos.x() + tg.y * circle1.pos.y();
|
||||
}
|
||||
|
||||
Ok(tgs)
|
||||
}
|
||||
|
||||
fn cast_point_to_canonical_line(pt: Point, line: CanonicalLine) -> Point {
|
||||
fn cast_point_to_canonical_line(pt: Point, line: NormalLine) -> Point {
|
||||
(
|
||||
(line.b * (line.b * pt.x() - line.a * pt.y()) - line.a * line.c)
|
||||
/ (line.a * line.a + line.b * line.b),
|
||||
(line.a * (-line.b * pt.x() + line.a * pt.y()) - line.b * line.c)
|
||||
/ (line.a * line.a + line.b * line.b),
|
||||
(line.y * (line.y * pt.x() - line.x * pt.y()) - line.x * line.offset)
|
||||
/ (line.x * line.x + line.y * line.y),
|
||||
(line.x * (-line.y * pt.x() + line.x * pt.y()) - line.y * line.offset)
|
||||
/ (line.x * line.x + line.y * line.y),
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue