improve:插入图片及墨迹平滑

This commit is contained in:
2025-08-30 22:59:12 +08:00
parent b64cefad46
commit d7df39290f
2 changed files with 71 additions and 20 deletions
+53 -13
View File
@@ -97,13 +97,20 @@ namespace Ink_Canvas.Helpers
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
// 确保点数合理 // 严格控制点数,避免产生过多点
if (smoothedPoints.Length > originalPoints.Length * 3) if (smoothedPoints.Length > originalPoints.Length * 2)
{ {
// 如果点数增加太多,进行重采样 // 如果点数增加太多,进行重采样
smoothedPoints = ResampleEquidistantOptimized(smoothedPoints, ResampleInterval); smoothedPoints = ResampleEquidistantOptimized(smoothedPoints, ResampleInterval);
} }
// 最终检查:确保点数不会过多
if (smoothedPoints.Length > originalPoints.Length * 1.5)
{
// 如果仍然太多点,使用原始笔画
return stroke;
}
// 创建平滑后的笔画 // 创建平滑后的笔画
var smoothedStroke = new Stroke(new StylusPointCollection(smoothedPoints)) var smoothedStroke = new Stroke(new StylusPointCollection(smoothedPoints))
{ {
@@ -125,23 +132,23 @@ namespace Ink_Canvas.Helpers
// 添加第一个点 // 添加第一个点
result.Add(points[0]); result.Add(points[0]);
// 使用滑动窗口进行贝塞尔曲线拟合 // 使用非重叠的窗口进行贝塞尔曲线拟合
for (int i = 0; i <= points.Length - 4; i++) for (int i = 0; i < points.Length - 3; i += 3) // 每次移动3个点,避免重叠
{ {
var p0 = points[i]; var p0 = points[i];
var p1 = points[i + 1]; var p1 = points[Math.Min(i + 1, points.Length - 1)];
var p2 = points[i + 2]; var p2 = points[Math.Min(i + 2, points.Length - 1)];
var p3 = points[i + 3]; var p3 = points[Math.Min(i + 3, points.Length - 1)];
// 计算改进的控制点 // 计算改进的控制点
var controlPoints = CalculateImprovedControlPoints(p0, p1, p2, p3); var controlPoints = CalculateImprovedControlPoints(p0, p1, p2, p3);
// 自适应插值步数 // 限制插值步数,避免点数爆炸
int steps = UseAdaptiveInterpolation ? int steps = Math.Min(UseAdaptiveInterpolation ?
CalculateAdaptiveSteps(p0, p1, p2, p3) : InterpolationSteps; CalculateAdaptiveSteps(p0, p1, p2, p3) : InterpolationSteps, 16);
// 生成贝塞尔曲线点 // 生成贝塞尔曲线点,但跳过第一个点避免重复
for (int j = 1; j <= steps; j++) // 从1开始避免重复第一个点 for (int j = 1; j <= steps; j++)
{ {
double t = (double)j / steps; double t = (double)j / steps;
var bezierPoint = CubicBezierWithControlPoints(controlPoints, t, p0, p3); var bezierPoint = CubicBezierWithControlPoints(controlPoints, t, p0, p3);
@@ -152,7 +159,8 @@ namespace Ink_Canvas.Helpers
// 添加最后一个点 // 添加最后一个点
result.Add(points[points.Length - 1]); result.Add(points[points.Length - 1]);
return result.ToArray(); // 去重和优化点数
return RemoveDuplicatePoints(result.ToArray());
} }
/// <summary> /// <summary>
@@ -233,6 +241,38 @@ namespace Ink_Canvas.Helpers
return (angle1 + angle2) / Math.PI; // 归一化到0-1 return (angle1 + angle2) / Math.PI; // 归一化到0-1
} }
/// <summary>
/// 去除重复和过近的点
/// </summary>
private StylusPoint[] RemoveDuplicatePoints(StylusPoint[] points)
{
if (points.Length < 2) return points;
var result = new List<StylusPoint>();
result.Add(points[0]);
double minDistance = ResampleInterval * 0.5; // 最小距离阈值
for (int i = 1; i < points.Length; i++)
{
var lastPoint = result[result.Count - 1];
var currentPoint = points[i];
// 计算距离
double distance = Math.Sqrt(
(currentPoint.X - lastPoint.X) * (currentPoint.X - lastPoint.X) +
(currentPoint.Y - lastPoint.Y) * (currentPoint.Y - lastPoint.Y));
// 如果距离足够大,添加这个点
if (distance >= minDistance)
{
result.Add(currentPoint);
}
}
return result.ToArray();
}
/// <summary> /// <summary>
/// 使用控制点的三次贝塞尔曲线计算 /// 使用控制点的三次贝塞尔曲线计算
/// </summary> /// </summary>
@@ -40,11 +40,6 @@ namespace Ink_Canvas
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff"); string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
image.Name = timestamp; image.Name = timestamp;
// 初始化TransformGroup
InitializeElementTransform(image);
CenterAndScaleElement(image);
// 设置图片属性,避免被InkCanvas选择系统处理 // 设置图片属性,避免被InkCanvas选择系统处理
image.IsHitTestVisible = true; image.IsHitTestVisible = true;
image.Focusable = false; image.Focusable = false;
@@ -52,8 +47,15 @@ namespace Ink_Canvas
// 初始化InkCanvas选择设置 // 初始化InkCanvas选择设置
InitializeInkCanvasSelectionSettings(); InitializeInkCanvasSelectionSettings();
// 先添加到画布
inkCanvas.Children.Add(image); inkCanvas.Children.Add(image);
// 初始化TransformGroup
InitializeElementTransform(image);
// 居中缩放
CenterAndScaleElement(image);
// 绑定事件处理器 // 绑定事件处理器
BindElementEvents(image); BindElementEvents(image);
@@ -99,6 +101,8 @@ namespace Ink_Canvas
{ {
if (sender is FrameworkElement element) if (sender is FrameworkElement element)
{ {
LogHelper.WriteLogToFile($"图片鼠标按下: {element.Name}");
// 取消之前选中的元素 // 取消之前选中的元素
if (currentSelectedElement != null && currentSelectedElement != element) if (currentSelectedElement != null && currentSelectedElement != element)
{ {
@@ -151,6 +155,8 @@ namespace Ink_Canvas
{ {
if (sender is FrameworkElement element) if (sender is FrameworkElement element)
{ {
LogHelper.WriteLogToFile($"图片滚轮事件: {element.Name}, Delta={e.Delta}");
// 使用滚轮缩放的核心机制 // 使用滚轮缩放的核心机制
ApplyWheelScaleTransform(element, e); ApplyWheelScaleTransform(element, e);
@@ -890,8 +896,13 @@ namespace Ink_Canvas
InkCanvas.SetLeft(element, centerX); InkCanvas.SetLeft(element, centerX);
InkCanvas.SetTop(element, centerY); InkCanvas.SetTop(element, centerY);
// 清除任何现有的RenderTransform // 保持TransformGroup,不清除RenderTransform
element.RenderTransform = Transform.Identity; // 这样可以保持滚轮缩放和拖动功能
if (element.RenderTransform == null || element.RenderTransform == Transform.Identity)
{
// 只有在没有TransformGroup时才创建
InitializeElementTransform(element);
}
LogHelper.WriteLogToFile($"元素居中完成: 位置({centerX}, {centerY}), 尺寸({newWidth}x{newHeight})"); LogHelper.WriteLogToFile($"元素居中完成: 位置({centerX}, {centerY}), 尺寸({newWidth}x{newHeight})");
} }