直方图将柱状图替换为面积图,优化密集数据显示效果,Y轴刻度自动取整支持 K/M 缩写,X 轴根据数据范围自动设置。
This commit is contained in:
@@ -13,7 +13,7 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
internal sealed class ChartRenderer
|
||||
{
|
||||
private readonly RadCartesianChart _chart;
|
||||
private readonly BarSeries _barSeries;
|
||||
private readonly ScatterAreaSeries _areaSeries;
|
||||
private readonly LinearAxis _xAxis;
|
||||
|
||||
/// <summary>
|
||||
@@ -25,12 +25,12 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
/// 构造函数,接收 RadCartesianChart 实例 | Constructor, receives RadCartesianChart instance
|
||||
/// </summary>
|
||||
/// <param name="chart">图表控件实例 | Chart control instance</param>
|
||||
/// <param name="barSeries">柱状图系列 | Bar series</param>
|
||||
/// <param name="areaSeries">面积图系列 | Area series</param>
|
||||
/// <param name="xAxis">X 轴 | X axis</param>
|
||||
public ChartRenderer(RadCartesianChart chart, BarSeries barSeries, LinearAxis xAxis)
|
||||
public ChartRenderer(RadCartesianChart chart, ScatterAreaSeries areaSeries, LinearAxis xAxis)
|
||||
{
|
||||
_chart = chart ?? throw new ArgumentNullException(nameof(chart));
|
||||
_barSeries = barSeries ?? throw new ArgumentNullException(nameof(barSeries));
|
||||
_areaSeries = areaSeries ?? throw new ArgumentNullException(nameof(areaSeries));
|
||||
_xAxis = xAxis ?? throw new ArgumentNullException(nameof(xAxis));
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
// 设置 X 轴范围 | Set X axis range
|
||||
_xAxis.Minimum = 0;
|
||||
_xAxis.Maximum = xAxisMax;
|
||||
// 根据范围自动设置刻度间隔(保持 4-5 个刻度)| Auto set major step based on range (keep 4-5 ticks)
|
||||
_xAxis.MajorStep = xAxisMax <= 255 ? 64 : 16384;
|
||||
|
||||
// 构建数据点 | Build data points
|
||||
var dataPoints = new List<HistogramDataPoint>();
|
||||
@@ -103,7 +105,7 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
}
|
||||
|
||||
// 更新图表数据 | Update chart data
|
||||
_barSeries.ItemsSource = dataPoints;
|
||||
_areaSeries.ItemsSource = dataPoints;
|
||||
|
||||
// 设置 Y 轴范围 | Set Y axis range
|
||||
UpdateYAxis(displayData, isLogarithmic);
|
||||
@@ -114,7 +116,7 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_barSeries.ItemsSource = null;
|
||||
_areaSeries.ItemsSource = null;
|
||||
|
||||
// X 轴范围重置为 0-255 | Reset X axis range to 0-255
|
||||
_xAxis.Minimum = 0;
|
||||
@@ -131,9 +133,9 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_barSeries.ItemsSource is ICollection<HistogramDataPoint> collection)
|
||||
if (_areaSeries.ItemsSource is ICollection<HistogramDataPoint> collection)
|
||||
return collection.Count;
|
||||
if (_barSeries.ItemsSource is IEnumerable<HistogramDataPoint> enumerable)
|
||||
if (_areaSeries.ItemsSource is IEnumerable<HistogramDataPoint> enumerable)
|
||||
return enumerable.Count();
|
||||
return 0;
|
||||
}
|
||||
@@ -173,7 +175,48 @@ namespace XP.Common.Controls.ImageHistogram
|
||||
if (maxValue == 0)
|
||||
maxValue = 1;
|
||||
|
||||
SetYAxisRange(0, maxValue, isLogarithmic);
|
||||
// 计算取整的 MajorStep(约 4 个刻度,对齐到 K/M 整数倍)| Calculate rounded MajorStep (~4 ticks, aligned to K/M multiples)
|
||||
if (_chart.VerticalAxis is LinearAxis linearAxis)
|
||||
{
|
||||
long rawStep = maxValue / 4;
|
||||
long step = RoundStepToNice(rawStep);
|
||||
if (step < 1) step = 1;
|
||||
linearAxis.MajorStep = step;
|
||||
|
||||
// 将最大值向上取整到 step 的整数倍 | Round max up to multiple of step
|
||||
long roundedMax = ((maxValue / step) + 1) * step;
|
||||
SetYAxisRange(0, roundedMax, isLogarithmic);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetYAxisRange(0, maxValue, isLogarithmic);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将步长取整为"好看"的数值(1, 2, 5 的倍数 × 10^n)| Round step to "nice" value (multiples of 1, 2, 5 × 10^n)
|
||||
/// 例如:123456 → 100000,350000 → 500000,780000 → 1000000
|
||||
/// </summary>
|
||||
private static long RoundStepToNice(long rawStep)
|
||||
{
|
||||
if (rawStep <= 0) return 1;
|
||||
|
||||
// 找到数量级 | Find order of magnitude
|
||||
double magnitude = Math.Pow(10, Math.Floor(Math.Log10(rawStep)));
|
||||
double normalized = rawStep / magnitude;
|
||||
|
||||
// 取整到 1, 2, 5 中最近的 | Round to nearest of 1, 2, 5
|
||||
double niceNormalized;
|
||||
if (normalized <= 1.5)
|
||||
niceNormalized = 1;
|
||||
else if (normalized <= 3.5)
|
||||
niceNormalized = 2;
|
||||
else if (normalized <= 7.5)
|
||||
niceNormalized = 5;
|
||||
else
|
||||
niceNormalized = 10;
|
||||
|
||||
return (long)(niceNormalized * magnitude);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user