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