using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Linq;
namespace BeamPlugin
{
public class BeamCommands
{
// 梁信息存储类
private class BeamInfo
{
public string Name { get; set; }
public string Size { get; set; }
public double? Elevation { get; set; } // 标高值(单位:米)
}
// 主命令:识别并标注梁 (缩写为 BD)
[CommandMethod("BD")]
public void BeamDimensioning()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
// 1. 点选识别集中标注和原位标注
var beamDict = new Dictionary<ObjectId, BeamInfo>();
IdentifyBeams(ed, tr, beamDict);
// 2. 框选识别所有梁并标注
PromptSelectionResult selRes = ed.GetSelection();
if (selRes.Status == PromptStatus.OK)
{
SelectionSet selSet = selRes.Value;
ProcessBeams(tr, selSet, beamDict);
}
// 3. 清理不需要的图层
CleanupLayers(db); // 传递Database对象
tr.Commit();
}
catch (System.Exception ex) // 明确指定System.Exception
{
ed.WriteMessage($"\n错误: {ex.Message}");
}
}
}
// 识别梁信息
private void IdentifyBeams(Editor ed, Transaction tr, Dictionary<ObjectId, BeamInfo> beamDict)
{
// 点选集中标注(假设为文字实体)
PromptEntityOptions opt = new PromptEntityOptions("\n选择梁集中标注: ");
opt.SetRejectMessage("\n请选择文字对象");
opt.AddAllowedClass(typeof(DBText), false);
PromptEntityResult res = ed.GetEntity(opt);
if (res.Status == PromptStatus.OK)
{
DBText dimText = tr.GetObject(res.ObjectId, OpenMode.ForRead) as DBText;
BeamInfo info = ParseBeamText(dimText.TextString);
beamDict.Add(dimText.OwnerId, info); // 关联到梁实体
}
// 点选原位标注(类似逻辑)
opt.Message = "\n选择梁原位标注: ";
res = ed.GetEntity(opt);
if (res.Status == PromptStatus.OK)
{
DBText dimText = tr.GetObject(res.ObjectId, OpenMode.ForRead) as DBText;
BeamInfo info = ParseBeamText(dimText.TextString);
beamDict.Add(dimText.OwnerId, info);
}
}
// 解析梁文本信息
private BeamInfo ParseBeamText(string text)
{
var info = new BeamInfo();
// 示例解析逻辑
if (text.Contains(";"))
{
string[] parts = text.Split(';');
info.Name = parts[0].Trim();
if (parts.Length > 1 && double.TryParse(parts[1], out double elev))
info.Elevation = elev;
}
else
{
info.Name = text;
}
// 从名称中提取尺寸(示例:2-Lg22(6) 600x800)
if (info.Name.Contains(" "))
{
string[] nameParts = info.Name.Split(' ');
info.Name = nameParts[0];
if (nameParts.Length > 1 && nameParts[1].Contains('x'))
{
info.Size = nameParts[1];
}
}
return info;
}
// 处理梁并标注
private void ProcessBeams(Transaction tr, SelectionSet selSet, Dictionary<ObjectId, BeamInfo> beamDict)
{
BlockTable bt = (BlockTable)tr.GetObject(tr.Database.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
foreach (SelectedObject selObj in selSet)
{
if (selObj != null)
{
Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity;
if (ent != null && ent is Polyline && ent.Layer == "梁") // 假设梁在"梁"图层
{
Polyline beam = ent as Polyline;
BeamInfo info = FindBeamInfo(beam, beamDict);
if (info != null)
{
// 创建梁标注
DBText label = CreateBeamLabel(beam, info);
btr.AppendEntity(label);
tr.AddNewlyCreatedDBObject(label, true);
}
}
}
}
}
// 查找梁信息(支持同名匹配)
private BeamInfo FindBeamInfo(Polyline beam, Dictionary<ObjectId, BeamInfo> beamDict)
{
// 1. 尝试直接获取
if (beamDict.TryGetValue(beam.ObjectId, out BeamInfo directInfo))
return directInfo;
// 2. 通过同名匹配
string beamName = GetBeamName(beam);
if (!string.IsNullOrEmpty(beamName))
{
return beamDict.Values.FirstOrDefault(v => v.Name.StartsWith(beamName));
}
return null;
}
// 获取梁名称(从未标注梁中提取)
private string GetBeamName(Polyline beam)
{
// 实际项目中应根据图层/扩展数据等获取
// 示例:从图层名提取(图层格式为"梁-名称")
return beam.Layer.Contains('-')
? beam.Layer.Split('-').Last()
: beam.Layer;
}
// 获取梁中点坐标 (修复GetPointAtDist参数问题)
private Point3d GetBeamMidPoint(Polyline beam)
{
double halfLength = beam.Length / 2;
return beam.GetPointAtDist(halfLength);
}
// 估算文字宽度
private double EstimateTextWidth(string text, double height)
{
// 近似计算:每个字符宽度=高度的0.7倍
return text.Length * height * 0.7;
}
// 创建梁标注文字
private DBText CreateBeamLabel(Polyline beam, BeamInfo info)
{
Point3d midPoint = GetBeamMidPoint(beam);
double textHeight = 150; // 标注高度
DBText label = new DBText
{
Position = midPoint,
TextString = FormatLabelText(info, beam.Length),
Height = textHeight,
Layer = "梁标注",
AlignmentPoint = midPoint,
Justify = AttachmentPoint.MiddleCenter
};
// 自动调整文字大小
double textWidth = EstimateTextWidth(label.TextString, textHeight);
if (textWidth > beam.Length * 0.8) // 超过梁长的80%
{
label.Height = textHeight * (beam.Length * 0.8 / textWidth);
}
return label;
}
// 格式化标注文本
private string FormatLabelText(BeamInfo info, double beamLength)
{
string label = info.Name;
if (!string.IsNullOrEmpty(info.Size))
label += " " + info.Size;
if (info.Elevation.HasValue)
{
label += $";{info.Elevation.Value.ToString(info.Elevation.Value < 0 ? "0.00" : "0")}";
}
return label;
}
// 清理图层
private void CleanupLayers(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
// 要保留的图层
string[] keepLayers = { "轴网", "轴号", "梁", "墙", "柱", "尺寸标注", "填充" };
foreach (ObjectId layerId in lt)
{
LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForRead);
if (!keepLayers.Contains(ltr.Name))
{
// 删除非保留图层上的所有实体
DeleteEntitiesOnLayer(tr, db, ltr.Name);
}
}
tr.Commit();
}
}
// 删除指定图层上的所有实体 (修复遍历问题)
private void DeleteEntitiesOnLayer(Transaction tr, Database db, string layerName)
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
// 使用安全方式遍历
ObjectIdCollection idsToErase = new ObjectIdCollection();
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent != null && ent.Layer == layerName)
{
idsToErase.Add(id);
}
}
// 单独执行删除
foreach (ObjectId id in idsToErase)
{
Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity;
if (ent != null && !ent.IsErased)
{
ent.Erase();
}
}
}
// 统计梁截面命令 (缩写为 BS)
[CommandMethod("BS")]
public void BeamStatistics()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptSelectionResult selRes = ed.GetSelection();
if (selRes.Status != PromptStatus.OK) return;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
try
{
// 统计梁截面尺寸
var sizeStats = new Dictionary<string, int>();
foreach (SelectedObject selObj in selRes.Value)
{
Entity ent = tr.GetObject(selObj.ObjectId, OpenMode.ForRead) as Entity;
if (ent is Polyline && ent.Layer == "梁")
{
// 从梁标注中提取尺寸
string beamSize = ExtractBeamSize(ent);
if (!string.IsNullOrEmpty(beamSize))
{
if (sizeStats.ContainsKey(beamSize))
{
sizeStats[beamSize]++;
}
else
{
sizeStats[beamSize] = 1;
}
}
}
}
// 生成统计表格
GenerateStatisticsTable(ed, tr, sizeStats);
tr.Commit();
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n错误: {ex.Message}");
}
}
}
private string ExtractBeamSize(Entity ent)
{
// 实际实现从梁实体或标注中提取尺寸
// 这里返回模拟数据
return "600x800";
}
private void GenerateStatisticsTable(Editor ed, Transaction tr, Dictionary<string, int> sizeStats)
{
// 创建统计表格
ed.WriteMessage("\n梁截面尺寸统计:");
foreach (var kvp in sizeStats.OrderBy(x => x.Key))
{
ed.WriteMessage($"\n尺寸 {kvp.Key}: {kvp.Value} 根");
}
}
}
}
S1061“Transaction”未包含”Database”的定义,并且找不到可接受第一个“Transaction”类型参数的可访问扩展方法”Database”(是否缺少using 指令或程序集引用?