更新20260613
This commit is contained in:
@@ -22,6 +22,7 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
private const double SensorMaxTorque = 100;
|
private const double SensorMaxTorque = 100;
|
||||||
private const double MinimumTorqueRange = 0.1;
|
private const double MinimumTorqueRange = 0.1;
|
||||||
private const double MinimumSpeedRange = 1;
|
private const double MinimumSpeedRange = 1;
|
||||||
|
private const double TorqueTrendBinSize = 0.1;
|
||||||
|
|
||||||
private bool _isManualView;
|
private bool _isManualView;
|
||||||
private double _viewMinTorque = SensorMinTorque;
|
private double _viewMinTorque = SensorMinTorque;
|
||||||
@@ -135,10 +136,15 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
var points = samples
|
var points = samples
|
||||||
.Select(sample => ToPlotPoint(sample, plot, minTorque, maxTorque, minSpeed, maxSpeed))
|
.Select(sample => ToPlotPoint(sample, plot, minTorque, maxTorque, minSpeed, maxSpeed))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
List<TorqueTrendPoint> trendPoints = BuildTrendPoints(samples);
|
||||||
|
|
||||||
drawingContext.PushClip(new RectangleGeometry(plot));
|
drawingContext.PushClip(new RectangleGeometry(plot));
|
||||||
DrawTrajectory(drawingContext, points);
|
|
||||||
DrawSamplePoints(drawingContext, points);
|
DrawSamplePoints(drawingContext, points);
|
||||||
|
DrawTrendLine(
|
||||||
|
drawingContext,
|
||||||
|
trendPoints
|
||||||
|
.Select(point => ToPlotPoint(point.Torque, point.Speed, plot, minTorque, maxTorque, minSpeed, maxSpeed))
|
||||||
|
.ToList());
|
||||||
DrawCurrentPoint(drawingContext, points[^1]);
|
DrawCurrentPoint(drawingContext, points[^1]);
|
||||||
drawingContext.Pop();
|
drawingContext.Pop();
|
||||||
|
|
||||||
@@ -149,6 +155,16 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
12,
|
12,
|
||||||
Color.FromRgb(15, 118, 110),
|
Color.FromRgb(15, 118, 110),
|
||||||
new Point(plot.Left + 6, plot.Top + 5));
|
new Point(plot.Left + 6, plot.Top + 5));
|
||||||
|
DrawLegend(drawingContext, plot, trendPoints.Count >= 2);
|
||||||
|
if (trendPoints.Count < 2)
|
||||||
|
{
|
||||||
|
DrawText(
|
||||||
|
drawingContext,
|
||||||
|
"扭矩变化小于传感器精度,暂无有效趋势线",
|
||||||
|
11,
|
||||||
|
Color.FromRgb(180, 83, 9),
|
||||||
|
new Point(plot.Left + 6, plot.Bottom - 38));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
||||||
@@ -297,27 +313,58 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
return new Point(x, y);
|
return new Point(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawTrajectory(DrawingContext drawingContext, IReadOnlyList<Point> points)
|
private static Point ToPlotPoint(
|
||||||
|
double torque,
|
||||||
|
double speed,
|
||||||
|
Rect plot,
|
||||||
|
double minTorque,
|
||||||
|
double maxTorque,
|
||||||
|
double minSpeed,
|
||||||
|
double maxSpeed)
|
||||||
{
|
{
|
||||||
|
double x = plot.Left + plot.Width * (torque - minTorque) / (maxTorque - minTorque);
|
||||||
|
double y = plot.Bottom - (speed - minSpeed) / (maxSpeed - minSpeed) * plot.Height;
|
||||||
|
return new Point(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<TorqueTrendPoint> BuildTrendPoints(IReadOnlyList<TorqueSamplePayload> samples)
|
||||||
|
{
|
||||||
|
return samples
|
||||||
|
.Where(sample => sample.TorqueMilliNewtonMeters >= SensorMinTorque
|
||||||
|
&& sample.TorqueMilliNewtonMeters <= SensorMaxTorque)
|
||||||
|
.GroupBy(sample => Math.Floor(sample.TorqueMilliNewtonMeters / TorqueTrendBinSize))
|
||||||
|
.Select(group => new TorqueTrendPoint(
|
||||||
|
group.Average(sample => sample.TorqueMilliNewtonMeters),
|
||||||
|
group.Average(sample => sample.SpeedRpm)))
|
||||||
|
.OrderBy(point => point.Torque)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DrawTrendLine(DrawingContext drawingContext, IReadOnlyList<Point> points)
|
||||||
|
{
|
||||||
|
if (points.Count < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var geometry = new StreamGeometry();
|
var geometry = new StreamGeometry();
|
||||||
using (StreamGeometryContext context = geometry.Open())
|
using (StreamGeometryContext context = geometry.Open())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < points.Count; i++)
|
context.BeginFigure(points[0], false, false);
|
||||||
|
for (int i = 1; i < points.Count; i++)
|
||||||
{
|
{
|
||||||
if (i == 0)
|
Point previous = points[i - 1];
|
||||||
{
|
Point current = points[i];
|
||||||
context.BeginFigure(points[i], false, false);
|
double deltaX = current.X - previous.X;
|
||||||
}
|
var control1 = new Point(previous.X + deltaX / 3, previous.Y);
|
||||||
else
|
var control2 = new Point(current.X - deltaX / 3, current.Y);
|
||||||
{
|
context.BezierTo(control1, control2, current, true, false);
|
||||||
context.LineTo(points[i], true, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geometry.Freeze();
|
geometry.Freeze();
|
||||||
var lineBrush = new SolidColorBrush(Color.FromArgb(85, 29, 78, 216));
|
var lineBrush = new SolidColorBrush(Color.FromRgb(15, 118, 110));
|
||||||
drawingContext.DrawGeometry(null, new Pen(lineBrush, 1.2), geometry);
|
drawingContext.DrawGeometry(null, new Pen(lineBrush, 2.4), geometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void DrawSamplePoints(DrawingContext drawingContext, IReadOnlyList<Point> points)
|
private static void DrawSamplePoints(DrawingContext drawingContext, IReadOnlyList<Point> points)
|
||||||
@@ -344,6 +391,23 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
drawingContext.DrawEllipse(brush, new Pen(Brushes.White, 1.5), point, 5, 5);
|
drawingContext.DrawEllipse(brush, new Pen(Brushes.White, 1.5), point, 5, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawLegend(DrawingContext drawingContext, Rect plot, bool hasTrend)
|
||||||
|
{
|
||||||
|
double y = plot.Bottom + 5;
|
||||||
|
var sampleBrush = new SolidColorBrush(Color.FromArgb(175, 29, 78, 216));
|
||||||
|
drawingContext.DrawEllipse(sampleBrush, null, new Point(plot.Left + 116, y + 7), 2.5, 2.5);
|
||||||
|
DrawText(drawingContext, "原始采样点", 10, Color.FromRgb(82, 97, 111), new Point(plot.Left + 122, y));
|
||||||
|
|
||||||
|
if (!hasTrend)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trendPen = new Pen(new SolidColorBrush(Color.FromRgb(15, 118, 110)), 2.4);
|
||||||
|
drawingContext.DrawLine(trendPen, new Point(plot.Left + 194, y + 7), new Point(plot.Left + 214, y + 7));
|
||||||
|
DrawText(drawingContext, "显示趋势线", 10, Color.FromRgb(82, 97, 111), new Point(plot.Left + 220, y));
|
||||||
|
}
|
||||||
|
|
||||||
private void DrawAxisLabels(
|
private void DrawAxisLabels(
|
||||||
DrawingContext drawingContext,
|
DrawingContext drawingContext,
|
||||||
Rect plot,
|
Rect plot,
|
||||||
@@ -485,4 +549,6 @@ public sealed class TorqueTrendControl : FrameworkElement
|
|||||||
|
|
||||||
drawingContext.DrawText(formattedText, origin);
|
drawingContext.DrawText(formattedText, origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private readonly record struct TorqueTrendPoint(double Torque, double Speed);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user