2 Commits 91a848b3f0 ... 76e164b7df

Tác giả SHA1 Thông báo Ngày
  Kevin Lee 76e164b7df Debug spew cleanup 10 tháng trước cách đây
  Kevin Lee 8a91cad412 Support randomizing pens 10 tháng trước cách đây
6 tập tin đã thay đổi với 143 bổ sung48 xóa
  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)
     }
 }