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 XP.ImageProcessing.RoiControl { /// /// 多边形装饰器,用于编辑多边形顶点 /// public class PolygonAdorner : Adorner { private List vertexThumbs = new List(); // 顶点控制�? 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) { // 右键删除顶点(至少保�?个顶点) 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]; } } }