更新20260613

This commit is contained in:
GukSang.Jin
2026-06-13 18:19:24 +08:00
parent 5d9f7d2215
commit 999dde26c4

View File

@@ -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);
} }