还是一堆bug的状态
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user