Skip to main content

lib_gerber_edit/
lib.rs

1pub mod board;
2pub mod error;
3pub mod excellon_format;
4pub mod gerber;
5pub mod gerber_ascii;
6pub mod layer;
7pub mod unit_able;
8
9pub use gerber_parser;
10pub use gerber_parser::gerber_types;
11
12use crate::layer::{LayerData, LayerType};
13use derive_more::Display;
14
15#[cfg(feature = "serde")]
16use serde::{Deserialize, Serialize};
17
18pub type Result<T> = std::result::Result<T, error::Error>;
19
20pub trait LayerCorners {
21
22    /// Returns size of layer calculated by corners diff
23    fn get_size(&self) -> Size {
24        let (min, max) = self.get_corners();
25        let width = max.x - min.x;
26        let height = max.y - min.y;
27        Size { width, height }
28    }
29
30    /// Returns min (x, y) and max (x, y) position
31    fn get_corners(&self) -> (Pos, Pos);
32}
33
34pub trait LayerTransform {
35
36    /// Adds an offset to given data
37    fn transform(&mut self, transform: &Pos);
38}
39
40pub trait LayerScale {
41
42    /// Scales to given data by x and y
43    fn scale(&mut self, x: f64, y: f64);
44}
45
46pub trait LayerMerge {
47
48    /// Appends given data, tools need to be merged and remapped
49    fn merge(&mut self, other: &Self);
50}
51
52pub trait LayerStepAndRepeat {
53
54    /// Multiplies given data by x and y with offset
55    fn step_and_repeat(&mut self, x_repetitions: u32, y_repetitions: u32, offset: &Pos);
56}
57
58/// Position in mm
59#[derive(Debug, Clone, PartialEq, Display)]
60#[display("x: {x:.2}, y: {y:.2}")]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub struct Pos {
63    pub x: f64,
64    pub y: f64,
65}
66
67/// Size in mm
68#[derive(Debug, Clone, PartialEq, Display)]
69#[display("width: {width:.2}, height: {height:.2}")]
70#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
71pub struct Size {
72    pub width: f64,
73    pub height: f64,
74}
75
76/// And macro to load a single layer statically
77///
78/// Used for loading static assets
79#[macro_export]
80macro_rules! load_layer_data {
81    ($file:expr $(,)?) => {{
82        let data = include_str!($file);
83        let reader = std::io::BufReader::new(std::io::Cursor::new(data));
84        let ty = LayerType::try_from($file.to_string().rsplitn(2, ".").next().unwrap()).unwrap();
85        LayerData::parse(ty, reader).unwrap()
86    }};
87}
88
89/// And macro to load a board statically
90///
91/// Used for loading static assets
92#[macro_export]
93macro_rules! load_board_data {
94    ($path:expr, $(($name:literal, $ty:expr)),* $(,)?) => {{
95        let mut board = Board::empty();
96         $(
97            board.add_layer(Layer {
98                ty: $ty,
99                name: $name.to_string(),
100                data: load_layer_data!(concat!($path, $name)).1
101            });
102         )*
103        board
104    }};
105}
106
107#[cfg(test)]
108mod tests {
109    use std::fs;
110    use std::path::Path;
111    use crate::board::Board;
112    use super::*;
113
114    #[test]
115    fn it_works() {
116        let folders = ["mobo"];
117        if Path::new("output").exists() {
118            fs::remove_dir_all("output").unwrap();
119        }
120        for folder in folders {
121            let in_path = Path::new("test").join(folder);
122            let out_path = Path::new("output").join(folder);
123            fs::create_dir_all(&out_path).unwrap();
124            println!("Processing folder: {:?}", in_path);
125            let mut board = Board::from_folder(&in_path).unwrap();
126
127            let (min, max) = board.get_corners();
128            println!(
129                "Transformed Corners: ({}, {}) - ({}, {})",
130                min.x, min.y, max.x, max.y
131            );
132
133            let size = board.get_size();
134
135            board.transform(&Pos {
136                x: 100.0,
137                y: -100.0,
138            });
139
140            board.transform(&Pos {
141                x: -100.0,
142                y: 100.0,
143            });
144
145            let mut copy = board.clone();
146            copy.transform(&Pos {
147                y: size.height + 5.0,
148                x: 0.0,
149            });
150            board.merge(&copy);
151
152            board.write_to_folder(&out_path).unwrap();
153        }
154    }
155}