idf_parser/
point.rs

1use crate::primitives::ws;
2use crate::ws_separated;
3
4use nom::character::complete::u32;
5use nom::number::complete::float;
6use nom::{IResult, Parser};
7
8/// Represents a point which exists as part of 2D loop of points which describe an outline of a
9/// component or board section.
10///
11/// Used repeatedly in the IDF format to represent points in a loop.
12/// First mention here:
13/// http://www.simplifiedsolutionsinc.com/images/idf_v30_spec.pdf#page=10 in Record 3
14#[derive(Debug, PartialEq, Clone, Default, PartialOrd)]
15pub struct Point {
16    /// The label of the loop the point exist in, 0 for counter-clockwise, 1 for clockwise.
17    pub loop_label: u32,
18    /// The x coordinate of the point.
19    pub x: f32,
20    /// The y coordinate of the point.
21    pub y: f32,
22    /// 0 for a straight line, between 0 and 360 for an arc, 360 for a full circle.
23    pub angle: f32,
24}
25
26/// Parses a point from the input string.
27///
28/// # Example
29/// ```
30/// use idf_parser::point::{point, Point};
31/// let input = "0 100.0 200.0 45.0";
32///
33/// let (remaining, point) = point(input).unwrap();
34/// assert_eq!(point, Point { loop_label: 0, x: 100.0, y: 200.0, angle: 45.0 });
35/// ```
36pub fn point(input: &str) -> IResult<&str, Point> {
37    let (remaining, (loop_label, x, y, angle)) =
38        ws_separated!((u32, float, float, float)).parse(input)?;
39    let point = Point {
40        loop_label,
41        x,
42        y,
43        angle,
44    };
45    Ok((remaining, point))
46}
47
48#[cfg(test)]
49
50mod tests {
51    use super::*;
52
53    #[test]
54    fn test_point() {
55        let input = "0 100.0 200.0 45.0";
56        let (remaining, point) = point(input).unwrap();
57        assert_eq!(remaining, "");
58        assert_eq!(
59            point,
60            Point {
61                loop_label: 0,
62                x: 100.0,
63                y: 200.0,
64                angle: 45.0
65            }
66        );
67    }
68}