improve:端点吸附
避免点线和虚线吸附
This commit is contained in:
@@ -18,21 +18,19 @@ namespace Ink_Canvas
|
|||||||
{
|
{
|
||||||
private StrokeCollection newStrokes = new StrokeCollection();
|
private StrokeCollection newStrokes = new StrokeCollection();
|
||||||
private List<Circle> circles = new List<Circle>();
|
private List<Circle> circles = new List<Circle>();
|
||||||
private const double LINE_STRAIGHTEN_THRESHOLD = 0.20; // 默认灵敏度阈值,与UI默认值对应
|
private const double LINE_STRAIGHTEN_THRESHOLD = 0.20;
|
||||||
|
|
||||||
// 矩形参考线系统
|
|
||||||
private List<RectangleGuideLine> rectangleGuideLines = new List<RectangleGuideLine>();
|
private List<RectangleGuideLine> rectangleGuideLines = new List<RectangleGuideLine>();
|
||||||
private const double RECTANGLE_ENDPOINT_THRESHOLD = 30.0; // 端点相交判断阈值
|
private const double RECTANGLE_ENDPOINT_THRESHOLD = 30.0;
|
||||||
private const double RECTANGLE_ANGLE_THRESHOLD = 15.0; // 角度判断阈值(度)
|
private const double RECTANGLE_ANGLE_THRESHOLD = 15.0;
|
||||||
|
|
||||||
// 矩形参考线数据结构
|
|
||||||
private class RectangleGuideLine
|
private class RectangleGuideLine
|
||||||
{
|
{
|
||||||
public Stroke OriginalStroke { get; set; }
|
public Stroke OriginalStroke { get; set; }
|
||||||
public Point StartPoint { get; set; }
|
public Point StartPoint { get; set; }
|
||||||
public Point EndPoint { get; set; }
|
public Point EndPoint { get; set; }
|
||||||
public DateTime CreatedTime { get; set; }
|
public DateTime CreatedTime { get; set; }
|
||||||
public double Angle { get; set; } // 直线角度(弧度)
|
public double Angle { get; set; }
|
||||||
public bool IsHorizontal { get; set; }
|
public bool IsHorizontal { get; set; }
|
||||||
public bool IsVertical { get; set; }
|
public bool IsVertical { get; set; }
|
||||||
|
|
||||||
@@ -64,7 +62,6 @@ namespace Ink_Canvas
|
|||||||
var startPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[0].ToPoint() : new Point();
|
var startPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[0].ToPoint() : new Point();
|
||||||
var endPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1].ToPoint() : new Point();
|
var endPoint = e.Stroke.StylusPoints.Count > 0 ? e.Stroke.StylusPoints[e.Stroke.StylusPoints.Count - 1].ToPoint() : new Point();
|
||||||
|
|
||||||
// 确保InkCanvas保持Ink编辑模式,防止自动切换到鼠标模式
|
|
||||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink)
|
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink)
|
||||||
{
|
{
|
||||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||||
@@ -80,19 +77,15 @@ namespace Ink_Canvas
|
|||||||
LogHelper.WriteLogToFile("StrokeCollected: 墨迹渐隐管理器为空,无法添加墨迹", LogHelper.LogType.Error);
|
LogHelper.WriteLogToFile("StrokeCollected: 墨迹渐隐管理器为空,无法添加墨迹", LogHelper.LogType.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 延迟移除墨迹,避免立即移除导致模式切换
|
|
||||||
// 使用Dispatcher.BeginInvoke确保在UI线程上异步执行
|
|
||||||
Dispatcher.BeginInvoke(new Action(() =>
|
Dispatcher.BeginInvoke(new Action(() =>
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 再次确保InkCanvas保持Ink编辑模式
|
|
||||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink)
|
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink)
|
||||||
{
|
{
|
||||||
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
inkCanvas.EditingMode = InkCanvasEditingMode.Ink;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从InkCanvas中移除墨迹,因为我们要用渐隐管理器来管理它
|
|
||||||
if (inkCanvas.Strokes.Contains(e.Stroke))
|
if (inkCanvas.Strokes.Contains(e.Stroke))
|
||||||
{
|
{
|
||||||
inkCanvas.Strokes.Remove(e.Stroke);
|
inkCanvas.Strokes.Remove(e.Stroke);
|
||||||
@@ -104,21 +97,18 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
}), DispatcherPriority.Background);
|
}), DispatcherPriority.Background);
|
||||||
|
|
||||||
// 墨迹渐隐模式下不参与墨迹纠正和其他处理,直接返回
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 标记是否进行了直线拉直
|
// 标记是否进行了直线拉直
|
||||||
bool wasStraightened = false;
|
bool wasStraightened = false;
|
||||||
|
|
||||||
// 禁用原有的FitToCurve,使用新的高级贝塞尔曲线平滑
|
|
||||||
if (Settings.Canvas.FitToCurve) drawingAttributes.FitToCurve = false;
|
if (Settings.Canvas.FitToCurve) drawingAttributes.FitToCurve = false;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
inkCanvas.Opacity = 1;
|
inkCanvas.Opacity = 1;
|
||||||
|
|
||||||
// 应用屏蔽压感功能 - 如果启用,所有笔画都使用统一粗细
|
|
||||||
if (Settings.Canvas.DisablePressure)
|
if (Settings.Canvas.DisablePressure)
|
||||||
{
|
{
|
||||||
var uniformPoints = new StylusPointCollection();
|
var uniformPoints = new StylusPointCollection();
|
||||||
@@ -129,13 +119,11 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
e.Stroke.StylusPoints = uniformPoints;
|
e.Stroke.StylusPoints = uniformPoints;
|
||||||
}
|
}
|
||||||
// 应用压感触屏模式 - 如果启用并且检测到触屏输入
|
|
||||||
else if (Settings.Canvas.EnablePressureTouchMode)
|
else if (Settings.Canvas.EnablePressureTouchMode)
|
||||||
{
|
{
|
||||||
bool isTouchInput = true;
|
bool isTouchInput = true;
|
||||||
foreach (StylusPoint point in e.Stroke.StylusPoints)
|
foreach (StylusPoint point in e.Stroke.StylusPoints)
|
||||||
{
|
{
|
||||||
// 检测是否为压感笔输入(压感笔的PressureFactor不等于0.5或0)
|
|
||||||
if ((point.PressureFactor > 0.501 || point.PressureFactor < 0.5) && point.PressureFactor != 0)
|
if ((point.PressureFactor > 0.501 || point.PressureFactor < 0.5) && point.PressureFactor != 0)
|
||||||
{
|
{
|
||||||
isTouchInput = false;
|
isTouchInput = false;
|
||||||
@@ -143,7 +131,6 @@ namespace Ink_Canvas
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是触屏输入,则应用模拟压感
|
|
||||||
if (isTouchInput)
|
if (isTouchInput)
|
||||||
{
|
{
|
||||||
switch (Settings.Canvas.InkStyle)
|
switch (Settings.Canvas.InkStyle)
|
||||||
@@ -1551,11 +1538,66 @@ namespace Ink_Canvas
|
|||||||
return distance;
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 判断一个 stroke 是否是直线(排除虚线和点线)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="stroke">要检查的 stroke</param>
|
||||||
|
/// <returns>如果是直线返回 true,否则返回 false</returns>
|
||||||
|
private bool IsStraightLine(Stroke stroke)
|
||||||
|
{
|
||||||
|
if (stroke == null || stroke.StylusPoints.Count == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int pointCount = stroke.StylusPoints.Count;
|
||||||
|
|
||||||
|
if (pointCount == 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 最简单的直线:只有2个点
|
||||||
|
if (pointCount == 2)
|
||||||
|
{
|
||||||
|
Point p1 = stroke.StylusPoints[0].ToPoint();
|
||||||
|
Point p2 = stroke.StylusPoints[1].ToPoint();
|
||||||
|
double lineLength = GetDistance(p1, p2);
|
||||||
|
|
||||||
|
if (lineLength < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pointCount > 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 对于3个点的情况,检查它们是否基本在一条直线上
|
||||||
|
if (pointCount == 3)
|
||||||
|
{
|
||||||
|
Point p1 = stroke.StylusPoints[0].ToPoint();
|
||||||
|
Point p2 = stroke.StylusPoints[1].ToPoint();
|
||||||
|
Point p3 = stroke.StylusPoints[2].ToPoint();
|
||||||
|
|
||||||
|
double totalLength = GetDistance(p1, p3);
|
||||||
|
if (totalLength < 10)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// 计算点到直线的距离
|
||||||
|
// 使用 p1 和 p3 作为直线端点,检查 p2 是否在这条直线上
|
||||||
|
double distance = DistanceFromLineToPoint(p1, p3, p2);
|
||||||
|
|
||||||
|
// 如果点到直线的距离相对于线段长度很小,认为是直线
|
||||||
|
// 使用相对误差阈值(比如 1%)
|
||||||
|
if (totalLength > 0 && distance / totalLength < 0.01)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// New method: Attempts to snap endpoints to existing stroke endpoints
|
// New method: Attempts to snap endpoints to existing stroke endpoints
|
||||||
private Point[] GetSnappedEndpoints(Point start, Point end)
|
private Point[] GetSnappedEndpoints(Point start, Point end)
|
||||||
{
|
{
|
||||||
// 如果端点吸附功能关闭,直接返回null
|
|
||||||
// 这里不再返回原始点,因为调用此方法的地方会判断返回值是否为null
|
|
||||||
if (!Settings.Canvas.LineEndpointSnapping)
|
if (!Settings.Canvas.LineEndpointSnapping)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -1572,6 +1614,10 @@ namespace Ink_Canvas
|
|||||||
{
|
{
|
||||||
if (stroke.StylusPoints.Count == 0) continue;
|
if (stroke.StylusPoints.Count == 0) continue;
|
||||||
|
|
||||||
|
// 只对直线进行端点吸附,跳过虚线和点线
|
||||||
|
if (!IsStraightLine(stroke))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Get stroke endpoints
|
// Get stroke endpoints
|
||||||
Point strokeStart = stroke.StylusPoints.First().ToPoint();
|
Point strokeStart = stroke.StylusPoints.First().ToPoint();
|
||||||
Point strokeEnd = stroke.StylusPoints.Last().ToPoint();
|
Point strokeEnd = stroke.StylusPoints.Last().ToPoint();
|
||||||
|
|||||||
Reference in New Issue
Block a user