97 lines
3.5 KiB
C#
97 lines
3.5 KiB
C#
using System;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace XP.ImageProcessing.RoiControl.Models
|
|
{
|
|
/// <summary>一次点线距测量的所有视觉元素(直线两端点 + 测量点 + 垂线 + 标签)</summary>
|
|
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);
|
|
}
|
|
}
|