microcad_core/geo2d/
line.rs1use cgmath::{Angle, InnerSpace, Rad};
7use geo::AffineOps;
8
9use crate::*;
10
11#[derive(Debug, Clone)]
13pub struct Line(pub geo2d::Point, pub geo2d::Point);
14
15impl Line {
16 pub fn shorter(&self, amount: Scalar) -> Self {
18 let d = self.vec();
19 let d = 0.5 * d * (1.0 - amount / d.magnitude());
20 let c = self.center();
21 Self(c - (d.x, d.y).into(), c + (d.x, d.y).into())
22 }
23
24 pub fn radius_edge(circle: &Circle, angle: &Rad<Scalar>) -> Self {
28 let Circle {
29 radius,
30 offset: Vec2 { x, y },
31 } = &circle;
32 let x1 = x + radius * angle.cos();
33 let y1 = y + radius * angle.sin();
34 Self(geo::Point::new(*x, *y), geo::Point::new(x1, y1))
35 }
36
37 pub fn vec(&self) -> Vec2 {
39 Vec2::from(self.1.x_y()) - Vec2::from(self.0.x_y())
40 }
41
42 pub fn center(&self) -> geo2d::Point {
44 (self.0 + self.1) * 0.5
45 }
46
47 pub fn angle(&self) -> Rad<Scalar> {
49 let (p1, p2) = (self.0, self.1);
50 let dx = p2.x() - p1.x();
51 let dy = p2.y() - p1.y();
52 Rad(dy.atan2(dx))
53 }
54
55 pub fn matrix(&self) -> Mat3 {
57 let rot = Mat2::from_angle(self.angle());
58 let mut m = Mat3::from_translation(self.0.x_y().into());
59 m.x = Vec3::new(rot.x.x, rot.x.y, 0.0);
60 m.y = Vec3::new(rot.y.x, rot.y.y, 0.0);
61 m
62 }
63}
64
65impl CalcBounds2D for Line {
66 fn calc_bounds_2d(&self) -> geo2d::Bounds2D {
67 geo2d::Bounds2D::new(self.0.x_y().into(), self.1.x_y().into())
68 }
69}
70
71impl Transformed2D for Line {
72 fn transformed_2d(&self, mat: &Mat3) -> Self {
73 let transform = &geo2d::mat3_to_affine_transform(mat);
74 Self(
75 self.0.affine_transform(transform),
76 self.1.affine_transform(transform),
77 )
78 }
79}