improve:插入图片及墨迹平滑
This commit is contained in:
@@ -97,13 +97,20 @@ namespace Ink_Canvas.Helpers
|
||||
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
// 确保点数合理
|
||||
if (smoothedPoints.Length > originalPoints.Length * 3)
|
||||
// 严格控制点数,避免产生过多点
|
||||
if (smoothedPoints.Length > originalPoints.Length * 2)
|
||||
{
|
||||
// 如果点数增加太多,进行重采样
|
||||
smoothedPoints = ResampleEquidistantOptimized(smoothedPoints, ResampleInterval);
|
||||
}
|
||||
|
||||
// 最终检查:确保点数不会过多
|
||||
if (smoothedPoints.Length > originalPoints.Length * 1.5)
|
||||
{
|
||||
// 如果仍然太多点,使用原始笔画
|
||||
return stroke;
|
||||
}
|
||||
|
||||
// 创建平滑后的笔画
|
||||
var smoothedStroke = new Stroke(new StylusPointCollection(smoothedPoints))
|
||||
{
|
||||
@@ -125,23 +132,23 @@ namespace Ink_Canvas.Helpers
|
||||
// 添加第一个点
|
||||
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 p1 = points[i + 1];
|
||||
var p2 = points[i + 2];
|
||||
var p3 = points[i + 3];
|
||||
var p1 = points[Math.Min(i + 1, points.Length - 1)];
|
||||
var p2 = points[Math.Min(i + 2, points.Length - 1)];
|
||||
var p3 = points[Math.Min(i + 3, points.Length - 1)];
|
||||
|
||||
// 计算改进的控制点
|
||||
var controlPoints = CalculateImprovedControlPoints(p0, p1, p2, p3);
|
||||
|
||||
// 自适应插值步数
|
||||
int steps = UseAdaptiveInterpolation ?
|
||||
CalculateAdaptiveSteps(p0, p1, p2, p3) : InterpolationSteps;
|
||||
// 限制插值步数,避免点数爆炸
|
||||
int steps = Math.Min(UseAdaptiveInterpolation ?
|
||||
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;
|
||||
var bezierPoint = CubicBezierWithControlPoints(controlPoints, t, p0, p3);
|
||||
@@ -152,7 +159,8 @@ namespace Ink_Canvas.Helpers
|
||||
// 添加最后一个点
|
||||
result.Add(points[points.Length - 1]);
|
||||
|
||||
return result.ToArray();
|
||||
// 去重和优化点数
|
||||
return RemoveDuplicatePoints(result.ToArray());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -233,6 +241,38 @@ namespace Ink_Canvas.Helpers
|
||||
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>
|
||||
|
||||
@@ -40,11 +40,6 @@ namespace Ink_Canvas
|
||||
string timestamp = "img_" + DateTime.Now.ToString("yyyyMMdd_HH_mm_ss_fff");
|
||||
image.Name = timestamp;
|
||||
|
||||
// 初始化TransformGroup
|
||||
InitializeElementTransform(image);
|
||||
|
||||
CenterAndScaleElement(image);
|
||||
|
||||
// 设置图片属性,避免被InkCanvas选择系统处理
|
||||
image.IsHitTestVisible = true;
|
||||
image.Focusable = false;
|
||||
@@ -52,8 +47,15 @@ namespace Ink_Canvas
|
||||
// 初始化InkCanvas选择设置
|
||||
InitializeInkCanvasSelectionSettings();
|
||||
|
||||
// 先添加到画布
|
||||
inkCanvas.Children.Add(image);
|
||||
|
||||
// 初始化TransformGroup
|
||||
InitializeElementTransform(image);
|
||||
|
||||
// 居中缩放
|
||||
CenterAndScaleElement(image);
|
||||
|
||||
// 绑定事件处理器
|
||||
BindElementEvents(image);
|
||||
|
||||
@@ -99,6 +101,8 @@ namespace Ink_Canvas
|
||||
{
|
||||
if (sender is FrameworkElement element)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"图片鼠标按下: {element.Name}");
|
||||
|
||||
// 取消之前选中的元素
|
||||
if (currentSelectedElement != null && currentSelectedElement != element)
|
||||
{
|
||||
@@ -151,6 +155,8 @@ namespace Ink_Canvas
|
||||
{
|
||||
if (sender is FrameworkElement element)
|
||||
{
|
||||
LogHelper.WriteLogToFile($"图片滚轮事件: {element.Name}, Delta={e.Delta}");
|
||||
|
||||
// 使用滚轮缩放的核心机制
|
||||
ApplyWheelScaleTransform(element, e);
|
||||
|
||||
@@ -890,8 +896,13 @@ namespace Ink_Canvas
|
||||
InkCanvas.SetLeft(element, centerX);
|
||||
InkCanvas.SetTop(element, centerY);
|
||||
|
||||
// 清除任何现有的RenderTransform
|
||||
element.RenderTransform = Transform.Identity;
|
||||
// 保持TransformGroup,不清除RenderTransform
|
||||
// 这样可以保持滚轮缩放和拖动功能
|
||||
if (element.RenderTransform == null || element.RenderTransform == Transform.Identity)
|
||||
{
|
||||
// 只有在没有TransformGroup时才创建
|
||||
InitializeElementTransform(element);
|
||||
}
|
||||
|
||||
LogHelper.WriteLogToFile($"元素居中完成: 位置({centerX}, {centerY}), 尺寸({newWidth}x{newHeight})");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user