delete:墨迹预测
This commit is contained in:
@@ -1,217 +0,0 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Ink;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Ink_Canvas
|
||||
{
|
||||
/// <summary>
|
||||
/// 墨迹预测:书写过程中根据速度与选项外推一小段预览线,减轻感知延迟。
|
||||
/// </summary>
|
||||
public partial class MainWindow
|
||||
{
|
||||
private bool _inkPredictionStrokeActive;
|
||||
private bool _inkPredictionHasSample;
|
||||
private bool _inkPredictionHasVelocity;
|
||||
private Point _inkPredictionLastPos;
|
||||
private int _inkPredictionLastTime;
|
||||
private double _inkPredictionVx;
|
||||
private double _inkPredictionVy;
|
||||
|
||||
private void SyncInkStrokePredictionLeadComboVisibility()
|
||||
{
|
||||
try
|
||||
{
|
||||
bool on = Settings?.Canvas != null && Settings.Canvas.EnableInkStrokePrediction;
|
||||
var v = on ? Visibility.Visible : Visibility.Collapsed;
|
||||
if (ComboBoxInkStrokePredictionLeadSettings != null)
|
||||
ComboBoxInkStrokePredictionLeadSettings.Visibility = v;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearInkPredictionOverlay()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (InkPredictionPolyline == null) return;
|
||||
InkPredictionPolyline.Visibility = Visibility.Collapsed;
|
||||
InkPredictionPolyline.Points.Clear();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void BeginInkPredictionStrokeIfNeeded()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings?.Canvas == null || !Settings.Canvas.EnableInkStrokePrediction)
|
||||
{
|
||||
_inkPredictionStrokeActive = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_inkPredictionStrokeActive = inkCanvas != null
|
||||
&& inkCanvas.EditingMode == InkCanvasEditingMode.Ink
|
||||
&& penType != 1
|
||||
&& !_isBoardBrushMode;
|
||||
_inkPredictionHasSample = false;
|
||||
_inkPredictionHasVelocity = false;
|
||||
ClearInkPredictionOverlay();
|
||||
}
|
||||
catch
|
||||
{
|
||||
_inkPredictionStrokeActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void EndInkPredictionStroke()
|
||||
{
|
||||
_inkPredictionStrokeActive = false;
|
||||
_inkPredictionHasSample = false;
|
||||
_inkPredictionHasVelocity = false;
|
||||
ClearInkPredictionOverlay();
|
||||
}
|
||||
|
||||
private double GetInkPredictionLeadMs()
|
||||
{
|
||||
int mode = Settings?.Canvas?.InkStrokePredictionLeadMode ?? 0;
|
||||
if (mode == 1) return 25.0;
|
||||
if (mode == 2) return 50.0;
|
||||
|
||||
double speed = Math.Sqrt(_inkPredictionVx * _inkPredictionVx + _inkPredictionVy * _inkPredictionVy);
|
||||
double norm = Math.Min(1.0, speed / 2600.0);
|
||||
double lead = 16.0 + norm * 34.0;
|
||||
return Math.Max(14.0, Math.Min(52.0, lead));
|
||||
}
|
||||
|
||||
private double GetInkPredictionMaxDistance(double leadMs)
|
||||
{
|
||||
double baseD = Math.Max(4.0, Settings?.Canvas?.InkStrokePredictionMaxDistance ?? 18.0);
|
||||
int mode = Settings?.Canvas?.InkStrokePredictionLeadMode ?? 0;
|
||||
if (mode != 0)
|
||||
return Math.Max(6.0, Math.Min(42.0, baseD * (leadMs / 24.0)));
|
||||
|
||||
double speed = Math.Sqrt(_inkPredictionVx * _inkPredictionVx + _inkPredictionVy * _inkPredictionVy);
|
||||
double norm = Math.Min(1.0, speed / 2200.0);
|
||||
return Math.Max(6.0, Math.Min(48.0, baseD + norm * baseD * 0.9));
|
||||
}
|
||||
|
||||
private void inkCanvas_PreviewStylusMove(object sender, StylusEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings?.Canvas == null || !Settings.Canvas.EnableInkStrokePrediction) return;
|
||||
if (inkCanvas == null || InkPredictionPolyline == null) return;
|
||||
if (!_inkPredictionStrokeActive || penType == 1) return;
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink) return;
|
||||
|
||||
if (e.InAir)
|
||||
{
|
||||
ClearInkPredictionOverlay();
|
||||
return;
|
||||
}
|
||||
|
||||
var pos = e.GetPosition(inkCanvas);
|
||||
UpdateInkPredictionCore(pos, e.Timestamp);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void inkCanvas_LostStylusCapture(object sender, StylusEventArgs e)
|
||||
{
|
||||
EndInkPredictionStroke();
|
||||
}
|
||||
|
||||
private void inkCanvas_PreviewMouseMoveForPrediction(object sender, MouseEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Settings?.Canvas == null || !Settings.Canvas.EnableInkStrokePrediction) return;
|
||||
if (inkCanvas == null || InkPredictionPolyline == null) return;
|
||||
if (!_inkPredictionStrokeActive || penType == 1) return;
|
||||
if (inkCanvas.EditingMode != InkCanvasEditingMode.Ink) return;
|
||||
if (e.LeftButton != MouseButtonState.Pressed) return;
|
||||
if (e.StylusDevice != null) return;
|
||||
|
||||
var pos = e.GetPosition(inkCanvas);
|
||||
UpdateInkPredictionCore(pos, Environment.TickCount & int.MaxValue);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateInkPredictionCore(Point pos, int timestamp)
|
||||
{
|
||||
if (InkPredictionPolyline == null || Settings?.Canvas == null) return;
|
||||
|
||||
if (!_inkPredictionHasSample)
|
||||
{
|
||||
_inkPredictionLastPos = pos;
|
||||
_inkPredictionLastTime = timestamp;
|
||||
_inkPredictionHasSample = true;
|
||||
return;
|
||||
}
|
||||
|
||||
double dtMs = timestamp - _inkPredictionLastTime;
|
||||
if (dtMs <= 0 || dtMs > 120) dtMs = 16;
|
||||
|
||||
double vx = (pos.X - _inkPredictionLastPos.X) / dtMs * 1000.0;
|
||||
double vy = (pos.Y - _inkPredictionLastPos.Y) / dtMs * 1000.0;
|
||||
|
||||
const double velocitySmooth = 0.62;
|
||||
if (!_inkPredictionHasVelocity)
|
||||
{
|
||||
_inkPredictionVx = vx;
|
||||
_inkPredictionVy = vy;
|
||||
_inkPredictionHasVelocity = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
_inkPredictionVx = velocitySmooth * _inkPredictionVx + (1.0 - velocitySmooth) * vx;
|
||||
_inkPredictionVy = velocitySmooth * _inkPredictionVy + (1.0 - velocitySmooth) * vy;
|
||||
}
|
||||
|
||||
double leadMs = GetInkPredictionLeadMs();
|
||||
double predX = pos.X + _inkPredictionVx * (leadMs / 1000.0);
|
||||
double predY = pos.Y + _inkPredictionVy * (leadMs / 1000.0);
|
||||
|
||||
double maxDist = GetInkPredictionMaxDistance(leadMs);
|
||||
double dx = predX - pos.X;
|
||||
double dy = predY - pos.Y;
|
||||
double len = Math.Sqrt(dx * dx + dy * dy);
|
||||
if (len > maxDist && len > 1e-6)
|
||||
{
|
||||
double s = maxDist / len;
|
||||
predX = pos.X + dx * s;
|
||||
predY = pos.Y + dy * s;
|
||||
}
|
||||
|
||||
_inkPredictionLastPos = pos;
|
||||
_inkPredictionLastTime = timestamp;
|
||||
|
||||
var da = inkCanvas.DefaultDrawingAttributes;
|
||||
var c = da.Color;
|
||||
InkPredictionPolyline.Stroke = new SolidColorBrush(Color.FromArgb(110, c.R, c.G, c.B));
|
||||
InkPredictionPolyline.StrokeThickness = Math.Max(1.0, da.Width * 0.42);
|
||||
|
||||
InkPredictionPolyline.Points.Clear();
|
||||
InkPredictionPolyline.Points.Add(pos);
|
||||
InkPredictionPolyline.Points.Add(new Point(predX, predY));
|
||||
InkPredictionPolyline.Visibility = Visibility.Visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2700,28 +2700,6 @@ namespace Ink_Canvas
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchInkStrokePredictionSettings_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
|
||||
bool on = ToggleSwitchInkStrokePredictionSettings != null && ToggleSwitchInkStrokePredictionSettings.IsOn;
|
||||
Settings.Canvas.EnableInkStrokePrediction = on;
|
||||
SyncInkStrokePredictionLeadComboVisibility();
|
||||
if (!on)
|
||||
EndInkPredictionStroke();
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ComboBoxInkStrokePredictionLeadSettings_SelectionChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
var cb = sender as ComboBox;
|
||||
if (cb?.SelectedIndex < 0) return;
|
||||
|
||||
Settings.Canvas.InkStrokePredictionLeadMode = cb.SelectedIndex;
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
|
||||
private void ToggleSwitchAutoStraightenLine_Toggled(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (!isLoaded) return;
|
||||
|
||||
@@ -951,16 +951,6 @@ namespace Ink_Canvas
|
||||
// 初始化直线端点吸附相关设置
|
||||
ToggleSwitchLineEndpointSnapping.IsOn = Settings.Canvas.LineEndpointSnapping;
|
||||
ToggleSwitchCompressPicturesUploaded.IsOn = Settings.Canvas.IsCompressPicturesUploaded;
|
||||
|
||||
int leadMode = Settings.Canvas.InkStrokePredictionLeadMode;
|
||||
if (leadMode < 0 || leadMode > 2) leadMode = 0;
|
||||
Settings.Canvas.InkStrokePredictionLeadMode = leadMode;
|
||||
|
||||
if (ToggleSwitchInkStrokePredictionSettings != null)
|
||||
ToggleSwitchInkStrokePredictionSettings.IsOn = Settings.Canvas.EnableInkStrokePrediction;
|
||||
if (ComboBoxInkStrokePredictionLeadSettings != null)
|
||||
ComboBoxInkStrokePredictionLeadSettings.SelectedIndex = leadMode;
|
||||
SyncInkStrokePredictionLeadComboVisibility();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -2565,8 +2565,7 @@ namespace Ink_Canvas
|
||||
/// </remarks>
|
||||
private void inkCanvas_MouseUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
EndInkPredictionStroke();
|
||||
HandleEraserOperationEnded(); // 橡皮擦自动切换回批注模式:松手后启动/重置计时
|
||||
HandleEraserOperationEnded();
|
||||
inkCanvas.ReleaseMouseCapture();
|
||||
ViewboxFloatingBar.IsHitTestVisible = true;
|
||||
BlackboardUIGridForInkReplay.IsHitTestVisible = true;
|
||||
|
||||
@@ -632,7 +632,6 @@ namespace Ink_Canvas
|
||||
else if (result.ShapeName.Contains("Triangle") &&
|
||||
Settings.InkToShape.IsInkToShapeTriangle)
|
||||
{
|
||||
var shape = result.InkDrawingNode.GetShape();
|
||||
var p = result.HotPoints;
|
||||
if ((Math.Max(Math.Max(p[0].X, p[1].X), p[2].X) -
|
||||
Math.Min(Math.Min(p[0].X, p[1].X), p[2].X) >= 100 ||
|
||||
@@ -671,10 +670,10 @@ namespace Ink_Canvas
|
||||
result.ShapeName.Contains("Diamond") ||
|
||||
result.ShapeName.Contains("Parallelogram") ||
|
||||
result.ShapeName.Contains("Square") ||
|
||||
result.ShapeName.Contains("Trapezoid")) &&
|
||||
result.ShapeName.Contains("Trapezoid") ||
|
||||
result.ShapeName.Contains("Quadrilateral")) &&
|
||||
Settings.InkToShape.IsInkToShapeRectangle)
|
||||
{
|
||||
var shape = result.InkDrawingNode.GetShape();
|
||||
var p = result.HotPoints;
|
||||
if ((Math.Max(Math.Max(Math.Max(p[0].X, p[1].X), p[2].X), p[3].X) -
|
||||
Math.Min(Math.Min(Math.Min(p[0].X, p[1].X), p[2].X), p[3].X) >= 100 ||
|
||||
|
||||
Reference in New Issue
Block a user