|
@@ -9,90 +9,17 @@ use ezcad::{
|
|
|
array_of::ArrayOf,
|
|
|
layer::Layer,
|
|
|
objects::{
|
|
|
+ circle::Circle,
|
|
|
hatch::{Hatch, HatchFlag, HatchPattern, HatchSetting, Hatches},
|
|
|
rectangle::Rectangle,
|
|
|
- Object, ObjectCore,
|
|
|
+ Object, ObjectCore, Translate,
|
|
|
},
|
|
|
pen::Pen,
|
|
|
types::{ObjectType, Point},
|
|
|
};
|
|
|
-use log::debug;
|
|
|
+use log::{debug, warn};
|
|
|
use rand::{seq::SliceRandom, thread_rng};
|
|
|
-use serde::{Deserialize, Serialize};
|
|
|
-
|
|
|
-#[derive(Debug, Serialize, Deserialize)]
|
|
|
-#[serde(rename_all = "PascalCase")]
|
|
|
-pub struct ExportObject {
|
|
|
- layer: usize,
|
|
|
- object: usize,
|
|
|
- path: PathBuf,
|
|
|
-}
|
|
|
-
|
|
|
-impl ExportObject {
|
|
|
- pub fn export(&self, layers: &ArrayOf<Layer>) {
|
|
|
- debug!(
|
|
|
- "Exporting layer #{} object #{} to '{}'",
|
|
|
- self.layer,
|
|
|
- self.object,
|
|
|
- self.path.to_string_lossy()
|
|
|
- );
|
|
|
-
|
|
|
- let layer = layers.get(self.layer).expect("Invalid layer index");
|
|
|
- let object = layer
|
|
|
- .objects
|
|
|
- .get(self.object)
|
|
|
- .expect("Invalid object index");
|
|
|
-
|
|
|
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
|
|
|
- buffer.write_le(object).expect("Failed to serialize object");
|
|
|
-
|
|
|
- let mut output: File = File::create(&self.path).expect("Failed to open output file");
|
|
|
- output
|
|
|
- .write_all(buffer.into_inner().as_slice())
|
|
|
- .expect("Failed to write to output file");
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-#[derive(Debug, Serialize, Deserialize)]
|
|
|
-#[serde(rename_all = "PascalCase")]
|
|
|
-pub struct ImportObject {
|
|
|
- layer: usize,
|
|
|
- object: Option<usize>,
|
|
|
- path: PathBuf,
|
|
|
-}
|
|
|
-
|
|
|
-impl ImportObject {
|
|
|
- pub fn import(&self, layers: &mut ArrayOf<Layer>) {
|
|
|
- debug!(
|
|
|
- "Importing layer #{}{} from '{}'",
|
|
|
- self.layer,
|
|
|
- match &self.object {
|
|
|
- Some(object) => format!(" object #{}", object),
|
|
|
- None => String::new(),
|
|
|
- },
|
|
|
- self.path.to_string_lossy(),
|
|
|
- );
|
|
|
-
|
|
|
- let mut input: File = File::open(&self.path).expect("Failed to open input file");
|
|
|
-
|
|
|
- let mut buffer: Cursor<Vec<u8>> = Cursor::new(vec![]);
|
|
|
- input
|
|
|
- .read_to_end(buffer.get_mut())
|
|
|
- .expect("Failed to read input file");
|
|
|
-
|
|
|
- let object: Object =
|
|
|
- Object::read_le(&mut buffer).expect("Failed to deserialize input as object");
|
|
|
-
|
|
|
- let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
|
|
|
-
|
|
|
- if let Some(index) = self.object {
|
|
|
- let dst: &mut Object = layer.objects.get_mut(index).expect("Invalid object index");
|
|
|
- *dst = object;
|
|
|
- } else {
|
|
|
- (*layer.objects).push(object);
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
+use serde::{de, Deserialize, Serialize};
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
#[serde(rename_all = "PascalCase")]
|
|
@@ -104,7 +31,7 @@ pub struct DeleteObjects {
|
|
|
impl DeleteObjects {
|
|
|
pub fn delete(&self, layers: &mut ArrayOf<Layer>) {
|
|
|
debug!(
|
|
|
- "Deleting {} from layer #{}",
|
|
|
+ "Deleting layer #{} {}",
|
|
|
match &self.object {
|
|
|
Some(object) => format!("object #{}", object),
|
|
|
None => format!("all objects"),
|
|
@@ -146,56 +73,33 @@ pub struct HatchConfig {
|
|
|
|
|
|
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());
|
|
|
- }
|
|
|
+ value
|
|
|
+ .follow_edge_once
|
|
|
+ .map(|x| flags.set_follow_edge_once(x.into()));
|
|
|
+ value.cross_hatch.map(|x| flags.set_cross_hatch(x.into()));
|
|
|
+
|
|
|
if value.start_offset.is_none() && value.end_offset.is_none() {
|
|
|
flags.set_average_distribute_line(1);
|
|
|
}
|
|
|
|
|
|
+ let mut ret = Self::default();
|
|
|
+
|
|
|
+ *ret.line_spacing = value.line_spacing;
|
|
|
+ value.count.map(|x| *ret.count = x.into());
|
|
|
+ value.edge_offset.map(|x| *ret.edge_offset = x.into());
|
|
|
+ value.start_offset.map(|x| *ret.start_offset = x.into());
|
|
|
+ value.end_offset.map(|x| *ret.end_offset = x.into());
|
|
|
+ value.angle.map(|x| *ret.angle = x.into());
|
|
|
+ value.rotate_angle.map(|x| *ret.rotate_angle = x.into());
|
|
|
+ value.line_reduction.map(|x| *ret.line_reduction = x.into());
|
|
|
+ value.loop_distance.map(|x| *ret.loop_distance = x.into());
|
|
|
+ value.loop_count.map(|x| *ret.loop_count = x.into());
|
|
|
+
|
|
|
*ret.flags = flags;
|
|
|
*ret.enabled = true.into();
|
|
|
|
|
@@ -205,104 +109,258 @@ impl From<HatchConfig> for HatchSetting {
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
#[serde(rename_all = "PascalCase")]
|
|
|
-pub struct HatchArray {
|
|
|
- layer: usize,
|
|
|
- width: f64,
|
|
|
- height: f64,
|
|
|
+pub struct ArrayConfig {
|
|
|
columns: usize,
|
|
|
rows: usize,
|
|
|
spacing: f64,
|
|
|
- z: f64,
|
|
|
- starting_pen: usize,
|
|
|
- hatch: HatchConfig,
|
|
|
+ randomize_order: bool,
|
|
|
+ starting_pen: u32,
|
|
|
}
|
|
|
|
|
|
-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 #{}",
|
|
|
- self.columns, self.rows, self.width, self.height, self.spacing, self.starting_pen, self.layer
|
|
|
- );
|
|
|
- assert!(
|
|
|
- self.rows >= 1 && self.columns >= 1,
|
|
|
- "Invalid row/column value"
|
|
|
- );
|
|
|
- assert!(
|
|
|
- self.starting_pen + (self.rows * self.columns) < pens.len(),
|
|
|
- "Invalid starting pen"
|
|
|
- );
|
|
|
+#[derive(Debug, Serialize, Deserialize, strum::Display)]
|
|
|
+#[serde(rename_all = "PascalCase")]
|
|
|
+pub enum InputObject {
|
|
|
+ Rectangle {
|
|
|
+ width: f64,
|
|
|
+ height: f64,
|
|
|
+ round_corner: Option<f64>,
|
|
|
+ },
|
|
|
+ Circle {
|
|
|
+ radius: f64,
|
|
|
+ },
|
|
|
+ Import {
|
|
|
+ path: PathBuf,
|
|
|
+ },
|
|
|
+ Existing {
|
|
|
+ layer: usize,
|
|
|
+ object: usize,
|
|
|
+ },
|
|
|
+}
|
|
|
|
|
|
- let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
|
|
|
+impl InputObject {
|
|
|
+ fn new(&self, layers: &ArrayOf<Layer>) -> Object {
|
|
|
+ match self {
|
|
|
+ InputObject::Rectangle {
|
|
|
+ width,
|
|
|
+ height,
|
|
|
+ round_corner,
|
|
|
+ } => Object::Rectangle(Rectangle {
|
|
|
+ corner_a: Point::from((-width / 2.0, -height / 2.0)).into(),
|
|
|
+ corner_b: Point::from((width / 2.0, height / 2.0)).into(),
|
|
|
+ round_bottom_left: round_corner.unwrap_or(0.0).into(),
|
|
|
+ round_bottom_right: round_corner.unwrap_or(0.0).into(),
|
|
|
+ round_top_left: round_corner.unwrap_or(0.0).into(),
|
|
|
+ round_top_right: round_corner.unwrap_or(0.0).into(),
|
|
|
+ ..Default::default()
|
|
|
+ }),
|
|
|
+ InputObject::Circle { radius } => Object::Circle(Circle {
|
|
|
+ radius: (*radius).into(),
|
|
|
+ ..Default::default()
|
|
|
+ }),
|
|
|
+ InputObject::Import { path } => Object::read_from_file(path),
|
|
|
+ InputObject::Existing { layer, object } => {
|
|
|
+ let layer: &Layer = layers.get(*layer).expect("Invalid layer index");
|
|
|
+ layer
|
|
|
+ .objects
|
|
|
+ .get(*object)
|
|
|
+ .expect("Invalid object index")
|
|
|
+ .clone()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
- let incr_x: f64 = self.width + self.spacing;
|
|
|
- let incr_y: f64 = self.height + self.spacing;
|
|
|
+#[derive(Debug, Serialize, Deserialize)]
|
|
|
+#[serde(rename_all = "PascalCase")]
|
|
|
+pub struct ObjectOperation {
|
|
|
+ input: InputObject,
|
|
|
+ z: Option<f64>,
|
|
|
+ origin: Option<Point>,
|
|
|
+ pen: Option<u32>,
|
|
|
+ layer: Option<usize>,
|
|
|
+ array: Option<ArrayConfig>,
|
|
|
+ hatch: Option<HatchConfig>,
|
|
|
+ export: Option<PathBuf>,
|
|
|
+ replace_object: Option<usize>,
|
|
|
+}
|
|
|
|
|
|
- let bottom_left: Point = Point {
|
|
|
- x: (self.columns - 1) as f64 * -incr_x / 2.0,
|
|
|
- y: (self.rows - 1) as f64 * -incr_y / 2.0,
|
|
|
- };
|
|
|
+impl ObjectOperation {
|
|
|
+ pub fn process(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
|
|
|
+ debug!("Processing object {}", self.input);
|
|
|
|
|
|
- // Closure that returns origin point of given index in array, where index starts
|
|
|
- // from bottom left and increments to the right and wraps around to the row above
|
|
|
- let calc_pt = |index: usize| {
|
|
|
- let x_pos: f64 = (index % self.columns) as f64;
|
|
|
- let y_pos: f64 = (index / self.columns) as f64;
|
|
|
+ let mut object: Object = self.input.new(layers);
|
|
|
|
|
|
- Point {
|
|
|
- x: bottom_left.x + incr_x * x_pos,
|
|
|
- y: bottom_left.y + incr_y * y_pos,
|
|
|
- }
|
|
|
- };
|
|
|
+ // Process basic transformation
|
|
|
+ object.translate(self.origin, self.z);
|
|
|
+ self.pen.map(|pen| object.set_pen(pen));
|
|
|
|
|
|
- // Randomize draw order
|
|
|
- let mut seq: Vec<usize> = (0..(self.rows * self.columns)).collect();
|
|
|
- seq.shuffle(&mut thread_rng());
|
|
|
+ // Process conversion to hatch object
|
|
|
|
|
|
- // Generate objects and append to layer
|
|
|
- for obj_idx in seq.into_iter() {
|
|
|
- let pen: u32 = (self.starting_pen + obj_idx).try_into().unwrap();
|
|
|
+ // Process array generation of object
|
|
|
+ let new_objects = self.array.as_ref().map_or(vec![object.clone()], |array| {
|
|
|
+ let bottom_left: Point = Point {
|
|
|
+ x: (array.columns - 1) as f64 * array.spacing / -2.0,
|
|
|
+ y: (array.rows - 1) as f64 * array.spacing / -2.0,
|
|
|
+ };
|
|
|
|
|
|
- // Build outline object
|
|
|
- let mut rect: Rectangle = Rectangle::default();
|
|
|
- let origin: Point = calc_pt(obj_idx);
|
|
|
+ // Closure that returns origin point of given index in array, where index starts
|
|
|
+ // from bottom left and increments to the right and wraps around to the row above
|
|
|
+ let calc_pt = |index: usize| {
|
|
|
+ let x_pos: f64 = (index % array.columns) as f64;
|
|
|
+ let y_pos: f64 = (index / array.columns) as f64;
|
|
|
|
|
|
- *rect.corner_a = Point {
|
|
|
- x: origin.x - self.width / 2.0,
|
|
|
- y: origin.y - self.height / 2.0,
|
|
|
- };
|
|
|
- *rect.corner_b = Point {
|
|
|
- x: origin.x + self.width / 2.0,
|
|
|
- y: origin.y + self.height / 2.0,
|
|
|
- };
|
|
|
- *rect.core.origin = origin;
|
|
|
- *rect.core.pen = pen;
|
|
|
- *rect.core.z = self.z;
|
|
|
-
|
|
|
- debug!(
|
|
|
- "Adding hatched rectangle with pen #{} at {} (from {} to {})",
|
|
|
- *rect.core.pen, *rect.core.origin, *rect.corner_a, *rect.corner_b
|
|
|
- );
|
|
|
-
|
|
|
- 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(),
|
|
|
- }),
|
|
|
+ Point {
|
|
|
+ x: bottom_left.x + array.spacing * x_pos,
|
|
|
+ y: bottom_left.y + array.spacing * y_pos,
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- layer.objects.push(Object::Hatch(hatch));
|
|
|
+ // Randomize draw order
|
|
|
+ let mut seq: Vec<usize> = (0..(array.rows * array.columns)).collect();
|
|
|
+ if array.randomize_order {
|
|
|
+ seq.shuffle(&mut thread_rng());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Generate objects
|
|
|
+ let mut new_obj: Vec<Object> = vec![];
|
|
|
+
|
|
|
+ for obj_idx in seq.into_iter() {
|
|
|
+ let mut object: Object = object.clone();
|
|
|
+ object.translate(Some(calc_pt(obj_idx)), None);
|
|
|
+ object.set_pen(array.starting_pen + u32::try_from(obj_idx).unwrap());
|
|
|
+
|
|
|
+ new_obj.push(object);
|
|
|
+ }
|
|
|
+
|
|
|
+ new_obj
|
|
|
+ });
|
|
|
+
|
|
|
+ // Process export of object
|
|
|
+ self.export.as_ref().map(|path| {
|
|
|
+ if new_objects.len() > 1 {
|
|
|
+ warn!("Exporting only the first object in list of objects");
|
|
|
+ } else {
|
|
|
+ debug!(
|
|
|
+ "Exporting object {} to '{}'",
|
|
|
+ new_objects[0],
|
|
|
+ path.to_string_lossy()
|
|
|
+ );
|
|
|
+ }
|
|
|
+ new_objects[0].write_to_file(path);
|
|
|
+ });
|
|
|
+
|
|
|
+ // Append or replace object in layer
|
|
|
+ let layer: &mut Layer = layers
|
|
|
+ .get_mut(self.layer.unwrap_or(0))
|
|
|
+ .expect("Invalid layer index");
|
|
|
+ match self.replace_object {
|
|
|
+ Some(object) => {
|
|
|
+ // debug!("Replacing object #{} with {}", object, new_objects);
|
|
|
+ layer.objects.splice(object..=object, new_objects);
|
|
|
+ }
|
|
|
+ None => {
|
|
|
+ layer.objects.extend(new_objects);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+// #[derive(Debug, Serialize, Deserialize)]
|
|
|
+// #[serde(rename_all = "PascalCase")]
|
|
|
+// pub struct Array {
|
|
|
+// layer: usize,
|
|
|
+// z: f64,
|
|
|
+// columns: usize,
|
|
|
+// rows: usize,
|
|
|
+// spacing: f64,
|
|
|
+// starting_pen: usize,
|
|
|
+// object: InputObject,
|
|
|
+// hatch: Option<HatchConfig>,
|
|
|
+// }
|
|
|
+
|
|
|
+// impl Array {
|
|
|
+// pub fn generate(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
|
|
|
+// debug!(
|
|
|
+// "Generating {} x {} array of {:?} with spacing of {} starting from pen #{} on layer #{}",
|
|
|
+// self.columns, self.rows, self.object, self.spacing, self.starting_pen, self.layer
|
|
|
+// );
|
|
|
+// assert!(
|
|
|
+// self.rows >= 1 && self.columns >= 1,
|
|
|
+// "Invalid row/column value"
|
|
|
+// );
|
|
|
+// assert!(
|
|
|
+// self.starting_pen + (self.rows * self.columns) < pens.len(),
|
|
|
+// "Invalid starting pen"
|
|
|
+// );
|
|
|
+
|
|
|
+// let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
|
|
|
+
|
|
|
+// let bottom_left: Point = Point {
|
|
|
+// x: (self.columns - 1) as f64 * self.spacing / -2.0,
|
|
|
+// y: (self.rows - 1) as f64 * self.spacing / -2.0,
|
|
|
+// };
|
|
|
+
|
|
|
+// // Closure that returns origin point of given index in array, where index starts
|
|
|
+// // from bottom left and increments to the right and wraps around to the row above
|
|
|
+// let calc_pt = |index: usize| {
|
|
|
+// let x_pos: f64 = (index % self.columns) as f64;
|
|
|
+// let y_pos: f64 = (index / self.columns) as f64;
|
|
|
+
|
|
|
+// Point {
|
|
|
+// x: bottom_left.x + self.spacing * x_pos,
|
|
|
+// y: bottom_left.y + self.spacing * y_pos,
|
|
|
+// }
|
|
|
+// };
|
|
|
+
|
|
|
+// // Randomize draw order
|
|
|
+// let mut seq: Vec<usize> = (0..(self.rows * self.columns)).collect();
|
|
|
+// seq.shuffle(&mut thread_rng());
|
|
|
+
|
|
|
+// // Generate objects and append to layer
|
|
|
+// 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);
|
|
|
+
|
|
|
+// // *rect.corner_a = Point {
|
|
|
+// // x: origin.x - self.width / 2.0,
|
|
|
+// // y: origin.y - self.height / 2.0,
|
|
|
+// // };
|
|
|
+// // *rect.corner_b = Point {
|
|
|
+// // x: origin.x + self.width / 2.0,
|
|
|
+// // y: origin.y + self.height / 2.0,
|
|
|
+// // };
|
|
|
+// // *rect.core.origin = origin;
|
|
|
+// // *rect.core.pen = pen;
|
|
|
+// // *rect.core.z = self.z;
|
|
|
+
|
|
|
+// // debug!(
|
|
|
+// // "Adding hatched rectangle with pen #{} at {} (from {} to {})",
|
|
|
+// // *rect.core.pen, *rect.core.origin, *rect.corner_a, *rect.corner_b
|
|
|
+// // );
|
|
|
+
|
|
|
+// // 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));
|
|
|
+// }
|
|
|
+// }
|
|
|
+// }
|