diff --git a/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs b/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs index d4e9b53..e6a3d9f 100644 --- a/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs +++ b/XP.ImageProcessing.RoiControl/Controls/PolygonRoiCanvas.xaml.cs @@ -578,11 +578,87 @@ namespace XP.ImageProcessing.RoiControl.Controls var g = new Models.MeasureGroup { P1 = p1, P2 = p2 }; g.Line = new Line { Stroke = Brushes.Lime, StrokeThickness = 1, IsHitTestVisible = false }; g.Label = new TextBlock { Foreground = Brushes.Yellow, FontSize = 13, FontWeight = FontWeights.Bold, IsHitTestVisible = false }; + + // 使用垂直线段代替圆点 + g.PerpLine1 = new Line { Stroke = Brushes.Yellow, StrokeThickness = 1, IsHitTestVisible = true, Cursor = Cursors.Hand }; + g.PerpLine2 = new Line { Stroke = Brushes.Yellow, StrokeThickness = 1, IsHitTestVisible = true, Cursor = Cursors.Hand }; + + // 保留圆点以兼容拖拽逻辑(但设为不可见) g.Dot1 = CreateMDot(Brushes.Red); g.Dot2 = CreateMDot(Brushes.Blue); - foreach (UIElement el in new UIElement[] { g.Line, g.Label, g.Dot1, g.Dot2 }) + g.Dot1.Visibility = Visibility.Collapsed; + g.Dot2.Visibility = Visibility.Collapsed; + + foreach (UIElement el in new UIElement[] { g.Line, g.Label, g.PerpLine1, g.PerpLine2, g.Dot1, g.Dot2 }) _measureOverlay.Children.Add(el); + + // 设置圆点位置(用于拖拽计算) SetDotPos(g.Dot1, p1); SetDotPos(g.Dot2, p2); + + // 垂直线段1的拖拽处理 - 直接设置拖拽状态 + g.PerpLine1.MouseLeftButtonDown += (s, e) => + { + _mDraggingOwner = g; + _mDraggingRole = "Dot1"; + _mDraggingDot = g.Dot1; + g.PerpLine1.CaptureMouse(); + e.Handled = true; + }; + g.PerpLine1.MouseMove += (s, e) => + { + if (_mDraggingOwner != g || _mDraggingRole != "Dot1" || _measureOverlay == null) return; + if (e.LeftButton != MouseButtonState.Pressed) return; + var pos = e.GetPosition(_measureOverlay); + SetDotPos(g.Dot1, pos); + g.P1 = pos; + g.UpdateLine(); + g.UpdateLabel(FormatDistance(g.Distance)); + RaiseMeasureCompleted(g.P1, g.P2, g.Distance, MeasureCount, "PointDistance"); + }; + g.PerpLine1.MouseLeftButtonUp += (s, e) => + { + if (_mDraggingOwner == g && _mDraggingRole == "Dot1") + { + _mDraggingOwner = null; + _mDraggingRole = null; + _mDraggingDot = null; + g.PerpLine1.ReleaseMouseCapture(); + } + e.Handled = true; + }; + + // 垂直线段2的拖拽处理 + g.PerpLine2.MouseLeftButtonDown += (s, e) => + { + _mDraggingOwner = g; + _mDraggingRole = "Dot2"; + _mDraggingDot = g.Dot2; + g.PerpLine2.CaptureMouse(); + e.Handled = true; + }; + g.PerpLine2.MouseMove += (s, e) => + { + if (_mDraggingOwner != g || _mDraggingRole != "Dot2" || _measureOverlay == null) return; + if (e.LeftButton != MouseButtonState.Pressed) return; + var pos = e.GetPosition(_measureOverlay); + SetDotPos(g.Dot2, pos); + g.P2 = pos; + g.UpdateLine(); + g.UpdateLabel(FormatDistance(g.Distance)); + RaiseMeasureCompleted(g.P1, g.P2, g.Distance, MeasureCount, "PointDistance"); + }; + g.PerpLine2.MouseLeftButtonUp += (s, e) => + { + if (_mDraggingOwner == g && _mDraggingRole == "Dot2") + { + _mDraggingOwner = null; + _mDraggingRole = null; + _mDraggingDot = null; + g.PerpLine2.ReleaseMouseCapture(); + } + e.Handled = true; + }; + g.UpdateLine(); g.UpdateLabel(FormatDistance(g.Distance)); return g; } diff --git a/XP.ImageProcessing.RoiControl/Models/MeasureGroup.cs b/XP.ImageProcessing.RoiControl/Models/MeasureGroup.cs index 32ba2aa..0c93043 100644 --- a/XP.ImageProcessing.RoiControl/Models/MeasureGroup.cs +++ b/XP.ImageProcessing.RoiControl/Models/MeasureGroup.cs @@ -9,12 +9,21 @@ namespace XP.ImageProcessing.RoiControl.Models /// 一次点点距测量的所有视觉元素 public class MeasureGroup { + // 保留原有圆点属性以兼容其他代码 public Ellipse Dot1 { get; set; } public Ellipse Dot2 { get; set; } + + // 新增:垂直线段(替代圆点的视觉表现) + public Line PerpLine1 { get; set; } + public Line PerpLine2 { get; set; } + public Line Line { get; set; } public TextBlock Label { get; set; } public Point P1 { get; set; } public Point P2 { get; set; } + + /// 垂直线段长度(像素) + public double PerpLineLength { get; set; } = 10.0; public double Distance { @@ -30,6 +39,46 @@ namespace XP.ImageProcessing.RoiControl.Models Line.X1 = P1.X; Line.Y1 = P1.Y; Line.X2 = P2.X; Line.Y2 = P2.Y; Line.Visibility = Visibility.Visible; + + // 更新垂直线段位置 + UpdatePerpLines(); + } + + /// 更新两条垂直线段的位置 + public void UpdatePerpLines() + { + if (PerpLine1 == null || PerpLine2 == null) return; + + // 计算两点连线的方向向量 + double dx = P2.X - P1.X; + double dy = P2.Y - P1.Y; + double len = Math.Sqrt(dx * dx + dy * dy); + + if (len < 0.001) return; // 避免除零 + + // 归一化方向向量 + double ux = dx / len; + double uy = dy / len; + + // 垂直方向向量 (-uy, ux) + double vx = -uy; + double vy = ux; + + // P1处的垂直线段 + double halfLen1 = PerpLineLength / 2; + PerpLine1.X1 = P1.X + vx * halfLen1; + PerpLine1.Y1 = P1.Y + vy * halfLen1; + PerpLine1.X2 = P1.X - vx * halfLen1; + PerpLine1.Y2 = P1.Y - vy * halfLen1; + PerpLine1.Visibility = Visibility.Visible; + + // P2处的垂直线段 + double halfLen2 = PerpLineLength / 2; + PerpLine2.X1 = P2.X + vx * halfLen2; + PerpLine2.Y1 = P2.Y + vy * halfLen2; + PerpLine2.X2 = P2.X - vx * halfLen2; + PerpLine2.Y2 = P2.Y - vy * halfLen2; + PerpLine2.Visibility = Visibility.Visible; } public void UpdateLabel(string distanceText = null)