Files
SzmediTools/Szmedi.CADkits/ReviewAndMatchWindow.xaml.cs
2025-12-23 21:37:02 +08:00

287 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<BlockReviewItem> ReviewItems { get; set; }
private readonly string _checkLineLayer;
private bool _isListeningToSelection = true;
private readonly PaletteSet _parentPalette;
private readonly Dictionary<ObjectId, TextWithPosition> _textDataMap;
public ReviewAndMatchWindow(
List<BlockRefWithPosition> allBlocks,
Dictionary<ObjectId, ObjectId> autoPairs,
List<TextWithPosition> allTexts,
string checkLineLayer,
PaletteSet parentPalette)
{
InitializeComponent();
_checkLineLayer = checkLineLayer;
_parentPalette = parentPalette;
_textDataMap = allTexts.ToDictionary(t => t.ObjectId, t => t);
ReviewItems = new ObservableCollection<BlockReviewItem>();
ReviewListView.ItemsSource = ReviewItems;
PopulateList(allBlocks, autoPairs);
}
private void PopulateList(List<BlockRefWithPosition> allBlocks, Dictionary<ObjectId, ObjectId> 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();
}
}
}
}