149 lines
5.7 KiB
C#
149 lines
5.7 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>通孔填锡率测量组(4个椭圆中心 + 连线 + 标签)</summary>
|
|
public class FillRateGroup
|
|
{
|
|
// 四个椭圆中心的可拖拽圆点
|
|
public Ellipse DotE1 { get; set; } // 底部(蓝)
|
|
public Ellipse DotE2 { get; set; } // 顶部(青)
|
|
public Ellipse DotE3 { get; set; } // 填锡起点(黄)
|
|
public Ellipse DotE4 { get; set; } // 填锡终点(绿)
|
|
|
|
// 长轴/短轴手柄(每个椭圆2个)
|
|
public Ellipse E1AH { get; set; }
|
|
public Ellipse E1BH { get; set; }
|
|
public Ellipse E2AH { get; set; }
|
|
public Ellipse E2BH { get; set; }
|
|
public Ellipse E3AH { get; set; }
|
|
public Ellipse E3BH { get; set; }
|
|
public Ellipse E4AH { get; set; }
|
|
public Ellipse E4BH { get; set; }
|
|
|
|
// 椭圆路径
|
|
public Path PathE1 { get; set; }
|
|
public Path PathE2 { get; set; }
|
|
public Path PathE3 { get; set; }
|
|
public Path PathE4 { get; set; }
|
|
|
|
// 连线:E1→E2(全高度),E3→E4(填锡高度)
|
|
public Line FullLine { get; set; }
|
|
public Line FillLine { get; set; }
|
|
|
|
public TextBlock Label { get; set; }
|
|
|
|
// 四个椭圆中心坐标
|
|
public Point E1 { get; set; }
|
|
public Point E2 { get; set; }
|
|
public Point E3 { get; set; }
|
|
public Point E4 { get; set; }
|
|
|
|
// 椭圆轴参数(默认值,后续可拖拽调整)
|
|
public double E1A { get; set; } = 60;
|
|
public double E1B { get; set; } = 50;
|
|
public double E1Angle { get; set; }
|
|
public double E2A { get; set; } = 60;
|
|
public double E2B { get; set; } = 50;
|
|
public double E2Angle { get; set; }
|
|
public double E3A { get; set; } = 60;
|
|
public double E3B { get; set; } = 50;
|
|
public double E3Angle { get; set; }
|
|
public double E4A { get; set; } = 55;
|
|
public double E4B { get; set; } = 45;
|
|
public double E4Angle { get; set; }
|
|
|
|
public double THTLimit { get; set; } = 75.0;
|
|
|
|
public double FillRate
|
|
{
|
|
get
|
|
{
|
|
double fullDx = E2.X - E1.X, fullDy = E2.Y - E1.Y;
|
|
double fullDist = Math.Sqrt(fullDx * fullDx + fullDy * fullDy);
|
|
double fillDx = E4.X - E3.X, fillDy = E4.Y - E3.Y;
|
|
double fillDist = Math.Sqrt(fillDx * fillDx + fillDy * fillDy);
|
|
return fullDist > 0 ? Math.Clamp(fillDist / fullDist * 100.0, 0, 100) : 0;
|
|
}
|
|
}
|
|
|
|
public string Classification => FillRate >= THTLimit ? "PASS" : "FAIL";
|
|
|
|
public void UpdateVisuals()
|
|
{
|
|
UpdateEllipsePath(PathE1, E1, E1A, E1B, E1Angle);
|
|
UpdateEllipsePath(PathE2, E2, E2A, E2B, E2Angle);
|
|
UpdateEllipsePath(PathE3, E3, E3A, E3B, E3Angle);
|
|
UpdateEllipsePath(PathE4, E4, E4A, E4B, E4Angle);
|
|
|
|
FullLine.X1 = E1.X; FullLine.Y1 = E1.Y;
|
|
FullLine.X2 = E2.X; FullLine.Y2 = E2.Y;
|
|
FullLine.Visibility = Visibility.Visible;
|
|
|
|
FillLine.X1 = E3.X; FillLine.Y1 = E3.Y;
|
|
FillLine.X2 = E4.X; FillLine.Y2 = E4.Y;
|
|
FillLine.Visibility = Visibility.Visible;
|
|
|
|
// 轴手柄定位
|
|
SetHandle(E1AH, EdgePoint(E1, E1A, E1Angle));
|
|
SetHandle(E1BH, EdgePoint(E1, E1B, E1Angle + 90));
|
|
SetHandle(E2AH, EdgePoint(E2, E2A, E2Angle));
|
|
SetHandle(E2BH, EdgePoint(E2, E2B, E2Angle + 90));
|
|
SetHandle(E3AH, EdgePoint(E3, E3A, E3Angle));
|
|
SetHandle(E3BH, EdgePoint(E3, E3B, E3Angle + 90));
|
|
SetHandle(E4AH, EdgePoint(E4, E4A, E4Angle));
|
|
SetHandle(E4BH, EdgePoint(E4, E4B, E4Angle + 90));
|
|
|
|
double rate = FillRate;
|
|
string cls = Classification;
|
|
Label.Text = $"Fill: {rate:F1}% | THTLimit: {THTLimit:F1}% | {cls}";
|
|
Label.Foreground = cls == "PASS" ? Brushes.Lime : Brushes.Red;
|
|
double labelX = Math.Max(Math.Max(E1.X, E2.X), Math.Max(E3.X, E4.X)) + 15;
|
|
double labelY = (E1.Y + E2.Y) / 2;
|
|
Canvas.SetLeft(Label, labelX);
|
|
Canvas.SetTop(Label, labelY - 10);
|
|
Label.Visibility = Visibility.Visible;
|
|
}
|
|
|
|
/// <summary>获取所有 UI 元素(用于添加/移除)</summary>
|
|
public UIElement[] AllElements => new UIElement[]
|
|
{
|
|
PathE1, PathE2, PathE3, PathE4, FullLine, FillLine, Label,
|
|
DotE1, DotE2, DotE3, DotE4,
|
|
E1AH, E1BH, E2AH, E2BH, E3AH, E3BH, E4AH, E4BH
|
|
};
|
|
|
|
private static Point EdgePoint(Point center, double radius, double angleDeg)
|
|
{
|
|
double rad = angleDeg * Math.PI / 180.0;
|
|
return new Point(center.X + radius * Math.Cos(rad), center.Y + radius * Math.Sin(rad));
|
|
}
|
|
|
|
private static void SetHandle(Ellipse h, Point pos)
|
|
{
|
|
if (h == null) return;
|
|
Canvas.SetLeft(h, pos.X - h.Width / 2);
|
|
Canvas.SetTop(h, pos.Y - h.Height / 2);
|
|
}
|
|
|
|
public static double Dist(Point a, Point b)
|
|
{
|
|
double dx = b.X - a.X, dy = b.Y - a.Y;
|
|
return Math.Sqrt(dx * dx + dy * dy);
|
|
}
|
|
|
|
private static void UpdateEllipsePath(Path path, Point center, double a, double b, double angleDeg)
|
|
{
|
|
var eg = new EllipseGeometry(center, a, b);
|
|
if (Math.Abs(angleDeg) > 0.01)
|
|
eg.Transform = new RotateTransform(angleDeg, center.X, center.Y);
|
|
path.Data = eg;
|
|
path.Visibility = Visibility.Visible;
|
|
}
|
|
}
|
|
}
|