PointSampler library (C++)
Loading...
Searching...
No Matches
utils.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 <fstream>
6#include <sstream>
7#include <string>
8#include <vector>
9
11
12namespace ps
13{
14
33template <typename T, size_t N>
34bool save_points_to_csv(const std::string &filename,
35 const std::vector<Point<T, N>> &points,
36 bool write_header = true)
37{
38 std::ofstream out(filename);
39 if (!out.is_open())
40 return false;
41
42 if (write_header)
43 {
44 for (size_t i = 0; i < N; ++i)
45 {
46 out << "x" << i;
47 if (i < N - 1)
48 out << ",";
49 }
50 out << "\n";
51 }
52
53 for (const auto &point : points)
54 {
55 for (size_t i = 0; i < N; ++i)
56 {
57 out << point[i];
58 if (i < N - 1)
59 out << ",";
60 }
61 out << "\n";
62 }
63
64 return true;
65}
66
95template <typename T>
96bool save_vector_to_csv(const std::string &filename,
97 const std::vector<T> &values,
98 bool write_header = true,
99 const std::string &header_name = "value")
100{
101 std::ofstream out(filename);
102 if (!out.is_open())
103 return false;
104
105 if (write_header)
106 out << header_name << "\n";
107
108 for (const auto &val : values)
109 out << val << "\n";
110
111 return true;
112}
113
141template <typename T, size_t N>
142std::vector<Point<T, N + 1>> add_dimension(const std::vector<Point<T, N>> &points,
143 const std::vector<T> &new_dimension)
144{
145 if (points.size() != new_dimension.size())
146 throw std::runtime_error(
147 "add_dimension: size mismatch between points and new dimension data");
148
149 std::vector<Point<T, N + 1>> result;
150 result.reserve(points.size());
151
152 for (size_t i = 0; i < points.size(); ++i)
153 {
154 std::array<T, N + 1> coords{};
155 std::copy(points[i].coords.begin(), points[i].coords.end(), coords.begin());
156 coords[N] = new_dimension[i];
157 result.emplace_back(coords);
158 }
159
160 return result;
161}
162
179template <typename T, size_t N>
180std::vector<std::vector<Point<T, N>>> extract_clusters(
181 const std::vector<Point<T, N>> &points,
182 const std::vector<int> &labels)
183{
184 if (points.size() != labels.size())
185 throw std::runtime_error("extract_clusters: mismatch between points and labels size");
186
187 // find max cluster id
188 int max_cluster_id = -1;
189 for (int lbl : labels)
190 if (lbl >= 0)
191 max_cluster_id = std::max(max_cluster_id, lbl);
192
193 std::vector<std::vector<Point<T, N>>> clusters(max_cluster_id + 1);
194
195 for (size_t i = 0; i < points.size(); ++i)
196 {
197 int lbl = labels[i];
198 if (lbl >= 0)
199 clusters[lbl].push_back(points[i]);
200 }
201
202 return clusters;
203}
204
244template <typename T, size_t N>
245std::vector<Point<T, N>> merge_by_dimension(
246 const std::array<std::vector<T>, N> &components)
247{
248 if constexpr (N > 0)
249 {
250 std::size_t count = components[0].size();
251 for (std::size_t i = 1; i < N; ++i)
252 {
253 if (components[i].size() != count)
254 throw std::invalid_argument("All component vectors must have the same size");
255 }
256
257 std::vector<Point<T, N>> points(count);
258 for (std::size_t i = 0; i < count; ++i)
259 {
260 for (std::size_t j = 0; j < N; ++j)
261 points[i][j] = components[j][i];
262 }
263
264 return points;
265 }
266 else
267 {
268 return {};
269 }
270}
271
298template <typename T, size_t N> void normalize_points(std::vector<Point<T, N>> &points)
299{
300 if (points.empty())
301 return;
302
303 std::array<T, N> min_vals;
304 std::array<T, N> max_vals;
305
306 // Initialize min/max arrays
307 for (size_t dim = 0; dim < N; ++dim)
308 {
309 min_vals[dim] = points[0].coords[dim];
310 max_vals[dim] = points[0].coords[dim];
311 }
312
313 // Find min/max for each axis
314 for (const auto &p : points)
315 {
316 for (size_t dim = 0; dim < N; ++dim)
317 {
318 min_vals[dim] = std::min(min_vals[dim], p.coords[dim]);
319 max_vals[dim] = std::max(max_vals[dim], p.coords[dim]);
320 }
321 }
322
323 // Normalize each point
324 for (auto &p : points)
325 {
326 for (size_t dim = 0; dim < N; ++dim)
327 {
329 if (range != T(0))
330 p.coords[dim] = (p.coords[dim] - min_vals[dim]) / range;
331 else
332 p.coords[dim] = T(0); // Avoid NaN if all values
333 // are equal
334 }
335 }
336}
337
360template <typename T, size_t N>
361std::array<std::vector<T>, N> split_by_dimension(const std::vector<Point<T, N>> &points)
362{
363 std::array<std::vector<T>, N> components;
364
365 for (const auto &point : points)
366 for (size_t i = 0; i < N; ++i)
367 {
368 components[i].push_back(point[i]);
369 }
370
371 return components;
372}
373
374} // 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
void normalize_points(std::vector< Point< T, N > > &points)
Normalize the coordinates of a set of points along each axis to the range [0, 1].
Definition utils.hpp:298
bool save_vector_to_csv(const std::string &filename, const std::vector< T > &values, bool write_header=true, const std::string &header_name="value")
Save a 1D vector of values to a CSV file.
Definition utils.hpp:96
std::vector< Point< T, N > > merge_by_dimension(const std::array< std::vector< T >, N > &components)
Reconstructs a list of N-dimensional points from N separate coordinate vectors.
Definition utils.hpp:245
bool save_points_to_csv(const std::string &filename, const std::vector< Point< T, N > > &points, bool write_header=true)
Save a set of N-dimensional points to a CSV file.
Definition utils.hpp:34
std::vector< Point< T, N+1 > > add_dimension(const std::vector< Point< T, N > > &points, const std::vector< T > &new_dimension)
Add a new dimension to a set of points.
Definition utils.hpp:142
std::vector< std::vector< Point< T, N > > > extract_clusters(const std::vector< Point< T, N > > &points, const std::vector< int > &labels)
Extract clusters of points given DBSCAN (or any clustering) labels.
Definition utils.hpp:180
std::array< std::vector< T >, N > split_by_dimension(const std::vector< Point< T, N > > &points)
Rearranges a list of N-dimensional points into N separate coordinate vectors.
Definition utils.hpp:361
A fixed-size N-dimensional point/vector class.
Definition point.hpp:39