From fdfbaedbd731f622a11b9c8f94246f921b43cd48 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Sun, 10 Aug 2025 11:58:58 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E5=87=A0=E4=BD=95=E8=A7=A6=E6=91=B8?= =?UTF-8?q?=E7=BB=98=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/.idea.Ink Canvas/.idea/vcs.xml | 1 + Ink Canvas/AssemblyInfo.cs | 4 +- .../MainWindow_cs/MW_FloatingBarIcons.cs | 8 +- Ink Canvas/MainWindow_cs/MW_Screenshot.cs | 123 ++++++++++++++---- Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs | 23 +++- Ink Canvas/MainWindow_cs/MW_TouchEvents.cs | 98 ++++++++++---- Ink Canvas/Properties/AssemblyInfo.cs | 4 +- .../Windows/ScreenshotSelectorWindow.xaml.cs | 70 +++++++++- 8 files changed, 261 insertions(+), 70 deletions(-) diff --git a/.idea/.idea.Ink Canvas/.idea/vcs.xml b/.idea/.idea.Ink Canvas/.idea/vcs.xml index 35eb1ddf..e7cf2141 100644 --- a/.idea/.idea.Ink Canvas/.idea/vcs.xml +++ b/.idea/.idea.Ink Canvas/.idea/vcs.xml @@ -2,5 +2,6 @@ + \ No newline at end of file diff --git a/Ink Canvas/AssemblyInfo.cs b/Ink Canvas/AssemblyInfo.cs index 2fcd67b5..79bbc863 100644 --- a/Ink Canvas/AssemblyInfo.cs +++ b/Ink Canvas/AssemblyInfo.cs @@ -49,5 +49,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.76.0")] -[assembly: AssemblyFileVersion("1.7.6.0")] +[assembly: AssemblyVersion("1.7.6.1")] +[assembly: AssemblyFileVersion("1.7.6.1")] diff --git a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs index 63e48bf8..45d9f6ac 100644 --- a/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs +++ b/Ink Canvas/MainWindow_cs/MW_FloatingBarIcons.cs @@ -1502,6 +1502,12 @@ namespace Ink_Canvas bool wasInInkMode = inkCanvas.EditingMode == InkCanvasEditingMode.Ink; bool wasHighlighter = drawingAttributes.IsHighlighter; + // 禁止几何绘制模式下切换到Ink + if (drawingShapeMode != 0) + { + return; + } + if (Pen_Icon.Background == null || StackPanelCanvasControls.Visibility == Visibility.Collapsed) { inkCanvas.EditingMode = InkCanvasEditingMode.Ink; @@ -1756,7 +1762,7 @@ namespace Ink_Canvas CursorIcon_Click(null, null); } - private void SelectIcon_MouseUp(object sender, RoutedEvent e) + private void SelectIcon_MouseUp(object sender, RoutedEventArgs e) { // 禁用高级橡皮擦系统 DisableAdvancedEraserSystem(); diff --git a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs index 495c1aad..38b40348 100644 --- a/Ink Canvas/MainWindow_cs/MW_Screenshot.cs +++ b/Ink Canvas/MainWindow_cs/MW_Screenshot.cs @@ -62,6 +62,12 @@ namespace Ink_Canvas using (var bitmap = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb)) using (var memoryGraphics = Graphics.FromImage(bitmap)) { + // 设置高质量渲染 + memoryGraphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; + memoryGraphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; + memoryGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + memoryGraphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; + memoryGraphics.CopyFromScreen(rc.X, rc.Y, 0, 0, rc.Size, CopyPixelOperation.SourceCopy); // 确保目录存在 @@ -71,6 +77,7 @@ namespace Ink_Canvas Directory.CreateDirectory(directory); } + // 使用PNG格式保存,确保透明度信息不丢失 bitmap.Save(savePath, ImageFormat.Png); } @@ -140,19 +147,32 @@ namespace Ink_Canvas if (originalBitmap != null) { Bitmap finalBitmap = originalBitmap; + bool needDisposeFinalBitmap = false; - // 如果有路径信息,应用形状遮罩 - if (screenshotResult.Value.Path != null && screenshotResult.Value.Path.Count > 0) + try { - finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Value.Path, screenshotResult.Value.Area); + // 如果有路径信息,应用形状遮罩 + if (screenshotResult.Value.Path != null && screenshotResult.Value.Path.Count > 0) + { + finalBitmap = ApplyShapeMask(originalBitmap, screenshotResult.Value.Path, screenshotResult.Value.Area); + needDisposeFinalBitmap = true; // 标记需要释放新创建的位图 + } + + // 将截图复制到剪贴板 + CopyBitmapToClipboard(finalBitmap); + + // 等待窗口完全显示后自动粘贴 + await Task.Delay(100); + await AutoPasteScreenshot(); + } + finally + { + // 如果创建了新的位图,需要释放它 + if (needDisposeFinalBitmap && finalBitmap != originalBitmap) + { + finalBitmap.Dispose(); + } } - - // 将截图复制到剪贴板 - CopyBitmapToClipboard(finalBitmap); - - // 等待窗口完全显示后自动粘贴 - await Task.Delay(100); - await AutoPasteScreenshot(); } } } @@ -212,6 +232,7 @@ namespace Ink_Canvas int width = Math.Max(1, right - x); int height = Math.Max(1, bottom - y); + // 创建支持透明度的位图 var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); using (var graphics = Graphics.FromImage(bitmap)) { @@ -219,6 +240,7 @@ namespace Ink_Canvas graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; + graphics.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver; // 截取屏幕区域 graphics.CopyFromScreen(x, y, 0, 0, new Size(width, height), CopyPixelOperation.SourceCopy); @@ -279,17 +301,30 @@ namespace Ink_Canvas { try { + // 验证路径参数 + if (path == null || path.Count < 3) + { + LogHelper.WriteLogToFile("路径点数不足,无法应用形状遮罩", LogHelper.LogType.Warning); + return bitmap; + } + // 获取DPI缩放比例 var dpiScale = GetDpiScale(); var virtualScreen = SystemInformation.VirtualScreen; - // 创建结果位图 + // 创建结果位图,确保支持透明度 var resultBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); + + // 首先将整个位图设置为透明 using (var resultGraphics = Graphics.FromImage(resultBitmap)) { + // 清除位图,设置为完全透明 + resultGraphics.Clear(System.Drawing.Color.Transparent); + // 设置高质量渲染 resultGraphics.SmoothingMode = SmoothingMode.AntiAlias; resultGraphics.CompositingQuality = CompositingQuality.HighQuality; + resultGraphics.CompositingMode = CompositingMode.SourceOver; // 创建路径 using (var pathGraphics = new GraphicsPath()) @@ -306,26 +341,51 @@ namespace Ink_Canvas float relativeX = (float)(screenX - area.X); float relativeY = (float)(screenY - area.Y); + // 确保坐标在有效范围内 + relativeX = Math.Max(0, Math.Min(relativeX, bitmap.Width - 1)); + relativeY = Math.Max(0, Math.Min(relativeY, bitmap.Height - 1)); + points[i] = new PointF(relativeX, relativeY); } - // 添加路径 + // 添加路径 - 使用FillMode.Winding确保路径正确填充 + pathGraphics.FillMode = FillMode.Winding; pathGraphics.AddPolygon(points); - // 设置裁剪区域为路径内部 - resultGraphics.SetClip(pathGraphics); + // 验证路径是否有效 + if (!pathGraphics.IsVisible(0, 0) && pathGraphics.GetBounds().Width > 0 && pathGraphics.GetBounds().Height > 0) + { + // 设置裁剪区域为路径内部 + resultGraphics.SetClip(pathGraphics); - // 在裁剪区域内绘制原始图像 - resultGraphics.DrawImage(bitmap, 0, 0); + // 在裁剪区域内绘制原始图像 + resultGraphics.DrawImage(bitmap, 0, 0); + + // 重置裁剪区域,确保后续操作不受影响 + resultGraphics.ResetClip(); + } + else + { + LogHelper.WriteLogToFile("生成的路径无效,返回原始图像", LogHelper.LogType.Warning); + // 如果路径无效,返回透明图像 + return resultBitmap; + } } } + LogHelper.WriteLogToFile($"成功应用形状遮罩,路径点数: {path.Count}", LogHelper.LogType.Info); return resultBitmap; } catch (Exception ex) { LogHelper.WriteLogToFile($"应用形状遮罩失败: {ex.Message}", LogHelper.LogType.Error); - return bitmap; // 如果失败,返回原始图像 + // 返回完全透明的图像而不是原始图像 + var transparentBitmap = new Bitmap(bitmap.Width, bitmap.Height, PixelFormat.Format32bppArgb); + using (var g = Graphics.FromImage(transparentBitmap)) + { + g.Clear(System.Drawing.Color.Transparent); + } + return transparentBitmap; } } @@ -343,19 +403,28 @@ namespace Ink_Canvas // 将System.Drawing.Bitmap转换为WPF BitmapSource private BitmapSource ConvertBitmapToBitmapSource(Bitmap bitmap) { - using (var memory = new MemoryStream()) + try { - bitmap.Save(memory, ImageFormat.Png); - memory.Position = 0; + using (var memory = new MemoryStream()) + { + // 使用PNG格式保存,确保透明度信息不丢失 + bitmap.Save(memory, ImageFormat.Png); + memory.Position = 0; - var bitmapImage = new BitmapImage(); - bitmapImage.BeginInit(); - bitmapImage.StreamSource = memory; - bitmapImage.CacheOption = BitmapCacheOption.OnLoad; - bitmapImage.EndInit(); - bitmapImage.Freeze(); + var bitmapImage = new BitmapImage(); + bitmapImage.BeginInit(); + bitmapImage.StreamSource = memory; + bitmapImage.CacheOption = BitmapCacheOption.OnLoad; + bitmapImage.EndInit(); + bitmapImage.Freeze(); - return bitmapImage; + return bitmapImage; + } + } + catch (Exception ex) + { + LogHelper.WriteLogToFile($"转换位图失败: {ex.Message}", LogHelper.LogType.Error); + throw; } } } diff --git a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs index fd2dbfb2..fcc8edf8 100644 --- a/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs +++ b/Ink Canvas/MainWindow_cs/MW_ShapeDrawing.cs @@ -132,6 +132,11 @@ namespace Ink_Canvas penType = 0; drawingAttributes.IsHighlighter = false; drawingAttributes.StylusTip = StylusTip.Ellipse; + // 禁止几何绘制模式下切换到Ink + if (drawingShapeMode != 0) + { + return; + } inkCanvas.EditingMode = InkCanvasEditingMode.Ink; // 修复:确保从橡皮擦切换到笔时,多指手势功能能正确恢复 @@ -158,9 +163,15 @@ namespace Ink_Canvas lastIsInMultiTouchMode = true; } + // 修复:几何绘制模式下确保不切换到Ink模式,避免触摸轨迹被收集 + if (drawingShapeMode != 0) + { + inkCanvas.EditingMode = InkCanvasEditingMode.None; + } + return Task.FromResult(true); } - + private async void BtnDrawLine_Click(object sender, MouseButtonEventArgs e) { await CheckIsDrawingShapesInMultiTouchMode(); @@ -432,9 +443,12 @@ namespace Ink_Canvas SetCursorBasedOnEditingMode(inkCanvas); } - // 处理几何绘制模式 + // 修复:几何绘制模式下完全禁止触摸轨迹收集 if (drawingShapeMode != 0) { + // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 + inkCanvas.EditingMode = InkCanvasEditingMode.None; + if (isWaitUntilNextTouchDown && dec.Count > 1) return; if (dec.Count > 1) { @@ -1403,7 +1417,7 @@ namespace Ink_Canvas return pointList; } - + private StrokeCollection GenerateDashedLineEllipseStrokeCollection(Point st, Point ed, bool isDrawTop = true, bool isDrawBottom = true) { @@ -1833,8 +1847,7 @@ namespace Ink_Canvas } } } - - // 在MainWindow类中添加: + private void EnterShapeDrawingMode(int mode) { forceEraser = true; diff --git a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs index 48877180..787dc8c2 100644 --- a/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs +++ b/Ink Canvas/MainWindow_cs/MW_TouchEvents.cs @@ -116,6 +116,14 @@ namespace Ink_Canvas HideSubPanels(); // 书写时自动隐藏二级菜单 } + // 修复:几何绘制模式下完全禁止触摸轨迹收集 + if (drawingShapeMode != 0) + { + // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 + inkCanvas.EditingMode = InkCanvasEditingMode.None; + return; + } + // 只保留普通橡皮逻辑 TouchDownPointsList[e.TouchDevice.Id] = InkCanvasEditingMode.None; inkCanvas.EraserShape = new EllipseStylusShape(50, 50); @@ -127,6 +135,22 @@ namespace Ink_Canvas private void MainWindow_StylusDown(object sender, StylusDownEventArgs e) { + // 新增:根据是否为笔尾自动切换橡皮擦/画笔模式 + if (e.StylusDevice.Inverted) + { + inkCanvas.EditingMode = InkCanvasEditingMode.EraseByPoint; + } + else + { + // 修复:几何绘制模式下完全禁止触摸轨迹收集 + if (drawingShapeMode != 0) + { + // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 + inkCanvas.EditingMode = InkCanvasEditingMode.None; + return; + } + inkCanvas.EditingMode = InkCanvasEditingMode.Ink; + } SetCursorBasedOnEditingMode(inkCanvas); inkCanvas.CaptureStylus(); @@ -285,17 +309,11 @@ namespace Ink_Canvas // 套索选状态下只return,保证套索选可用 return; } - if (drawingShapeMode == 9) - { - if (isFirstTouchCuboid) - { - CuboidFrontRectIniP = e.GetTouchPoint(inkCanvas).Position; - } - // 允许MouseTouchMove在TouchMove时处理 - return; - } + // 修复:几何绘制模式下完全禁止触摸轨迹收集 if (drawingShapeMode != 0) { + // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 + inkCanvas.EditingMode = InkCanvasEditingMode.None; return; } if (inkCanvas.EditingMode == InkCanvasEditingMode.Ink) @@ -321,10 +339,26 @@ namespace Ink_Canvas { return; } - // 修复:几何绘制模式下禁止自动收集墨迹 + // 修复:几何绘制模式下完全禁止触摸轨迹收集 if (drawingShapeMode != 0) { + // 确保几何绘制模式下不切换到Ink模式,避免触摸轨迹被收集 inkCanvas.EditingMode = InkCanvasEditingMode.None; + // 几何绘制模式下不记录触摸点,避免触摸轨迹被收集 + SetCursorBasedOnEditingMode(inkCanvas); + inkCanvas.CaptureTouch(e.TouchDevice); + ViewboxFloatingBar.IsHitTestVisible = false; + BlackboardUIGridForInkReplay.IsHitTestVisible = false; + + // 只记录几何绘制的起点,不记录触摸轨迹 + if (dec.Count == 0) + { + var touchPoint = e.GetTouchPoint(inkCanvas); + iniP = touchPoint.Position; + lastTouchDownStrokeCollection = inkCanvas.Strokes.Clone(); + } + dec.Add(e.TouchDevice.Id); + return; } SetCursorBasedOnEditingMode(inkCanvas); @@ -354,7 +388,7 @@ namespace Ink_Canvas var touchPoint = e.GetTouchPoint(inkCanvas); centerPoint = touchPoint.Position; - // 新增:几何绘制模式下,记录初始点 + // 只允许在此处赋值iniP,防止TouchMove等其他地方覆盖,保证几何绘制起点一致 if (drawingShapeMode != 0) { iniP = touchPoint.Position; @@ -370,7 +404,8 @@ namespace Ink_Canvas if (inkCanvas.EditingMode == InkCanvasEditingMode.None || inkCanvas.EditingMode == InkCanvasEditingMode.Select) return; lastInkCanvasEditingMode = inkCanvas.EditingMode; - if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) + // 修复:几何绘制模式下禁止切回Ink + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && drawingShapeMode == 0) { inkCanvas.EditingMode = InkCanvasEditingMode.None; } @@ -425,27 +460,31 @@ namespace Ink_Canvas //手势完成后切回之前的状态 // 修复:改进多指手势恢复逻辑,确保从橡皮擦切换到笔时多指手势能正确恢复 - if (dec.Count > 1) + // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 + if (drawingShapeMode == 0) { - if (inkCanvas.EditingMode == InkCanvasEditingMode.None) + if (dec.Count > 1) { - if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) + if (inkCanvas.EditingMode == InkCanvasEditingMode.None) + { + if (lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) + { + inkCanvas.EditingMode = lastInkCanvasEditingMode; + } + } + } + else if (dec.Count == 0) + { + // 当所有触摸点都抬起时,确保正确恢复编辑模式 + // 这对于从橡皮擦切换到笔后恢复多指手势功能很重要 + if (inkCanvas.EditingMode == InkCanvasEditingMode.None && + lastInkCanvasEditingMode != InkCanvasEditingMode.None && + lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) { inkCanvas.EditingMode = lastInkCanvasEditingMode; } } } - else if (dec.Count == 0) - { - // 当所有触摸点都抬起时,确保正确恢复编辑模式 - // 这对于从橡皮擦切换到笔后恢复多指手势功能很重要 - if (inkCanvas.EditingMode == InkCanvasEditingMode.None && - lastInkCanvasEditingMode != InkCanvasEditingMode.None && - lastInkCanvasEditingMode != InkCanvasEditingMode.EraseByPoint) - { - inkCanvas.EditingMode = lastInkCanvasEditingMode; - } - } inkCanvas.Opacity = 1; if (dec.Count == 0) @@ -468,6 +507,7 @@ namespace Ink_Canvas private void Main_Grid_ManipulationCompleted(object sender, ManipulationCompletedEventArgs e) { if (e.Manipulators.Count() != 0) return; + // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 if (drawingShapeMode == 0 && inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) { inkCanvas.EditingMode = InkCanvasEditingMode.Ink; @@ -590,7 +630,8 @@ namespace Ink_Canvas inkCanvas.StylusUp -= MainWindow_StylusUp; inkCanvas.TouchDown -= MainWindow_TouchDown; inkCanvas.TouchDown += Main_Grid_TouchDown; - if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) + // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && drawingShapeMode == 0) { inkCanvas.EditingMode = InkCanvasEditingMode.Ink; } @@ -620,7 +661,8 @@ namespace Ink_Canvas inkCanvas.StylusUp += MainWindow_StylusUp; inkCanvas.TouchDown += MainWindow_TouchDown; inkCanvas.TouchDown -= Main_Grid_TouchDown; - if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint) + // 修复:几何绘制模式下不自动切换到Ink模式,避免触摸轨迹被收集 + if (inkCanvas.EditingMode != InkCanvasEditingMode.EraseByPoint && drawingShapeMode == 0) { inkCanvas.EditingMode = InkCanvasEditingMode.None; } diff --git a/Ink Canvas/Properties/AssemblyInfo.cs b/Ink Canvas/Properties/AssemblyInfo.cs index 9c2ed554..25d0bddb 100644 --- a/Ink Canvas/Properties/AssemblyInfo.cs +++ b/Ink Canvas/Properties/AssemblyInfo.cs @@ -49,5 +49,5 @@ using System.Windows; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.7.6.0")] -[assembly: AssemblyFileVersion("1.7.6.0")] +[assembly: AssemblyVersion("1.7.6.1")] +[assembly: AssemblyFileVersion("1.7.6.1")] diff --git a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs index f8ed207f..ee5aa49e 100644 --- a/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs +++ b/Ink Canvas/Windows/ScreenshotSelectorWindow.xaml.cs @@ -185,15 +185,25 @@ namespace Ink_Canvas // 自由绘制模式:完成路径 if (_freehandPoints.Count > 3) // 至少需要3个点形成有效路径 { - // 闭合路径 - _freehandPoints.Add(_startPoint); - _freehandPolyline.Points.Add(_startPoint); + // 创建路径的副本,避免修改原始列表 + var pathPoints = new List(_freehandPoints); + + // 确保路径闭合(如果最后一个点不是起始点,则添加起始点) + if (pathPoints.Count > 0 && + (Math.Abs(pathPoints[pathPoints.Count - 1].X - _startPoint.X) > 1 || + Math.Abs(pathPoints[pathPoints.Count - 1].Y - _startPoint.Y) > 1)) + { + pathPoints.Add(_startPoint); + } + // 优化路径:移除重复点和过于接近的点,提高路径质量 + var optimizedPath = OptimizePath(pathPoints); + // 保存选择的路径 - SelectedPath = new List(_freehandPoints); + SelectedPath = optimizedPath; // 计算边界矩形用于截图 - var bounds = CalculatePathBounds(_freehandPoints); + var bounds = CalculatePathBounds(optimizedPath); var dpiScale = GetDpiScale(); var virtualScreen = System.Windows.Forms.SystemInformation.VirtualScreen; @@ -294,5 +304,55 @@ namespace Ink_Canvas return new Rect(minX, minY, maxX - minX, maxY - minY); } + + // 优化路径:移除重复点和过于接近的点,提高路径质量 + private List OptimizePath(List originalPath) + { + if (originalPath == null || originalPath.Count < 3) + return originalPath; + + var optimizedPath = new List(); + const double minDistance = 2.0; // 最小距离阈值 + + // 添加第一个点 + optimizedPath.Add(originalPath[0]); + + for (int i = 1; i < originalPath.Count - 1; i++) + { + var currentPoint = originalPath[i]; + var optimizedPoint = optimizedPath[optimizedPath.Count - 1]; + + // 计算与上一个优化点的距离 + double distance = Math.Sqrt( + Math.Pow(currentPoint.X - optimizedPoint.X, 2) + + Math.Pow(currentPoint.Y - optimizedPoint.Y, 2)); + + // 如果距离足够大,则添加这个点 + if (distance >= minDistance) + { + optimizedPath.Add(currentPoint); + } + } + + // 添加最后一个点(如果与上一个点距离足够) + var lastPoint = originalPath[originalPath.Count - 1]; + var lastOptimizedPoint = optimizedPath[optimizedPath.Count - 1]; + double finalDistance = Math.Sqrt( + Math.Pow(lastPoint.X - lastOptimizedPoint.X, 2) + + Math.Pow(lastPoint.Y - lastOptimizedPoint.Y, 2)); + + if (finalDistance >= minDistance) + { + optimizedPath.Add(lastPoint); + } + + // 确保路径至少有3个点 + if (optimizedPath.Count < 3) + { + return originalPath; + } + + return optimizedPath; + } } }