142 lines
4.9 KiB
C#
142 lines
4.9 KiB
C#
using System.Collections.Generic;
|
|
using System.Windows;
|
|
using System.Windows.Controls.Primitives;
|
|
using System.Windows.Documents;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media;
|
|
using System.Windows.Shapes;
|
|
|
|
namespace ImageROIControl
|
|
{
|
|
/// <summary>
|
|
/// 多边形装饰器,用于编辑多边形顶点
|
|
/// </summary>
|
|
public class PolygonAdorner : Adorner
|
|
{
|
|
private List<ControlThumb> vertexThumbs = new List<ControlThumb>(); // 顶点控制点
|
|
private VisualCollection visualChildren;
|
|
private double scaleFactor = 1;
|
|
private Models.PolygonROI? polygonROI;
|
|
|
|
public PolygonAdorner(UIElement adornedElement, double scaleFactor = 1, Models.PolygonROI? roiModel = null)
|
|
: base(adornedElement)
|
|
{
|
|
visualChildren = new VisualCollection(this);
|
|
this.scaleFactor = scaleFactor;
|
|
this.polygonROI = roiModel;
|
|
|
|
// 使用ROI模型的Points数量而不是Polygon的Points
|
|
int pointCount = polygonROI?.Points.Count ?? 0;
|
|
|
|
// 创建顶点控制点
|
|
for (int i = 0; i < pointCount; i++)
|
|
{
|
|
var thumb = new ControlThumb();
|
|
thumb.DragDelta += HandleDrag;
|
|
thumb.DragCompleted += HandleDragCompleted;
|
|
thumb.MouseRightButtonDown += HandleRightClick;
|
|
thumb.Tag = i;
|
|
thumb.Cursor = Cursors.Hand;
|
|
vertexThumbs.Add(thumb);
|
|
visualChildren.Add(thumb);
|
|
}
|
|
|
|
// 不再创建边中点控制点 - 使用智能插入算法代替
|
|
// 用户可以直接点击画布,系统会自动找到最近的边并插入顶点
|
|
}
|
|
|
|
private void HandleDrag(object sender, DragDeltaEventArgs args)
|
|
{
|
|
Thumb? hitThumb = sender as Thumb;
|
|
if (hitThumb == null || polygonROI == null) return;
|
|
|
|
int index = (int)hitThumb.Tag;
|
|
|
|
// 直接修改ROI模型的Points
|
|
if (index < polygonROI.Points.Count)
|
|
{
|
|
Point currentPoint = polygonROI.Points[index];
|
|
Point newPoint = new Point(
|
|
currentPoint.X + args.HorizontalChange,
|
|
currentPoint.Y + args.VerticalChange
|
|
);
|
|
|
|
// 使用索引器修改ObservableCollection中的元素
|
|
polygonROI.Points[index] = newPoint;
|
|
}
|
|
|
|
// 强制重新布局
|
|
InvalidateArrange();
|
|
}
|
|
|
|
private void HandleDragCompleted(object sender, DragCompletedEventArgs args)
|
|
{
|
|
// 拖拽完成后通知模型更新
|
|
if (polygonROI != null)
|
|
{
|
|
polygonROI.OnPropertyChanged(nameof(polygonROI.Points));
|
|
}
|
|
}
|
|
|
|
private void HandleRightClick(object sender, MouseButtonEventArgs e)
|
|
{
|
|
// 右键删除顶点(至少保留3个顶点)
|
|
if (polygonROI != null && polygonROI.Points.Count > 3)
|
|
{
|
|
Thumb? hitThumb = sender as Thumb;
|
|
if (hitThumb != null)
|
|
{
|
|
int index = (int)hitThumb.Tag;
|
|
|
|
// 删除顶点 - ObservableCollection会自动触发CollectionChanged事件
|
|
// PolygonRoiCanvas会监听到这个变化并自动更新Adorner
|
|
polygonROI.Points.RemoveAt(index);
|
|
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
{
|
|
// 使用ROI模型的Points而不是Polygon的Points
|
|
if (polygonROI != null)
|
|
{
|
|
double thumbSize = 12 * scaleFactor;
|
|
|
|
// 布局顶点控制点
|
|
for (int i = 0; i < vertexThumbs.Count && i < polygonROI.Points.Count; i++)
|
|
{
|
|
vertexThumbs[i].Arrange(new Rect(
|
|
polygonROI.Points[i].X - (thumbSize / 2),
|
|
polygonROI.Points[i].Y - (thumbSize / 2),
|
|
thumbSize,
|
|
thumbSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// 备用方案:使用Polygon的Points
|
|
Polygon poly = (Polygon)AdornedElement;
|
|
double thumbSize = 12 * scaleFactor;
|
|
|
|
for (int i = 0; i < vertexThumbs.Count && i < poly.Points.Count; i++)
|
|
{
|
|
vertexThumbs[i].Arrange(new Rect(
|
|
poly.Points[i].X - (thumbSize / 2),
|
|
poly.Points[i].Y - (thumbSize / 2),
|
|
thumbSize,
|
|
thumbSize));
|
|
}
|
|
}
|
|
|
|
return finalSize;
|
|
}
|
|
|
|
protected override int VisualChildrenCount
|
|
{ get { return visualChildren.Count; } }
|
|
|
|
protected override Visual GetVisualChild(int index)
|
|
{ return visualChildren[index]; }
|
|
}
|
|
} |