using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Shapes; namespace XP.ImageProcessing.RoiControl.Models { /// 一次点线距测量的所有视觉元素(直线两端点 + 测量点 + 垂线 + 标签) public class PointToLineGroup { public Ellipse DotL1 { get; set; } // 直线端点1 public Ellipse DotL2 { get; set; } // 直线端点2 public Ellipse DotP { get; set; } // 测量点 public Line MainLine { get; set; } // 原始线段(实线) public Line ExtLine { get; set; } // 延长线(虚线) public Line PerpLine { get; set; } // 垂线(测量点→垂足) public Ellipse FootDot { get; set; } // 垂足 public TextBlock Label { get; set; } public Point L1 { get; set; } public Point L2 { get; set; } public Point P { get; set; } public double Distance { get { double abx = L2.X - L1.X, aby = L2.Y - L1.Y; double abLen = Math.Sqrt(abx * abx + aby * aby); if (abLen < 0.001) return 0; return Math.Abs(abx * (L1.Y - P.Y) - aby * (L1.X - P.X)) / abLen; } } public Point FootPoint { get { double abx = L2.X - L1.X, aby = L2.Y - L1.Y; double abLen2 = abx * abx + aby * aby; if (abLen2 < 0.001) return L1; double t = ((P.X - L1.X) * abx + (P.Y - L1.Y) * aby) / abLen2; return new Point(L1.X + t * abx, L1.Y + t * aby); } } public void UpdateVisuals(string distanceText) { double abx = L2.X - L1.X, aby = L2.Y - L1.Y; double abLen2 = abx * abx + aby * aby; double t = abLen2 < 0.001 ? 0 : ((P.X - L1.X) * abx + (P.Y - L1.Y) * aby) / abLen2; var foot = FootPoint; // 主直线:始终画原始线段 MainLine.X1 = L1.X; MainLine.Y1 = L1.Y; MainLine.X2 = L2.X; MainLine.Y2 = L2.Y; MainLine.Visibility = Visibility.Visible; // 延长线:垂足在线段外时画虚线延伸 if (t < 0) { ExtLine.X1 = foot.X; ExtLine.Y1 = foot.Y; ExtLine.X2 = L1.X; ExtLine.Y2 = L1.Y; ExtLine.Visibility = Visibility.Visible; } else if (t > 1) { ExtLine.X1 = L2.X; ExtLine.Y1 = L2.Y; ExtLine.X2 = foot.X; ExtLine.Y2 = foot.Y; ExtLine.Visibility = Visibility.Visible; } else { ExtLine.Visibility = Visibility.Collapsed; } // 垂线 PerpLine.X1 = P.X; PerpLine.Y1 = P.Y; PerpLine.X2 = foot.X; PerpLine.Y2 = foot.Y; PerpLine.Visibility = Visibility.Visible; // 垂足 Canvas.SetLeft(FootDot, foot.X - FootDot.Width / 2); Canvas.SetTop(FootDot, foot.Y - FootDot.Height / 2); FootDot.Visibility = Visibility.Visible; // 标签 Label.Text = distanceText ?? $"{Distance:F2} px"; Canvas.SetLeft(Label, (P.X + foot.X) / 2 + 8); Canvas.SetTop(Label, (P.Y + foot.Y) / 2 - 18); Label.Visibility = Visibility.Visible; } public void UpdateVisuals() => UpdateVisuals(null); } }