Skip to content

Commit ae154ad

Browse files
committed
bump gerber-types.
* optional coordinates.
1 parent abcd8bc commit ae154ad

4 files changed

Lines changed: 95 additions & 96 deletions

File tree

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ env_logger = ["dep:env_logger"]
3030
[dependencies]
3131
# currently un-released, using latest gerber_types with updates to support macro expressions
3232
#gerber_types = "0.4.0"
33-
gerber_types = { git = "https://github.com/MakerPnP/gerber-types.git", rev = "357215682b77093c3693efa4fe9d74076c1685fa"}
33+
gerber_types = { git = "https://github.com/MakerPnP/gerber-types.git", rev = "6f77ef9d7d6529504ef1914cfeef0550112a518c"}
3434
#gerber_types = { path = "../gerber-types" }
3535

3636
# errors

src/parser.rs

Lines changed: 41 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ use crate::document::GerberDoc;
22
use crate::error::ContentError;
33
use crate::gerber_types::{
44
Aperture, ApertureAttribute, ApertureFunction, ApertureMacro, CenterLinePrimitive, Circle,
5-
CirclePrimitive, Command, CoordinateFormat, Coordinates, DCode, ExtendedCode, FiducialScope,
6-
FileAttribute, FileFunction, FilePolarity, FunctionCode, GCode, InterpolationMode, MCode,
7-
MacroBoolean, MacroContent, MacroDecimal, MacroInteger, Operation, OutlinePrimitive, Part,
8-
Polarity, Polygon, PolygonPrimitive, QuadrantMode, Rectangular, SmdPadType, StepAndRepeat,
9-
Unit, VectorLinePrimitive,
5+
CirclePrimitive, Command, CoordinateFormat, DCode, ExtendedCode, FiducialScope, FileAttribute,
6+
FileFunction, FilePolarity, FunctionCode, GCode, InterpolationMode, MCode, MacroBoolean,
7+
MacroContent, MacroDecimal, MacroInteger, Operation, OutlinePrimitive, Part, Polarity, Polygon,
8+
PolygonPrimitive, QuadrantMode, Rectangular, SmdPadType, StepAndRepeat, Unit,
9+
VectorLinePrimitive,
1010
};
11-
use crate::util::{coordinates_offset_from_gerber, partial_coordinates_from_gerber};
11+
use crate::util::{partial_coordinates_from_gerber, partial_coordinates_offset_from_gerber};
1212
use crate::ParseError;
1313
use gerber_types::{
1414
ApertureBlock, ComponentCharacteristics, ComponentDrill, ComponentMounting, ComponentOutline,
@@ -375,7 +375,6 @@ fn parse_line<T: Read>(
375375
Ok(vec![parse_aperture_selection_or_command(
376376
line,
377377
linechars.clone(),
378-
gerber_doc,
379378
)])
380379
}
381380
'M' => Ok(vec![Ok(FunctionCode::MCode(MCode::EndOfFile).into())]),
@@ -1202,35 +1201,24 @@ fn parse_aperture_code(code_str: &str) -> Result<i32, ContentError> {
12021201
fn parse_aperture_selection_or_command(
12031202
line: &str,
12041203
linechars: Chars,
1205-
gerber_doc: &GerberDoc,
12061204
) -> Result<Command, ContentError> {
12071205
let aperture_str = linechars.as_str();
12081206
if let Ok(aperture_code) = parse_aperture_code(aperture_str) {
12091207
Ok(FunctionCode::DCode(DCode::SelectAperture(aperture_code)).into())
12101208
} else {
1211-
parse_command(line, gerber_doc)
1209+
parse_command(line)
12121210
}
12131211
}
12141212

1215-
fn parse_command(command_str: &str, gerber_doc: &GerberDoc) -> Result<Command, ContentError> {
1213+
fn parse_command(command_str: &str) -> Result<Command, ContentError> {
12161214
static RE_STANDALONE_D: Lazy<Regex> = lazy_regex!(r"D(0)?([1-3])\*");
12171215
if let Some(captures) = RE_STANDALONE_D.captures(command_str) {
12181216
let command_code = captures.get(2).unwrap().as_str();
12191217
{
1220-
let format = gerber_doc
1221-
.format_specification
1222-
.ok_or(ContentError::OperationBeforeFormat {})?;
1223-
1224-
let coords = Coordinates {
1225-
x: None,
1226-
y: None,
1227-
format,
1228-
};
1229-
12301218
let operation = match command_code {
1231-
"1" => Operation::Interpolate(coords, None),
1232-
"2" => Operation::Move(coords),
1233-
"3" => Operation::Flash(coords),
1219+
"1" => Operation::Interpolate(None, None),
1220+
"2" => Operation::Move(None),
1221+
"3" => Operation::Flash(None),
12341222
_ => unreachable!(),
12351223
};
12361224
Ok(Command::FunctionCode(FunctionCode::DCode(
@@ -1254,54 +1242,40 @@ fn parse_interpolation(line: &str, gerber_doc: &GerberDoc) -> Result<Command, Co
12541242
.get(2)
12551243
.map(|y| parse_coord::<i64>(y.as_str()))
12561244
.transpose()?;
1245+
let i_coord = regmatch
1246+
.get(3)
1247+
.map(|i| parse_coord::<i64>(i.as_str()))
1248+
.transpose()?;
1249+
let j_coord = regmatch
1250+
.get(4)
1251+
.map(|i| parse_coord::<i64>(i.as_str()))
1252+
.transpose()?;
12571253

1258-
if let Some((i_offset_raw, j_offset_raw)) = regmatch.get(3).zip(regmatch.get(4)) {
1259-
// we have X,Y,I,J parameters and we are doing circular interpolation
1260-
let i_offset = parse_coord::<i64>(i_offset_raw.as_str())?;
1261-
let j_offset = parse_coord::<i64>(j_offset_raw.as_str())?;
1262-
1263-
let fs = gerber_doc
1264-
.format_specification
1265-
.ok_or(ContentError::OperationBeforeFormat {})?;
1254+
let fs = gerber_doc
1255+
.format_specification
1256+
.ok_or(ContentError::OperationBeforeFormat {})?;
12661257

1267-
let coordinates =
1268-
partial_coordinates_from_gerber(x_coord, y_coord, fs).map_err(|error| {
1269-
ContentError::CoordinateFormatMismatch {
1270-
format: fs,
1271-
cause: error,
1272-
}
1273-
})?;
1258+
let coordinates =
1259+
partial_coordinates_from_gerber(x_coord, y_coord, fs).map_err(|error| {
1260+
ContentError::CoordinateFormatMismatch {
1261+
format: fs,
1262+
cause: error,
1263+
}
1264+
})?;
12741265

1275-
let offset =
1276-
coordinates_offset_from_gerber(i_offset, j_offset, fs).map_err(|error| {
1277-
ContentError::CoordinateFormatMismatch {
1278-
format: fs,
1279-
cause: error,
1280-
}
1281-
})?;
1266+
let offset =
1267+
partial_coordinates_offset_from_gerber(i_coord, j_coord, fs).map_err(|error| {
1268+
ContentError::CoordinateFormatMismatch {
1269+
format: fs,
1270+
cause: error,
1271+
}
1272+
})?;
12821273

1283-
Ok(FunctionCode::DCode(DCode::Operation(Operation::Interpolate(
1284-
coordinates,
1285-
Some(offset),
1286-
)))
1287-
.into())
1288-
} else {
1289-
let fs = gerber_doc
1290-
.format_specification
1291-
.ok_or(ContentError::OperationBeforeFormat {})?;
1292-
1293-
// linear interpolation, only X,Y parameters
1294-
Ok(FunctionCode::DCode(DCode::Operation(Operation::Interpolate(
1295-
partial_coordinates_from_gerber(x_coord, y_coord, fs).map_err(|error| {
1296-
ContentError::CoordinateFormatMismatch {
1297-
format: fs,
1298-
cause: error,
1299-
}
1300-
})?,
1301-
None,
1302-
)))
1303-
.into())
1304-
}
1274+
Ok(FunctionCode::DCode(DCode::Operation(Operation::Interpolate(
1275+
coordinates,
1276+
offset,
1277+
)))
1278+
.into())
13051279
}
13061280
None => Err(ContentError::NoRegexMatch {
13071281
regex: RE_INTERPOLATION.clone(),

src/util.rs

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,24 @@ pub fn coordinates_from_gerber(
3333
mut x_as_int: i64,
3434
mut y_as_int: i64,
3535
fs: CoordinateFormat,
36-
) -> Result<Coordinates, GerberError> {
36+
) -> Result<Option<Coordinates>, GerberError> {
3737
// we have the raw gerber string as int but now have to convert it to nano precision format
3838
// (i.e. 6 decimal precision) as this is what CoordinateNumber uses internally
3939
let factor = (6u8 - fs.decimal) as u32;
4040
x_as_int *= 10i64.pow(factor);
4141
y_as_int *= 10i64.pow(factor);
42-
Ok(Coordinates::new(
42+
Ok(Some(Coordinates::new(
4343
CoordinateNumber::new(x_as_int).validate(&fs)?,
4444
CoordinateNumber::new(y_as_int).validate(&fs)?,
4545
fs,
46-
))
46+
)))
4747
}
4848

4949
pub fn partial_coordinates_from_gerber(
5050
x_as_int: Option<i64>,
5151
y_as_int: Option<i64>,
5252
fs: CoordinateFormat,
53-
) -> Result<Coordinates, GerberError> {
53+
) -> Result<Option<Coordinates>, GerberError> {
5454
// we have the raw gerber string as int but now have to convert it to nano precision format
5555
// (i.e. 6 decimal precision) as this is what CoordinateNumber uses internally
5656
let factor = (6u8 - fs.decimal) as u32;
@@ -61,22 +61,31 @@ pub fn partial_coordinates_from_gerber(
6161
.map(|value| CoordinateNumber::new(value * 10i64.pow(factor)).validate(&fs))
6262
.transpose()?;
6363

64-
Ok(Coordinates::new(x, y, fs))
64+
let coordinates = match (x, y) {
65+
(None, None) => None,
66+
(x, y) => Some(Coordinates::new(x, y, fs)),
67+
};
68+
Ok(coordinates)
6569
}
6670

67-
pub fn coordinates_offset_from_gerber(
68-
mut x_as_int: i64,
69-
mut y_as_int: i64,
71+
pub fn partial_coordinates_offset_from_gerber(
72+
x_as_int: Option<i64>,
73+
y_as_int: Option<i64>,
7074
fs: CoordinateFormat,
71-
) -> Result<CoordinateOffset, GerberError> {
75+
) -> Result<Option<CoordinateOffset>, GerberError> {
7276
// we have the raw gerber string as int but now have to convert it to nano precision format
7377
// (i.e. 6 decimal precision) as this is what CoordinateNumber uses internally
7478
let factor = (6u8 - fs.decimal) as u32;
75-
x_as_int *= 10i64.pow(factor);
76-
y_as_int *= 10i64.pow(factor);
77-
Ok(CoordinateOffset::new(
78-
CoordinateNumber::new(x_as_int).validate(&fs)?,
79-
CoordinateNumber::new(y_as_int).validate(&fs)?,
80-
fs,
81-
))
79+
let x = x_as_int
80+
.map(|value| CoordinateNumber::new(value * 10i64.pow(factor)).validate(&fs))
81+
.transpose()?;
82+
let y = y_as_int
83+
.map(|value| CoordinateNumber::new(value * 10i64.pow(factor)).validate(&fs))
84+
.transpose()?;
85+
86+
let coordinate_offset = match (x, y) {
87+
(None, None) => None,
88+
(x, y) => Some(CoordinateOffset::new(x, y, fs)),
89+
};
90+
Ok(coordinate_offset)
8291
}

tests/component_tests.rs

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ use std::collections::HashMap;
1515
use strum::VariantArray;
1616
mod util;
1717
use gerber_parser::util::{
18-
coordinates_from_gerber, coordinates_offset_from_gerber, gerber_to_reader,
19-
partial_coordinates_from_gerber,
18+
coordinates_from_gerber, gerber_to_reader, partial_coordinates_from_gerber,
19+
partial_coordinates_offset_from_gerber,
2020
};
2121
use util::testing::logging_init;
2222

@@ -392,7 +392,7 @@ fn D01_interpolation_circular() {
392392
Ok(Command::FunctionCode(FunctionCode::DCode(
393393
DCode::Operation(Operation::Interpolate(
394394
coordinates_from_gerber(-1000, -30000, fs).unwrap(),
395-
Some(coordinates_offset_from_gerber(200, -5000, fs).unwrap())
395+
partial_coordinates_offset_from_gerber(Some(200), Some(-5000), fs).unwrap()
396396
))
397397
)))
398398
]
@@ -2797,7 +2797,7 @@ fn diptrace_rounded_rectangle_pcb_outline() {
27972797
GCode::InterpolationMode(InterpolationMode::Linear)
27982798
))),
27992799
Ok(Command::FunctionCode(FunctionCode::DCode(
2800-
DCode::Operation(Operation::Move(Coordinates::new(5, 15, format)))
2800+
DCode::Operation(Operation::Move(Some(Coordinates::new(5, 15, format))))
28012801
))),
28022802
Ok(Command::FunctionCode(FunctionCode::DCode(
28032803
DCode::SelectAperture(12)
@@ -2807,7 +2807,7 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28072807
))),
28082808
Ok(Command::FunctionCode(FunctionCode::DCode(
28092809
DCode::Operation(Operation::Interpolate(
2810-
Coordinates::new(0, 10, format),
2810+
Some(Coordinates::new(0, 10, format)),
28112811
Some(CoordinateOffset::new(0, -5, format)),
28122812
))
28132813
))),
@@ -2816,7 +2816,11 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28162816
))),
28172817
Ok(Command::FunctionCode(FunctionCode::DCode(
28182818
DCode::Operation(Operation::Interpolate(
2819-
Coordinates::new::<Option<i32>, Option<i32>>(None, Some(5), format),
2819+
Some(Coordinates::new::<Option<i32>, Option<i32>>(
2820+
None,
2821+
Some(5),
2822+
format
2823+
)),
28202824
None,
28212825
))
28222826
))),
@@ -2825,7 +2829,7 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28252829
))),
28262830
Ok(Command::FunctionCode(FunctionCode::DCode(
28272831
DCode::Operation(Operation::Interpolate(
2828-
Coordinates::new(5, 0, format),
2832+
Some(Coordinates::new(5, 0, format)),
28292833
Some(CoordinateOffset::new(5, 0, format)),
28302834
))
28312835
))),
@@ -2834,7 +2838,11 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28342838
))),
28352839
Ok(Command::FunctionCode(FunctionCode::DCode(
28362840
DCode::Operation(Operation::Interpolate(
2837-
Coordinates::new::<Option<i32>, Option<i32>>(Some(15), None, format),
2841+
Some(Coordinates::new::<Option<i32>, Option<i32>>(
2842+
Some(15),
2843+
None,
2844+
format
2845+
)),
28382846
None,
28392847
))
28402848
))),
@@ -2843,7 +2851,7 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28432851
))),
28442852
Ok(Command::FunctionCode(FunctionCode::DCode(
28452853
DCode::Operation(Operation::Interpolate(
2846-
Coordinates::new(20, 5, format),
2854+
Some(Coordinates::new(20, 5, format)),
28472855
Some(CoordinateOffset::new(0, 5, format)),
28482856
))
28492857
))),
@@ -2852,7 +2860,11 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28522860
))),
28532861
Ok(Command::FunctionCode(FunctionCode::DCode(
28542862
DCode::Operation(Operation::Interpolate(
2855-
Coordinates::new::<Option<i32>, Option<i32>>(None, Some(10), format),
2863+
Some(Coordinates::new::<Option<i32>, Option<i32>>(
2864+
None,
2865+
Some(10),
2866+
format
2867+
)),
28562868
None,
28572869
))
28582870
))),
@@ -2861,7 +2873,7 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28612873
))),
28622874
Ok(Command::FunctionCode(FunctionCode::DCode(
28632875
DCode::Operation(Operation::Interpolate(
2864-
Coordinates::new(15, 15, format),
2876+
Some(Coordinates::new(15, 15, format)),
28652877
Some(CoordinateOffset::new(-5, 0, format)),
28662878
))
28672879
))),
@@ -2870,7 +2882,11 @@ fn diptrace_rounded_rectangle_pcb_outline() {
28702882
))),
28712883
Ok(Command::FunctionCode(FunctionCode::DCode(
28722884
DCode::Operation(Operation::Interpolate(
2873-
Coordinates::new::<Option<i32>, Option<i32>>(Some(5), None, format),
2885+
Some(Coordinates::new::<Option<i32>, Option<i32>>(
2886+
Some(5),
2887+
None,
2888+
format
2889+
)),
28742890
None,
28752891
))
28762892
))),

0 commit comments

Comments
 (0)