maker_panel/features/
r_mount.rs

1use super::InnerAtom;
2use geo::{Coordinate, MultiPolygon};
3use std::fmt;
4
5/// A cut-out edge region for mounting a board at right angles.
6#[derive(Debug, Clone)]
7pub struct RMount {
8    direction: crate::Direction,
9    rect: geo::Rect<f64>,
10    depth: f64,
11}
12
13impl RMount {
14    /// Creates a new r-mount with the provided depth.
15    pub fn new(depth: f64) -> Self {
16        let direction = crate::Direction::Up;
17        let tl: Coordinate<f64> = [-3.15f64, -depth / 2. - 1.].into();
18        let br: Coordinate<f64> = [3.15f64, depth / 2. + 1.].into();
19        let rect = geo::Rect::new(tl, br);
20        Self {
21            direction,
22            rect,
23            depth,
24        }
25    }
26
27    /// Returns a new r-mount with the specified direction.
28    pub fn direction(self, direction: crate::Direction) -> Self {
29        Self { direction, ..self }
30    }
31}
32
33impl fmt::Display for RMount {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        write!(f, "rmount({:?}, {:?})", self.rect.min(), self.rect.max(),)
36    }
37}
38
39impl super::Feature for RMount {
40    fn name(&self) -> &'static str {
41        "rmount"
42    }
43
44    fn edge_union(&self) -> Option<MultiPolygon<f64>> {
45        let out = self.rect.clone().to_polygon().into();
46        use geo::algorithm::rotate::Rotate;
47        match self.direction {
48            crate::Direction::Up => Some(out),
49            crate::Direction::Down => Some(out.rotate(180.)),
50            crate::Direction::Left => Some(out.rotate(-90.)),
51            crate::Direction::Right => Some(out.rotate(90.)),
52        }
53    }
54
55    fn edge_subtract(&self) -> Option<MultiPolygon<f64>> {
56        use geo_booleanop::boolean::BooleanOp;
57        let center = self.rect.center();
58
59        let channel = geo::Rect::new(
60            Coordinate::<f64>::from([-1.62f64, -self.depth / 2. - 1.]) + center,
61            Coordinate::<f64>::from([1.62f64, self.depth / 2.]) + center,
62        );
63        let nut = geo::Rect::new(
64            Coordinate::<f64>::from([-3.12f64, -1.4]) + center,
65            Coordinate::<f64>::from([3.12f64, 1.4]) + center,
66        );
67
68        let out = MultiPolygon::<f64>::from(channel.to_polygon()).union(&nut.to_polygon());
69
70        let origin = geo::Point::new(0., 0.);
71        use geo::algorithm::rotate::RotatePoint;
72        match self.direction {
73            crate::Direction::Up => Some(out),
74            crate::Direction::Down => Some(out.rotate_around_point(180., origin)),
75            crate::Direction::Left => Some(out.rotate_around_point(-90., origin)),
76            crate::Direction::Right => Some(out.rotate_around_point(90., origin)),
77        }
78    }
79
80    fn translate(&mut self, v: Coordinate<f64>) {
81        use geo::algorithm::translate::Translate;
82        self.rect.translate_inplace(v.x, v.y);
83    }
84
85    fn interior(&self) -> Vec<super::InnerAtom> {
86        let center = self.rect.center();
87        let angle = match self.direction {
88            crate::Direction::Up => 0.,
89            crate::Direction::Down => 180.,
90            crate::Direction::Left => -90.,
91            crate::Direction::Right => 90.,
92        };
93        let origin = geo::Point::new(0., 0.);
94
95        use geo::algorithm::rotate::RotatePoint;
96        vec![
97            InnerAtom::Drill {
98                center: (geo::Point::from([-3.08f64, -1.32]).rotate_around_point(angle, origin)
99                    + center.into())
100                .into(),
101                radius: 0.15,
102                plated: false,
103            },
104            InnerAtom::Drill {
105                center: (geo::Point::from([3.08f64, -1.32]).rotate_around_point(angle, origin)
106                    + center.into())
107                .into(),
108                radius: 0.15,
109                plated: false,
110            },
111            InnerAtom::Drill {
112                center: (geo::Point::from([-3.08f64, 1.32]).rotate_around_point(angle, origin)
113                    + center.into())
114                .into(),
115                radius: 0.15,
116                plated: false,
117            },
118            InnerAtom::Drill {
119                center: (geo::Point::from([3.08f64, 1.32]).rotate_around_point(angle, origin)
120                    + center.into())
121                .into(),
122                radius: 0.15,
123                plated: false,
124            },
125        ]
126    }
127}