From e54d92edc2796663effd38cd17b02b768e21c3df Mon Sep 17 00:00:00 2001 From: "GukSang.Jin" Date: Fri, 12 Jun 2026 09:25:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B02026012?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DentistryHandpieces/MainWindowViewModel.cs | 17 +++-- DentistryHandpieces/Models.cs | 2 + DentistryHandpieces/TorqueTrendControl.cs | 79 +++++++++++++++------- 3 files changed, 67 insertions(+), 31 deletions(-) diff --git a/DentistryHandpieces/MainWindowViewModel.cs b/DentistryHandpieces/MainWindowViewModel.cs index e4d9410..fbc4d46 100644 --- a/DentistryHandpieces/MainWindowViewModel.cs +++ b/DentistryHandpieces/MainWindowViewModel.cs @@ -770,7 +770,7 @@ public sealed class MainWindowViewModel : ObservableObject _axialForce = axialForce; _realtimeTorque = realtimeTorque; _realtimeSpeed = realtimeSpeed; - AppendTorqueSample(GetScaledTorque(), DateTime.Now); + AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, DateTime.Now); ApplyResetCoilValues(coilValues); bool isVentValveOpen = ReadCoilValue(coilValues, VentValveCoil); VentValveButtonText = isVentValveOpen ? "关闭气阀" : "通气阀"; @@ -2512,7 +2512,7 @@ public sealed class MainWindowViewModel : ObservableObject _speedTorqueStartedAt = DateTime.Now; _activeSpeedTorqueRun = CreateTestRun("转速/扭矩测试", _speedTorqueStartedAt.Value); ClearTorqueSamples(); - AppendTorqueSample(GetScaledTorque(), _speedTorqueStartedAt.Value); + AppendTorqueSample(GetScaledTorque(), _realtimeSpeed, _speedTorqueStartedAt.Value); _maxSpeedTorqueDisplacement = Math.Max(_maxSpeedTorqueDisplacement, Math.Abs(_speedTorqueDisplacement)); UpdateSpeedTorqueDisplay(); StatusText = "转速/扭矩测试已启动,通气阀与扭矩使能状态正常。"; @@ -3355,12 +3355,14 @@ public sealed class MainWindowViewModel : ObservableObject NoLoadSpeedErrorRateText = $"{FormatErrorRate(Math.Abs(_noLoadSpeedErrorRate))} %"; } - private void AppendTorqueSample(double value, DateTime sampledAt) + private void AppendTorqueSample(double torque, double speed, DateTime sampledAt) { if (!_isSpeedTorqueRunning || !_speedTorqueStartedAt.HasValue - || double.IsNaN(value) - || double.IsInfinity(value)) + || double.IsNaN(torque) + || double.IsInfinity(torque) + || double.IsNaN(speed) + || double.IsInfinity(speed)) { return; } @@ -3382,7 +3384,8 @@ public sealed class MainWindowViewModel : ObservableObject TorqueSamples.Add(new TorqueSamplePayload { ElapsedSeconds = elapsedSeconds, - TorqueMilliNewtonMeters = value + SpeedRpm = speed, + TorqueMilliNewtonMeters = torque }); _cachedTorqueCurve = null; @@ -3430,6 +3433,7 @@ public sealed class MainWindowViewModel : ObservableObject .Select(sample => new TorqueSamplePayload { ElapsedSeconds = sample.ElapsedSeconds, + SpeedRpm = sample.SpeedRpm, TorqueMilliNewtonMeters = sample.TorqueMilliNewtonMeters }) .ToList(); @@ -3486,6 +3490,7 @@ public sealed class MainWindowViewModel : ObservableObject .Select(sample => new TorqueSamplePayload { ElapsedSeconds = Math.Max(0, (sample.SampledAt - run.StartedAt).TotalSeconds), + SpeedRpm = sample.RealtimeSpeedRpm, TorqueMilliNewtonMeters = sample.RealtimeTorqueMilliNewtonMeters }) .Where(sample => sample.ElapsedSeconds <= holdTime) diff --git a/DentistryHandpieces/Models.cs b/DentistryHandpieces/Models.cs index a158edb..35bbe86 100644 --- a/DentistryHandpieces/Models.cs +++ b/DentistryHandpieces/Models.cs @@ -203,6 +203,8 @@ public sealed class TorqueSamplePayload { public double ElapsedSeconds { get; init; } + public double SpeedRpm { get; init; } + public double TorqueMilliNewtonMeters { get; init; } } diff --git a/DentistryHandpieces/TorqueTrendControl.cs b/DentistryHandpieces/TorqueTrendControl.cs index 33980bb..cf1e559 100644 --- a/DentistryHandpieces/TorqueTrendControl.cs +++ b/DentistryHandpieces/TorqueTrendControl.cs @@ -9,6 +9,7 @@ namespace DentistryHandpieces; public sealed class TorqueTrendControl : FrameworkElement { private const string TorqueUnit = "mN.m"; + private const string SpeedUnit = "r/min"; public static readonly DependencyProperty SamplesProperty = DependencyProperty.Register( @@ -63,42 +64,63 @@ public sealed class TorqueTrendControl : FrameworkElement List samples = ReadSamples(); if (samples.Count == 0) { - DrawText(drawingContext, "等待扭矩数据", 15, Color.FromRgb(82, 97, 111), new Point(plot.Left + 8, plot.Top + 8)); - DrawText(drawingContext, TorqueUnit, 13, Color.FromRgb(82, 97, 111), new Point(12, plot.Top)); + DrawText(drawingContext, "等待转速/扭矩数据", 15, Color.FromRgb(82, 97, 111), new Point(plot.Left + 8, plot.Top + 8)); + DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 12, Color.FromRgb(82, 97, 111), new Point(6, plot.Top)); + DrawText(drawingContext, $"转速 ({SpeedUnit})", 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom + 5)); return; } - List values = samples.Select(sample => sample.TorqueMilliNewtonMeters).ToList(); - double min = values.Min(); - double max = values.Max(); - double range = max - min; - if (range < 0.01) + List torqueValues = samples.Select(sample => sample.TorqueMilliNewtonMeters).ToList(); + double minTorque = torqueValues.Min(); + double maxTorque = torqueValues.Max(); + double torqueRange = maxTorque - minTorque; + if (torqueRange < 0.01) { - range = 1; - min -= 0.5; - max += 0.5; + torqueRange = 1; + minTorque -= 0.5; + maxTorque += 0.5; } else { - double padding = range * 0.12; - min -= padding; - max += padding; - range = max - min; + double padding = torqueRange * 0.12; + minTorque -= padding; + maxTorque += padding; + torqueRange = maxTorque - minTorque; } - DrawText(drawingContext, max.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Top - 2)); - DrawText(drawingContext, min.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Bottom - 14)); - DrawText(drawingContext, $"{samples[0].ElapsedSeconds:0.#}s", 12, Color.FromRgb(82, 97, 111), new Point(plot.Left, plot.Bottom + 5)); - DrawText(drawingContext, $"{samples[^1].ElapsedSeconds:0.#}s", 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 28, plot.Bottom + 5)); + List speedValues = samples.Select(sample => sample.SpeedRpm).ToList(); + double minSpeed = speedValues.Min(); + double maxSpeed = speedValues.Max(); + double speedRange = maxSpeed - minSpeed; + if (speedRange < 1) + { + double padding = Math.Max(Math.Abs(minSpeed) * 0.05, 1); + minSpeed -= padding; + maxSpeed += padding; + speedRange = maxSpeed - minSpeed; + } + else + { + double padding = speedRange * 0.05; + minSpeed -= padding; + maxSpeed += padding; + speedRange = maxSpeed - minSpeed; + } + + DrawText(drawingContext, maxTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Top - 2)); + DrawText(drawingContext, minTorque.ToString("0.##", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(8, plot.Bottom - 14)); + DrawText(drawingContext, minSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Left, plot.Bottom + 5)); + DrawText(drawingContext, maxSpeed.ToString("0", CultureInfo.InvariantCulture), 12, Color.FromRgb(82, 97, 111), new Point(plot.Right - 38, plot.Bottom + 5)); + DrawText(drawingContext, $"扭矩 ({TorqueUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Left + 4, plot.Top + 3)); + DrawText(drawingContext, $"转速 ({SpeedUnit})", 11, Color.FromRgb(82, 97, 111), new Point(plot.Right - 82, plot.Bottom - 18)); var geometry = new StreamGeometry(); using (StreamGeometryContext context = geometry.Open()) { - double elapsedRange = Math.Max(samples[^1].ElapsedSeconds - samples[0].ElapsedSeconds, 0.001); for (int i = 0; i < samples.Count; i++) { - double x = samples.Count == 1 ? plot.Right : plot.Left + plot.Width * (samples[i].ElapsedSeconds - samples[0].ElapsedSeconds) / elapsedRange; - double y = plot.Bottom - (samples[i].TorqueMilliNewtonMeters - min) / range * plot.Height; + double x = plot.Left + plot.Width * (samples[i].SpeedRpm - minSpeed) / speedRange; + double y = plot.Bottom - (samples[i].TorqueMilliNewtonMeters - minTorque) / torqueRange * plot.Height; Point point = new(x, y); if (i == 0) @@ -116,11 +138,16 @@ public sealed class TorqueTrendControl : FrameworkElement var linePen = new Pen(new SolidColorBrush(Color.FromRgb(29, 78, 216)), 2.4); drawingContext.DrawGeometry(null, linePen, geometry); - double current = values[^1]; - double currentY = plot.Bottom - (current - min) / range * plot.Height; + TorqueSamplePayload current = samples[^1]; + double currentY = plot.Bottom - (current.TorqueMilliNewtonMeters - minTorque) / torqueRange * plot.Height; var currentPen = new Pen(new SolidColorBrush(Color.FromRgb(15, 118, 110)), 1.2); drawingContext.DrawLine(currentPen, new Point(plot.Left, currentY), new Point(plot.Right, currentY)); - DrawText(drawingContext, $"当前 {current:0.##} {TorqueUnit}", 13, Color.FromRgb(15, 118, 110), new Point(plot.Right - 112, Math.Max(plot.Top, currentY - 22))); + DrawText( + drawingContext, + $"当前 {current.SpeedRpm:0} {SpeedUnit} / {current.TorqueMilliNewtonMeters:0.##} {TorqueUnit}", + 12, + Color.FromRgb(15, 118, 110), + new Point(plot.Left + 6, Math.Max(plot.Top + 18, currentY - 20))); } private static void OnSamplesChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) @@ -157,6 +184,8 @@ public sealed class TorqueTrendControl : FrameworkElement if (sample is TorqueSamplePayload torqueSample && !double.IsNaN(torqueSample.ElapsedSeconds) && !double.IsInfinity(torqueSample.ElapsedSeconds) + && !double.IsNaN(torqueSample.SpeedRpm) + && !double.IsInfinity(torqueSample.SpeedRpm) && !double.IsNaN(torqueSample.TorqueMilliNewtonMeters) && !double.IsInfinity(torqueSample.TorqueMilliNewtonMeters)) { @@ -164,7 +193,7 @@ public sealed class TorqueTrendControl : FrameworkElement } else if (sample is double value && !double.IsNaN(value) && !double.IsInfinity(value)) { - values.Add(new TorqueSamplePayload { ElapsedSeconds = values.Count, TorqueMilliNewtonMeters = value }); + values.Add(new TorqueSamplePayload { ElapsedSeconds = values.Count, SpeedRpm = values.Count, TorqueMilliNewtonMeters = value }); } }