From 964e6b5020152e1a0be506b7afaf5dc17a0994e8 Mon Sep 17 00:00:00 2001 From: Justin Lin Date: Wed, 29 Jun 2022 16:55:28 +0800 Subject: [PATCH] add pp_poisson --- src/experimental/note.md | 2 + src/pp/_impl/_pp_poisson.scad | 120 ++++++++++++++++++++++++++++++++++ src/pp/pp_poisson.scad | 28 ++++++++ 3 files changed, 150 insertions(+) create mode 100644 src/pp/_impl/_pp_poisson.scad create mode 100644 src/pp/pp_poisson.scad diff --git a/src/experimental/note.md b/src/experimental/note.md index b6dfada8..6fbcf5f4 100644 --- a/src/experimental/note.md +++ b/src/experimental/note.md @@ -26,6 +26,8 @@ new: - lsystem2, lsystem3, add seed param +- pp_poisson? + doc-ed deprecated: diff --git a/src/pp/_impl/_pp_poisson.scad b/src/pp/_impl/_pp_poisson.scad new file mode 100644 index 00000000..2b3d58d5 --- /dev/null +++ b/src/pp/_impl/_pp_poisson.scad @@ -0,0 +1,120 @@ +use <../../matrix/m_replace.scad> +use <../../util/every.scad> +use <../pp_disk.scad> + +function sampling(size, r, start, k) = + let( + w = r / sqrt(2), + rows = floor(size.y / w), + columns = floor(size.x / w), + pt = is_undef(start) ? size / 2 : start, + active = [pt], + px = floor(pt.x / w), + py = floor(pt.y / w), + grid_row = [for(i = [0:columns - 1]) undef], + grid = m_replace([for(j = [0:rows - 1]) grid_row], px, py, pt) + ) + [r, k, w, active, grid, rows, columns, []]; + +function sampling_r(s) = s[0]; +function sampling_k(s) = s[1]; +function sampling_w(s) = s[2]; +function sampling_active(s) = s[3]; +function sampling_grid(s) = s[4]; +function sampling_rows(s) = s[5]; +function sampling_columns(s) = s[6]; +function sampling_history(s) = s[7]; + +function sampling_inRow(s, y) = y > -1 && y < sampling_rows(s); + +function sampling_inGrid(s, x, y) = + sampling_inRow(s, y) && x > -1 && x < sampling_columns(s); + +function sampling_noAdjacentNeighbor(s, sample, x, y) = + every( + [ + [x - 1, y - 1], [x, y - 1], [x + 1, y - 1], + [x - 1, y], [x, y], [x + 1, y], + [x - 1, y + 1], [x, y + 1], [x + 1, y + 1] + ], + function(nbr) !sampling_inRow(s, nbr.y) || + (let(p = sampling_grid(s)[nbr.y][nbr.x]) + is_undef(p) || + norm(sample - p) >= sampling_r(s)) + ); + +function sampling_randomSample(s, pos) = + let( + r = sampling_r(s), + a = rands(0, 360, 1)[0] + ) + rands(r, 2 * r, 1)[0] * [cos(a), sin(a)] + pos; + +function sampling_hasActive(s) = len(sampling_active(s)) > 0; + +function sampling_kSamples(s, pos) = [ + for(n = [0:sampling_k(s) - 1]) + let( + sample = sampling_randomSample(s, pos), + w = sampling_w(s), + x = floor(sample.x / w), + y = floor(sample.y / w) + ) + if(sampling_inGrid(s, x, y) && sampling_noAdjacentNeighbor(s, sample, x, y)) + sample +]; + +function sampling_minDistSample(s, pos, samples) = + len(samples) == 1 ? samples[0] : + _sampling_minDistSample(s, pos, samples, samples[0], norm(pos - samples[0])); + +function _sampling_minDistSample(s, pos, samples, min_s, min_dist, i = 1) = + i == len(samples) ? min_s : + let( + sample = samples[i], + d = norm(pos - sample), + params = min_dist > d ? [sample, d] : [min_s, min_dist] + ) + _sampling_minDistSample(s, pos, samples, params[0], params[1], i + 1); + +function sampling_trySampleFromOneActive(s) = + let( + active = sampling_active(s), + i = floor(rands(0, len(active) - 1, 1)[0]), + pos = active[i], + samples = sampling_kSamples(s, pos) + ) + len(samples) == 0 ? + [ + sampling_r(s), + sampling_k(s), + sampling_w(s), + [for(j = [0:len(active) - 1]) if(j != i) active[j]], + sampling_grid(s), + sampling_rows(s), + sampling_columns(s), + sampling_history(s) + ] + : + let( + sample = sampling_minDistSample(s, pos, samples), + nx_active = [each active, sample], + w = sampling_w(s), + x = floor(sample.x / w), + y = floor(sample.y / w), + nx_grid = m_replace(sampling_grid(s), x, y, sample) + ) + [ + sampling_r(s), + sampling_k(s), + w, + nx_active, + nx_grid, + sampling_rows(s), + sampling_columns(s), + [each sampling_history(s), [pos, sample]] + ]; + +function _pp_poisson(s) = + !sampling_hasActive(s) ? s : _pp_poisson(sampling_trySampleFromOneActive(s)); + \ No newline at end of file diff --git a/src/pp/pp_poisson.scad b/src/pp/pp_poisson.scad new file mode 100644 index 00000000..5812c8f6 --- /dev/null +++ b/src/pp/pp_poisson.scad @@ -0,0 +1,28 @@ +use <_impl/_pp_poisson.scad> + +function pp_poisson(size, r, start, k = 30, history = false) = + let( + s = _pp_poisson(sampling(size, r, start, k)), + samples = [ + for(row = sampling_grid(s), sample = row) + if(!is_undef(sample)) sample + ] + ) + history ? [samples, sampling_history(s)] : samples; + +/* +use +use + + +pts_history = pp_poisson([100, 100], 5, history = true); +for(p = pts_history[0]) { + translate(p) + circle(1); +} + +for(h = pts_history[1]) { + polyline_join(h) + circle(.5); +} +*/ \ No newline at end of file