From 60c6e0632df2e9863b0f89e25fe3aa19c0e785a2 Mon Sep 17 00:00:00 2001 From: CJK_mkp <113243675+CJKmkp@users.noreply.github.com> Date: Sun, 29 Jun 2025 14:15:20 +0800 Subject: [PATCH] =?UTF-8?q?add:=E9=AB=98=E7=B2=BE=E5=BA=A6=E7=9B=B4?= =?UTF-8?q?=E7=BA=BF=E6=8B=89=E7=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/MainWindow.xaml | 10 +- Ink Canvas/MainWindow.xaml.cs | 2 +- Ink Canvas/MainWindow_cs/MW_Settings.cs | 8 + Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 2 + .../MW_SimulatePressure&InkToShape.cs | 169 ++++++++++++++++-- Ink Canvas/Resources/Settings.cs | 2 + 6 files changed, 179 insertions(+), 14 deletions(-) diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 2ebb8efb..546a061f 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -970,7 +970,15 @@ - + + + + + diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index c9b41a61..98de85fd 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -395,7 +395,7 @@ namespace Ink_Canvas { if (string.IsNullOrEmpty(releaseNotes)) { releaseNotes = $@"# InkCanvasForClass v{AvailableLatestVersion}更新 - + 无法获取更新日志,但新版本已准备就绪。"; } diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index 099212cf..074e9dd6 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -782,6 +782,14 @@ namespace Ink_Canvas { // 立即保存设置到文件,确保设置不会丢失 SaveSettingsToFile(); } + + private void ToggleSwitchHighPrecisionLineStraighten_Toggled(object sender, RoutedEventArgs e) { + if (!isLoaded) return; + + Settings.Canvas.HighPrecisionLineStraighten = ToggleSwitchHighPrecisionLineStraighten.IsOn; + System.Diagnostics.Debug.WriteLine($"HighPrecisionLineStraighten changed: {Settings.Canvas.HighPrecisionLineStraighten}"); + SaveSettingsToFile(); + } #endregion diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index d36a7f9d..100de955 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -533,6 +533,8 @@ namespace Ink_Canvas { AutoStraightenLineThresholdSlider.Value = Settings.Canvas.AutoStraightenLineThreshold; // 直线拉直灵敏度也在这里初始化,即使它存储在InkToShape中 LineStraightenSensitivitySlider.Value = Settings.InkToShape.LineStraightenSensitivity; + // 初始化高精度直线拉直设置 + ToggleSwitchHighPrecisionLineStraighten.IsOn = Settings.Canvas.HighPrecisionLineStraighten; // 初始化直线端点吸附相关设置 ToggleSwitchLineEndpointSnapping.IsOn = Settings.Canvas.LineEndpointSnapping; diff --git a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs index e1a386ca..bb67682a 100644 --- a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs +++ b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs @@ -687,20 +687,97 @@ namespace Ink_Canvas { double totalDeviation = 0; int pointCount = 0; - // Calculate deviation for each point - foreach (StylusPoint sp in stroke.StylusPoints) { - Point p = sp.ToPoint(); - double deviation = DistanceFromLineToPoint(start, end, p); - maxDeviation = Math.Max(maxDeviation, deviation); - totalDeviation += deviation; - pointCount++; + // 检查是否启用了高精度直线拉直 + bool useHighPrecision = Settings.Canvas.HighPrecisionLineStraighten; + + if (useHighPrecision) { + System.Diagnostics.Debug.WriteLine("使用高精度直线拉直模式"); + + // 高精度模式:每隔10像素取一个计数点 + double strokeLength = 0; + double sampleInterval = 10.0; // 10像素间隔 + + // 计算笔画的总长度,用于后续采样 + for (int i = 1; i < stroke.StylusPoints.Count; i++) { + Point p1 = stroke.StylusPoints[i-1].ToPoint(); + Point p2 = stroke.StylusPoints[i].ToPoint(); + strokeLength += GetDistance(p1, p2); + } + + // 如果笔画太短,直接使用所有点 + if (strokeLength < sampleInterval * 5) { + foreach (StylusPoint sp in stroke.StylusPoints) { + Point p = sp.ToPoint(); + double deviation = DistanceFromLineToPoint(start, end, p); + maxDeviation = Math.Max(maxDeviation, deviation); + totalDeviation += deviation; + pointCount++; + } + } else { + // 使用等距采样点 + double currentLength = 0; + double nextSampleAt = 0; + + // 总是包含起点 + Point lastPoint = start; + double deviation = DistanceFromLineToPoint(start, end, lastPoint); + maxDeviation = Math.Max(maxDeviation, deviation); + totalDeviation += deviation; + pointCount++; + + // 采样中间点 + for (int i = 1; i < stroke.StylusPoints.Count; i++) { + Point currentPoint = stroke.StylusPoints[i].ToPoint(); + double segmentLength = GetDistance(lastPoint, currentPoint); + + // 如果这段线段跨越了下一个采样点 + while (currentLength + segmentLength >= nextSampleAt) { + // 计算采样点在线段上的位置 + double t = (nextSampleAt - currentLength) / segmentLength; + Point samplePoint = new Point( + lastPoint.X + t * (currentPoint.X - lastPoint.X), + lastPoint.Y + t * (currentPoint.Y - lastPoint.Y) + ); + + // 计算采样点的偏差 + deviation = DistanceFromLineToPoint(start, end, samplePoint); + maxDeviation = Math.Max(maxDeviation, deviation); + totalDeviation += deviation; + pointCount++; + + // 设置下一个采样点位置 + nextSampleAt += sampleInterval; + + // 防止无限循环 + if (nextSampleAt > strokeLength) break; + } + + currentLength += segmentLength; + lastPoint = currentPoint; + } + + // 总是包含终点 + deviation = DistanceFromLineToPoint(start, end, end); + maxDeviation = Math.Max(maxDeviation, deviation); + totalDeviation += deviation; + pointCount++; + } + } else { + // 原始模式:使用所有点 + foreach (StylusPoint sp in stroke.StylusPoints) { + Point p = sp.ToPoint(); + double deviation = DistanceFromLineToPoint(start, end, p); + maxDeviation = Math.Max(maxDeviation, deviation); + totalDeviation += deviation; + pointCount++; + } } // 计算平均偏差 double avgDeviation = totalDeviation / pointCount; // 更详细的调试信息 - System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}"); + System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}, Points: {pointCount}"); // 支持更广泛的灵敏度范围 (0.05-2.0) @@ -722,11 +799,79 @@ namespace Ink_Canvas { else { // 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲 double deviationVariance = 0; - foreach (StylusPoint sp in stroke.StylusPoints) { - Point p = sp.ToPoint(); - double deviation = DistanceFromLineToPoint(start, end, p); - deviationVariance += Math.Pow(deviation - avgDeviation, 2); + + // 使用相同的高精度/原始模式来计算方差 + if (useHighPrecision) { + // 高精度模式:重新采样计算方差 + double strokeLength = 0; + double sampleInterval = 10.0; // 10像素间隔 + + // 计算笔画的总长度,用于后续采样 + for (int i = 1; i < stroke.StylusPoints.Count; i++) { + Point p1 = stroke.StylusPoints[i-1].ToPoint(); + Point p2 = stroke.StylusPoints[i].ToPoint(); + strokeLength += GetDistance(p1, p2); + } + + // 如果笔画太短,直接使用所有点 + if (strokeLength < sampleInterval * 5) { + foreach (StylusPoint sp in stroke.StylusPoints) { + Point p = sp.ToPoint(); + double deviation = DistanceFromLineToPoint(start, end, p); + deviationVariance += Math.Pow(deviation - avgDeviation, 2); + } + } else { + // 使用等距采样点 + double currentLength = 0; + double nextSampleAt = 0; + Point lastPoint = start; + + // 起点方差 + double deviation = DistanceFromLineToPoint(start, end, lastPoint); + deviationVariance += Math.Pow(deviation - avgDeviation, 2); + + // 采样中间点 + for (int i = 1; i < stroke.StylusPoints.Count; i++) { + Point currentPoint = stroke.StylusPoints[i].ToPoint(); + double segmentLength = GetDistance(lastPoint, currentPoint); + + // 如果这段线段跨越了下一个采样点 + while (currentLength + segmentLength >= nextSampleAt) { + // 计算采样点在线段上的位置 + double t = (nextSampleAt - currentLength) / segmentLength; + Point samplePoint = new Point( + lastPoint.X + t * (currentPoint.X - lastPoint.X), + lastPoint.Y + t * (currentPoint.Y - lastPoint.Y) + ); + + // 计算采样点的方差 + deviation = DistanceFromLineToPoint(start, end, samplePoint); + deviationVariance += Math.Pow(deviation - avgDeviation, 2); + + // 设置下一个采样点位置 + nextSampleAt += sampleInterval; + + // 防止无限循环 + if (nextSampleAt > strokeLength) break; + } + + currentLength += segmentLength; + lastPoint = currentPoint; + } + + // 终点方差 + deviation = DistanceFromLineToPoint(start, end, end); + deviationVariance += Math.Pow(deviation - avgDeviation, 2); + } + } else { + // 原始模式:使用所有点计算方差 + foreach (StylusPoint sp in stroke.StylusPoints) { + Point p = sp.ToPoint(); + double deviation = DistanceFromLineToPoint(start, end, p); + deviationVariance += Math.Pow(deviation - avgDeviation, 2); + } } + deviationVariance /= pointCount; // 输出更多调试信息 diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index a5abddbc..9513fe39 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -56,6 +56,8 @@ namespace Ink_Canvas public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直 [JsonProperty("autoStraightenLineThreshold")] public int AutoStraightenLineThreshold { get; set; } = 30; // 直线自动拉直的长度阈值(像素) + [JsonProperty("highPrecisionLineStraighten")] + public bool HighPrecisionLineStraighten { get; set; } = true; // 是否启用高精度直线拉直 [JsonProperty("lineEndpointSnapping")] public bool LineEndpointSnapping { get; set; } = true; // 是否启用直线端点吸附 [JsonProperty("lineEndpointSnappingThreshold")]