add:高精度直线拉直
This commit is contained in:
@@ -970,7 +970,15 @@
|
|||||||
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=LineStraightenSensitivitySlider, Path=Value, StringFormat={}{0:F2}}"
|
<TextBlock Foreground="#fafafa" Text="{Binding ElementName=LineStraightenSensitivitySlider, Path=Value, StringFormat={}{0:F2}}"
|
||||||
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
|
VerticalAlignment="Center" FontSize="14" Margin="16,0,0,0" />
|
||||||
</ui:SimpleStackPanel>
|
</ui:SimpleStackPanel>
|
||||||
<TextBlock Text="# 开启后,当绘制的直线超过设定长度阈值时,将自动调整为完美直线。灵敏度范围0.05-2.0,越小要求越严格,弯曲的线条越不容易被拉直;值越大越容易识别为直线。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left"
|
||||||
|
Visibility="{Binding ElementName=ToggleSwitchAutoStraightenLine, Path=IsOn, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||||
|
<TextBlock Foreground="#fafafa" Text="高精度直线拉直" VerticalAlignment="Center"
|
||||||
|
FontSize="14" Margin="0,0,16,0" />
|
||||||
|
<ui:ToggleSwitch OnContent="" OffContent="" Name="ToggleSwitchHighPrecisionLineStraighten"
|
||||||
|
IsOn="True" FontFamily="Microsoft YaHei UI" FontWeight="Bold"
|
||||||
|
Toggled="ToggleSwitchHighPrecisionLineStraighten_Toggled" />
|
||||||
|
</ui:SimpleStackPanel>
|
||||||
|
<TextBlock Text="# 开启后,当绘制的直线超过设定长度阈值时,将自动调整为完美直线。灵敏度范围0.05-2.0,越小要求越严格,弯曲的线条越不容易被拉直;值越大越容易识别为直线。高精度模式下,每隔10像素取一个计数点,获取更准确的平均值用于判断。" TextWrapping="Wrap" Foreground="#a1a1aa" />
|
||||||
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
<Line HorizontalAlignment="Center" X1="0" Y1="0" X2="400" Y2="0"
|
||||||
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
Stroke="#3f3f46" StrokeThickness="1" Margin="0,4,0,4" />
|
||||||
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
<ui:SimpleStackPanel Orientation="Horizontal" HorizontalAlignment="Left">
|
||||||
|
|||||||
@@ -783,6 +783,14 @@ namespace Ink_Canvas {
|
|||||||
SaveSettingsToFile();
|
SaveSettingsToFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ToggleSwitchHighPrecisionLineStraighten_Toggled(object sender, RoutedEventArgs e) {
|
||||||
|
if (!isLoaded) return;
|
||||||
|
|
||||||
|
Settings.Canvas.HighPrecisionLineStraighten = ToggleSwitchHighPrecisionLineStraighten.IsOn;
|
||||||
|
System.Diagnostics.Debug.WriteLine($"HighPrecisionLineStraighten changed: {Settings.Canvas.HighPrecisionLineStraighten}");
|
||||||
|
SaveSettingsToFile();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Canvas
|
#region Canvas
|
||||||
|
|||||||
@@ -533,6 +533,8 @@ namespace Ink_Canvas {
|
|||||||
AutoStraightenLineThresholdSlider.Value = Settings.Canvas.AutoStraightenLineThreshold;
|
AutoStraightenLineThresholdSlider.Value = Settings.Canvas.AutoStraightenLineThreshold;
|
||||||
// 直线拉直灵敏度也在这里初始化,即使它存储在InkToShape中
|
// 直线拉直灵敏度也在这里初始化,即使它存储在InkToShape中
|
||||||
LineStraightenSensitivitySlider.Value = Settings.InkToShape.LineStraightenSensitivity;
|
LineStraightenSensitivitySlider.Value = Settings.InkToShape.LineStraightenSensitivity;
|
||||||
|
// 初始化高精度直线拉直设置
|
||||||
|
ToggleSwitchHighPrecisionLineStraighten.IsOn = Settings.Canvas.HighPrecisionLineStraighten;
|
||||||
|
|
||||||
// 初始化直线端点吸附相关设置
|
// 初始化直线端点吸附相关设置
|
||||||
ToggleSwitchLineEndpointSnapping.IsOn = Settings.Canvas.LineEndpointSnapping;
|
ToggleSwitchLineEndpointSnapping.IsOn = Settings.Canvas.LineEndpointSnapping;
|
||||||
|
|||||||
@@ -687,20 +687,97 @@ namespace Ink_Canvas {
|
|||||||
double totalDeviation = 0;
|
double totalDeviation = 0;
|
||||||
int pointCount = 0;
|
int pointCount = 0;
|
||||||
|
|
||||||
// Calculate deviation for each point
|
// 检查是否启用了高精度直线拉直
|
||||||
foreach (StylusPoint sp in stroke.StylusPoints) {
|
bool useHighPrecision = Settings.Canvas.HighPrecisionLineStraighten;
|
||||||
Point p = sp.ToPoint();
|
|
||||||
double deviation = DistanceFromLineToPoint(start, end, p);
|
if (useHighPrecision) {
|
||||||
maxDeviation = Math.Max(maxDeviation, deviation);
|
System.Diagnostics.Debug.WriteLine("使用高精度直线拉直模式");
|
||||||
totalDeviation += deviation;
|
|
||||||
pointCount++;
|
// 高精度模式:每隔10像素取一个计数点
|
||||||
|
double strokeLength = 0;
|
||||||
|
double sampleInterval = 10.0; // 10像素间隔
|
||||||
|
|
||||||
|
// 计算笔画的总长度,用于后续采样
|
||||||
|
for (int i = 1; i < stroke.StylusPoints.Count; i++) {
|
||||||
|
Point p1 = stroke.StylusPoints[i-1].ToPoint();
|
||||||
|
Point p2 = stroke.StylusPoints[i].ToPoint();
|
||||||
|
strokeLength += GetDistance(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果笔画太短,直接使用所有点
|
||||||
|
if (strokeLength < sampleInterval * 5) {
|
||||||
|
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||||
|
Point p = sp.ToPoint();
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||||
|
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||||
|
totalDeviation += deviation;
|
||||||
|
pointCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 使用等距采样点
|
||||||
|
double currentLength = 0;
|
||||||
|
double nextSampleAt = 0;
|
||||||
|
|
||||||
|
// 总是包含起点
|
||||||
|
Point lastPoint = start;
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, lastPoint);
|
||||||
|
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||||
|
totalDeviation += deviation;
|
||||||
|
pointCount++;
|
||||||
|
|
||||||
|
// 采样中间点
|
||||||
|
for (int i = 1; i < stroke.StylusPoints.Count; i++) {
|
||||||
|
Point currentPoint = stroke.StylusPoints[i].ToPoint();
|
||||||
|
double segmentLength = GetDistance(lastPoint, currentPoint);
|
||||||
|
|
||||||
|
// 如果这段线段跨越了下一个采样点
|
||||||
|
while (currentLength + segmentLength >= nextSampleAt) {
|
||||||
|
// 计算采样点在线段上的位置
|
||||||
|
double t = (nextSampleAt - currentLength) / segmentLength;
|
||||||
|
Point samplePoint = new Point(
|
||||||
|
lastPoint.X + t * (currentPoint.X - lastPoint.X),
|
||||||
|
lastPoint.Y + t * (currentPoint.Y - lastPoint.Y)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 计算采样点的偏差
|
||||||
|
deviation = DistanceFromLineToPoint(start, end, samplePoint);
|
||||||
|
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||||
|
totalDeviation += deviation;
|
||||||
|
pointCount++;
|
||||||
|
|
||||||
|
// 设置下一个采样点位置
|
||||||
|
nextSampleAt += sampleInterval;
|
||||||
|
|
||||||
|
// 防止无限循环
|
||||||
|
if (nextSampleAt > strokeLength) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLength += segmentLength;
|
||||||
|
lastPoint = currentPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 总是包含终点
|
||||||
|
deviation = DistanceFromLineToPoint(start, end, end);
|
||||||
|
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||||
|
totalDeviation += deviation;
|
||||||
|
pointCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 原始模式:使用所有点
|
||||||
|
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||||
|
Point p = sp.ToPoint();
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||||
|
maxDeviation = Math.Max(maxDeviation, deviation);
|
||||||
|
totalDeviation += deviation;
|
||||||
|
pointCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 计算平均偏差
|
// 计算平均偏差
|
||||||
double avgDeviation = totalDeviation / pointCount;
|
double avgDeviation = totalDeviation / pointCount;
|
||||||
|
|
||||||
// 更详细的调试信息
|
// 更详细的调试信息
|
||||||
System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}");
|
System.Diagnostics.Debug.WriteLine($"Max deviation: {maxDeviation}, Avg: {avgDeviation}, Threshold: {sensitivity * lineLength}, Points: {pointCount}");
|
||||||
|
|
||||||
// 支持更广泛的灵敏度范围 (0.05-2.0)
|
// 支持更广泛的灵敏度范围 (0.05-2.0)
|
||||||
|
|
||||||
@@ -722,11 +799,79 @@ namespace Ink_Canvas {
|
|||||||
else {
|
else {
|
||||||
// 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲
|
// 检查点分布的一致性 - 如果有些点偏离很大而其他点很接近直线,表明线条有明显弯曲
|
||||||
double deviationVariance = 0;
|
double deviationVariance = 0;
|
||||||
foreach (StylusPoint sp in stroke.StylusPoints) {
|
|
||||||
Point p = sp.ToPoint();
|
// 使用相同的高精度/原始模式来计算方差
|
||||||
double deviation = DistanceFromLineToPoint(start, end, p);
|
if (useHighPrecision) {
|
||||||
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
// 高精度模式:重新采样计算方差
|
||||||
|
double strokeLength = 0;
|
||||||
|
double sampleInterval = 10.0; // 10像素间隔
|
||||||
|
|
||||||
|
// 计算笔画的总长度,用于后续采样
|
||||||
|
for (int i = 1; i < stroke.StylusPoints.Count; i++) {
|
||||||
|
Point p1 = stroke.StylusPoints[i-1].ToPoint();
|
||||||
|
Point p2 = stroke.StylusPoints[i].ToPoint();
|
||||||
|
strokeLength += GetDistance(p1, p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果笔画太短,直接使用所有点
|
||||||
|
if (strokeLength < sampleInterval * 5) {
|
||||||
|
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||||
|
Point p = sp.ToPoint();
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||||
|
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 使用等距采样点
|
||||||
|
double currentLength = 0;
|
||||||
|
double nextSampleAt = 0;
|
||||||
|
Point lastPoint = start;
|
||||||
|
|
||||||
|
// 起点方差
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, lastPoint);
|
||||||
|
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||||
|
|
||||||
|
// 采样中间点
|
||||||
|
for (int i = 1; i < stroke.StylusPoints.Count; i++) {
|
||||||
|
Point currentPoint = stroke.StylusPoints[i].ToPoint();
|
||||||
|
double segmentLength = GetDistance(lastPoint, currentPoint);
|
||||||
|
|
||||||
|
// 如果这段线段跨越了下一个采样点
|
||||||
|
while (currentLength + segmentLength >= nextSampleAt) {
|
||||||
|
// 计算采样点在线段上的位置
|
||||||
|
double t = (nextSampleAt - currentLength) / segmentLength;
|
||||||
|
Point samplePoint = new Point(
|
||||||
|
lastPoint.X + t * (currentPoint.X - lastPoint.X),
|
||||||
|
lastPoint.Y + t * (currentPoint.Y - lastPoint.Y)
|
||||||
|
);
|
||||||
|
|
||||||
|
// 计算采样点的方差
|
||||||
|
deviation = DistanceFromLineToPoint(start, end, samplePoint);
|
||||||
|
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||||
|
|
||||||
|
// 设置下一个采样点位置
|
||||||
|
nextSampleAt += sampleInterval;
|
||||||
|
|
||||||
|
// 防止无限循环
|
||||||
|
if (nextSampleAt > strokeLength) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentLength += segmentLength;
|
||||||
|
lastPoint = currentPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 终点方差
|
||||||
|
deviation = DistanceFromLineToPoint(start, end, end);
|
||||||
|
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 原始模式:使用所有点计算方差
|
||||||
|
foreach (StylusPoint sp in stroke.StylusPoints) {
|
||||||
|
Point p = sp.ToPoint();
|
||||||
|
double deviation = DistanceFromLineToPoint(start, end, p);
|
||||||
|
deviationVariance += Math.Pow(deviation - avgDeviation, 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deviationVariance /= pointCount;
|
deviationVariance /= pointCount;
|
||||||
|
|
||||||
// 输出更多调试信息
|
// 输出更多调试信息
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ namespace Ink_Canvas
|
|||||||
public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直
|
public bool AutoStraightenLine { get; set; } = true; // 是否启用直线自动拉直
|
||||||
[JsonProperty("autoStraightenLineThreshold")]
|
[JsonProperty("autoStraightenLineThreshold")]
|
||||||
public int AutoStraightenLineThreshold { get; set; } = 30; // 直线自动拉直的长度阈值(像素)
|
public int AutoStraightenLineThreshold { get; set; } = 30; // 直线自动拉直的长度阈值(像素)
|
||||||
|
[JsonProperty("highPrecisionLineStraighten")]
|
||||||
|
public bool HighPrecisionLineStraighten { get; set; } = true; // 是否启用高精度直线拉直
|
||||||
[JsonProperty("lineEndpointSnapping")]
|
[JsonProperty("lineEndpointSnapping")]
|
||||||
public bool LineEndpointSnapping { get; set; } = true; // 是否启用直线端点吸附
|
public bool LineEndpointSnapping { get; set; } = true; // 是否启用直线端点吸附
|
||||||
[JsonProperty("lineEndpointSnappingThreshold")]
|
[JsonProperty("lineEndpointSnappingThreshold")]
|
||||||
|
|||||||
Reference in New Issue
Block a user