Browse Source

Finish rect array generation

Kevin Lee 1 year ago
parent
commit
b37566d4a4
7 changed files with 177 additions and 14 deletions
  1. 60 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 15 0
      README.md
  4. 13 6
      config.yml
  5. 1 1
      src/config/mod.rs
  6. 81 7
      src/config/object.rs
  7. 6 0
      src/ezcad/types.rs

+ 60 - 0
Cargo.lock

@@ -107,6 +107,12 @@ version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6"
 
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
 [[package]]
 name = "clap"
 version = "4.4.11"
@@ -232,11 +238,23 @@ dependencies = [
  "log",
  "modular-bitfield",
  "num",
+ "rand",
  "serde",
  "serde_yaml",
  "strum",
 ]
 
+[[package]]
+name = "getrandom"
+version = "0.2.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
 [[package]]
 name = "hashbrown"
 version = "0.14.3"
@@ -415,6 +433,12 @@ version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
 
+[[package]]
+name = "ppv-lite86"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
 [[package]]
 name = "proc-macro2"
 version = "1.0.71"
@@ -433,6 +457,36 @@ dependencies = [
  "proc-macro2",
 ]
 
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
 [[package]]
 name = "regex"
 version = "1.10.2"
@@ -603,6 +657,12 @@ version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
 [[package]]
 name = "winapi"
 version = "0.3.9"

+ 1 - 0
Cargo.toml

@@ -22,6 +22,7 @@ env_logger = "0.10.1"
 log = "0.4.20"
 modular-bitfield = "0.11.2"
 num = "0.4.1"
+rand = "0.8.5"
 serde = { version = "1.0.193", features = ["derive"] }
 serde_yaml = "0.9.29"
 strum = { version = "0.25.0", features = ["derive"] }

+ 15 - 0
README.md

@@ -124,3 +124,18 @@ Ops:
     Layer: 0
     Object: 3 # Optional, will delete specific object instead
 ```
+
+Generating a grid of rectangles with incrementing pens:
+
+``` yaml
+Ops:
+  - !RectangleArray
+    Width: 10.0
+    Height: 10.0
+    Rows: 5
+    Columns: 3
+    Spacing: 0.5
+    Z: 0.0
+    StartingPen: 0
+    RandomOrder: True
+```

+ 13 - 6
config.yml

@@ -13,6 +13,10 @@ Ops:
   #   To: 1
   #   LoopCount: 2
 
+  # - !ClonePenRange
+  #   From: 0
+  #   To: 4
+
   # - !PatternPen
   #   From: 1
   #   To: 5
@@ -37,9 +41,12 @@ Ops:
   #   Path: export_object.bin
 
   - !RectangleArray
-    Width: 3.0
-    Height: 3.0
-    Rows: 10
-    Columns: 4
-    Spacing: 0.5
-    Pen: 0
+    Layer: 0
+    Width: 10.0
+    Height: 10.0
+    Columns: 2
+    Rows: 2
+    Spacing: 4.0
+    Z: 0.0
+    StartingPen: 1
+    RandomOrder: True

+ 1 - 1
src/config/mod.rs

@@ -40,7 +40,7 @@ impl Operations for Vec<Operation> {
                 Operation::ExportObject(x) => x.export(layers),
                 Operation::ImportObject(x) => x.import(layers),
                 Operation::DeleteObjects(x) => x.delete(layers),
-                Operation::RectangleArray(x) => x.generate(layers),
+                Operation::RectangleArray(x) => x.generate(pens, layers),
             }
         }
     }

+ 81 - 7
src/config/object.rs

@@ -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));
+        }
     }
 }

+ 6 - 0
src/ezcad/types.rs

@@ -117,6 +117,12 @@ pub struct Point {
     pub y: f64,
 }
 
+impl Display for Point {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "({}, {})", self.x, self.y)
+    }
+}
+
 #[derive(Clone, Debug, Diff, PartialEq, BinRead, BinWrite, strum::Display)]
 #[diff(attr(
     #[derive(Debug, PartialEq)]