216 lines
9.1 KiB
Rust
216 lines
9.1 KiB
Rust
|
use clipper2::Paths;
|
||
|
use gerber_types::{
|
||
|
Aperture, Command, Coordinates, DCode, FunctionCode, GCode, InterpolationMode, MCode,
|
||
|
Operation, Unit,
|
||
|
};
|
||
|
use tracing::{debug, error, info};
|
||
|
|
||
|
use crate::{
|
||
|
geometry::{
|
||
|
elements::{
|
||
|
circle::Circle, linepath::LinePath, obround::Obround, rectangle::Rectangle, Element,
|
||
|
},
|
||
|
point::Point,
|
||
|
},
|
||
|
gerber::doc::GerberDoc,
|
||
|
};
|
||
|
|
||
|
use super::{
|
||
|
union::{union_lines, union_with_apertures},
|
||
|
Geometry,
|
||
|
};
|
||
|
|
||
|
impl From<GerberDoc> for Geometry {
|
||
|
fn from(gerber: GerberDoc) -> Self {
|
||
|
// working variables
|
||
|
let mut selected_aperture = None;
|
||
|
let mut selected_interpolation_mode = InterpolationMode::Linear;
|
||
|
let mut current_position = Point::new(0., 0.);
|
||
|
let mut active_path: LinePath = LinePath::new();
|
||
|
let mut path_container: Vec<LinePath> = Vec::new();
|
||
|
let mut added_apertures: Vec<Element> = Vec::new();
|
||
|
|
||
|
for command in gerber.commands {
|
||
|
println!("{command:?}");
|
||
|
match command {
|
||
|
Command::FunctionCode(f) => {
|
||
|
match f {
|
||
|
FunctionCode::DCode(code) => {
|
||
|
match code {
|
||
|
DCode::Operation(op) => match op {
|
||
|
Operation::Interpolate(coordinates, offset) => {
|
||
|
if selected_interpolation_mode == InterpolationMode::Linear
|
||
|
{
|
||
|
// self.add_draw_segment(coord);
|
||
|
let point = Point::try_from(&coordinates);
|
||
|
if active_path.is_empty() {
|
||
|
active_path.add(current_position);
|
||
|
}
|
||
|
match point {
|
||
|
Ok(point) => {
|
||
|
active_path.add(point);
|
||
|
}
|
||
|
Err(e) => error!("{e:?}"),
|
||
|
}
|
||
|
} else {
|
||
|
// TODO
|
||
|
// self.add_arc_segment(coord, offset.as_ref().expect(format!("No offset coord with 'Circular' state\r\n{:#?}", c).as_str()))
|
||
|
}
|
||
|
Self::move_position(&coordinates, &mut current_position);
|
||
|
}
|
||
|
Operation::Move(m) => {
|
||
|
debug!("Move to {:?}, create path.", &m);
|
||
|
// self.create_path_from_data();
|
||
|
if let Some(Aperture::Circle(c)) =
|
||
|
selected_aperture.as_ref()
|
||
|
{
|
||
|
if !active_path.is_empty() {
|
||
|
active_path.finalize(c.diameter);
|
||
|
path_container.push(active_path);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
active_path = LinePath::new();
|
||
|
Geometry::move_position(&m, &mut current_position);
|
||
|
}
|
||
|
Operation::Flash(f) => {
|
||
|
// self.create_path_from_data();
|
||
|
Self::add_geometry(
|
||
|
&mut added_apertures,
|
||
|
¤t_position,
|
||
|
&f,
|
||
|
&selected_aperture,
|
||
|
);
|
||
|
|
||
|
Self::move_position(&f, &mut current_position);
|
||
|
}
|
||
|
},
|
||
|
DCode::SelectAperture(ap) => {
|
||
|
// self.create_path_from_data();
|
||
|
selected_aperture = Some(
|
||
|
gerber
|
||
|
.apertures
|
||
|
.get(&ap)
|
||
|
.unwrap_or_else(|| {
|
||
|
panic!("Unknown aperture id '{}'", ap)
|
||
|
})
|
||
|
.clone(),
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
FunctionCode::GCode(code) => match code {
|
||
|
GCode::InterpolationMode(im) => selected_interpolation_mode = im,
|
||
|
GCode::Comment(c) => info!("[COMMENT] \"{}\"", c),
|
||
|
_ => error!("Unsupported GCode:\r\n{:#?}", code),
|
||
|
},
|
||
|
FunctionCode::MCode(m) => {
|
||
|
// check for end of file
|
||
|
if m == MCode::EndOfFile && !active_path.is_empty() {
|
||
|
// finish current path if one is present
|
||
|
if let Some(Aperture::Circle(c)) = selected_aperture.as_ref() {
|
||
|
active_path.finalize(c.diameter);
|
||
|
path_container.push(active_path);
|
||
|
break; // finish executing commands
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
Command::ExtendedCode(_) => {}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let mut result = clipper2::Paths::new(vec![]);
|
||
|
// if path_container.len() > 1 {
|
||
|
// let mut clipper = path_container[1]
|
||
|
// .outline
|
||
|
// // .to_paths()
|
||
|
// .to_clipper_subject()
|
||
|
// .add_clip(path_container[2].outline.clone());
|
||
|
// // .add_clip(path_container[3].outline.clone())
|
||
|
// // .add_clip(path_container[4].outline.clone());
|
||
|
|
||
|
// // for clip in added_apertures.iter().skip(2) {
|
||
|
// // clipper = clipper.add_clip(clip.to_paths());
|
||
|
// // }
|
||
|
|
||
|
// // for line in path_container.iter().skip(2) {
|
||
|
// // clipper = clipper.add_clip(line.to_paths())
|
||
|
// // }
|
||
|
|
||
|
// result = clipper.union(clipper2::FillRule::default()).unwrap();
|
||
|
|
||
|
// result = result
|
||
|
// .to_clipper_subject()
|
||
|
// .add_clip(path_container[3].outline.clone())
|
||
|
// .add_clip(path_container[4].outline.clone())
|
||
|
// .union(clipper2::FillRule::default())
|
||
|
// .unwrap();
|
||
|
// }
|
||
|
|
||
|
let mut geo = Paths::new(vec![]);
|
||
|
let conductor_net = union_lines(&path_container);
|
||
|
|
||
|
for outline in &conductor_net {
|
||
|
println!("{:?}", outline.included_points);
|
||
|
geo.push(outline.outline.clone());
|
||
|
}
|
||
|
|
||
|
println!("Number of conductor net paths: {}", geo.len());
|
||
|
|
||
|
if let Some(geo) = union_with_apertures(&added_apertures, conductor_net) {
|
||
|
println!("Number of finalized net paths: {}", geo.len());
|
||
|
result = geo;
|
||
|
}
|
||
|
Self {
|
||
|
outline_union: result,
|
||
|
apertures: added_apertures,
|
||
|
paths: path_container,
|
||
|
units: gerber.units.unwrap_or(Unit::Millimeters).into(),
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Geometry {
|
||
|
fn move_position(coord: &Coordinates, position: &mut Point) -> () {
|
||
|
if let Ok(pos) = Point::try_from(coord) {
|
||
|
debug!("Moved position to {pos:?}");
|
||
|
*position = pos;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
fn add_geometry(
|
||
|
geometries: &mut Vec<Element>,
|
||
|
position: &Point,
|
||
|
coordinates: &Coordinates,
|
||
|
aperture: &Option<Aperture>,
|
||
|
) {
|
||
|
let target = match Point::try_from(coordinates) {
|
||
|
Ok(point) => point,
|
||
|
Err(_) => *position,
|
||
|
};
|
||
|
|
||
|
match aperture.as_ref().expect("No aperture selected") {
|
||
|
Aperture::Circle(c) => {
|
||
|
geometries.push(Element::Circle(Circle::from_aperture_circle(c, target)));
|
||
|
}
|
||
|
Aperture::Rectangle(r) => {
|
||
|
geometries.push(Element::Rectangle(Rectangle::from_aperture_rectangular(
|
||
|
r, target,
|
||
|
)));
|
||
|
}
|
||
|
Aperture::Obround(o) => {
|
||
|
// error!("Unsupported Obround aperture:\r\n{:#?}", o);
|
||
|
geometries.push(Element::Obround(Obround::from_aperture_obround(o, target)));
|
||
|
}
|
||
|
Aperture::Polygon(p) => {
|
||
|
error!("Unsupported Polygon aperture:\r\n{:#?}", p);
|
||
|
}
|
||
|
Aperture::Other(o) => {
|
||
|
error!("Unsupported Other aperture:\r\n{:#?}", o);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|