Files
Renderive/Core/Axis/Frequency_Axis_p.h
T
2026-08-02 03:43:39 +08:00

65 lines
2.2 KiB
C++

#pragma once
#include <cmath>
#include <string>
#include <vector>
#include "Abs_Axis_p.h"
#include "Axis_p.h"
#include "Frequency_Axis.h"
namespace renderive {
struct Frequency_Axis_Input_Data : Axis_Input_Data {};
struct Frequency_Axis_Render_State : Axis_Render_State {};
struct Frequency_Axis_Private : Typed_Render_Data_Base<Axis_Private, Frequency_Axis, Frequency_Axis_Render_State, Frequency_Axis_Input_Data> {
std::vector<std::string> create_label_vector(const std::vector<double>& ticks, State_Role src) override {
const int exponent = unit_exponent(ticks);
if (!ticks.empty())
render_state()->unit_text = "Frequency/" + unit_text(exponent);
std::vector<std::string> result;
result.reserve(ticks.size());
for (const double& tick_coord : ticks)
result.push_back(get_true_value(get_tick_label(tick_coord, src), exponent));
return result;
}
static int unit_exponent(const std::vector<double>& ticks) {
if (ticks.empty())
return 0;
const double range = std::abs(ticks.back() - ticks.front());
if (range >= 1e9)
return 9;
if (range >= 1e6)
return 6;
if (range >= 1e3)
return 3;
return 0;
}
static std::string unit_text(int exponent) {
switch (exponent) {
case 0:
return "Hz";
case 3:
return "kHz";
case 6:
return "MHz";
case 9:
return "GHz";
}
return "Hz";
}
std::string get_true_value(std::string value, int exponent) {
auto s = render_state();
int precision = s->label_precision;
auto dot_pos = value.find('.');
if (dot_pos == std::string::npos)
dot_pos = value.size();
std::string number = value.substr(0, dot_pos) + value.substr(dot_pos + 1);
int after_dot_index = static_cast<int>(dot_pos) - exponent;
if (after_dot_index < 1) {
for (int i = 0; i < 1 - after_dot_index; ++i)
number.insert(0, 1, '0');
after_dot_index = 1;
}
number.insert(after_dot_index, ".");
return format_number(std::stod(number), {.precision = precision});
}
};
} // namespace renderive