BGA辅助面板:气泡/焊球模式切换、VoidLimit面板调节、去掉标签右键编辑、未完成组气泡可拖拽调整
This commit is contained in:
@@ -394,6 +394,23 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
public void SetBubbleBrushSize(int val) => _bubbleBrushSize = val;
|
public void SetBubbleBrushSize(int val) => _bubbleBrushSize = val;
|
||||||
public Rect? BubbleRoi => _bubbleRoi;
|
public Rect? BubbleRoi => _bubbleRoi;
|
||||||
|
|
||||||
|
/// <summary>设置 BGA 测量的气泡/焊球绘制模式</summary>
|
||||||
|
public void SetBgaDrawBall(bool drawBall)
|
||||||
|
{
|
||||||
|
_bgaDrawBall = drawBall;
|
||||||
|
RaiseMeasureStatusChanged(drawBall ? "BGA - 画焊球模式" : "BGA - 画气泡模式");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>设置所有 BGA 组的 VoidLimit 并刷新标签</summary>
|
||||||
|
public void SetBgaVoidLimit(double limit)
|
||||||
|
{
|
||||||
|
foreach (var g in _bgaGroups)
|
||||||
|
{
|
||||||
|
g.VoidLimit = limit;
|
||||||
|
g.UpdateLabel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 拖拽状态
|
// 拖拽状态
|
||||||
private Ellipse _mDraggingDot;
|
private Ellipse _mDraggingDot;
|
||||||
private object _mDraggingOwner;
|
private object _mDraggingOwner;
|
||||||
@@ -722,9 +739,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
{
|
{
|
||||||
_bgaCurrent = new Models.BgaVoidGroup();
|
_bgaCurrent = new Models.BgaVoidGroup();
|
||||||
var currentGroup = _bgaCurrent; // 局部变量供闭包捕获
|
var currentGroup = _bgaCurrent; // 局部变量供闭包捕获
|
||||||
_bgaCurrent.Label = new TextBlock { FontSize = 13, FontWeight = FontWeights.Bold, Cursor = System.Windows.Input.Cursors.Hand, Visibility = Visibility.Collapsed };
|
_bgaCurrent.Label = new TextBlock { FontSize = 13, FontWeight = FontWeights.Bold, IsHitTestVisible = false, Visibility = Visibility.Collapsed };
|
||||||
_bgaCurrent.Label.SetValue(ContextMenuService.IsEnabledProperty, false);
|
|
||||||
_bgaCurrent.Label.PreviewMouseRightButtonUp += (s, ev) => { ShowBgaLimitEditor(currentGroup); ev.Handled = true; };
|
|
||||||
_measureOverlay.Children.Add(_bgaCurrent.Label);
|
_measureOverlay.Children.Add(_bgaCurrent.Label);
|
||||||
_bgaDrawBall = false;
|
_bgaDrawBall = false;
|
||||||
RaiseMeasureStatusChanged("BGA空隙 - 点击画气泡圆心(右键切换为画焊球)");
|
RaiseMeasureStatusChanged("BGA空隙 - 点击画气泡圆心(右键切换为画焊球)");
|
||||||
@@ -924,10 +939,12 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
if (g.E4BH == dot) { _mDraggingOwner = g; _mDraggingRole = "E4B"; break; }
|
if (g.E4BH == dot) { _mDraggingOwner = g; _mDraggingRole = "E4B"; break; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 查找 BGA 组
|
// 查找 BGA 组(已完成的 + 正在编辑的)
|
||||||
if (_mDraggingOwner == null)
|
if (_mDraggingOwner == null)
|
||||||
{
|
{
|
||||||
foreach (var g in _bgaGroups)
|
var allBga = new System.Collections.Generic.List<Models.BgaVoidGroup>(_bgaGroups);
|
||||||
|
if (_bgaCurrent != null) allBga.Add(_bgaCurrent);
|
||||||
|
foreach (var g in allBga)
|
||||||
{
|
{
|
||||||
if (g.Ball?.CenterDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallCenter"; break; }
|
if (g.Ball?.CenterDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallCenter"; break; }
|
||||||
if (g.Ball?.EdgeDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallEdge"; break; }
|
if (g.Ball?.EdgeDot == dot) { _mDraggingOwner = g; _mDraggingRole = "BallEdge"; break; }
|
||||||
|
|||||||
@@ -492,11 +492,29 @@ namespace XplorePlane.ViewModels
|
|||||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.ThroughHoleFillRate);
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.ThroughHoleFillRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Window _bgaMeasurePanel;
|
||||||
|
|
||||||
private void ExecuteBgaVoidMeasure()
|
private void ExecuteBgaVoidMeasure()
|
||||||
{
|
{
|
||||||
if (!CheckImageLoaded()) return;
|
if (!CheckImageLoaded()) return;
|
||||||
_logger.Info("BGA空隙测量功能已触发");
|
_logger.Info("BGA空隙测量功能已触发");
|
||||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BgaVoid);
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BgaVoid);
|
||||||
|
|
||||||
|
if (_bgaMeasurePanel != null && _bgaMeasurePanel.IsVisible)
|
||||||
|
{
|
||||||
|
_bgaMeasurePanel.Activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_bgaMeasurePanel = new Views.ImageProcessing.BgaMeasurePanel
|
||||||
|
{
|
||||||
|
Owner = System.Windows.Application.Current.MainWindow
|
||||||
|
};
|
||||||
|
_bgaMeasurePanel.Closed += (s, e) =>
|
||||||
|
{
|
||||||
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.None);
|
||||||
|
};
|
||||||
|
_bgaMeasurePanel.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Window _bubbleMeasurePanel;
|
private Window _bubbleMeasurePanel;
|
||||||
|
|||||||
@@ -0,0 +1,74 @@
|
|||||||
|
<Window
|
||||||
|
x:Class="XplorePlane.Views.ImageProcessing.BgaMeasurePanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="BGA空隙测量"
|
||||||
|
Width="240" Height="260"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Topmost="True"
|
||||||
|
ShowInTaskbar="False">
|
||||||
|
<Window.Resources>
|
||||||
|
<Style x:Key="ToolToggleStyle" TargetType="RadioButton">
|
||||||
|
<Setter Property="Template">
|
||||||
|
<Setter.Value>
|
||||||
|
<ControlTemplate TargetType="RadioButton">
|
||||||
|
<Border x:Name="Bd" Background="#EEEEEE" BorderBrush="#CCCCCC"
|
||||||
|
BorderThickness="1" CornerRadius="3" Padding="14,5" Cursor="Hand">
|
||||||
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||||
|
</Border>
|
||||||
|
<ControlTemplate.Triggers>
|
||||||
|
<Trigger Property="IsChecked" Value="True">
|
||||||
|
<Setter TargetName="Bd" Property="Background" Value="#0078D7" />
|
||||||
|
<Setter TargetName="Bd" Property="BorderBrush" Value="#005A9E" />
|
||||||
|
<Setter Property="Foreground" Value="White" />
|
||||||
|
</Trigger>
|
||||||
|
<Trigger Property="IsMouseOver" Value="True">
|
||||||
|
<Setter TargetName="Bd" Property="Background" Value="#DDDDDD" />
|
||||||
|
</Trigger>
|
||||||
|
<MultiTrigger>
|
||||||
|
<MultiTrigger.Conditions>
|
||||||
|
<Condition Property="IsMouseOver" Value="True" />
|
||||||
|
<Condition Property="IsChecked" Value="True" />
|
||||||
|
</MultiTrigger.Conditions>
|
||||||
|
<Setter TargetName="Bd" Property="Background" Value="#006CBE" />
|
||||||
|
</MultiTrigger>
|
||||||
|
</ControlTemplate.Triggers>
|
||||||
|
</ControlTemplate>
|
||||||
|
</Setter.Value>
|
||||||
|
</Setter>
|
||||||
|
</Style>
|
||||||
|
</Window.Resources>
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<!-- 绘制模式 -->
|
||||||
|
<TextBlock Text="绘制模式" FontWeight="SemiBold" Margin="0,0,0,4" />
|
||||||
|
<WrapPanel>
|
||||||
|
<RadioButton x:Name="RbVoid" Content="画气泡" IsChecked="True" Margin="0,0,6,4"
|
||||||
|
Style="{StaticResource ToolToggleStyle}" />
|
||||||
|
<RadioButton x:Name="RbBall" Content="画焊球" Margin="0,0,0,4"
|
||||||
|
Style="{StaticResource ToolToggleStyle}" />
|
||||||
|
</WrapPanel>
|
||||||
|
<TextBlock Text="左键点两次画圆(圆心+半径),右键删除" FontSize="10" Foreground="Gray" Margin="0,2,0,0" />
|
||||||
|
|
||||||
|
<Separator Margin="0,8" />
|
||||||
|
|
||||||
|
<!-- VoidLimit -->
|
||||||
|
<TextBlock Text="VoidLimit(%)" Margin="0,0,0,4" />
|
||||||
|
<DockPanel>
|
||||||
|
<TextBox x:Name="TbVoidLimit" DockPanel.Dock="Right" Width="50" Text="25.0"
|
||||||
|
VerticalContentAlignment="Center" Margin="6,0,0,0" />
|
||||||
|
<Slider x:Name="SliderVoidLimit" Minimum="0" Maximum="100" Value="25"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<Separator Margin="0,8" />
|
||||||
|
|
||||||
|
<!-- 结果 -->
|
||||||
|
<TextBlock x:Name="TbResult" Text="空隙率: --" FontSize="14" FontWeight="SemiBold" Margin="0,0,0,8" />
|
||||||
|
|
||||||
|
<!-- 操作 -->
|
||||||
|
<WrapPanel HorizontalAlignment="Center">
|
||||||
|
<Button Content="完成" Padding="14,4" Click="Finish_Click" />
|
||||||
|
</WrapPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using XP.ImageProcessing.RoiControl.Controls;
|
||||||
|
|
||||||
|
namespace XplorePlane.Views.ImageProcessing
|
||||||
|
{
|
||||||
|
public partial class BgaMeasurePanel : Window
|
||||||
|
{
|
||||||
|
private PolygonRoiCanvas _canvas;
|
||||||
|
|
||||||
|
public BgaMeasurePanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Loaded += OnLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mainWin = Owner as MainWindow;
|
||||||
|
if (mainWin != null)
|
||||||
|
_canvas = FindChild<PolygonRoiCanvas>(mainWin);
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
// 模式切换:通知 canvas 切换气泡/焊球
|
||||||
|
RbVoid.Checked += (s, ev) =>
|
||||||
|
{
|
||||||
|
if (_canvas != null) _canvas.SetBgaDrawBall(false);
|
||||||
|
};
|
||||||
|
RbBall.Checked += (s, ev) =>
|
||||||
|
{
|
||||||
|
if (_canvas != null) _canvas.SetBgaDrawBall(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// VoidLimit 同步
|
||||||
|
SliderVoidLimit.ValueChanged += (s, ev) =>
|
||||||
|
{
|
||||||
|
TbVoidLimit.Text = SliderVoidLimit.Value.ToString("F1");
|
||||||
|
_canvas?.SetBgaVoidLimit(SliderVoidLimit.Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听测量完成事件更新结果
|
||||||
|
if (_canvas != null)
|
||||||
|
{
|
||||||
|
_canvas.MeasureCompleted += (s, ev) =>
|
||||||
|
{
|
||||||
|
if (ev is MeasureCompletedEventArgs args && args.MeasureType == "BgaVoid")
|
||||||
|
{
|
||||||
|
TbResult.Text = $"空隙率: {args.Distance:F1}%";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Finish_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static T FindChild<T>(DependencyObject parent) where T : DependencyObject
|
||||||
|
{
|
||||||
|
int count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(parent);
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
var child = System.Windows.Media.VisualTreeHelper.GetChild(parent, i);
|
||||||
|
if (child is T t) return t;
|
||||||
|
var result = FindChild<T>(child);
|
||||||
|
if (result != null) return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user