|
@@ -5,8 +5,15 @@ use std::{
|
|
|
};
|
|
|
|
|
|
use binrw::{BinRead, BinWriterExt};
|
|
|
-use ezcad::{array_of::ArrayOf, layer::Layer, objects::Object};
|
|
|
-use log::debug;
|
|
|
+use ezcad::{
|
|
|
+ array_of::ArrayOf,
|
|
|
+ layer::Layer,
|
|
|
+ objects::{rectangle::Rectangle, Object},
|
|
|
+ pen::Pen,
|
|
|
+ types::Point,
|
|
|
+};
|
|
|
+use log::{debug, trace};
|
|
|
+use rand::{seq::SliceRandom, thread_rng};
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
@@ -116,19 +123,86 @@ impl DeleteObjects {
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
#[serde(rename_all = "PascalCase")]
|
|
|
pub struct RectangleArray {
|
|
|
+ layer: usize,
|
|
|
width: f64,
|
|
|
height: f64,
|
|
|
- rows: usize,
|
|
|
columns: usize,
|
|
|
+ rows: usize,
|
|
|
spacing: f64,
|
|
|
- pen: usize,
|
|
|
+ z: f64,
|
|
|
+ starting_pen: usize,
|
|
|
+ random_order: bool,
|
|
|
}
|
|
|
|
|
|
impl RectangleArray {
|
|
|
- pub fn generate(&self, layers: &mut ArrayOf<Layer>) {
|
|
|
+ pub fn generate(&self, pens: &Vec<Pen>, layers: &mut ArrayOf<Layer>) {
|
|
|
debug!(
|
|
|
- "Generating {} x {} array of ({} x {}) with spacing of {} starting from pen {}",
|
|
|
- self.rows, self.columns, self.width, self.height, self.spacing, self.pen
|
|
|
+ "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"
|
|
|
+ );
|
|
|
+
|
|
|
+ let layer: &mut Layer = layers.get_mut(self.layer).expect("Invalid layer index");
|
|
|
+
|
|
|
+ let incr_x: f64 = self.width + self.spacing;
|
|
|
+ let incr_y: f64 = self.height + self.spacing;
|
|
|
+
|
|
|
+ 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,
|
|
|
+ };
|
|
|
+
|
|
|
+ // Closure that returns origin point of given index in array, where index starts
|
|
|
+ // from top left and increments to the right and wraps around to the row below
|
|
|
+ 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 - incr_x * x_pos,
|
|
|
+ y: bottom_left.y - incr_y * y_pos,
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // Determine order in which to draw objects
|
|
|
+ let mut seq: Vec<usize> = (0..(self.rows * self.columns)).collect();
|
|
|
+ if self.random_order {
|
|
|
+ seq.shuffle(&mut thread_rng());
|
|
|
+ }
|
|
|
+
|
|
|
+ // Generate objects and append to layer
|
|
|
+ for (pen_incr, obj_idx) in seq.into_iter().enumerate() {
|
|
|
+ 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 = (self.starting_pen + pen_incr).try_into().unwrap();
|
|
|
+ *rect.core.z = self.z;
|
|
|
+
|
|
|
+ trace!(
|
|
|
+ "Adding rectangle with pen #{} at {} (from {} to {})",
|
|
|
+ *rect.core.pen,
|
|
|
+ *rect.core.origin,
|
|
|
+ *rect.corner_a,
|
|
|
+ *rect.corner_b
|
|
|
+ );
|
|
|
+
|
|
|
+ layer.objects.push(Object::Rectangle(rect));
|
|
|
+ }
|
|
|
}
|
|
|
}
|