using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.Linq; using System.Windows; using System.Windows.Controls; using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Windows; using Application = Autodesk.AutoCAD.ApplicationServices.Application; namespace Szmedi.CADkits { public partial class ReviewAndMatchWindow : UserControl { public ObservableCollection ReviewItems { get; set; } private readonly string _checkLineLayer; private bool _isListeningToSelection = true; private readonly PaletteSet _parentPalette; private readonly Dictionary _textDataMap; public ReviewAndMatchWindow( List allBlocks, Dictionary autoPairs, List allTexts, string checkLineLayer, PaletteSet parentPalette) { InitializeComponent(); _checkLineLayer = checkLineLayer; _parentPalette = parentPalette; _textDataMap = allTexts.ToDictionary(t => t.ObjectId, t => t); ReviewItems = new ObservableCollection(); ReviewListView.ItemsSource = ReviewItems; PopulateList(allBlocks, autoPairs); } private void PopulateList(List allBlocks, Dictionary autoPairs) { foreach (var blockData in allBlocks) { var item = new BlockReviewItem { BlockId = blockData.ObjectId, Handle = blockData.ObjectId.Handle.Value.ToString(), Position = $"{blockData.Position.X:F2}, {blockData.Position.Y:F2}" }; if (autoPairs.TryGetValue(blockData.ObjectId, out ObjectId textId)) { // 自动匹配成功 item.Status = _textDataMap[textId].TextContent; } else { // 未匹配 item.Status = "--- 未匹配 ---"; } ReviewItems.Add(item); } } //private void LocateButton_Click(object sender, RoutedEventArgs e) //{ // if (UnmatchedBlocksListView.SelectedItem is UnmatchedBlockItem selected) // { // ZoomToEntity(selected.BlockId); // } // else // { // MessageBox.Show("请先在列表中选择一个块。", "提示"); // } //} private void MatchButton_Click(object sender, RoutedEventArgs e) { if (!(ReviewListView.SelectedItem is BlockReviewItem selected)) { MessageBox.Show("请先在列表中选择一个要匹配的块。", "提示"); return; } Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; // 通过控制父面板来隐藏 _parentPalette.Visible = false; try { PromptEntityOptions peo = new PromptEntityOptions("\n请点选此块对应的标高文字: "); peo.SetRejectMessage("\n选择的不是文字对象。"); peo.AddAllowedClass(typeof(DBText), true); peo.AddAllowedClass(typeof(MText), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { UpdateBlockWithSelectedText(selected, per.ObjectId); } } catch (System.Exception ex) { MessageBox.Show($"发生错误: {ex.Message}"); } finally { // 操作结束后,重新显示父面板 _parentPalette.Visible = true; } } private void UpdateBlockWithSelectedText(BlockReviewItem itemToUpdate, ObjectId textId) { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; using (DocumentLock docLock = doc.LockDocument()) { using (Transaction tr = db.TransactionManager.StartTransaction()) { // 1. 获取文字内容和中心点 Entity textEnt = (Entity)tr.GetObject(textId, OpenMode.ForRead); string textContent = ""; if (textEnt is MText mtext) textContent = mtext.Contents; else if (textEnt is DBText dbtext) textContent = dbtext.TextString; // 验证文字内容 if (!double.TryParse(textContent, NumberStyles.Float, CultureInfo.InvariantCulture, out double elevationZ)) { MessageBox.Show($"文字内容 '{textContent}' 不是有效的数字。", "匹配失败"); tr.Abort(); return; } // 2. 更新块 BlockReference blockRef = (BlockReference)tr.GetObject(itemToUpdate.BlockId, OpenMode.ForWrite); blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ); // 3. 创建校对线 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite); Extents3d textExtents = textEnt.GeometricExtents; Point3d textCenter = textExtents.MinPoint + (textExtents.MaxPoint - textExtents.MinPoint) * 0.5; Line checkLine = new Line(blockRef.Position, textCenter); checkLine.Layer = _checkLineLayer; checkLine.ColorIndex = 256; // ByLayer btr.AppendEntity(checkLine); tr.AddNewlyCreatedDBObject(checkLine, true); itemToUpdate.Status = $"手动: {elevationZ}"; tr.Commit(); //Autodesk.AutoCAD.ApplicationServices.Application.ShowAlertDialog($"块 {itemToUpdate.Handle} 已手动更新为 {elevationZ}。"); } } } private void CloseButton_Click(object sender, RoutedEventArgs e) { _parentPalette.Visible = false; } // 辅助方法:缩放到实体 private void ZoomToEntity(ObjectId entId) { Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument; if (doc == null) return; Editor ed = doc.Editor; Database db = doc.Database; using (Transaction tr = db.TransactionManager.StartTransaction()) { if (entId.IsErased) return; Entity ent = tr.GetObject(entId, OpenMode.ForRead) as Entity; if (ent != null) { // 创建一个基于实体包围盒的视图 Extents3d extents = ent.GeometricExtents; Matrix3d ucs = ed.CurrentUserCoordinateSystem; double viewSize = Math.Max(extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y) * 5.0; // 扩大一点包围盒,使其不至于占满全屏 extents.TransformBy(ucs.Inverse()); ViewTableRecord view = new ViewTableRecord { CenterPoint = new Point2d( (extents.MinPoint.X + extents.MaxPoint.X) / 2.0, (extents.MinPoint.Y + extents.MaxPoint.Y) / 2.0), Height = viewSize, Width = viewSize }; ed.SetCurrentView(view); ed.SetImpliedSelection(new ObjectId[] { entId }); } tr.Commit(); } } private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e) { if (ReviewListView.SelectedItem is BlockReviewItem selected) { ZoomToEntity(selected.BlockId); } } private void SelectAndScrollToItem(ObjectId blockId) { var itemToSelect = ReviewItems.FirstOrDefault(item => item.BlockId == blockId); if (itemToSelect != null) { ReviewListView.SelectedItem = itemToSelect; ReviewListView.ScrollIntoView(itemToSelect); } } private void CleanLinesButton_Click(object sender, RoutedEventArgs e) { MessageBoxResult result = MessageBox.Show( "确定要删除所有由本工具创建的校对线吗?\n此操作不可撤销。", "确认清理", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { // 调用主类中的公共静态方法来执行清理 TerrainTools.CleanAllCheckLines(); } } private void LocateInListButton_Click(object sender, RoutedEventArgs e) { Document doc = Application.DocumentManager.MdiActiveDocument; Editor ed = doc.Editor; ObjectId targetId = ObjectId.Null; _isListeningToSelection = false; // 暂时关闭自动监听,避免冲突 try { // 1. 检查是否已经有选中的对象 PromptSelectionResult psr = ed.GetSelection(); if (psr.Status == PromptStatus.OK && psr.Value.Count > 0) { // 如果有,直接使用第一个 targetId = psr.Value.GetObjectIds()[0]; } else { // 2. 如果没有选中,则提示用户去选择 _parentPalette.Visible = false; // 隐藏面板方便用户选择 PromptEntityOptions peo = new PromptEntityOptions("\n请在图中选择一个地形点块进行定位: "); peo.SetRejectMessage("\n选择的不是块参照。"); peo.AddAllowedClass(typeof(BlockReference), true); PromptEntityResult per = ed.GetEntity(peo); if (per.Status == PromptStatus.OK) { targetId = per.ObjectId; } } // 3. 如果成功获取到ID,则在列表中定位 if (!targetId.IsNull) { SelectAndScrollToItem(targetId); } } finally { // 4. 无论如何都恢复UI状态 _isListeningToSelection = true; // 重新开启监听 _parentPalette.Visible = true; this.Focus(); } } } }