ai改了半天还是不对

This commit is contained in:
2026-08-28 02:52:44 +08:00
parent 144602ef45
commit 5c2be8eef0
18 changed files with 1091 additions and 390 deletions
+69 -3
View File
@@ -1,6 +1,7 @@
#include "Axis.hpp"
#include <algorithm>
#include <cctype>
#include <cmath>
#include <iomanip>
#include <limits>
@@ -39,6 +40,71 @@ std::string numeric_label(double value, int precision) {
return result;
}
bool ascii_iequals(std::string_view left, std::string_view right) {
return left.size() == right.size() &&
std::ranges::equal(left, right, [](char first, char second) {
return std::tolower(static_cast<unsigned char>(first)) ==
std::tolower(static_cast<unsigned char>(second));
});
}
std::string time_label(double seconds, int precision,
std::string_view unit) {
if (!unit.empty() && !ascii_iequals(unit, "s") &&
!ascii_iequals(unit, "sec") && !ascii_iequals(unit, "second") &&
!ascii_iequals(unit, "seconds"))
return numeric_label(seconds, precision) + " " + std::string(unit);
const auto sign = seconds < 0.0 ? "-" : "";
const auto absolute = std::abs(seconds);
if (absolute == 0.0) return "0 s";
if (absolute < 1.0)
return std::string(sign) +
numeric_label(absolute * 1'000.0, precision) + " ms";
if (absolute < 60.0)
return std::string(sign) + numeric_label(absolute, precision) + " s";
const auto hours = static_cast<std::uint64_t>(absolute / 3'600.0);
const auto minutes = static_cast<std::uint64_t>(absolute / 60.0) % 60U;
const auto remaining = absolute -
static_cast<double>(hours * 3'600U + minutes * 60U);
std::ostringstream stream;
stream << sign;
if (hours != 0U) stream << hours << ':' << std::setfill('0') << std::setw(2);
stream << minutes << ':' << std::setfill('0')
<< std::setw(precision > 0 ? precision + 3 : 2)
<< std::fixed << std::setprecision(std::clamp(precision, 0, 6))
<< remaining;
return stream.str();
}
std::string frequency_label(double frequency, int precision) {
const auto magnitude = std::abs(frequency);
double divisor{1.0};
std::string_view unit{"Hz"};
if (magnitude >= 1.0e9) {
divisor = 1.0e9;
unit = "GHz";
}
else if (magnitude >= 1.0e6) {
divisor = 1.0e6;
unit = "MHz";
}
else if (magnitude >= 1.0e3) {
divisor = 1.0e3;
unit = "kHz";
}
return numeric_label(frequency / divisor, precision) + " " +
std::string(unit);
}
std::string axis_tick_label(const Axis_Descriptor& axis, double coordinate) {
if (axis.scale == Axis_Scale::time)
return time_label(coordinate, axis.precision, axis.unit);
if (ascii_iequals(axis.unit, "hz"))
return frequency_label(coordinate, axis.precision);
return numeric_label(coordinate, axis.precision);
}
std::vector<Axis_Tick> linear_ticks(const Axis_Descriptor& axis) {
const auto step = nice_tick_step(axis.range, axis.target_tick_count);
if (!(step > 0.0) || !std::isfinite(step)) return {};
@@ -49,7 +115,7 @@ std::vector<Axis_Tick> linear_ticks(const Axis_Descriptor& axis) {
for (std::size_t index = 0; index < maximum_count; ++index) {
const auto coordinate = first + static_cast<double>(index) * step;
if (coordinate > maximum + step * 1.0e-9) break;
ticks.push_back({coordinate, numeric_label(coordinate, axis.precision)});
ticks.push_back({coordinate, axis_tick_label(axis, coordinate)});
}
if (axis.range.length() < 0.0) std::ranges::reverse(ticks);
return ticks;
@@ -73,7 +139,7 @@ std::vector<Axis_Tick> logarithmic_ticks(const Axis_Descriptor& axis) {
const auto coordinate = multiple * decade;
if (coordinate >= minimum * (1.0 - 1.0e-12) &&
coordinate <= maximum * (1.0 + 1.0e-12))
ticks.push_back({coordinate, numeric_label(coordinate, axis.precision)});
ticks.push_back({coordinate, axis_tick_label(axis, coordinate)});
}
}
const auto add_boundary = [&](double coordinate) {
@@ -95,7 +161,7 @@ std::vector<Axis_Tick> logarithmic_ticks(const Axis_Descriptor& axis) {
logarithmic_span < minimum_spacing)
ticks.erase(nearest);
}
ticks.push_back({coordinate, numeric_label(coordinate, axis.precision)});
ticks.push_back({coordinate, axis_tick_label(axis, coordinate)});
}
};
add_boundary(minimum);
+52
View File
@@ -0,0 +1,52 @@
#include <gtest/gtest.h>
#include <plot/Axis.hpp>
#include <algorithm>
#include <string>
#include <vector>
namespace aethera::plot {
namespace {
TEST(Axis_Formatting, Time_Scale_Uses_Elapsed_Time_Labels) {
const Axis_Descriptor axis{
{0.0, 4.0}, Axis_Scale::time, "Time", "s",
5, 1, true, true, true};
const auto ticks = axis_ticks(axis);
ASSERT_EQ(ticks.size(), 5U);
EXPECT_EQ(ticks.front().label, "0 s");
EXPECT_EQ(ticks[1].label, "1 s");
EXPECT_EQ(ticks.back().label, "4 s");
}
TEST(Axis_Formatting, Time_Scale_Formats_Long_Durations) {
const Axis_Descriptor axis{
{0.0, 4'000.0}, Axis_Scale::time, "Elapsed", "s",
5, 0, true, true, true};
const auto ticks = axis_ticks(axis);
ASSERT_FALSE(ticks.empty());
EXPECT_EQ(ticks.front().label, "0 s");
EXPECT_EQ(ticks.back().label, "1:06:40");
}
TEST(Axis_Formatting, Hertz_Unit_Uses_Frequency_Prefixes) {
const Axis_Descriptor axis{
{10.0, 20'000.0}, Axis_Scale::logarithmic, "Frequency", "Hz",
5, 0, true, true, true};
const auto ticks = axis_ticks(axis);
const std::vector<std::string> labels = [&] {
std::vector<std::string> result;
result.reserve(ticks.size());
for (const auto& tick : ticks) result.push_back(tick.label);
return result;
}();
EXPECT_NE(std::ranges::find(labels, "10 Hz"), labels.end());
EXPECT_NE(std::ranges::find(labels, "1 kHz"), labels.end());
EXPECT_NE(std::ranges::find(labels, "20 kHz"), labels.end());
}
} // namespace
} // namespace aethera::plot