|
@@ -8,9 +8,13 @@ use binrw::{BinRead, BinWriterExt};
|
|
|
use ezcad::{
|
|
|
array_of::ArrayOf,
|
|
|
layer::Layer,
|
|
|
- objects::{rectangle::Rectangle, Object},
|
|
|
+ objects::{
|
|
|
+ hatch::{Hatch, HatchFlag, HatchPattern, HatchSetting, Hatches},
|
|
|
+ rectangle::Rectangle,
|
|
|
+ Object, ObjectCore,
|
|
|
+ },
|
|
|
pen::Pen,
|
|
|
- types::Point,
|
|
|
+ types::{ObjectType, Point},
|
|
|
};
|
|
|
use log::debug;
|
|
|
use rand::{seq::SliceRandom, thread_rng};
|
|
@@ -120,9 +124,88 @@ impl DeleteObjects {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
|
|
+#[serde(rename_all = "PascalCase")]
|
|
|
+pub struct HatchConfig {
|
|
|
+ line_spacing: f64,
|
|
|
+
|
|
|
+ count: Option<u32>,
|
|
|
+ edge_offset: Option<f64>,
|
|
|
+ start_offset: Option<f64>,
|
|
|
+ end_offset: Option<f64>,
|
|
|
+ angle: Option<f64>,
|
|
|
+ rotate_angle: Option<f64>,
|
|
|
+ line_reduction: Option<f64>,
|
|
|
+ loop_distance: Option<f64>,
|
|
|
+ loop_count: Option<u32>,
|
|
|
+
|
|
|
+ pattern: Option<HatchPattern>,
|
|
|
+ follow_edge_once: Option<bool>,
|
|
|
+ cross_hatch: Option<bool>,
|
|
|
+}
|
|
|
+
|
|
|
+impl From<HatchConfig> for HatchSetting {
|
|
|
+ fn from(value: HatchConfig) -> Self {
|
|
|
+ let mut ret = Self::default();
|
|
|
+
|
|
|
+ *ret.line_spacing = value.line_spacing;
|
|
|
+
|
|
|
+ if let Some(count) = value.count {
|
|
|
+ *ret.count = count.into();
|
|
|
+ }
|
|
|
+ if let Some(edge_offset) = value.edge_offset {
|
|
|
+ *ret.edge_offset = edge_offset.into();
|
|
|
+ }
|
|
|
+ if let Some(start_offset) = value.start_offset {
|
|
|
+ *ret.start_offset = start_offset.into();
|
|
|
+ }
|
|
|
+ if let Some(end_offset) = value.end_offset {
|
|
|
+ *ret.end_offset = end_offset.into();
|
|
|
+ }
|
|
|
+ if let Some(angle) = value.angle {
|
|
|
+ *ret.angle = angle.into();
|
|
|
+ }
|
|
|
+ if let Some(rotate_angle) = value.rotate_angle {
|
|
|
+ *ret.rotate_angle = rotate_angle.into();
|
|
|
+ }
|
|
|
+ if let Some(line_reduction) = value.line_reduction {
|
|
|
+ *ret.line_reduction = line_reduction.into();
|
|
|
+ }
|
|
|
+ if let Some(line_reduction) = value.line_reduction {
|
|
|
+ *ret.line_reduction = line_reduction.into();
|
|
|
+ }
|
|
|
+ if let Some(loop_distance) = value.loop_distance {
|
|
|
+ *ret.loop_distance = loop_distance.into();
|
|
|
+ }
|
|
|
+ if let Some(loop_count) = value.loop_count {
|
|
|
+ *ret.loop_count = loop_count.into();
|
|
|
+ }
|
|
|
+
|
|
|
+ let mut flags: HatchFlag = match value.pattern {
|
|
|
+ Some(pattern) => pattern.into(),
|
|
|
+ None => HatchPattern::Directional.into(),
|
|
|
+ };
|
|
|
+
|
|
|
+ if let Some(follow_edge) = value.follow_edge_once {
|
|
|
+ flags.set_follow_edge_once(follow_edge.into());
|
|
|
+ }
|
|
|
+ if let Some(cross_hatch) = value.cross_hatch {
|
|
|
+ flags.set_cross_hatch(cross_hatch.into());
|
|
|
+ }
|
|
|
+ if value.start_offset.is_none() && value.end_offset.is_none() {
|
|
|
+ flags.set_average_distribute_line(1);
|
|
|
+ }
|
|
|
+
|
|
|
+ *ret.flags = flags;
|
|
|
+ *ret.enabled = true.into();
|
|
|
+
|
|
|
+ ret
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
#[serde(rename_all = "PascalCase")]
|
|
|
-pub struct RectangleArray {
|
|
|
+pub struct HatchArray {
|
|
|
layer: usize,
|
|
|
width: f64,
|
|
|
height: f64,
|
|
@@ -131,9 +214,10 @@ pub struct RectangleArray {
|
|
|
spacing: f64,
|
|
|
z: f64,
|
|
|
starting_pen: usize,
|
|
|
+ hatch: HatchConfig,
|
|
|
}
|
|
|
|
|
|
-impl RectangleArray {
|
|
|
+impl HatchArray {
|
|
|
pub fn generate(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
|
|
|
debug!(
|
|
|
"Generating {} x {} array of {} x {} rectangles with spacing of {} starting from pen #{} on layer #{}",
|
|
@@ -175,7 +259,10 @@ impl RectangleArray {
|
|
|
seq.shuffle(&mut thread_rng());
|
|
|
|
|
|
// Generate objects and append to layer
|
|
|
- for (pen_incr, obj_idx) in seq.into_iter().enumerate() {
|
|
|
+ for obj_idx in seq.into_iter() {
|
|
|
+ let pen: u32 = (self.starting_pen + obj_idx).try_into().unwrap();
|
|
|
+
|
|
|
+ // Build outline object
|
|
|
let mut rect: Rectangle = Rectangle::default();
|
|
|
let origin: Point = calc_pt(obj_idx);
|
|
|
|
|
@@ -188,15 +275,34 @@ impl RectangleArray {
|
|
|
y: origin.y + self.height / 2.0,
|
|
|
};
|
|
|
*rect.core.origin = origin;
|
|
|
- *rect.core.pen = (self.starting_pen + pen_incr).try_into().unwrap();
|
|
|
+ *rect.core.pen = pen;
|
|
|
*rect.core.z = self.z;
|
|
|
|
|
|
debug!(
|
|
|
- "Adding rectangle with pen #{} at {} (from {} to {})",
|
|
|
+ "Adding hatched rectangle with pen #{} at {} (from {} to {})",
|
|
|
*rect.core.pen, *rect.core.origin, *rect.corner_a, *rect.corner_b
|
|
|
);
|
|
|
|
|
|
- layer.objects.push(Object::Rectangle(rect));
|
|
|
+ let mut hatch_setting: HatchSetting = self.hatch.into();
|
|
|
+ *hatch_setting.pen = pen;
|
|
|
+
|
|
|
+ // Build hatch object
|
|
|
+ let hatch: Hatch = Hatch {
|
|
|
+ core: ObjectCore {
|
|
|
+ origin: origin.into(),
|
|
|
+ z: self.z.into(),
|
|
|
+ ..ObjectCore::default(ObjectType::Hatch)
|
|
|
+ },
|
|
|
+ outline: vec![Object::Rectangle(rect)].into(),
|
|
|
+ legacy_setting: vec![hatch_setting.clone()].into(),
|
|
|
+ hatch_settings: vec![hatch_setting.clone()].into(),
|
|
|
+ hatches: Some(Hatches {
|
|
|
+ core: ObjectCore::default(ObjectType::HatchLine),
|
|
|
+ hatch_lines: vec![].into(),
|
|
|
+ }),
|
|
|
+ };
|
|
|
+
|
|
|
+ layer.objects.push(Object::Hatch(hatch));
|
|
|
}
|
|
|
}
|
|
|
}
|