功能更新

This commit is contained in:
GG Z
2026-02-23 11:21:51 +08:00
parent 3650f8550e
commit 6beb8b5be9
24 changed files with 694 additions and 1975 deletions

View File

@@ -14,18 +14,29 @@ using Autodesk.AutoCAD.Windows;
using Application = Autodesk.AutoCAD.ApplicationServices.Application;
namespace Szmedi.CADkits
{
// 定义视图模型,对应列表中的一行
public class EntityReviewItem
{
public ObjectId EntityId { get; set; }
public string Handle { get; set; }
public string Position { get; set; }
// 支持属性通知可使用 INotifyPropertyChanged这里为了简化直接使用属性
public string Status { get; set; }
}
public partial class ReviewAndMatchWindow : UserControl
{
public ObservableCollection<BlockReviewItem> ReviewItems { get; set; }
public ObservableCollection<EntityReviewItem> ReviewItems { get; set; }
private readonly string _checkLineLayer;
private bool _isListeningToSelection = true;
private readonly PaletteSet _parentPalette;
private readonly Dictionary<ObjectId, TextWithPosition> _textDataMap;
// 构造函数参数改为 TerrainEntityInfo
public ReviewAndMatchWindow(
List<BlockRefWithPosition> allBlocks,
List<TerrainEntityInfo> allEntities,
Dictionary<ObjectId, ObjectId> autoPairs,
List<TextWithPosition> allTexts,
string checkLineLayer,
@@ -36,67 +47,51 @@ namespace Szmedi.CADkits
_parentPalette = parentPalette;
_textDataMap = allTexts.ToDictionary(t => t.ObjectId, t => t);
ReviewItems = new ObservableCollection<BlockReviewItem>();
ReviewItems = new ObservableCollection<EntityReviewItem>();
ReviewListView.ItemsSource = ReviewItems;
PopulateList(allBlocks, autoPairs);
PopulateList(allEntities, autoPairs);
}
private void PopulateList(List<BlockRefWithPosition> allBlocks, Dictionary<ObjectId, ObjectId> autoPairs)
private void PopulateList(List<TerrainEntityInfo> allEntities, Dictionary<ObjectId, ObjectId> autoPairs)
{
foreach (var blockData in allBlocks)
foreach (var entData in allEntities)
{
var item = new BlockReviewItem
var item = new EntityReviewItem
{
BlockId = blockData.ObjectId,
Handle = blockData.ObjectId.Handle.Value.ToString(),
Position = $"{blockData.Position.X:F2}, {blockData.Position.Y:F2}"
EntityId = entData.ObjectId,
Handle = entData.Handle,
Position = $"{entData.Position.X:F2}, {entData.Position.Y:F2}"
};
if (autoPairs.TryGetValue(blockData.ObjectId, out ObjectId textId))
if (autoPairs.TryGetValue(entData.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))
if (!(ReviewListView.SelectedItem is EntityReviewItem selected))
{
MessageBox.Show("请先在列表中选择一个要匹配的。", "提示");
MessageBox.Show("请先在列表中选择一个要匹配的实体。", "提示");
return;
}
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
if (_parentPalette.Dock == DockSides.None)
{
// 通过控制父面板来隐藏
_parentPalette.Visible = false;
}
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = false;
MatchButton.IsEnabled = false;
try
{
PromptEntityOptions peo = new PromptEntityOptions("\n请点选此对应的标高文字: ");
PromptEntityOptions peo = new PromptEntityOptions("\n请点选此实体对应的标高文字: ");
peo.SetRejectMessage("\n选择的不是文字对象。");
peo.AddAllowedClass(typeof(DBText), true);
peo.AddAllowedClass(typeof(MText), true);
@@ -105,7 +100,7 @@ namespace Szmedi.CADkits
if (per.Status == PromptStatus.OK)
{
UpdateBlockWithSelectedText(selected, per.ObjectId);
UpdateEntityWithSelectedText(selected, per.ObjectId);
}
}
catch (System.Exception ex)
@@ -114,17 +109,12 @@ namespace Szmedi.CADkits
}
finally
{
if (_parentPalette.Dock == DockSides.None)
{
// 操作结束后,重新显示父面板
_parentPalette.Visible = true;
}
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = true;
MatchButton.IsEnabled = true;
}
}
private void UpdateBlockWithSelectedText(BlockReviewItem itemToUpdate, ObjectId textId)
private void UpdateEntityWithSelectedText(EntityReviewItem itemToUpdate, ObjectId textId)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
@@ -132,13 +122,11 @@ namespace Szmedi.CADkits
{
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}' 不是有效的数字。", "匹配失败");
@@ -146,40 +134,62 @@ namespace Szmedi.CADkits
return;
}
// 2. 更新块
BlockReference blockRef = (BlockReference)tr.GetObject(itemToUpdate.BlockId, OpenMode.ForWrite);
blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ);
// --- 更新逻辑:区分 BlockReference 和 DBPoint ---
Entity targetEnt = (Entity)tr.GetObject(itemToUpdate.EntityId, OpenMode.ForWrite);
Point3d currentPos;
// 3. 创建校对线
if (targetEnt is BlockReference blockRef)
{
blockRef.Position = new Point3d(blockRef.Position.X, blockRef.Position.Y, elevationZ);
currentPos = blockRef.Position;
}
else if (targetEnt is DBPoint dbPoint)
{
dbPoint.Position = new Point3d(dbPoint.Position.X, dbPoint.Position.Y, elevationZ);
currentPos = dbPoint.Position;
}
else if (targetEnt is Polyline polyline)
{
//// 修改多段线的整体标高
//polyline.Elevation = elevationZ;
//currentPos = polyline.GetPoint3dAt(0);
polyline.Elevation = elevationZ;
// 重新计算中心点用于校对线绘制
Extents3d ext = polyline.GeometricExtents;
currentPos = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
}
else
{
MessageBox.Show("未知的实体类型,无法更新。");
tr.Abort();
return;
}
// 创建连线
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);
Line checkLine = new Line(currentPos, textCenter);
checkLine.Layer = _checkLineLayer;
checkLine.ColorIndex = 256; // ByLayer
checkLine.ColorIndex = 256;
btr.AppendEntity(checkLine);
tr.AddNewlyCreatedDBObject(checkLine, true);
// 更新UI
itemToUpdate.Status = $"手动: {elevationZ}";
// 强制刷新列表显示 (如果需要)
ReviewListView.Items.Refresh();
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)
{
if (!entId.IsValid)
{
return;
}
if (!entId.IsValid) return;
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
if (doc == null) return;
Editor ed = doc.Editor;
@@ -191,11 +201,17 @@ namespace Szmedi.CADkits
Entity ent = tr.GetObject(entId, OpenMode.ForRead) as Entity;
if (ent != null)
{
// 创建一个基于实体包围盒的视图
Extents3d extents = ent.GeometricExtents;
// 如果是点,包围盒可能很小,稍微扩大一点显示范围
if (ent is DBPoint)
{
extents = new Extents3d(extents.MinPoint - new Vector3d(1, 1, 0), extents.MaxPoint + new Vector3d(1, 1, 0));
}
Matrix3d ucs = ed.CurrentUserCoordinateSystem;
double viewSize = Math.Max(extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y) * 5.0;
// 扩大一点包围盒,使其不至于占满全屏
double viewSize = Math.Max(extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y) * 10.0;
if (viewSize < 1.0) viewSize = 20.0; // 最小视野
extents.TransformBy(ucs.Inverse());
ViewTableRecord view = new ViewTableRecord
{
@@ -214,16 +230,15 @@ namespace Szmedi.CADkits
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
if (ReviewListView.SelectedItem is BlockReviewItem selected)
if (ReviewListView.SelectedItem is EntityReviewItem selected)
{
ZoomToEntity(selected.BlockId);
ZoomToEntity(selected.EntityId);
}
}
private void SelectAndScrollToItem(ObjectId blockId)
private void SelectAndScrollToItem(ObjectId entId)
{
var itemToSelect = ReviewItems.FirstOrDefault(item => item.BlockId == blockId);
var itemToSelect = ReviewItems.FirstOrDefault(item => item.EntityId == entId);
if (itemToSelect != null)
{
ReviewListView.SelectedItem = itemToSelect;
@@ -231,8 +246,6 @@ namespace Szmedi.CADkits
}
}
private void CleanLinesButton_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult result = MessageBox.Show(
@@ -243,7 +256,6 @@ namespace Szmedi.CADkits
if (result == MessageBoxResult.Yes)
{
// 调用主类中的公共静态方法来执行清理
TerrainTools.CleanAllCheckLines();
}
}
@@ -253,34 +265,25 @@ namespace Szmedi.CADkits
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
ObjectId targetId = ObjectId.Null;
_isListeningToSelection = false; // 暂时关闭自动监听,避免冲突
_isListeningToSelection = false;
LocateInListButton.IsEnabled = false;
try
{
// 1. 检查是否已经有选中的对象
PromptSelectionResult psr = ed.GetSelection();
if (psr.Status == PromptStatus.OK && psr.Value.Count > 0)
{
// 如果有,直接使用第一个
targetId = psr.Value.GetObjectIds()[0];
}
else
{
if (_parentPalette.Dock == DockSides.None)
{
// 2. 如果没有选中,则提示用户去选择
_parentPalette.Visible = false; // 隐藏面板方便用户选择
}
else
{
LocateInListButton.IsEnabled = false;
}
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = false;
PromptEntityOptions peo = new PromptEntityOptions("\n请在图中选择一个地形点块进行定位: ");
peo.SetRejectMessage("\n选择的不是块参照。");
// 允许选择块或点
PromptEntityOptions peo = new PromptEntityOptions("\n请在图中选择一个地形点(块或点)进行定位: ");
peo.SetRejectMessage("\n选择的不是块参照或点。");
peo.AddAllowedClass(typeof(BlockReference), true);
peo.AddAllowedClass(typeof(DBPoint), true);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status == PromptStatus.OK)
@@ -289,7 +292,6 @@ namespace Szmedi.CADkits
}
}
// 3. 如果成功获取到ID则在列表中定位
if (!targetId.IsNull)
{
SelectAndScrollToItem(targetId);
@@ -297,17 +299,84 @@ namespace Szmedi.CADkits
}
finally
{
// 4. 无论如何都恢复UI状态
_isListeningToSelection = true; // 重新开启监听
if (_parentPalette.Dock == DockSides.None)
{
// 操作结束后,重新显示父面板
_parentPalette.Visible = true;
}
_isListeningToSelection = true;
if (_parentPalette.Dock == DockSides.None) _parentPalette.Visible = true;
LocateInListButton.IsEnabled = true;
this.Focus();
}
}
private void ConvertToPointsButton_Click(object sender, RoutedEventArgs e)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
if (doc == null) return;
Database db = doc.Database;
Editor ed = doc.Editor;
int convertCount = 0;
using (DocumentLock docLock = doc.LockDocument())
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
// 遍历列表中所有的项
foreach (var item in ReviewItems)
{
// 获取实体对象,判断是否为多段线
if (item.EntityId.IsErased) continue;
Entity ent = tr.GetObject(item.EntityId, OpenMode.ForRead) as Entity;
if (ent is Polyline pl)
{
try
{
// 1. 计算几何中心
Extents3d ext = pl.GeometricExtents;
Point3d center = ext.MinPoint + (ext.MaxPoint - ext.MinPoint) * 0.5;
// 2. 创建新点 (继承图层和当前的高程)
DBPoint newPoint = new DBPoint(center);
newPoint.Layer = pl.Layer;
newPoint.Color = pl.Color;
btr.AppendEntity(newPoint);
tr.AddNewlyCreatedDBObject(newPoint, true);
// 3. 更新列表中的数据源 (核心步骤)
item.EntityId = newPoint.ObjectId;
item.Handle = newPoint.ObjectId.Handle.Value.ToString();
// 坐标显示也更新一下
item.Position = $"{center.X:F2}, {center.Y:F2}";
// 4. 删除原多段线
pl.UpgradeOpen();
pl.Erase();
convertCount++;
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n转换句柄为 {item.Handle} 的对象时失败: {ex.Message}");
}
}
}
tr.Commit();
}
}
if (convertCount > 0)
{
// 强制刷新 UI 列表显示
ReviewListView.Items.Refresh();
MessageBox.Show($"成功将 {convertCount} 个多段线符号转换为中心点。", "转换完成");
}
else
{
MessageBox.Show("列表中没有检测到可转换的多段线实体。", "提示");
}
}
}
}