From 62d35127b18987353212fe427c469f4403c95b38 Mon Sep 17 00:00:00 2001 From: unknown <2564608840@qq.com> Date: Sun, 20 Jul 2025 15:57:51 +0800 Subject: [PATCH] =?UTF-8?q?improve:=E5=A2=A8=E8=BF=B9=E5=B9=B3=E6=BB=91?= =?UTF-8?q?=E6=96=B9=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/AdvancedBezierSmoothing.cs | 382 ++++++++++++++++-- Ink Canvas/MainWindow.xaml | 34 +- Ink Canvas/MainWindow_cs/MW_Settings.cs | 21 + Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs | 3 + Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs | 5 +- .../MW_SimulatePressure&InkToShape.cs | 49 ++- Ink Canvas/Resources/Settings.cs | 6 + 7 files changed, 446 insertions(+), 54 deletions(-) diff --git a/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs b/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs index f05135dc..35ea4088 100644 --- a/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs +++ b/Ink Canvas/Helpers/AdvancedBezierSmoothing.cs @@ -40,6 +40,21 @@ namespace Ink_Canvas.Helpers /// public double MaxPointDistance { get; set; } = 30.0; // 减少最大间距,提高平滑度 + /// + /// 手抖修正强度 (0.0 - 1.0) + /// + public double ShakeCorrectionStrength { get; set; } = 0.6; + + /// + /// 速度加权平滑强度 (0.0 - 1.0) + /// + public double VelocityWeightedSmoothingStrength { get; set; } = 0.7; + + /// + /// 时间加权平滑强度 (0.0 - 1.0) + /// + public double TimeWeightedSmoothingStrength { get; set; } = 0.5; + /// /// 对笔画进行高级贝塞尔曲线平滑处理 /// @@ -53,18 +68,35 @@ namespace Ink_Canvas.Helpers var originalPoints = stroke.StylusPoints.ToList(); var smoothedPoints = new List(); - // 第一步:点过滤和重采样 - var filteredPoints = FilterAndResamplePoints(originalPoints); + // 检查采样率,如果点太少则使用不同的处理策略 + bool isLowSamplingRate = originalPoints.Count < 10; // 少于10个点认为是低采样率 - // 第二步:计算控制点 + if (isLowSamplingRate) + { + // 低采样率情况下的特殊处理 + return HandleLowSamplingRateStroke(stroke); + } + + // 第一步:手抖修正 + var shakeCorrectedPoints = ApplyShakeCorrection(originalPoints); + + // 第二步:基于速度和时间的加权平滑 + var velocityTimeWeightedPoints = ApplyVelocityTimeWeightedSmoothing(shakeCorrectedPoints); + + // 第三步:点过滤和重采样 + var filteredPoints = FilterAndResamplePoints(velocityTimeWeightedPoints); + + // 第四步:计算控制点 var controlPoints = CalculateControlPoints(filteredPoints); - // 第三步:生成平滑曲线点 + // 第五步:生成平滑曲线点 var curvePoints = GenerateCurvePoints(filteredPoints, controlPoints); - // 第四步:创建新的笔画 - var newStylusPoints = new StylusPointCollection(curvePoints); - var smoothedStroke = new Stroke(newStylusPoints) + // 第六步:修正收尾相连问题 + var fixedStylusPoints = FixEndToEndConnection(new StylusPointCollection(curvePoints)); + + // 第七步:创建新的笔画 + var smoothedStroke = new Stroke(fixedStylusPoints) { DrawingAttributes = stroke.DrawingAttributes.Clone() }; @@ -72,6 +104,39 @@ namespace Ink_Canvas.Helpers return smoothedStroke; } + /// + /// 检测并修正收尾相连问题 + /// + private StylusPointCollection FixEndToEndConnection(StylusPointCollection points) + { + if (points.Count < 3) return points; + + var resultPoints = new StylusPointCollection(); + + // 复制所有点 + foreach (var point in points) + { + resultPoints.Add(point); + } + + // 检查首尾是否过于接近 + var firstPoint = resultPoints[0]; + var lastPoint = resultPoints[resultPoints.Count - 1]; + double endToEndDistance = GetDistance(firstPoint.ToPoint(), lastPoint.ToPoint()); + + // 如果首尾距离太近,可能是收尾相连问题 + if (endToEndDistance < 5.0) + { + // 移除最后一个点,避免收尾相连 + if (resultPoints.Count > 1) + { + resultPoints.RemoveAt(resultPoints.Count - 1); + } + } + + return resultPoints; + } + /// /// 过滤和重采样点 /// @@ -145,6 +210,11 @@ namespace Ink_Canvas.Helpers if (points.Count < 2) return controlPoints; + // 检查点密度,如果点太稀疏则使用更保守的控制点计算 + bool isSparsePoints = points.Count < 5; + double tensionMultiplier = isSparsePoints ? 0.1 : 0.3; // 稀疏点时使用更小的张力 + double maxOffset = isSparsePoints ? 5.0 : 10.0; // 稀疏点时使用更小的最大偏移 + for (int i = 0; i < points.Count; i++) { Point currentPoint = points[i].ToPoint(); @@ -154,19 +224,39 @@ namespace Ink_Canvas.Helpers { // 第一个点的控制点 Point nextPoint = points[i + 1].ToPoint(); - controlPoint = new Point( - currentPoint.X + (nextPoint.X - currentPoint.X) * Tension * 0.3, // 减少张力,减少毛刺 - currentPoint.Y + (nextPoint.Y - currentPoint.Y) * Tension * 0.3 - ); + double distance = GetDistance(currentPoint, nextPoint); + + // 如果距离太远,使用更保守的控制点 + if (distance > 50.0) + { + controlPoint = currentPoint; // 直接使用当前点作为控制点 + } + else + { + controlPoint = new Point( + currentPoint.X + (nextPoint.X - currentPoint.X) * Tension * tensionMultiplier, + currentPoint.Y + (nextPoint.Y - currentPoint.Y) * Tension * tensionMultiplier + ); + } } else if (i == points.Count - 1) { // 最后一个点的控制点 Point prevPoint = points[i - 1].ToPoint(); - controlPoint = new Point( - currentPoint.X + (currentPoint.X - prevPoint.X) * Tension * 0.3, - currentPoint.Y + (currentPoint.Y - prevPoint.Y) * Tension * 0.3 - ); + double distance = GetDistance(currentPoint, prevPoint); + + // 如果距离太远,使用更保守的控制点 + if (distance > 50.0) + { + controlPoint = currentPoint; // 直接使用当前点作为控制点 + } + else + { + controlPoint = new Point( + currentPoint.X + (currentPoint.X - prevPoint.X) * Tension * tensionMultiplier, + currentPoint.Y + (currentPoint.Y - prevPoint.Y) * Tension * tensionMultiplier + ); + } } else { @@ -174,27 +264,41 @@ namespace Ink_Canvas.Helpers Point prevPoint = points[i - 1].ToPoint(); Point nextPoint = points[i + 1].ToPoint(); - // 计算切线方向,使用更保守的方法 - double tangentX = (nextPoint.X - prevPoint.X) * 0.3; // 减少切线强度 - double tangentY = (nextPoint.Y - prevPoint.Y) * 0.3; - - // 应用张力参数,但限制最大偏移 - double maxOffset = 10.0; // 限制控制点最大偏移距离 - double offsetX = tangentX * Tension; - double offsetY = tangentY * Tension; + // 检查前后点的距离,如果太远则使用更保守的方法 + double prevDistance = GetDistance(currentPoint, prevPoint); + double nextDistance = GetDistance(currentPoint, nextPoint); - // 限制偏移距离 - double offsetDistance = Math.Sqrt(offsetX * offsetX + offsetY * offsetY); - if (offsetDistance > maxOffset) + if (prevDistance > 50.0 || nextDistance > 50.0) { - offsetX = offsetX * maxOffset / offsetDistance; - offsetY = offsetY * maxOffset / offsetDistance; + // 距离太远,使用线性插值作为控制点 + controlPoint = new Point( + (prevPoint.X + nextPoint.X) / 2.0, + (prevPoint.Y + nextPoint.Y) / 2.0 + ); } + else + { + // 计算切线方向,使用更保守的方法 + double tangentX = (nextPoint.X - prevPoint.X) * tensionMultiplier; + double tangentY = (nextPoint.Y - prevPoint.Y) * tensionMultiplier; - controlPoint = new Point( - currentPoint.X + offsetX, - currentPoint.Y + offsetY - ); + // 应用张力参数,但限制最大偏移 + double offsetX = tangentX * Tension; + double offsetY = tangentY * Tension; + + // 限制偏移距离 + double offsetDistance = Math.Sqrt(offsetX * offsetX + offsetY * offsetY); + if (offsetDistance > maxOffset) + { + offsetX = offsetX * maxOffset / offsetDistance; + offsetY = offsetY * maxOffset / offsetDistance; + } + + controlPoint = new Point( + currentPoint.X + offsetX, + currentPoint.Y + offsetY + ); + } } controlPoints.Add(controlPoint); @@ -222,7 +326,17 @@ namespace Ink_Canvas.Helpers // 计算自适应步长,减少步数以避免毛刺 double distance = GetDistance(startPoint.ToPoint(), endPoint.ToPoint()); - int steps = Math.Max(2, Math.Min(15, (int)(distance / 8.0))); // 减少步数,增加步长 + + // 根据点密度调整步数 + int steps; + if (points.Count < 5) // 低密度点 + { + steps = Math.Max(1, Math.Min(3, (int)(distance / 15.0))); // 更少的步数 + } + else + { + steps = Math.Max(2, Math.Min(15, (int)(distance / 8.0))); // 正常步数 + } // 生成贝塞尔曲线点 for (int j = 0; j <= steps; j++) @@ -305,6 +419,208 @@ namespace Ink_Canvas.Helpers return t * t * (3.0 - 2.0 * t); } + /// + /// 应用手抖修正 + /// + private List ApplyShakeCorrection(List points) + { + if (points.Count < 3) return points; + + var correctedPoints = new List(); + correctedPoints.Add(points[0]); // 添加第一个点 + + for (int i = 1; i < points.Count - 1; i++) + { + var prev = points[i - 1]; + var curr = points[i]; + var next = points[i + 1]; + + // 计算当前点的预期位置(基于前后点的线性插值) + double expectedX = (prev.X + next.X) / 2.0; + double expectedY = (prev.Y + next.Y) / 2.0; + + // 计算当前点与预期位置的偏差 + double deviationX = Math.Abs(curr.X - expectedX); + double deviationY = Math.Abs(curr.Y - expectedY); + double deviation = Math.Sqrt(deviationX * deviationX + deviationY * deviationY); + + // 如果偏差超过阈值,认为是手抖 + double shakeThreshold = 5.0; // 手抖检测阈值 + if (deviation > shakeThreshold) + { + // 应用手抖修正 + double correctionFactor = ShakeCorrectionStrength; + double correctedX = curr.X + (expectedX - curr.X) * correctionFactor; + double correctedY = curr.Y + (expectedY - curr.Y) * correctionFactor; + + // 保持压感值不变 + var correctedPoint = new StylusPoint(correctedX, correctedY, curr.PressureFactor); + correctedPoints.Add(correctedPoint); + } + else + { + correctedPoints.Add(curr); + } + } + + correctedPoints.Add(points[points.Count - 1]); // 添加最后一个点 + return correctedPoints; + } + + /// + /// 应用基于速度和时间的加权平滑 + /// + private List ApplyVelocityTimeWeightedSmoothing(List points) + { + if (points.Count < 3) return points; + + var smoothedPoints = new List(); + smoothedPoints.Add(points[0]); // 添加第一个点 + + // 计算每个点的速度和加速度 + var velocities = new List(); + var accelerations = new List(); + var timeWeights = new List(); + + for (int i = 1; i < points.Count; i++) + { + var prev = points[i - 1]; + var curr = points[i]; + + // 计算速度(距离/时间,这里假设时间间隔为1) + double velocity = GetDistance(prev.ToPoint(), curr.ToPoint()); + velocities.Add(velocity); + + // 计算加速度 + if (i > 1) + { + double prevVelocity = velocities[velocities.Count - 2]; + double acceleration = velocity - prevVelocity; + accelerations.Add(acceleration); + } + + // 计算时间权重(基于点的密度) + double timeWeight = 1.0; + if (i > 1) + { + // 如果点过于密集,增加时间权重 + double avgDistance = velocity; + if (avgDistance < 2.0) + { + timeWeight = 1.5; // 增加权重 + } + else if (avgDistance > 20.0) + { + timeWeight = 0.5; // 减少权重 + } + } + timeWeights.Add(timeWeight); + } + + // 应用加权平滑 + for (int i = 1; i < points.Count - 1; i++) + { + var prev = points[i - 1]; + var curr = points[i]; + var next = points[i + 1]; + + // 计算速度权重 + double velocityWeight = 1.0; + if (i < velocities.Count) + { + double velocity = velocities[i - 1]; + // 速度越快,权重越大(更平滑) + velocityWeight = Math.Min(2.0, velocity / 10.0 + 0.5); + } + + // 计算加速度权重 + double accelerationWeight = 1.0; + if (i < accelerations.Count) + { + double acceleration = Math.Abs(accelerations[i - 1]); + // 加速度越大,权重越大(更平滑) + accelerationWeight = Math.Min(2.0, acceleration / 5.0 + 0.5); + } + + // 获取时间权重 + double timeWeight = timeWeights[i]; + + // 综合权重 + double totalWeight = (velocityWeight * VelocityWeightedSmoothingStrength + + accelerationWeight * VelocityWeightedSmoothingStrength + + timeWeight * TimeWeightedSmoothingStrength) / 3.0; + + // 应用加权平滑 + double smoothedX = curr.X; + double smoothedY = curr.Y; + + if (totalWeight > 1.0) + { + // 向相邻点加权平均 + double weight = (totalWeight - 1.0) * 0.3; // 限制最大影响 + smoothedX = curr.X * (1.0 - weight) + (prev.X + next.X) * 0.5 * weight; + smoothedY = curr.Y * (1.0 - weight) + (prev.Y + next.Y) * 0.5 * weight; + } + + var smoothedPoint = new StylusPoint(smoothedX, smoothedY, curr.PressureFactor); + smoothedPoints.Add(smoothedPoint); + } + + smoothedPoints.Add(points[points.Count - 1]); // 添加最后一个点 + return smoothedPoints; + } + + /// + /// 处理低采样率笔画 + /// + private Stroke HandleLowSamplingRateStroke(Stroke stroke) + { + var points = stroke.StylusPoints.ToList(); + var resultPoints = new List(); + + // 对于低采样率,使用简单的线性插值而不是贝塞尔曲线 + for (int i = 0; i < points.Count - 1; i++) + { + var currentPoint = points[i]; + var nextPoint = points[i + 1]; + + // 添加当前点 + resultPoints.Add(currentPoint); + + // 计算两点间距离 + double distance = GetDistance(currentPoint.ToPoint(), nextPoint.ToPoint()); + + // 如果距离太远,插入中间点 + if (distance > 20.0) // 低采样率下使用更大的阈值 + { + int segments = Math.Max(2, Math.Min(5, (int)(distance / 10.0))); // 限制插值段数 + for (int j = 1; j < segments; j++) + { + double ratio = (double)j / segments; + var interpolatedPoint = InterpolatePoint(currentPoint, nextPoint, ratio); + resultPoints.Add(interpolatedPoint); + } + } + } + + // 添加最后一个点 + resultPoints.Add(points[points.Count - 1]); + + // 应用轻微的手抖修正 + var shakeCorrectedPoints = ApplyShakeCorrection(resultPoints); + + // 修正收尾相连问题 + var fixedStylusPoints = FixEndToEndConnection(new StylusPointCollection(shakeCorrectedPoints)); + + // 创建新的笔画 + var smoothedStroke = new Stroke(fixedStylusPoints) + { + DrawingAttributes = stroke.DrawingAttributes.Clone() + }; + + return smoothedStroke; + } + /// /// 应用自适应平滑 /// diff --git a/Ink Canvas/MainWindow.xaml b/Ink Canvas/MainWindow.xaml index 5916c263..40878556 100644 --- a/Ink Canvas/MainWindow.xaml +++ b/Ink Canvas/MainWindow.xaml @@ -782,7 +782,7 @@ Foreground="#a1a1aa" /> + VerticalAlignment="Center" FontSize="14" Margin="0,0,16,0" /> @@ -822,7 +822,37 @@ IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold" Toggled="ToggleSwitchEnableAdaptiveSmoothing_Toggled" /> - + + + + + + + + + + + + + + + + diff --git a/Ink Canvas/MainWindow_cs/MW_Settings.cs b/Ink Canvas/MainWindow_cs/MW_Settings.cs index d93965a6..63a3b2c5 100644 --- a/Ink Canvas/MainWindow_cs/MW_Settings.cs +++ b/Ink Canvas/MainWindow_cs/MW_Settings.cs @@ -1329,6 +1329,24 @@ namespace Ink_Canvas { SaveSettingsToFile(); } + private void ShakeCorrectionStrengthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { + if (!isLoaded) return; + Settings.Canvas.ShakeCorrectionStrength = ShakeCorrectionStrengthSlider.Value; + SaveSettingsToFile(); + } + + private void VelocityWeightedSmoothingStrengthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { + if (!isLoaded) return; + Settings.Canvas.VelocityWeightedSmoothingStrength = VelocityWeightedSmoothingStrengthSlider.Value; + SaveSettingsToFile(); + } + + private void TimeWeightedSmoothingStrengthSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs e) { + if (!isLoaded) return; + Settings.Canvas.TimeWeightedSmoothingStrength = TimeWeightedSmoothingStrengthSlider.Value; + SaveSettingsToFile(); + } + private void ToggleSwitchAutoSaveStrokesInPowerPoint_Toggled(object sender, RoutedEventArgs e) { if (!isLoaded) return; Settings.PowerPointSettings.IsAutoSaveStrokesInPowerPoint = ToggleSwitchAutoSaveStrokesInPowerPoint.IsOn; @@ -1634,6 +1652,9 @@ namespace Ink_Canvas { Settings.Canvas.AdvancedSmoothingStrength = 0.4; Settings.Canvas.AdvancedSmoothingTension = 0.3; Settings.Canvas.EnableAdaptiveSmoothing = true; + Settings.Canvas.ShakeCorrectionStrength = 0.6; + Settings.Canvas.VelocityWeightedSmoothingStrength = 0.7; + Settings.Canvas.TimeWeightedSmoothingStrength = 0.5; Settings.Canvas.EnablePressureTouchMode = false; Settings.Canvas.DisablePressure = false; Settings.Canvas.AutoStraightenLine = true; diff --git a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs index e1dd2960..81fb018a 100644 --- a/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs +++ b/Ink Canvas/MainWindow_cs/MW_SettingsToLoad.cs @@ -540,6 +540,9 @@ namespace Ink_Canvas { AdvancedSmoothingStrengthSlider.Value = Settings.Canvas.AdvancedSmoothingStrength; AdvancedSmoothingTensionSlider.Value = Settings.Canvas.AdvancedSmoothingTension; ToggleSwitchEnableAdaptiveSmoothing.IsOn = Settings.Canvas.EnableAdaptiveSmoothing; + ShakeCorrectionStrengthSlider.Value = Settings.Canvas.ShakeCorrectionStrength; + VelocityWeightedSmoothingStrengthSlider.Value = Settings.Canvas.VelocityWeightedSmoothingStrength; + TimeWeightedSmoothingStrengthSlider.Value = Settings.Canvas.TimeWeightedSmoothingStrength; // 初始化直线自动拉直相关设置 ToggleSwitchAutoStraightenLine.IsOn = Settings.Canvas.AutoStraightenLine; diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs index 46037236..661bf3e0 100644 --- a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs +++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs @@ -1599,7 +1599,10 @@ namespace Ink_Canvas { { SmoothingStrength = Settings.Canvas.AdvancedSmoothingStrength, Tension = Settings.Canvas.AdvancedSmoothingTension, - EnableAdaptiveSmoothing = Settings.Canvas.EnableAdaptiveSmoothing + EnableAdaptiveSmoothing = Settings.Canvas.EnableAdaptiveSmoothing, + ShakeCorrectionStrength = Settings.Canvas.ShakeCorrectionStrength, + VelocityWeightedSmoothingStrength = Settings.Canvas.VelocityWeightedSmoothingStrength, + TimeWeightedSmoothingStrength = Settings.Canvas.TimeWeightedSmoothingStrength }; // 对临时笔画应用平滑 diff --git a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs index 9cc49768..d6909954 100644 --- a/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs +++ b/Ink Canvas/MainWindow_cs/MW_SimulatePressure&InkToShape.cs @@ -16,6 +16,9 @@ namespace Ink_Canvas { private const double LINE_STRAIGHTEN_THRESHOLD = 0.20; // 默认灵敏度阈值,与UI默认值对应 private void inkCanvas_StrokeCollected(object sender, InkCanvasStrokeCollectedEventArgs e) { + // 标记是否进行了直线拉直 + bool wasStraightened = false; + // 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑 if (Settings.Canvas.FitToCurve == true) drawingAttributes.FitToCurve = false; @@ -118,8 +121,9 @@ namespace Ink_Canvas { } } - // Apply line straightening and endpoint snapping if ink-to-shape is enabled - if (Settings.InkToShape.IsInkToShapeEnabled) { + // Apply line straightening and endpoint snapping if ink-to-shape is enabled + + if (Settings.InkToShape.IsInkToShapeEnabled) { // 检查是否启用了直线自动拉直功能 if (Settings.Canvas.AutoStraightenLine && IsPotentialStraightLine(e.Stroke)) { // Get start and end points of the stroke @@ -169,6 +173,8 @@ namespace Ink_Canvas { newStrokes.Remove(e.Stroke); newStrokes.Add(straightStroke); } + + wasStraightened = true; // 标记已进行直线拉直 } } } @@ -573,26 +579,33 @@ namespace Ink_Canvas { } catch { } - // 应用高级贝塞尔曲线平滑 - if (Settings.Canvas.UseAdvancedBezierSmoothing) + // 应用高级贝塞尔曲线平滑(仅在未进行直线拉直时) + if (Settings.Canvas.UseAdvancedBezierSmoothing && !wasStraightened) { try { - var advancedSmoothing = new Helpers.AdvancedBezierSmoothing + // 检查原始笔画是否仍然存在于画布中 + if (inkCanvas.Strokes.Contains(e.Stroke)) { - SmoothingStrength = Settings.Canvas.AdvancedSmoothingStrength, - Tension = Settings.Canvas.AdvancedSmoothingTension, - EnableAdaptiveSmoothing = Settings.Canvas.EnableAdaptiveSmoothing - }; + var advancedSmoothing = new Helpers.AdvancedBezierSmoothing + { + SmoothingStrength = Settings.Canvas.AdvancedSmoothingStrength, + Tension = Settings.Canvas.AdvancedSmoothingTension, + EnableAdaptiveSmoothing = Settings.Canvas.EnableAdaptiveSmoothing, + ShakeCorrectionStrength = Settings.Canvas.ShakeCorrectionStrength, + VelocityWeightedSmoothingStrength = Settings.Canvas.VelocityWeightedSmoothingStrength, + TimeWeightedSmoothingStrength = Settings.Canvas.TimeWeightedSmoothingStrength + }; - var smoothedStroke = advancedSmoothing.SmoothStroke(e.Stroke); - - // 替换原始笔画 - SetNewBackupOfStroke(); - _currentCommitType = CommitReason.ShapeRecognition; - inkCanvas.Strokes.Remove(e.Stroke); - inkCanvas.Strokes.Add(smoothedStroke); - _currentCommitType = CommitReason.UserInput; + var smoothedStroke = advancedSmoothing.SmoothStroke(e.Stroke); + + // 替换原始笔画 + SetNewBackupOfStroke(); + _currentCommitType = CommitReason.ShapeRecognition; + inkCanvas.Strokes.Remove(e.Stroke); + inkCanvas.Strokes.Add(smoothedStroke); + _currentCommitType = CommitReason.UserInput; + } } catch (Exception ex) { @@ -600,7 +613,7 @@ namespace Ink_Canvas { System.Diagnostics.Debug.WriteLine($"高级贝塞尔曲线平滑失败: {ex.Message}"); } } - else if (Settings.Canvas.FitToCurve == true) + else if (Settings.Canvas.FitToCurve == true && !wasStraightened) { drawingAttributes.FitToCurve = true; } diff --git a/Ink Canvas/Resources/Settings.cs b/Ink Canvas/Resources/Settings.cs index 04bf5e92..47e98dfe 100644 --- a/Ink Canvas/Resources/Settings.cs +++ b/Ink Canvas/Resources/Settings.cs @@ -56,6 +56,12 @@ namespace Ink_Canvas public double AdvancedSmoothingTension { get; set; } = 0.3; // 高级平滑张力 (0.0 - 1.0),降低以减少毛刺 [JsonProperty("enableAdaptiveSmoothing")] public bool EnableAdaptiveSmoothing { get; set; } = true; // 是否启用自适应平滑 + [JsonProperty("shakeCorrectionStrength")] + public double ShakeCorrectionStrength { get; set; } = 0.6; // 手抖修正强度 (0.0 - 1.0) + [JsonProperty("velocityWeightedSmoothingStrength")] + public double VelocityWeightedSmoothingStrength { get; set; } = 0.7; // 速度加权平滑强度 (0.0 - 1.0) + [JsonProperty("timeWeightedSmoothingStrength")] + public double TimeWeightedSmoothingStrength { get; set; } = 0.5; // 时间加权平滑强度 (0.0 - 1.0) [JsonProperty("clearCanvasAndClearTimeMachine")] public bool ClearCanvasAndClearTimeMachine { get; set; } = false; [JsonProperty("enablePressureTouchMode")]