PointSampler library (C++)
Loading...
Searching...
No Matches
jittered_grid.hpp
Go to the documentation of this file.
1/* Copyright (c) 2025 Otto Link. Distributed under the terms of the GNU General
2 Public License. The full license is in the file LICENSE, distributed with
3 this software. */
4#pragma once
5#include <optional>
6#include <random>
7
9
10namespace ps
11{
12
48template <typename T, size_t N>
49std::vector<Point<T, N>> jittered_grid(size_t count,
50 const std::array<std::pair<T, T>, N> &axis_ranges,
51 const std::array<T, N> &jitter_amount,
52 const std::array<T, N> &stagger_ratio,
53 std::optional<unsigned int> seed = std::nullopt)
54{
55 std::mt19937 gen(seed ? *seed : std::random_device{}());
56 std::uniform_real_distribution<T> uniform01(0.0, 1.0);
57
58 std::array<size_t, N> resolution;
59 size_t total_cells = 1;
60
61 T volume = 1;
62 for (const auto &[min, max] : axis_ranges)
63 volume *= (max - min);
64
65 T target_cell_volume = volume / static_cast<T>(count);
66 T cell_size_estimate = std::pow(target_cell_volume, static_cast<T>(1.0) / N);
67
68 for (size_t i = 0; i < N; ++i)
69 {
70 T range = axis_ranges[i].second - axis_ranges[i].first;
71 resolution[i] = std::max<size_t>(1, static_cast<size_t>(range / cell_size_estimate));
73 }
74
75 std::vector<Point<T, N>> points;
76 points.reserve(std::min(count, total_cells));
77
78 std::vector<std::array<size_t, N>> cell_indices;
79 for (size_t linear = 0; linear < total_cells; ++linear)
80 {
81 std::array<size_t, N> index{};
82 size_t div = 1;
83 for (size_t i = 0; i < N; ++i)
84 {
85 index[i] = (linear / div) % resolution[i];
86 div *= resolution[i];
87 }
88 cell_indices.push_back(index);
89 }
90
91 std::shuffle(cell_indices.begin(), cell_indices.end(), gen);
92 size_t limit = std::min(count, cell_indices.size());
93
94 for (size_t i = 0; i < limit; ++i)
95 {
96 const auto &idx = cell_indices[i];
98
99 for (size_t d = 0; d < N; ++d)
100 {
101 T range_min = axis_ranges[d].first;
102 T range_max = axis_ranges[d].second;
103 T cell_size = (range_max - range_min) / static_cast<T>(resolution[d]);
104
105 T jitter_range = jitter_amount[d] * cell_size;
106 T jitter_center = (1.0 - jitter_amount[d]) * 0.5 * cell_size;
108
109 // Compute stagger offset from higher dimensions
110 T stagger_offset = 0;
111 for (size_t k = d + 1; k < N; ++k)
112 {
113 if (idx[k] % 2 == 1)
114 stagger_offset += stagger_ratio[d] * cell_size;
115 }
116
117 p[d] = range_min + idx[d] * cell_size + jitter_center + jitter + stagger_offset;
118 }
119
120 points.push_back(p);
121 }
122
123 return points;
124}
125
146template <typename T, size_t N>
147std::vector<Point<T, N>> jittered_grid(size_t count,
148 const std::array<std::pair<T, T>, N> &axis_ranges,
149 std::optional<unsigned int> seed = std::nullopt)
150{
151 std::array<T, N> full_jitter;
152 std::array<T, N> stagger_ratio;
153 full_jitter.fill(static_cast<T>(1.0));
154 stagger_ratio.fill(static_cast<T>(0.0));
155
157}
158
159} // namespace ps
Definition dbscan_clustering.hpp:11
std::vector< Point< T, N > > random(size_t count, const std::array< std::pair< T, T >, N > &axis_ranges, std::optional< unsigned int > seed=std::nullopt)
Generates a specified number of uniformly distributed random points in N-dimensional space.
Definition random.hpp:66
std::vector< Point< T, N > > jittered_grid(size_t count, const std::array< std::pair< T, T >, N > &axis_ranges, const std::array< T, N > &jitter_amount, const std::array< T, N > &stagger_ratio, std::optional< unsigned int > seed=std::nullopt)
Generates a point set on a jittered and optionally staggered grid.
Definition jittered_grid.hpp:49
A fixed-size N-dimensional point/vector class.
Definition point.hpp:39