还是一堆bug的状态

This commit is contained in:
2026-08-01 20:09:45 +08:00
parent 0df7beda49
commit 8fb9683182
294 changed files with 13678 additions and 10864 deletions
+115
View File
@@ -0,0 +1,115 @@
#pragma once
#include <algorithm>
#include <array>
#include <cmath>
#include <iterator>
#include <limits>
#include <memory_resource>
#include <span>
#include "../Axis/Abs_Axis_p.h"
#include "../base/Frame_Memory.h"
#include "../plottable/Interpolation_p.h"
#include "Curve.h"
namespace renderive {
struct Curve_Peak_Bucket {
bool used = false;
int first = -1;
int last = -1;
int min = -1;
int max = -1;
double min_value = std::numeric_limits<double>::max();
double max_value = std::numeric_limits<double>::lowest();
};
class Curve_Utils {
public:
template <typename Point_At>
static std::pmr::vector<PointF> create_points(int count, Point_At point_at, std::pmr::memory_resource* resource = frame_memory_resource()) {
std::pmr::vector<PointF> points(resource);
points.reserve(count);
for (int i = 0; i < count; ++i)
points.push_back(point_at(i));
return points;
}
template <typename Value_At>
static std::pmr::vector<PointF> create_sampled_points(Abs_Axis* domain_axis, Abs_Axis* value_axis, const Range& data_range, int total_count, int available_count, bool visible_range_only, Line_Interpolation_Mode mode, Value_At value_at) {
return create_line_points(domain_axis, value_axis, data_range, total_count, available_count, visible_range_only, mode, value_at);
}
template <typename Value_At>
static std::pmr::vector<PointF> create_sampled_points(const Axis_Mapping_2D& mapping, const Range& data_range, int total_count, int available_count, bool visible_range_only, Line_Interpolation_Mode mode, Value_At value_at, std::pmr::memory_resource* resource = frame_memory_resource()) {
return create_line_points(mapping, data_range, total_count, available_count, visible_range_only, mode, value_at, resource);
}
template <typename Value_At>
static std::pmr::vector<PointF> create_peak_bucket_points(const Axis_Mapping_2D& mapping, const Range& data_range, int total_count, int available_count, bool visible_range_only, Value_At value_at, std::pmr::memory_resource* resource = frame_memory_resource()) {
Line_Sample_Window window = line_sample_window(mapping.domain, data_range, total_count, available_count, visible_range_only);
if (!window)
return {};
int first_source = std::clamp(static_cast<int>(std::floor(std::min(window.first_index, window.last_index))), 0, available_count - 1);
int last_source = std::clamp(static_cast<int>(std::ceil(std::max(window.first_index, window.last_index))), first_source, available_count - 1);
double first_pixel = mapping.domain.coord_to_pixel(source_index_to_coord(data_range, total_count, window.first_index));
double last_pixel = mapping.domain.coord_to_pixel(source_index_to_coord(data_range, total_count, window.last_index));
double pixel_min = std::min(first_pixel, last_pixel);
double pixel_max = std::max(first_pixel, last_pixel);
int bucket_count = std::max(1, static_cast<int>(std::ceil(pixel_max - pixel_min)) + 1);
bucket_count = std::min(bucket_count, mapping.domain.pixel_size() + 1);
std::pmr::vector<Curve_Peak_Bucket> buckets(bucket_count, resource);
double pixel_span = std::max(1.0, pixel_max - pixel_min);
for (int i = first_source; i <= last_source; ++i) {
double coord = source_index_to_coord(data_range, total_count, i);
double pixel = mapping.domain.coord_to_pixel(coord);
int bucket_index = std::clamp(static_cast<int>((pixel - pixel_min) * static_cast<double>(bucket_count - 1) / pixel_span), 0, bucket_count - 1);
Curve_Peak_Bucket& bucket = buckets[bucket_index];
double value = value_at(i);
if (!bucket.used) {
bucket.used = true;
bucket.first = i;
bucket.min = i;
bucket.max = i;
bucket.min_value = value;
bucket.max_value = value;
}
bucket.last = i;
if (value < bucket.min_value) {
bucket.min_value = value;
bucket.min = i;
}
if (value > bucket.max_value) {
bucket.max_value = value;
bucket.max = i;
}
}
std::pmr::vector<PointF> points(resource);
points.reserve(bucket_count * 4);
bool pixel_forward = first_pixel <= last_pixel;
for (int b = pixel_forward ? 0 : bucket_count - 1; pixel_forward ? b < bucket_count : b >= 0; pixel_forward ? ++b : --b) {
const Curve_Peak_Bucket& bucket = buckets[b];
if (!bucket.used)
continue;
std::array<int, 4> indexes{bucket.first, bucket.min, bucket.max, bucket.last};
std::sort(indexes.begin(), indexes.end());
auto end = std::unique(indexes.begin(), indexes.end());
if (pixel_forward) {
for (auto it = indexes.begin(); it != end; ++it)
append_peak_point(points, mapping, data_range, total_count, *it, value_at(*it));
}
else {
for (auto it = std::make_reverse_iterator(end); it != indexes.rend(); ++it)
append_peak_point(points, mapping, data_range, total_count, *it, value_at(*it));
}
}
return points;
}
template <typename Value_At>
static std::pmr::vector<PointF> create_peak_bucket_points(Abs_Axis* domain_axis, Abs_Axis* value_axis, const Range& data_range, int total_count, int available_count, bool visible_range_only, Value_At value_at) {
return create_peak_bucket_points(Axis_Render_Access::mapping(domain_axis, value_axis), data_range, total_count, available_count, visible_range_only, value_at, frame_memory_resource());
}
static void draw_polyline(Canvas* painter, std::span<const PointF> points, const Pen& pen);
static void draw_fill_to_value(Canvas* painter, std::span<const PointF> points, const Axis_Mapping_2D& mapping, double baseline_value, const Brush& brush);
private:
static void append_peak_point(std::pmr::vector<PointF>& points, const Axis_Mapping_2D& mapping, const Range& data_range, int total_count, int index, double value);
};
} // namespace renderive