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
8
9namespace ps
10{
11
47template <typename T, size_t N>
48std::vector<Point<T, N>> jittered_grid(size_t count,
49 const std::array<std::pair<T, T>, N> &axis_ranges,
50 const std::array<T, N> &jitter_amount,
51 const std::array<T, N> &stagger_ratio,
52 std::optional<unsigned int> seed = std::nullopt)
53{
54 std::mt19937 gen(seed ? *seed : std::random_device{}());
55 std::uniform_real_distribution<T> uniform01(0.0, 1.0);
56
57 std::array<size_t, N> resolution;
58 size_t total_cells = 1;
59
60 T volume = 1;
61 for (const auto &[min, max] : axis_ranges)
62 volume *= (max - min);
63
64 T target_cell_volume = volume / static_cast<T>(count);
65 T cell_size_estimate = std::pow(target_cell_volume, static_cast<T>(1.0) / N);
66
67 for (size_t i = 0; i < N; ++i)
68 {
69 T range = axis_ranges[i].second - axis_ranges[i].first;
70 resolution[i] = std::max<size_t>(1, static_cast<size_t>(range / cell_size_estimate));
72 }
73
74 std::vector<Point<T, N>> points;
75 points.reserve(std::min(count, total_cells));
76
77 std::vector<std::array<size_t, N>> cell_indices;
78 for (size_t linear = 0; linear < total_cells; ++linear)
79 {
80 std::array<size_t, N> index{};
81 size_t div = 1;
82 for (size_t i = 0; i < N; ++i)
83 {
84 index[i] = (linear / div) % resolution[i];
85 div *= resolution[i];
86 }
87 cell_indices.push_back(index);
88 }
89
90 std::shuffle(cell_indices.begin(), cell_indices.end(), gen);
91 size_t limit = std::min(count, cell_indices.size());
92
93 for (size_t i = 0; i < limit; ++i)
94 {
95 const auto &idx = cell_indices[i];
97
98 for (size_t d = 0; d < N; ++d)
99 {
100 T range_min = axis_ranges[d].first;
101 T range_max = axis_ranges[d].second;
102 T cell_size = (range_max - range_min) / static_cast<T>(resolution[d]);
103
104 T jitter_range = jitter_amount[d] * cell_size;
105 T jitter_center = (1.0 - jitter_amount[d]) * 0.5 * cell_size;
107
108 // Compute stagger offset from higher dimensions
109 T stagger_offset = 0;
110 for (size_t k = d + 1; k < N; ++k)
111 {
112 if (idx[k] % 2 == 1)
113 stagger_offset += stagger_ratio[d] * cell_size;
114 }
115
116 p[d] = range_min + idx[d] * cell_size + jitter_center + jitter + stagger_offset;
117 }
118
119 points.push_back(p);
120 }
121
122 return points;
123}
124
145template <typename T, size_t N>
146std::vector<Point<T, N>> jittered_grid(size_t count,
147 const std::array<std::pair<T, T>, N> &axis_ranges,
148 std::optional<unsigned int> seed = std::nullopt)
149{
150 std::array<T, N> full_jitter;
151 std::array<T, N> stagger_ratio;
152 full_jitter.fill(static_cast<T>(1.0));
153 stagger_ratio.fill(static_cast<T>(0.0));
154
156}
157
158} // 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:48
A fixed-size N-dimensional point/vector class.
Definition point.hpp:39