From b4d35e7139e265087fd764f58c3042ae135f1524 Mon Sep 17 00:00:00 2001 From: John Wildkins Date: Sun, 9 Apr 2023 01:02:06 -0400 Subject: [PATCH 1/2] Implement fast-poisson sampling --- Cargo.lock | 38 ++++++++++++++++++++++++++++++++++++++ Cargo.toml | 4 ++++ dmsrc/noise.dm | 1 + src/noise_gen.rs | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index de5653d1..d2dd888a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -643,6 +643,17 @@ dependencies = [ "libc", ] +[[package]] +name = "fast_poisson" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d84ebb823253944c532a40f80c15cd7ba646c80deacd31f7e35f386329b33511" +dependencies = [ + "rand 0.8.5", + "rand_distr", + "rand_xoshiro", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -1272,6 +1283,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" + [[package]] name = "libz-sys" version = "1.1.8" @@ -1578,6 +1595,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -1896,6 +1914,16 @@ dependencies = [ "getrandom 0.2.8", ] +[[package]] +name = "rand_distr" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32cb0b9bc82b0a0876c2dd994a7e7a2683d3e7390ca40e6886785ef0c7e3ee31" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + [[package]] name = "rand_hc" version = "0.2.0" @@ -1932,6 +1960,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_xoshiro" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa" +dependencies = [ + "rand_core 0.6.4", +] + [[package]] name = "rayon" version = "1.7.0" @@ -2093,6 +2130,7 @@ dependencies = [ "const-random", "dashmap", "dbpnoise", + "fast_poisson", "flume", "git2", "hex", diff --git a/Cargo.toml b/Cargo.toml index f77d3620..ac0708c0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,10 +56,13 @@ rayon = { version = "1.5", optional = true } dbpnoise = { version = "0.1.2", optional = true } pathfinding = { version = "3.0.13", optional = true } num = { version = "0.4.0", optional = true } +fast_poisson = { version = "0.5.2", optional = true } [features] default = [ "acreplace", +# Aurora special snowflake noise gen + "auroranoise", "cellularnoise", "dmi", "file", @@ -80,6 +83,7 @@ default = [ # default features acreplace = ["aho-corasick"] +auroranoise = ["fast_poisson"] cellularnoise = ["rand", "rayon"] dmi = ["png", "image"] file = [] diff --git a/dmsrc/noise.dm b/dmsrc/noise.dm index 5630600e..d6550fee 100644 --- a/dmsrc/noise.dm +++ b/dmsrc/noise.dm @@ -1 +1,2 @@ #define rustg_noise_get_at_coordinates(seed, x, y) RUSTG_CALL(RUST_G, "noise_get_at_coordinates")(seed, x, y) +#define rustg_noise_poisson_sample(seed, x, y, r) RUSTG_CALL(RUST_G, "generate_poisson_sample")(seed, x, y, r) diff --git a/src/noise_gen.rs b/src/noise_gen.rs index d97a17e9..f8fc5743 100644 --- a/src/noise_gen.rs +++ b/src/noise_gen.rs @@ -1,5 +1,7 @@ +use fast_poisson::Poisson2D; use noise::{NoiseFn, Perlin}; use std::{ + fmt::Write, cell::RefCell, collections::hash_map::{Entry, HashMap}, }; @@ -14,6 +16,40 @@ byond_fn!(fn noise_get_at_coordinates(seed, x, y) { get_at_coordinates(seed, x, y).ok() }); +byond_fn!(fn generate_poisson_sample(seed, x, y, r) { + get_poisson_sample(seed, x, y, r).ok() +}); + +fn get_poisson_sample(seed_as_str: &str, x_as_str: &str, y_as_str: &str, radius_as_str: &str) -> Result { + let x = x_as_str.parse::()?; + let y = y_as_str.parse::()?; + let r = radius_as_str.parse::()?; + let seed = seed_as_str.parse::()?; + + let points = Poisson2D::new().with_dimensions([x, y], r).with_seed(seed).iter(); + let mut pointmap = vec![vec![0usize; y as usize]; x as usize]; + let mut output = String::new(); + + // we're just gonna truncate these to the nearest point + for p in points { + let point_x = p[0] as usize; + let point_y = p[1] as usize; + pointmap[point_x][point_y] = 1; + } + + for row in pointmap { + for cell in row { + if cell > 0 { + let _ = write!(output, "1"); + } else { + let _ = write!(output, "0"); + } + } + } + + Ok(output) +} + //note that this will be 0 at integer x & y, scaling is left up to the caller fn get_at_coordinates(seed_as_str: &str, x_as_str: &str, y_as_str: &str) -> Result { let x = x_as_str.parse::()?; From 30ca67e246040a964c0347faf6e3ccff4ca42497 Mon Sep 17 00:00:00 2001 From: John Wildkins Date: Sun, 9 Apr 2023 13:05:24 -0400 Subject: [PATCH 2/2] fix for fmt, add dbpnoise --- Cargo.toml | 2 ++ src/noise_gen.rs | 14 +++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ac0708c0..bdc471f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,6 +63,8 @@ default = [ "acreplace", # Aurora special snowflake noise gen "auroranoise", +# Not default either but we need it + "batchnoise", "cellularnoise", "dmi", "file", diff --git a/src/noise_gen.rs b/src/noise_gen.rs index f8fc5743..b8d911c2 100644 --- a/src/noise_gen.rs +++ b/src/noise_gen.rs @@ -1,9 +1,9 @@ use fast_poisson::Poisson2D; use noise::{NoiseFn, Perlin}; use std::{ - fmt::Write, cell::RefCell, collections::hash_map::{Entry, HashMap}, + fmt::Write, }; use crate::error::Result; @@ -20,13 +20,21 @@ byond_fn!(fn generate_poisson_sample(seed, x, y, r) { get_poisson_sample(seed, x, y, r).ok() }); -fn get_poisson_sample(seed_as_str: &str, x_as_str: &str, y_as_str: &str, radius_as_str: &str) -> Result { +fn get_poisson_sample( + seed_as_str: &str, + x_as_str: &str, + y_as_str: &str, + radius_as_str: &str, +) -> Result { let x = x_as_str.parse::()?; let y = y_as_str.parse::()?; let r = radius_as_str.parse::()?; let seed = seed_as_str.parse::()?; - let points = Poisson2D::new().with_dimensions([x, y], r).with_seed(seed).iter(); + let points = Poisson2D::new() + .with_dimensions([x, y], r) + .with_seed(seed) + .iter(); let mut pointmap = vec![vec![0usize; y as usize]; x as usize]; let mut output = String::new();