1
0

2 کامیت‌ها 91a848b3f0 ... 76e164b7df

نویسنده SHA1 پیام تاریخ
  Kevin Lee 76e164b7df Debug spew cleanup 10 ماه پیش
  Kevin Lee 8a91cad412 Support randomizing pens 10 ماه پیش
6فایلهای تغییر یافته به همراه143 افزوده شده و 48 حذف شده
  1. 10 0
      Cargo.lock
  2. 1 0
      Cargo.toml
  3. 15 0
      README.md
  4. 49 47
      src/config/mod.rs
  5. 67 0
      src/config/pen.rs
  6. 1 1
      src/ezcad/types.rs

+ 10 - 0
Cargo.lock

@@ -282,6 +282,15 @@ dependencies = [
  "windows-sys 0.48.0",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "1.0.10"
@@ -321,6 +330,7 @@ dependencies = [
  "clap-verbosity-flag",
  "diff-struct",
  "env_logger",
+ "itertools",
  "log",
  "modular-bitfield",
  "num",

+ 1 - 0
Cargo.toml

@@ -19,6 +19,7 @@ clap = { version = "4.4.11", features = ["derive"] }
 clap-verbosity-flag = "2.1.1"
 diff-struct = "0.5.3"
 env_logger = "0.10.1"
+itertools = "0.12.0"
 log = "0.4.20"
 modular-bitfield = "0.11.2"
 num = "0.4.1"

+ 15 - 0
README.md

@@ -83,6 +83,21 @@ Field: !Frequency 1000
 Field: !PulseWidth 2 # Increment
 ```
 
+Randomizing pen values:
+
+``` yaml
+Op:
+  - !RandomizePen
+    Index: 0
+    Count: 10
+    
+    # Specify one or more of the following:
+    Speed: [100, 1000, 100] # [min, max, incr]
+    Power: [10, 100, 5] # [min, max, incr]
+    Frequency: [20000, 100000, 1000] # [min, max, incr]
+    PulseWidth: [2, 250] #[min, max]
+```
+
 Exporting a pen to a file:
 
 ``` yaml

+ 49 - 47
src/config/mod.rs

@@ -1,47 +1,49 @@
-use ezcad::{array_of::ArrayOf, layer::Layer, pen::Pen};
-use serde::{Deserialize, Serialize};
-
-use self::{
-    object::{DeleteObjects, ObjectOperation},
-    pen::{ClonePen, ImportExportPen, PatchPen, PatternPen},
-};
-
-pub mod object;
-pub mod pen;
-
-#[derive(Debug, Serialize, Deserialize)]
-pub enum Operation {
-    PatchPen(PatchPen),
-    ClonePen(ClonePen),
-    PatternPen(PatternPen),
-    ExportPen(ImportExportPen),
-    ImportPen(ImportExportPen),
-    DeleteObjects(DeleteObjects),
-    Object(ObjectOperation),
-}
-
-pub trait Operations {
-    fn apply(&self, pens: &mut Vec<Pen>, layers: &mut ArrayOf<Layer>);
-}
-
-impl Operations for Vec<Operation> {
-    fn apply(&self, pens: &mut Vec<Pen>, layers: &mut ArrayOf<Layer>) {
-        for op in self {
-            match op {
-                Operation::PatchPen(x) => x.patch(pens),
-                Operation::ClonePen(x) => x.clone(pens),
-                Operation::PatternPen(x) => x.pattern(pens),
-                Operation::ImportPen(x) => x.import(pens),
-                Operation::ExportPen(x) => x.export(pens),
-                Operation::DeleteObjects(x) => x.delete(layers),
-                Operation::Object(x) => x.process(pens, layers),
-            }
-        }
-    }
-}
-
-#[derive(Debug, Serialize, Deserialize)]
-#[serde(rename_all = "PascalCase")]
-pub struct Config {
-    pub ops: Vec<Operation>,
-}
+use ezcad::{array_of::ArrayOf, layer::Layer, pen::Pen};
+use serde::{Deserialize, Serialize};
+
+use self::{
+    object::{DeleteObjects, ObjectOperation},
+    pen::{ClonePen, ImportExportPen, PatchPen, PatternPen, RandomizePen},
+};
+
+pub mod object;
+pub mod pen;
+
+#[derive(Debug, Serialize, Deserialize)]
+pub enum Operation {
+    PatchPen(PatchPen),
+    ClonePen(ClonePen),
+    PatternPen(PatternPen),
+    RandomizePen(RandomizePen),
+    ExportPen(ImportExportPen),
+    ImportPen(ImportExportPen),
+    DeleteObjects(DeleteObjects),
+    Object(ObjectOperation),
+}
+
+pub trait Operations {
+    fn apply(&self, pens: &mut Vec<Pen>, layers: &mut ArrayOf<Layer>);
+}
+
+impl Operations for Vec<Operation> {
+    fn apply(&self, pens: &mut Vec<Pen>, layers: &mut ArrayOf<Layer>) {
+        for op in self {
+            match op {
+                Operation::PatchPen(x) => x.patch(pens),
+                Operation::ClonePen(x) => x.clone(pens),
+                Operation::PatternPen(x) => x.pattern(pens),
+                Operation::RandomizePen(x) => x.random(pens),
+                Operation::ImportPen(x) => x.import(pens),
+                Operation::ExportPen(x) => x.export(pens),
+                Operation::DeleteObjects(x) => x.delete(layers),
+                Operation::Object(x) => x.process(pens, layers),
+            }
+        }
+    }
+}
+
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct Config {
+    pub ops: Vec<Operation>,
+}

+ 67 - 0
src/config/pen.rs

@@ -4,7 +4,9 @@ use ezcad::{
     pen::Pen,
     types::{PulseWidth, Rgba},
 };
+use itertools::Itertools;
 use log::debug;
+use rand::{seq::SliceRandom, Rng};
 use serde::{Deserialize, Serialize};
 use strum::IntoEnumIterator;
 
@@ -317,6 +319,71 @@ impl PatternPen {
     }
 }
 
+#[derive(Debug, Serialize, Deserialize)]
+#[serde(rename_all = "PascalCase")]
+pub struct RandomizePen {
+    index: usize,
+    count: usize,
+    speed: Option<(f64, f64, f64)>,
+    power: Option<(f64, f64, f64)>,
+    frequency: Option<(u32, u32, u32)>,
+    pulse_width: Option<(PulseWidth, PulseWidth)>,
+}
+
+impl RandomizePen {
+    pub fn random(&self, pens: &mut Vec<Pen>) {
+        debug!(
+            "Randomizing from pen #{} to #{}",
+            self.index,
+            self.index + self.count - 1
+        );
+
+        for (index, pen) in pens
+            .iter_mut()
+            .skip(self.index)
+            .take(self.count)
+            .enumerate()
+        {
+            if let Some((min, max, incr)) = self.speed {
+                let offset: usize = rand::thread_rng().gen_range(0..=((max - min) / incr) as usize);
+                let value: f64 = min + incr * offset as f64;
+                debug!("Randomizing speed for pen #{} to {}", index, value);
+                *pen.speed = value;
+            }
+
+            if let Some((min, max, incr)) = self.power {
+                let offset: usize = rand::thread_rng().gen_range(0..=((max - min) / incr) as usize);
+                let value: f64 = min + incr * offset as f64;
+                debug!("Randomizing power for pen #{} to {}", index, value);
+                *pen.power = value;
+            }
+
+            if let Some((min, max, incr)) = self.frequency {
+                let offset: usize = rand::thread_rng().gen_range(0..=((max - min) / incr) as usize);
+                let value: u32 = min + incr * offset as u32;
+                debug!("Randomizing frequency for pen #{} to {}", index, value);
+                *pen.frequency = value;
+                *pen.frequency_2 = value.try_into().unwrap();
+            }
+
+            if let Some((min, max)) = self.pulse_width {
+                let mut pw = PulseWidth::iter();
+                let mut v: Vec<PulseWidth> = vec![pw.find(|x| *x == min).unwrap()];
+                v.extend(pw.take_while_inclusive(|x| *x != max).collect_vec());
+
+                let width: &PulseWidth = v
+                    .choose_multiple(&mut rand::thread_rng(), 1)
+                    .next()
+                    .unwrap();
+                let value: u32 = (*width).into();
+                debug!("Randomizing pulse width for pen #{} to {}", index, value);
+                *pen.pulse_width = value;
+                *pen.pulse_width_2 = value.try_into().unwrap();
+            }
+        }
+    }
+}
+
 #[derive(Debug, Serialize, Deserialize)]
 #[serde(rename_all = "PascalCase")]
 pub struct ImportExportPen {

+ 1 - 1
src/ezcad/types.rs

@@ -141,7 +141,7 @@ pub struct Coordinate {
 
 impl Display for Coordinate {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "({}, {})", self.x, self.y)
+        write!(f, "({:.2}, {:.2})", self.x, self.y)
     }
 }