2025-06-02 08:27:45 -04:00

147 lines
4.6 KiB
C++

#include "calc.hpp"
#include <cmath>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <boost/multiprecision/cpp_dec_float.hpp>
std::vector<std::vector<Decimal>> calculate_distances(const std::vector<Position>& positions) {
int N = positions.size();
std::vector<std::vector<Decimal>> dists(N, std::vector<Decimal>(N, Decimal(0)));
for (int i = 0; i < N; ++i) {
for (int j = i + 1; j < N; ++j) {
Decimal sum = Decimal(0);
for (int k = 0; k < 3; ++k) {
Decimal diff = positions[i][k] - positions[j][k];
sum += diff * diff;
}
Decimal d = std::sqrt(sum);
dists[i][j] = d;
dists[j][i] = d;
}
}
return dists;
}
std::string format_sig_figs(Decimal value, int sig_figs) {
if (value == 0) {
return "0";
}
std::stringstream ss;
ss << std::scientific << std::setprecision(sig_figs - 1) << value;
return ss.str();
}
void print_progress_bar(int iteration, int total, std::chrono::time_point<std::chrono::steady_clock> start_time, int length, Decimal step_size) {
float percent = (float)iteration / total * 100;
int filled_length = length * iteration / total;
std::string bar;
bar.reserve(length + 1);
bar += '[';
bar.append(filled_length, '#');
bar.append(length - filled_length, '-');
bar += ']';
auto now = std::chrono::steady_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::seconds>(now - start_time).count();
double steps_per_second = elapsed > 0 ? real_time(Decimal(iteration) * step_size) / elapsed : 0;
// Determine appropriate time unit
std::string time_unit;
if (steps_per_second >= 3600) {
time_unit = "hour/s";
steps_per_second /= 3600;
} else if (steps_per_second >= 60) {
time_unit = "min/s";
steps_per_second /= 60;
} else {
time_unit = "s/s";
}
// Clear the current line and move cursor to start
std::cout << "\r\033[K";
// Print the progress bar
std::cout << bar << " " << std::fixed << std::setprecision(2)
<< percent << "% " << std::setprecision(1) << steps_per_second << " " << time_unit << std::flush;
}
#ifdef NCURSES_ENABLED
void plot_points_terminal(const std::vector<Position>& vectors, WINDOW* stdscr,
Decimal scale, int grid_width, int grid_height) {
if (vectors.empty()) {
mvwaddstr(stdscr, 0, 0, "No vectors provided.");
wrefresh(stdscr);
return;
}
// Scale and round vectors
std::vector<std::pair<int, int>> scaled_vectors;
for (const auto& vec : vectors) {
scaled_vectors.emplace_back(
std::round(vec[0] / scale),
std::round(vec[1] / scale)
);
}
// Find bounds
int min_x = scaled_vectors[0].first;
int max_x = min_x;
int min_y = scaled_vectors[0].second;
int max_y = min_y;
for (const auto& vec : scaled_vectors) {
min_x = std::min(min_x, vec.first);
max_x = std::max(max_x, vec.first);
min_y = std::min(min_y, vec.second);
max_y = std::max(max_y, vec.second);
}
// Center offsets
int center_x = (grid_width / 2) - min_x;
int center_y = (grid_height / 2) - min_y;
// Adjust coordinates
std::vector<std::pair<int, int>> adjusted_vectors;
for (const auto& vec : scaled_vectors) {
adjusted_vectors.emplace_back(
vec.first + center_x,
vec.second + center_y
);
}
// Get terminal bounds
int max_terminal_y, max_terminal_x;
getmaxyx(stdscr, max_terminal_y, max_terminal_x);
max_x = std::min(grid_width, max_terminal_x - 5);
max_y = std::min(grid_height, max_terminal_y - 5);
// Draw grid
for (int i = grid_height; i >= 0; --i) {
std::string row = std::to_string(i - center_y) + " | ";
for (int j = 0; j <= grid_width; ++j) {
bool has_point = false;
for (const auto& vec : adjusted_vectors) {
if (vec.first == j && vec.second == i) {
has_point = true;
break;
}
}
row += has_point ? "" : ". ";
}
mvwaddstr(stdscr, max_y - i, 0, row.substr(0, max_terminal_x - 1).c_str());
}
// Print X-axis labels
std::string x_labels = " ";
for (int j = 0; j <= max_x; ++j) {
x_labels += std::to_string(j - center_x) + " ";
}
mvwaddstr(stdscr, max_y + 1, 0, x_labels.substr(0, max_terminal_x - 1).c_str());
wrefresh(stdscr);
}
#endif