气泡测量:工具面板UI、BubbleMeasure模式、矩形ROI绘制/拖动/右下角调整大小、工具切换联动
This commit is contained in:
@@ -370,6 +370,28 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
private Point? _bgaPendingCenter; // 等待第二次点击定半径
|
private Point? _bgaPendingCenter; // 等待第二次点击定半径
|
||||||
private Ellipse _bgaPendingDot;
|
private Ellipse _bgaPendingDot;
|
||||||
|
|
||||||
|
// 气泡测量状态
|
||||||
|
public enum BubbleSubTool { Roi, Wand, Brush, Eraser }
|
||||||
|
private BubbleSubTool _bubbleTool = BubbleSubTool.Roi;
|
||||||
|
private Rectangle _bubbleRoiRect;
|
||||||
|
private Ellipse _bubbleRoiHandle; // 右下角调整手柄
|
||||||
|
private Rect? _bubbleRoi;
|
||||||
|
private Point? _bubbleRoiStart;
|
||||||
|
private bool _bubbleRoiDragging;
|
||||||
|
private bool _bubbleRoiMoving; // 拖动整个 ROI
|
||||||
|
private bool _bubbleRoiResizing; // 右下角调整大小
|
||||||
|
private Point _bubbleRoiDragOffset;
|
||||||
|
private Image _bubbleMaskImage;
|
||||||
|
private System.Windows.Media.Imaging.WriteableBitmap _bubbleMask;
|
||||||
|
private int _bubbleThreshold = 128;
|
||||||
|
private int _bubbleBrushSize = 5;
|
||||||
|
private bool _bubbleBrushDragging;
|
||||||
|
|
||||||
|
public void SetBubbleTool(BubbleSubTool tool) => _bubbleTool = tool;
|
||||||
|
public void SetBubbleThreshold(int val) => _bubbleThreshold = val;
|
||||||
|
public void SetBubbleBrushSize(int val) => _bubbleBrushSize = val;
|
||||||
|
public Rect? BubbleRoi => _bubbleRoi;
|
||||||
|
|
||||||
// 拖拽状态
|
// 拖拽状态
|
||||||
private Ellipse _mDraggingDot;
|
private Ellipse _mDraggingDot;
|
||||||
private object _mDraggingOwner;
|
private object _mDraggingOwner;
|
||||||
@@ -448,6 +470,7 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
HandleFillRateClick(pos);
|
HandleFillRateClick(pos);
|
||||||
else if (CurrentMeasureMode == Models.MeasureMode.BgaVoid)
|
else if (CurrentMeasureMode == Models.MeasureMode.BgaVoid)
|
||||||
HandleBgaVoidClick(pos);
|
HandleBgaVoidClick(pos);
|
||||||
|
// BubbleMeasure 的点击在 MouseDown/Move/Up 中处理(拖拽画 ROI 和画笔)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── 点点距 ──
|
// ── 点点距 ──
|
||||||
@@ -1084,6 +1107,125 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── 气泡测量辅助 ──
|
||||||
|
|
||||||
|
private void EnsureBubbleRoiVisuals()
|
||||||
|
{
|
||||||
|
EnsureMeasureOverlay();
|
||||||
|
if (_bubbleRoiRect == null)
|
||||||
|
{
|
||||||
|
_bubbleRoiRect = new Rectangle
|
||||||
|
{
|
||||||
|
Stroke = Brushes.Red,
|
||||||
|
StrokeThickness = 1.5,
|
||||||
|
Fill = Brushes.Transparent,
|
||||||
|
Visibility = Visibility.Collapsed,
|
||||||
|
IsHitTestVisible = false
|
||||||
|
};
|
||||||
|
_measureOverlay.Children.Add(_bubbleRoiRect);
|
||||||
|
}
|
||||||
|
if (_bubbleRoiHandle == null)
|
||||||
|
{
|
||||||
|
_bubbleRoiHandle = new Ellipse
|
||||||
|
{
|
||||||
|
Width = 10, Height = 10,
|
||||||
|
Fill = Brushes.Red, Stroke = Brushes.White, StrokeThickness = 1,
|
||||||
|
Cursor = Cursors.SizeNWSE,
|
||||||
|
Visibility = Visibility.Collapsed,
|
||||||
|
IsHitTestVisible = false // 命中测试由 MouseDown 中的距离判断处理
|
||||||
|
};
|
||||||
|
_measureOverlay.Children.Add(_bubbleRoiHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SyncBubbleRoiVisuals()
|
||||||
|
{
|
||||||
|
if (_bubbleRoiRect == null || !_bubbleRoi.HasValue) return;
|
||||||
|
var r = _bubbleRoi.Value;
|
||||||
|
Canvas.SetLeft(_bubbleRoiRect, r.X);
|
||||||
|
Canvas.SetTop(_bubbleRoiRect, r.Y);
|
||||||
|
_bubbleRoiRect.Width = r.Width;
|
||||||
|
_bubbleRoiRect.Height = r.Height;
|
||||||
|
_bubbleRoiRect.Visibility = Visibility.Visible;
|
||||||
|
|
||||||
|
if (_bubbleRoiHandle != null)
|
||||||
|
{
|
||||||
|
Canvas.SetLeft(_bubbleRoiHandle, r.Right - _bubbleRoiHandle.Width / 2);
|
||||||
|
Canvas.SetTop(_bubbleRoiHandle, r.Bottom - _bubbleRoiHandle.Height / 2);
|
||||||
|
_bubbleRoiHandle.Visibility = Visibility.Visible;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InitBubbleMask()
|
||||||
|
{
|
||||||
|
if (!_bubbleRoi.HasValue) return;
|
||||||
|
int w = (int)CanvasWidth, h = (int)CanvasHeight;
|
||||||
|
if (w <= 0 || h <= 0) return;
|
||||||
|
|
||||||
|
_bubbleMask = new System.Windows.Media.Imaging.WriteableBitmap(w, h, 96, 96,
|
||||||
|
PixelFormats.Bgra32, null);
|
||||||
|
|
||||||
|
if (_bubbleMaskImage == null)
|
||||||
|
{
|
||||||
|
EnsureMeasureOverlay();
|
||||||
|
_bubbleMaskImage = new Image
|
||||||
|
{
|
||||||
|
IsHitTestVisible = false,
|
||||||
|
Opacity = 0.45,
|
||||||
|
Stretch = Stretch.Fill
|
||||||
|
};
|
||||||
|
_bubbleMaskImage.SetBinding(Image.WidthProperty, new System.Windows.Data.Binding("CanvasWidth") { Source = this });
|
||||||
|
_bubbleMaskImage.SetBinding(Image.HeightProperty, new System.Windows.Data.Binding("CanvasHeight") { Source = this });
|
||||||
|
_measureOverlay.Children.Add(_bubbleMaskImage);
|
||||||
|
}
|
||||||
|
_bubbleMaskImage.Source = _bubbleMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyBrushAt(Point pos)
|
||||||
|
{
|
||||||
|
// 画笔/橡皮:暂时空实现,下一步实现
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateBubbleResult()
|
||||||
|
{
|
||||||
|
// 计算空隙率:暂时空实现,下一步实现
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>清除气泡测量所有状态</summary>
|
||||||
|
public void ClearBubbleMeasure()
|
||||||
|
{
|
||||||
|
if (_measureOverlay != null)
|
||||||
|
{
|
||||||
|
if (_bubbleRoiRect != null) { _measureOverlay.Children.Remove(_bubbleRoiRect); _bubbleRoiRect = null; }
|
||||||
|
if (_bubbleRoiHandle != null) { _measureOverlay.Children.Remove(_bubbleRoiHandle); _bubbleRoiHandle = null; }
|
||||||
|
if (_bubbleMaskImage != null) { _measureOverlay.Children.Remove(_bubbleMaskImage); _bubbleMaskImage = null; }
|
||||||
|
}
|
||||||
|
_bubbleRoi = null;
|
||||||
|
_bubbleMask = null;
|
||||||
|
_bubbleRoiStart = null;
|
||||||
|
_bubbleRoiDragging = false;
|
||||||
|
_bubbleRoiMoving = false;
|
||||||
|
_bubbleRoiResizing = false;
|
||||||
|
_bubbleBrushDragging = false;
|
||||||
|
_bubbleTool = BubbleSubTool.Roi;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 气泡工具切换事件
|
||||||
|
public static readonly RoutedEvent BubbleToolChangedEvent =
|
||||||
|
EventManager.RegisterRoutedEvent(nameof(BubbleToolChanged), RoutingStrategy.Bubble,
|
||||||
|
typeof(RoutedEventHandler), typeof(PolygonRoiCanvas));
|
||||||
|
|
||||||
|
public event RoutedEventHandler BubbleToolChanged
|
||||||
|
{
|
||||||
|
add { AddHandler(BubbleToolChangedEvent, value); }
|
||||||
|
remove { RemoveHandler(BubbleToolChangedEvent, value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RaiseBubbleToolChanged()
|
||||||
|
{
|
||||||
|
RaiseEvent(new RoutedEventArgs(BubbleToolChangedEvent));
|
||||||
|
}
|
||||||
|
|
||||||
// ── 重编号 ──
|
// ── 重编号 ──
|
||||||
|
|
||||||
private void RenumberAll()
|
private void RenumberAll()
|
||||||
@@ -1354,6 +1496,57 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
|
|
||||||
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
|
// 气泡测量模式:ROI 拖拽 / 画笔涂抹
|
||||||
|
if (CurrentMeasureMode == Models.MeasureMode.BubbleMeasure)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
if (_bubbleTool == BubbleSubTool.Roi)
|
||||||
|
{
|
||||||
|
// 检查是否点击了右下角手柄
|
||||||
|
if (_bubbleRoiHandle != null && _bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
var hx = Canvas.GetLeft(_bubbleRoiHandle) + _bubbleRoiHandle.Width / 2;
|
||||||
|
var hy = Canvas.GetTop(_bubbleRoiHandle) + _bubbleRoiHandle.Height / 2;
|
||||||
|
if (Math.Abs(pos.X - hx) < 10 && Math.Abs(pos.Y - hy) < 10)
|
||||||
|
{
|
||||||
|
_bubbleRoiResizing = true;
|
||||||
|
mainCanvas.CaptureMouse();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 检查是否点击了 ROI 内部(拖动)
|
||||||
|
if (_bubbleRoi.HasValue && _bubbleRoi.Value.Contains(pos))
|
||||||
|
{
|
||||||
|
_bubbleRoiMoving = true;
|
||||||
|
_bubbleRoiDragOffset = new Point(pos.X - _bubbleRoi.Value.X, pos.Y - _bubbleRoi.Value.Y);
|
||||||
|
mainCanvas.CaptureMouse();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 没有 ROI 时才画新的,有 ROI 时点击外部不拦截(让图像正常拖动)
|
||||||
|
if (!_bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
_bubbleRoiStart = pos;
|
||||||
|
_bubbleRoiDragging = true;
|
||||||
|
EnsureBubbleRoiVisuals();
|
||||||
|
mainCanvas.CaptureMouse();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 有 ROI 但点击了外部 → 不拦截,走正常拖动逻辑
|
||||||
|
}
|
||||||
|
if ((_bubbleTool == BubbleSubTool.Brush || _bubbleTool == BubbleSubTool.Eraser) && _bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
_bubbleBrushDragging = true;
|
||||||
|
ApplyBrushAt(pos);
|
||||||
|
mainCanvas.CaptureMouse();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 魔棒在 MouseUp(CanvasClicked)中处理
|
||||||
|
}
|
||||||
|
|
||||||
lastMousePosition = e.GetPosition(imageDisplayGrid);
|
lastMousePosition = e.GetPosition(imageDisplayGrid);
|
||||||
isDragging = false;
|
isDragging = false;
|
||||||
mainCanvas.CaptureMouse();
|
mainCanvas.CaptureMouse();
|
||||||
@@ -1361,6 +1554,54 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
|
|
||||||
private void Canvas_MouseMove(object sender, MouseEventArgs e)
|
private void Canvas_MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
|
// 气泡测量:ROI 拖拽画新矩形
|
||||||
|
if (_bubbleRoiDragging && _bubbleRoiStart.HasValue && _bubbleRoiRect != null)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
double x = Math.Min(_bubbleRoiStart.Value.X, pos.X);
|
||||||
|
double y = Math.Min(_bubbleRoiStart.Value.Y, pos.Y);
|
||||||
|
double w = Math.Abs(pos.X - _bubbleRoiStart.Value.X);
|
||||||
|
double h = Math.Abs(pos.Y - _bubbleRoiStart.Value.Y);
|
||||||
|
Canvas.SetLeft(_bubbleRoiRect, x);
|
||||||
|
Canvas.SetTop(_bubbleRoiRect, y);
|
||||||
|
_bubbleRoiRect.Width = w;
|
||||||
|
_bubbleRoiRect.Height = h;
|
||||||
|
_bubbleRoiRect.Visibility = Visibility.Visible;
|
||||||
|
if (_bubbleRoiHandle != null) _bubbleRoiHandle.Visibility = Visibility.Collapsed;
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 气泡测量:拖动 ROI
|
||||||
|
if (_bubbleRoiMoving && _bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
double nx = pos.X - _bubbleRoiDragOffset.X;
|
||||||
|
double ny = pos.Y - _bubbleRoiDragOffset.Y;
|
||||||
|
_bubbleRoi = new Rect(nx, ny, _bubbleRoi.Value.Width, _bubbleRoi.Value.Height);
|
||||||
|
SyncBubbleRoiVisuals();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 气泡测量:右下角调整大小
|
||||||
|
if (_bubbleRoiResizing && _bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
double w = Math.Max(20, pos.X - _bubbleRoi.Value.X);
|
||||||
|
double h = Math.Max(20, pos.Y - _bubbleRoi.Value.Y);
|
||||||
|
_bubbleRoi = new Rect(_bubbleRoi.Value.X, _bubbleRoi.Value.Y, w, h);
|
||||||
|
SyncBubbleRoiVisuals();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 气泡测量:画笔/橡皮拖拽
|
||||||
|
if (_bubbleBrushDragging && _bubbleRoi.HasValue)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
ApplyBrushAt(pos);
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (e.LeftButton == MouseButtonState.Pressed && mainCanvas.IsMouseCaptured)
|
if (e.LeftButton == MouseButtonState.Pressed && mainCanvas.IsMouseCaptured)
|
||||||
{
|
{
|
||||||
Point currentPosition = e.GetPosition(imageDisplayGrid);
|
Point currentPosition = e.GetPosition(imageDisplayGrid);
|
||||||
@@ -1378,6 +1619,49 @@ namespace XP.ImageProcessing.RoiControl.Controls
|
|||||||
|
|
||||||
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
private void Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||||
{
|
{
|
||||||
|
// 气泡测量:ROI 拖拽完成
|
||||||
|
if (_bubbleRoiDragging && _bubbleRoiStart.HasValue)
|
||||||
|
{
|
||||||
|
var pos = e.GetPosition(mainCanvas);
|
||||||
|
double x = Math.Min(_bubbleRoiStart.Value.X, pos.X);
|
||||||
|
double y = Math.Min(_bubbleRoiStart.Value.Y, pos.Y);
|
||||||
|
double w = Math.Abs(pos.X - _bubbleRoiStart.Value.X);
|
||||||
|
double h = Math.Abs(pos.Y - _bubbleRoiStart.Value.Y);
|
||||||
|
_bubbleRoiDragging = false;
|
||||||
|
_bubbleRoiStart = null;
|
||||||
|
mainCanvas.ReleaseMouseCapture();
|
||||||
|
|
||||||
|
if (w > 5 && h > 5)
|
||||||
|
{
|
||||||
|
_bubbleRoi = new Rect(x, y, w, h);
|
||||||
|
SyncBubbleRoiVisuals();
|
||||||
|
InitBubbleMask();
|
||||||
|
RaiseMeasureStatusChanged($"ROI 已设置: {w:F0}×{h:F0},可拖动/调整大小,或在面板切换魔棒工具");
|
||||||
|
}
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 气泡测量:拖动/调整完成
|
||||||
|
if (_bubbleRoiMoving || _bubbleRoiResizing)
|
||||||
|
{
|
||||||
|
_bubbleRoiMoving = false;
|
||||||
|
_bubbleRoiResizing = false;
|
||||||
|
mainCanvas.ReleaseMouseCapture();
|
||||||
|
if (_bubbleRoi.HasValue)
|
||||||
|
RaiseMeasureStatusChanged($"ROI: {_bubbleRoi.Value.Width:F0}×{_bubbleRoi.Value.Height:F0}");
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 气泡测量:画笔/橡皮松开
|
||||||
|
if (_bubbleBrushDragging)
|
||||||
|
{
|
||||||
|
_bubbleBrushDragging = false;
|
||||||
|
mainCanvas.ReleaseMouseCapture();
|
||||||
|
UpdateBubbleResult();
|
||||||
|
e.Handled = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mainCanvas.ReleaseMouseCapture();
|
mainCanvas.ReleaseMouseCapture();
|
||||||
|
|
||||||
if (!isDragging)
|
if (!isDragging)
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace XP.ImageProcessing.RoiControl.Models
|
|||||||
PointToLine,
|
PointToLine,
|
||||||
Angle,
|
Angle,
|
||||||
FillRate,
|
FillRate,
|
||||||
BgaVoid
|
BgaVoid,
|
||||||
|
BubbleMeasure
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ namespace XplorePlane.Events
|
|||||||
PointLineDistance,
|
PointLineDistance,
|
||||||
Angle,
|
Angle,
|
||||||
ThroughHoleFillRate,
|
ThroughHoleFillRate,
|
||||||
BgaVoid
|
BgaVoid,
|
||||||
|
BubbleMeasure
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ namespace XplorePlane.ViewModels
|
|||||||
public DelegateCommand AngleMeasureCommand { get; }
|
public DelegateCommand AngleMeasureCommand { get; }
|
||||||
public DelegateCommand ThroughHoleFillRateMeasureCommand { get; }
|
public DelegateCommand ThroughHoleFillRateMeasureCommand { get; }
|
||||||
public DelegateCommand BgaVoidMeasureCommand { get; }
|
public DelegateCommand BgaVoidMeasureCommand { get; }
|
||||||
|
public DelegateCommand BubbleMeasureCommand { get; }
|
||||||
|
|
||||||
// 辅助线命令
|
// 辅助线命令
|
||||||
public DelegateCommand ToggleCrosshairCommand { get; }
|
public DelegateCommand ToggleCrosshairCommand { get; }
|
||||||
@@ -176,6 +177,7 @@ namespace XplorePlane.ViewModels
|
|||||||
AngleMeasureCommand = new DelegateCommand(ExecuteAngleMeasure);
|
AngleMeasureCommand = new DelegateCommand(ExecuteAngleMeasure);
|
||||||
ThroughHoleFillRateMeasureCommand = new DelegateCommand(ExecuteThroughHoleFillRateMeasure);
|
ThroughHoleFillRateMeasureCommand = new DelegateCommand(ExecuteThroughHoleFillRateMeasure);
|
||||||
BgaVoidMeasureCommand = new DelegateCommand(ExecuteBgaVoidMeasure);
|
BgaVoidMeasureCommand = new DelegateCommand(ExecuteBgaVoidMeasure);
|
||||||
|
BubbleMeasureCommand = new DelegateCommand(ExecuteBubbleMeasure);
|
||||||
|
|
||||||
// 辅助线命令
|
// 辅助线命令
|
||||||
ToggleCrosshairCommand = new DelegateCommand(() =>
|
ToggleCrosshairCommand = new DelegateCommand(() =>
|
||||||
@@ -497,6 +499,35 @@ namespace XplorePlane.ViewModels
|
|||||||
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BgaVoid);
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BgaVoid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Window _bubbleMeasurePanel;
|
||||||
|
|
||||||
|
private void ExecuteBubbleMeasure()
|
||||||
|
{
|
||||||
|
if (!CheckImageLoaded()) return;
|
||||||
|
_logger.Info("气泡测量功能已触发");
|
||||||
|
|
||||||
|
// 进入气泡测量模式
|
||||||
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.BubbleMeasure);
|
||||||
|
|
||||||
|
// 弹出工具面板
|
||||||
|
if (_bubbleMeasurePanel != null && _bubbleMeasurePanel.IsVisible)
|
||||||
|
{
|
||||||
|
_bubbleMeasurePanel.Activate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_bubbleMeasurePanel = new Views.ImageProcessing.BubbleMeasurePanel
|
||||||
|
{
|
||||||
|
Owner = System.Windows.Application.Current.MainWindow
|
||||||
|
};
|
||||||
|
_bubbleMeasurePanel.Closed += (s, e) =>
|
||||||
|
{
|
||||||
|
// 关闭面板时退出气泡测量模式
|
||||||
|
_eventAggregator.GetEvent<MeasurementToolEvent>().Publish(MeasurementToolMode.None);
|
||||||
|
};
|
||||||
|
_bubbleMeasurePanel.Show();
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region 设置命令实现
|
#region 设置命令实现
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
<Window
|
||||||
|
x:Class="XplorePlane.Views.ImageProcessing.BubbleMeasurePanel"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
Title="气泡测量工具"
|
||||||
|
Width="260" Height="320"
|
||||||
|
ResizeMode="NoResize"
|
||||||
|
WindowStartupLocation="CenterOwner"
|
||||||
|
Topmost="True"
|
||||||
|
ShowInTaskbar="False">
|
||||||
|
<StackPanel Margin="10">
|
||||||
|
<!-- 工具选择 -->
|
||||||
|
<TextBlock Text="工具" FontWeight="SemiBold" Margin="0,0,0,4" />
|
||||||
|
<WrapPanel>
|
||||||
|
<RadioButton x:Name="RbRoi" Content="ROI" IsChecked="True" Margin="0,0,12,4" />
|
||||||
|
<RadioButton x:Name="RbWand" Content="魔棒" Margin="0,0,12,4" />
|
||||||
|
<RadioButton x:Name="RbBrush" Content="画笔" Margin="0,0,12,4" />
|
||||||
|
<RadioButton x:Name="RbEraser" Content="橡皮擦" Margin="0,0,0,4" />
|
||||||
|
</WrapPanel>
|
||||||
|
|
||||||
|
<Separator Margin="0,6" />
|
||||||
|
|
||||||
|
<!-- 阈值 -->
|
||||||
|
<TextBlock Text="灰度阈值" Margin="0,0,0,4" />
|
||||||
|
<DockPanel>
|
||||||
|
<TextBox x:Name="TbThreshold" DockPanel.Dock="Right" Width="45" Text="128"
|
||||||
|
VerticalContentAlignment="Center" Margin="6,0,0,0" />
|
||||||
|
<Slider x:Name="SliderThreshold" Minimum="0" Maximum="255" Value="128"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<!-- 画笔大小 -->
|
||||||
|
<TextBlock Text="画笔/橡皮大小" Margin="0,8,0,4" />
|
||||||
|
<DockPanel>
|
||||||
|
<TextBox x:Name="TbBrushSize" DockPanel.Dock="Right" Width="45" Text="5"
|
||||||
|
VerticalContentAlignment="Center" Margin="6,0,0,0" />
|
||||||
|
<Slider x:Name="SliderBrushSize" Minimum="1" Maximum="30" Value="5"
|
||||||
|
VerticalAlignment="Center" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<Separator Margin="0,8" />
|
||||||
|
|
||||||
|
<!-- 结果 -->
|
||||||
|
<TextBlock Text="测量结果" FontWeight="SemiBold" Margin="0,0,0,4" />
|
||||||
|
<TextBlock x:Name="TbResult" Text="空隙率: --" FontSize="14" Margin="0,0,0,4" />
|
||||||
|
<DockPanel Margin="0,0,0,8">
|
||||||
|
<TextBlock Text="VoidLimit(%):" VerticalAlignment="Center" />
|
||||||
|
<TextBox x:Name="TbVoidLimit" Width="50" Text="25.0" Margin="6,0,0,0"
|
||||||
|
VerticalContentAlignment="Center" />
|
||||||
|
</DockPanel>
|
||||||
|
|
||||||
|
<!-- 操作按钮 -->
|
||||||
|
<WrapPanel HorizontalAlignment="Center">
|
||||||
|
<Button Content="清除标记" Padding="12,4" Margin="0,0,8,0" Click="ClearMask_Click" />
|
||||||
|
<Button Content="完成" Padding="12,4" Click="Finish_Click" />
|
||||||
|
</WrapPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Window>
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
using System.Windows;
|
||||||
|
using Prism.Ioc;
|
||||||
|
using XP.ImageProcessing.RoiControl.Controls;
|
||||||
|
using XplorePlane.ViewModels;
|
||||||
|
|
||||||
|
namespace XplorePlane.Views.ImageProcessing
|
||||||
|
{
|
||||||
|
public partial class BubbleMeasurePanel : Window
|
||||||
|
{
|
||||||
|
private PolygonRoiCanvas _canvas;
|
||||||
|
|
||||||
|
public BubbleMeasurePanel()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
Loaded += OnLoaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
// 获取主界面的 RoiCanvas
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mainWin = Owner as MainWindow;
|
||||||
|
if (mainWin != null)
|
||||||
|
{
|
||||||
|
_canvas = FindChild<PolygonRoiCanvas>(mainWin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
|
||||||
|
// 工具切换
|
||||||
|
RbRoi.Checked += (s, ev) => _canvas?.SetBubbleTool(PolygonRoiCanvas.BubbleSubTool.Roi);
|
||||||
|
RbWand.Checked += (s, ev) => _canvas?.SetBubbleTool(PolygonRoiCanvas.BubbleSubTool.Wand);
|
||||||
|
RbBrush.Checked += (s, ev) => _canvas?.SetBubbleTool(PolygonRoiCanvas.BubbleSubTool.Brush);
|
||||||
|
RbEraser.Checked += (s, ev) => _canvas?.SetBubbleTool(PolygonRoiCanvas.BubbleSubTool.Eraser);
|
||||||
|
|
||||||
|
// 阈值同步
|
||||||
|
SliderThreshold.ValueChanged += (s, ev) =>
|
||||||
|
{
|
||||||
|
TbThreshold.Text = ((int)SliderThreshold.Value).ToString();
|
||||||
|
_canvas?.SetBubbleThreshold((int)SliderThreshold.Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 画笔大小同步
|
||||||
|
SliderBrushSize.ValueChanged += (s, ev) =>
|
||||||
|
{
|
||||||
|
TbBrushSize.Text = ((int)SliderBrushSize.Value).ToString();
|
||||||
|
_canvas?.SetBubbleBrushSize((int)SliderBrushSize.Value);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 监听 canvas 的工具切换事件(ROI 画完后自动切换时同步面板)
|
||||||
|
if (_canvas != null)
|
||||||
|
{
|
||||||
|
_canvas.BubbleToolChanged += (s, ev) =>
|
||||||
|
{
|
||||||
|
// 暂不自动切换面板 radio button
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearMask_Click(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
_canvas?.ClearBubbleMeasure();
|
||||||
|
TbResult.Text = "空隙率: --";
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -79,6 +79,7 @@ namespace XplorePlane.Views
|
|||||||
MeasurementToolMode.Angle => XP.ImageProcessing.RoiControl.Models.MeasureMode.Angle,
|
MeasurementToolMode.Angle => XP.ImageProcessing.RoiControl.Models.MeasureMode.Angle,
|
||||||
MeasurementToolMode.ThroughHoleFillRate => XP.ImageProcessing.RoiControl.Models.MeasureMode.FillRate,
|
MeasurementToolMode.ThroughHoleFillRate => XP.ImageProcessing.RoiControl.Models.MeasureMode.FillRate,
|
||||||
MeasurementToolMode.BgaVoid => XP.ImageProcessing.RoiControl.Models.MeasureMode.BgaVoid,
|
MeasurementToolMode.BgaVoid => XP.ImageProcessing.RoiControl.Models.MeasureMode.BgaVoid,
|
||||||
|
MeasurementToolMode.BubbleMeasure => XP.ImageProcessing.RoiControl.Models.MeasureMode.BubbleMeasure,
|
||||||
_ => XP.ImageProcessing.RoiControl.Models.MeasureMode.None
|
_ => XP.ImageProcessing.RoiControl.Models.MeasureMode.None
|
||||||
};
|
};
|
||||||
}, Prism.Events.ThreadOption.UIThread);
|
}, Prism.Events.ThreadOption.UIThread);
|
||||||
|
|||||||
Reference in New Issue
Block a user