using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.GraphicsInterface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
// 使用别名解决 Exception 冲突
using SysException = System.Exception;
using AecException = Autodesk.AutoCAD.Runtime.Exception;
namespace ScaffoldPlugin
{
public class ScaffoldCommands
{
#region 常量配置(使用嵌入式图块映射表)
// 杆件长度配置
private static readonly double[] BarLengths = { 300, 600, 900, 1200, 1500, 1800 };
// 嵌入式图块映射表
private static readonly Dictionary<string, string> EmbeddedBlockMap = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
// 立杆
{ "ScaffoldPole立杆", "ScaffoldPole立杆" },
// 横杆系列
{ "ScaffoldPole横杆300mm", "ScaffoldPole横杆300mm" },
{ "ScaffoldPole横杆600mm", "ScaffoldPole横杆600mm" },
{ "ScaffoldPole横杆900mm", "ScaffoldPole横杆900mm" },
{ "ScaffoldPole横杆1200mm", "ScaffoldPole横杆1200mm" },
{ "ScaffoldPole横杆1500mm", "ScaffoldPole横杆1500mm" },
{ "ScaffoldPole横杆1800mm", "ScaffoldPole横杆1800mm" },
// 水平斜拉杆系列
{ "ScaffoldPole水平斜拉杆300mm", "ScaffoldPole水平斜拉杆300mm" },
{ "ScaffoldPole水平斜拉杆600mm", "ScaffoldPole水平斜拉杆600mm" },
{ "ScaffoldPole水平斜拉杆900mm", "ScaffoldPole水平斜拉杆900mm" },
{ "ScaffoldPole水平斜拉杆1200mm", "ScaffoldPole水平斜拉杆1200mm" },
{ "ScaffoldPole水平斜拉杆1500mm", "ScaffoldPole水平斜拉杆1500mm" },
{ "ScaffoldPole水平斜拉杆1800mm", "ScaffoldPole水平斜拉杆1800mm" },
// 其他可能用到的图块
{ "ScaffoldPole90度阳角型钢", "ScaffoldPole90度阳角型钢" },
{ "ScaffoldPole右45度角型钢", "ScaffoldPole右45度角型钢" },
{ "ScaffoldPole左45度角型钢", "ScaffoldPole左45度角型钢" },
{ "ScaffoldPole底托", "ScaffoldPole底托" },
{ "ScaffoldPole顶托", "ScaffoldPole顶托" }
};
// 容差参数
private const double ToleranceValue = 0.1;
private const double SpacingTolerance = 150.0;
private const double MinAxisLength = 100.0;
private const double MinDistanceForBar = 50.0;
private const double MaxGapFactor = 1.2;
private const double SkipTolerance = 1.0;
// 块名称定义
private const string PoleBlockName = "ScaffoldPole立杆";
private const string BarPrefix = "ScaffoldPole横杆";
private const string DiagonalBarPrefix = "ScaffoldPole水平斜拉杆";
// 图层定义
private const string PoleLayer = "盘扣-立杆";
private const string BarLayer = "盘扣-横杆";
private const string DiagonalBarLayer = "盘扣-斜拉杆";
private const string AxisLayer = "盘扣轴网";
private const string DebugLayer = "盘扣-调试";
#endregion
#region BP命令及辅助方法
[CommandMethod("BuildPlatform", "BP", CommandFlags.Modal)]
public void BuildPlatform()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 创建必要图层
CreateLayers(db);
// 选择轴网线
var axisLines = GetAxisLines(ed);
if (axisLines.Count == 0)
return;
// 计算交点
List<Point3d> intersections = CalculateIntersections(axisLines);
ed.WriteMessage($"\n共找到 {intersections.Count} 个有效交点");
// 加载块定义 - 修改为使用嵌入式映射表
if (!LoadBlockDefinitionsFromEmbeddedMap(db, ed))
return;
// 缓存现有实体
BuildExistingEntityCache(db);
// 布置立杆
int poleCount = PlacePoles(db, intersections, ed);
ed.WriteMessage($"\n已布置 {poleCount} 根立杆");
// 布置横杆
int barCount = PlaceBars(db, intersections, axisLines, ed);
ed.WriteMessage($"\n已布置 {barCount} 根横杆");
// 结果反馈
if (poleCount > 0 || barCount > 0)
{
Application.ShowAlertDialog($"成功布置 {poleCount}根立杆和{barCount}根横杆!");
}
else
{
ShowErrorDialog("脚手架布置失败,未布置任何构件!");
}
}
catch (AecException ex)
{
HandleException(ed, ex);
}
catch (SysException ex)
{
HandleException(ed, ex);
}
}
// 从嵌入式映射表加载块定义
private bool LoadBlockDefinitionsFromEmbeddedMap(Database db, Editor ed)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
bool allBlocksLoaded = true;
List<string> missingBlocks = new List<string>();
// 检查并加载立杆块
if (!bt.Has(PoleBlockName))
{
if (EmbeddedBlockMap.ContainsKey(PoleBlockName))
{
if (!LoadBlockUsingQuickInsert(PoleBlockName))
{
missingBlocks.Add(PoleBlockName);
allBlocksLoaded = false;
}
else
{
ed.WriteMessage($"\n已加载立杆块: {PoleBlockName}");
}
}
else
{
missingBlocks.Add(PoleBlockName);
allBlocksLoaded = false;
}
}
// 检查并加载横杆块
foreach (double len in BarLengths)
{
string barName = $"{BarPrefix}{len}mm";
if (!bt.Has(barName))
{
if (EmbeddedBlockMap.ContainsKey(barName))
{
if (!LoadBlockUsingQuickInsert(barName))
{
missingBlocks.Add(barName);
allBlocksLoaded = false;
}
else
{
ed.WriteMessage($"\n已加载横杆块: {barName}");
}
}
else
{
missingBlocks.Add(barName);
allBlocksLoaded = false;
}
}
}
// 检查并加载斜拉杆块
foreach (double len in BarLengths)
{
string diagonalName = $"{DiagonalBarPrefix}{len}mm";
if (!bt.Has(diagonalName))
{
if (EmbeddedBlockMap.ContainsKey(diagonalName))
{
if (!LoadBlockUsingQuickInsert(diagonalName))
{
// 如果斜拉杆块不存在,尝试使用横杆块作为替代
string barName = $"{BarPrefix}{len}mm";
if (bt.Has(barName))
{
CopyBlockDefinition(db, barName, diagonalName);
ed.WriteMessage($"\n已创建替代斜拉杆块: {diagonalName} (基于 {barName})");
}
else
{
missingBlocks.Add(diagonalName);
allBlocksLoaded = false;
}
}
else
{
ed.WriteMessage($"\n已加载斜拉杆块: {diagonalName}");
}
}
else
{
// 如果映射表中没有斜拉杆,尝试使用横杆作为替代
string barName = $"{BarPrefix}{len}mm";
if (bt.Has(barName))
{
CopyBlockDefinition(db, barName, diagonalName);
ed.WriteMessage($"\n已创建替代斜拉杆块: {diagonalName} (基于 {barName})");
}
else
{
missingBlocks.Add(diagonalName);
allBlocksLoaded = false;
}
}
}
}
if (!allBlocksLoaded)
{
string missingList = string.Join(", ", missingBlocks);
ed.WriteMessage($"\n警告:以下块未能加载: {missingList}");
ed.WriteMessage($"\n请使用QUICKINSERT命令手动加载缺失的块");
// 询问用户是否继续
PromptKeywordOptions pko = new PromptKeywordOptions(
$"\n有 {missingBlocks.Count} 个块未能自动加载,是否继续?[是(Y)/否(N)]");
pko.Keywords.Add("是");
pko.Keywords.Add("否");
pko.Keywords.Default = "是";
PromptResult pr = ed.GetKeywords(pko);
if (pr.Status != PromptStatus.OK || pr.StringResult == "否")
{
return false;
}
}
tr.Commit();
return true;
}
}
// 使用QUICKINSERT命令加载块
private bool LoadBlockUsingQuickInsert(string blockName)
{
try
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
// 在映射表中查找块
if (EmbeddedBlockMap.ContainsKey(blockName))
{
string mappedName = EmbeddedBlockMap[blockName];
// 执行QUICKINSERT命令来加载块
object result = Application.Invoke(
typeof(Application),
"SendStringToExecute",
doc,
$"(command \"QUICKINSERT\" \"{mappedName}\" \"\" \"\" \"\" \"\")\n");
ed.WriteMessage($"\n正在加载块: {mappedName}");
return true;
}
else
{
ed.WriteMessage($"\n警告:块 {blockName} 不在嵌入式映射表中");
return false;
}
}
catch (SysException ex)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
doc.Editor.WriteMessage($"\n加载块 {blockName} 失败: {ex.Message}");
return false;
}
}
// 复制块定义
private void CopyBlockDefinition(Database db, string sourceBlockName, string targetBlockName)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt.Has(sourceBlockName) && !bt.Has(targetBlockName))
{
BlockTableRecord sourceBtr = tr.GetObject(bt[sourceBlockName], OpenMode.ForRead) as BlockTableRecord;
BlockTableRecord targetBtr = new BlockTableRecord();
targetBtr.Name = targetBlockName;
// 复制源块定义中的所有实体
foreach (ObjectId id in sourceBtr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent != null)
{
Entity clonedEnt = ent.Clone() as Entity;
targetBtr.AppendEntity(clonedEnt);
tr.AddNewlyCreatedDBObject(clonedEnt, true);
}
}
bt.UpgradeOpen();
ObjectId targetId = bt.Add(targetBtr);
tr.AddNewlyCreatedDBObject(targetBtr, true);
}
tr.Commit();
}
}
private void CreateLayers(Database db)
{
CreateLayerIfNotExists(db, PoleLayer, 7);
CreateLayerIfNotExists(db, BarLayer, 1);
CreateLayerIfNotExists(db, DiagonalBarLayer, 4);
CreateLayerIfNotExists(db, AxisLayer, 3);
CreateLayerIfNotExists(db, DebugLayer, 2);
}
private List<Line> GetAxisLines(Editor ed)
{
var filter = new SelectionFilter(new[] {
new TypedValue(0, "LINE"),
new TypedValue(8, AxisLayer)
});
PromptSelectionResult selection = ed.GetSelection(
new PromptSelectionOptions
{
MessageForAdding = "\n选择盘扣轴网线: "
},
filter
);
if (selection.Status != PromptStatus.OK)
return new List<Line>();
List<Line> lines = new List<Line>();
using (Transaction tr = ed.Document.TransactionManager.StartTransaction())
{
foreach (ObjectId id in selection.Value.GetObjectIds())
{
Line line = tr.GetObject(id, OpenMode.ForRead) as Line;
if (line != null && line.Length > MinAxisLength)
{
lines.Add(line.Clone() as Line);
}
}
tr.Commit();
}
ed.WriteMessage($"\n已选择 {lines.Count} 条有效轴网线");
return lines;
}
private List<Point3d> CalculateIntersections(List<Line> lines)
{
var results = new HashSet<Point3d>(new Point3dComparer(ToleranceValue));
for (int i = 0; i < lines.Count; i++)
{
for (int j = i + 1; j < lines.Count; j++)
{
Point3dCollection pts = new Point3dCollection();
lines[i].IntersectWith(lines[j], Intersect.OnBothOperands, pts, IntPtr.Zero, IntPtr.Zero);
foreach (Point3d pt in pts)
{
if (IsPointOnLineSegment(pt, lines[i], ToleranceValue) &&
IsPointOnLineSegment(pt, lines[j], ToleranceValue))
{
results.Add(pt);
}
}
}
}
return results.ToList();
}
private bool IsPointOnLineSegment(Point3d pt, Line line, double tolerance)
{
Vector3d lineVec = line.EndPoint - line.StartPoint;
Vector3d startToPt = pt - line.StartPoint;
double dotProduct = lineVec.DotProduct(startToPt);
if (dotProduct < -tolerance || dotProduct > lineVec.LengthSqrd + tolerance)
return false;
double distSq = startToPt.LengthSqrd - (dotProduct * dotProduct) / lineVec.LengthSqrd;
return distSq <= tolerance * tolerance;
}
private void BuildExistingEntityCache(Database db)
{
_existingEntitiesCache = new HashSet<(string, Point3d, double)>(new EntityKeyComparer());
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForRead) as BlockTableRecord;
foreach (ObjectId id in btr)
{
BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
if (br != null && (br.Name == PoleBlockName || br.Name.StartsWith(BarPrefix) || br.Name.StartsWith(DiagonalBarPrefix)))
{
_existingEntitiesCache.Add((br.Name, br.Position, br.Rotation));
}
}
}
}
private int PlacePoles(Database db, List<Point3d> points, Editor ed)
{
int count = 0;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;
if (!bt.Has(PoleBlockName))
{
ShowErrorDialog($"错误:立杆块 {PoleBlockName} 未加载!");
return 0;
}
ObjectId poleBlockId = bt[PoleBlockName];
foreach (Point3d pt in points)
{
if (double.IsNaN(pt.X) || double.IsNaN(pt.Y)) continue;
if (IsCached(PoleBlockName, pt, 0)) continue;
BlockReference br = new BlockReference(pt, poleBlockId);
br.Layer = PoleLayer;
btr.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
count++;
}
tr.Commit();
}
return count;
}
private int PlaceBars(Database db, List<Point3d> points, List<Line> axisLines, Editor ed)
{
int count = 0;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord;
foreach (Line axisLine in axisLines)
{
List<Point3d> linePoints = points.Where(p =>
IsPointOnLineSegment(p, axisLine, ToleranceValue)).ToList();
if (linePoints.Count < 2) continue;
linePoints = SortPointsByLineParam(axisLine, linePoints);
List<Segment> segments = GroupPointsIntoSegments(linePoints);
foreach (Segment segment in segments)
{
for (int i = 0; i < segment.Points.Count - 1; i++)
{
Point3d start = segment.Points[i];
Point3d end = segment.Points[i + 1];
double distance = start.DistanceTo(end);
if (distance < MinDistanceForBar) continue;
double bestLength = FindBestBarLength(distance);
if (bestLength < 0) continue;
string blockName = $"{BarPrefix}{bestLength}mm";
if (!bt.Has(blockName)) continue;
Point3d midPoint = new Point3d(
(start.X + end.X) / 2,
(start.Y + end.Y) / 2,
(start.Z + end.Z) / 2);
Vector3d direction = (end - start).GetNormal();
double angle = Math.Atan2(direction.Y, direction.X);
if (IsCached(blockName, midPoint, angle)) continue;
BlockReference br = new BlockReference(midPoint, bt[blockName]);
br.Layer = BarLayer;
br.Rotation = angle;
btr.AppendEntity(br);
tr.AddNewlyCreatedDBObject(br, true);
count++;
}
}
}
tr.Commit();
}
return count;
}
private double FindBestBarLength(double distance)
{
double bestLength = -1;
double minDiff = double.MaxValue;
foreach (double len in BarLengths)
{
double diff = Math.Abs(len - distance);
if (diff < minDiff && diff <= SpacingTolerance)
{
minDiff = diff;
bestLength = len;
}
}
return bestLength;
}
private List<Point3d> SortPointsByLineParam(Line line, List<Point3d> points)
{
Vector3d lineVec = line.EndPoint - line.StartPoint;
double lineLength = lineVec.Length;
return points
.Select(p => new {
Point = p,
Param = lineVec.DotProduct(p - line.StartPoint) / lineLength
})
.OrderBy(x => x.Param)
.Select(x => x.Point)
.ToList();
}
private List<Segment> GroupPointsIntoSegments(List<Point3d> points)
{
List<Segment> segments = new List<Segment>();
if (points.Count < 2) return segments;
double maxGap = BarLengths.Max() * MaxGapFactor;
Segment currentSegment = new Segment { Points = { points[0] } };
for (int i = 1; i < points.Count; i++)
{
double distance = points[i - 1].DistanceTo(points[i]);
if (distance > maxGap)
{
if (currentSegment.Points.Count > 1) segments.Add(currentSegment);
currentSegment = new Segment { Points = { points[i] } };
}
else
{
currentSegment.Points.Add(points[i]);
}
}
if (currentSegment.Points.Count > 1) segments.Add(currentSegment);
return segments;
}
private void CreateLayerIfNotExists(Database db, string layerName, short colorIndex)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
if (lt.Has(layerName)) return;
lt.UpgradeOpen();
LayerTableRecord ltr = new LayerTableRecord
{
Name = layerName,
Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex)
};
lt.Add(ltr);
tr.AddNewlyCreatedDBObject(ltr, true);
tr.Commit();
}
}
private bool IsCached(string blockName, Point3d pos, double angle)
{
return _existingEntitiesCache?.Contains((blockName, pos, angle)) ?? false;
}
#endregion
#region 更换构件命令(使用嵌入式图块映射表)
[CommandMethod("ChangeComponent", "CC", CommandFlags.Modal)]
public void ChangeComponent()
{
ChangeComponentInternal(BarPrefix, BarLayer, "横杆");
}
[CommandMethod("ChangeDiagonal", "CD", CommandFlags.Modal)]
public void ChangeDiagonal()
{
ChangeComponentInternal(DiagonalBarPrefix, DiagonalBarLayer, "斜拉杆");
}
// 通用的更换构件方法
private void ChangeComponentInternal(string componentPrefix, string componentLayer, string componentName)
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 选择需要变换的对象
PromptSelectionResult selectionResult = ed.GetSelection(
new PromptSelectionOptions { MessageForAdding = $"\n请选择需要变换的{componentName}对象: " });
if (selectionResult.Status != PromptStatus.OK)
return;
ObjectId[] selectedIds = selectionResult.Value.GetObjectIds();
if (selectedIds.Length == 0)
return;
// 过滤出指定类型的块参照并收集信息
List<BarInfo> barInfos = new List<BarInfo>();
Point3d firstBarInsertPoint = Point3d.Origin;
double firstBarRotation = 0;
double firstBarLength = 0;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (ObjectId id in selectedIds)
{
if (id.ObjectClass.Name == "AcDbBlockReference")
{
BlockReference br = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
if (br != null && br.Name.StartsWith(componentPrefix))
{
// 从块名中提取长度
string lengthStr = br.Name.Replace(componentPrefix, "").Replace("mm", "");
if (double.TryParse(lengthStr, out double length))
{
barInfos.Add(new BarInfo
{
Id = id,
Position = br.Position,
Rotation = br.Rotation,
Length = length,
Layer = br.Layer,
OriginalStartPoint = CalculateStartPoint(br.Position, br.Rotation, length),
OriginalEndPoint = CalculateEndPoint(br.Position, br.Rotation, length)
});
// 获取第一个横杆的信息
if (firstBarInsertPoint == Point3d.Origin)
{
firstBarInsertPoint = br.Position;
firstBarRotation = br.Rotation;
firstBarLength = length;
}
}
}
}
}
tr.Commit();
}
if (barInfos.Count == 0)
{
ed.WriteMessage($"\n未选择任何{componentName}对象!");
return;
}
// 确保块定义已加载(使用嵌入式映射表)
if (!EnsureBlockDefinitionsLoadedFromEmbedded(db, ed, componentPrefix, componentName))
{
// 对于斜拉杆,如果块不存在,尝试使用横杆块作为替代
if (componentPrefix == DiagonalBarPrefix)
{
ed.WriteMessage($"\n警告:斜拉杆块未找到,将使用横杆块作为替代");
// 尝试从横杆块创建斜拉杆块
if (!CreateDiagonalBlocksFromBars(db, ed))
{
ed.WriteMessage($"\n错误:无法创建斜拉杆块替代!");
return;
}
}
else
{
ed.WriteMessage($"\n错误:{componentName}块定义未加载!");
return;
}
}
// 计算第一个横杆的端点和基点
Vector3d direction = new Vector3d(Math.Cos(firstBarRotation), Math.Sin(firstBarRotation), 0);
Point3d leftEndpoint = CalculateStartPoint(firstBarInsertPoint, firstBarRotation, firstBarLength);
Point3d rightEndpoint = CalculateEndPoint(firstBarInsertPoint, firstBarRotation, firstBarLength);
// 默认使用左端点作为基点
Point3d basePoint = leftEndpoint;
int basePointMode = 0; // 0:左端点, 1:右端点, 2:中心点
// 当前选择的长度
double currentLength = firstBarLength;
// 使用Jig实现实时预览
ChangeComponentJig jig = new ChangeComponentJig(barInfos, basePoint, currentLength, basePointMode, componentPrefix);
// 主循环
while (true)
{
// 设置Jig参数
jig.BasePoint = basePoint;
jig.CurrentLength = currentLength;
jig.BasePointMode = basePointMode;
jig.ComponentPrefix = componentPrefix;
// 运行Jig
PromptResult jigResult = ed.Drag(jig);
if (jigResult.Status == PromptStatus.Keyword)
{
string keyword = jig.KeywordResult;
if (keyword == "S") // 长度选项
{
// 创建长度选项
PromptKeywordOptions pko = new PromptKeywordOptions(
$"\n请选择需要更改的{componentName}长度[300mm/600mm/900mm/1200mm/1500mm/1800mm]: ");
// 只列出实际存在的块长度
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
foreach (double len in BarLengths)
{
string blockName = $"{componentPrefix}{len}mm";
if (bt.Has(blockName) || EmbeddedBlockMap.ContainsKey(blockName))
{
pko.Keywords.Add($"{len}mm");
}
}
tr.Commit();
}
pko.Keywords.Default = $"{currentLength}mm";
pko.AllowNone = true;
PromptResult pkr = ed.GetKeywords(pko);
if (pkr.Status == PromptStatus.OK)
{
string selectedLengthStr = pkr.StringResult.Replace("mm", "");
if (double.TryParse(selectedLengthStr, out double newLength))
{
// 确保新长度的块定义已加载
string newBlockName = $"{componentPrefix}{newLength}mm";
if (!CheckBlockExists(db, newBlockName))
{
// 使用嵌入式映射表加载块
if (EmbeddedBlockMap.ContainsKey(newBlockName))
{
if (!LoadBlockUsingQuickInsert(newBlockName))
{
// 对于斜拉杆,如果块不存在,尝试使用横杆块作为替代
if (componentPrefix == DiagonalBarPrefix)
{
string barBlockName = $"{BarPrefix}{newLength}mm";
if (CheckBlockExists(db, barBlockName) || EmbeddedBlockMap.ContainsKey(barBlockName))
{
if (!CheckBlockExists(db, barBlockName))
{
LoadBlockUsingQuickInsert(barBlockName);
}
// 复制横杆块作为斜拉杆块
CopyBlockDefinition(db, barBlockName, newBlockName);
ed.WriteMessage($"\n已创建替代斜拉杆块: {newBlockName}");
}
else
{
ed.WriteMessage($"\n错误:找不到{newBlockName}块定义!");
continue;
}
}
else
{
ed.WriteMessage($"\n错误:找不到{newBlockName}块定义!");
continue;
}
}
}
else
{
ed.WriteMessage($"\n错误:找不到{newBlockName}块定义!");
continue;
}
}
// 计算新长度下的基点偏移,确保基点位置不变
double lengthDiff = newLength - currentLength;
Vector3d offset = direction * (basePointMode == 1 ? lengthDiff : 0);
if (basePointMode == 2) // 中心点模式
{
offset = direction * (lengthDiff / 2);
}
basePoint = basePoint + offset;
currentLength = newLength;
ed.WriteMessage($"\n已选择 {newLength}mm {componentName}");
}
}
}
else if (keyword == "D") // 拾取点选项
{
// 切换基点模式
basePointMode = (basePointMode + 1) % 3;
// 更新基点
if (basePointMode == 0)
{
basePoint = CalculateStartPoint(firstBarInsertPoint, firstBarRotation, currentLength);
ed.WriteMessage("\n已切换到左端点");
}
else if (basePointMode == 1)
{
basePoint = CalculateEndPoint(firstBarInsertPoint, firstBarRotation, currentLength);
ed.WriteMessage("\n已切换到右端点");
}
else
{
basePoint = firstBarInsertPoint;
ed.WriteMessage("\n已切换到中心点");
}
// 更新Jig的基点
jig.BasePoint = basePoint;
jig.BasePointMode = basePointMode;
}
}
else if (jigResult.Status == PromptStatus.OK) // 指定了插入点
{
// 删除原位置的杆件
DeleteOriginalBars(db, barInfos);
// 应用变换
ApplyChanges(db, barInfos, jig.DisplacementMatrix, currentLength, jig.BasePointMode, componentPrefix, componentLayer);
ed.WriteMessage($"\n已更换 {barInfos.Count} 根{componentName}");
break;
}
else
{
break;
}
}
}
catch (AecException ex)
{
HandleException(ed, ex);
}
catch (SysException ex)
{
HandleException(ed, ex);
}
}
// 从横杆块创建斜拉杆块
private bool CreateDiagonalBlocksFromBars(Database db, Editor ed)
{
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
foreach (double len in BarLengths)
{
string barBlockName = $"{BarPrefix}{len}mm";
string diagonalBlockName = $"{DiagonalBarPrefix}{len}mm";
if ((bt.Has(barBlockName) || EmbeddedBlockMap.ContainsKey(barBlockName)) && !bt.Has(diagonalBlockName))
{
// 如果横杆块不存在但映射表中有,先加载横杆块
if (!bt.Has(barBlockName) && EmbeddedBlockMap.ContainsKey(barBlockName))
{
LoadBlockUsingQuickInsert(barBlockName);
}
// 复制横杆块定义作为斜拉杆块
CopyBlockDefinition(db, barBlockName, diagonalBlockName);
ed.WriteMessage($"\n已创建替代斜拉杆块: {diagonalBlockName} (基于 {barBlockName})");
}
}
tr.Commit();
}
return true;
}
catch (SysException ex)
{
ed.WriteMessage($"\n错误:创建斜拉杆块失败: {ex.Message}");
return false;
}
}
// 确保块定义已加载(使用嵌入式映射表)
private bool EnsureBlockDefinitionsLoadedFromEmbedded(Database db, Editor ed, string componentPrefix, string componentName)
{
bool atLeastOneLoaded = false;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
// 加载指定前缀的所有块
foreach (double len in BarLengths)
{
string blockName = $"{componentPrefix}{len}mm";
if (!bt.Has(blockName))
{
if (EmbeddedBlockMap.ContainsKey(blockName))
{
if (LoadBlockUsingQuickInsert(blockName))
{
ed.WriteMessage($"\n已加载{componentName}块: {blockName}");
atLeastOneLoaded = true;
}
}
}
else
{
atLeastOneLoaded = true;
}
}
tr.Commit();
}
return atLeastOneLoaded;
}
// 检查块是否存在
private bool CheckBlockExists(Database db, string blockName)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
return bt.Has(blockName);
}
}
// 计算杆件起点
private Point3d CalculateStartPoint(Point3d position, double rotation, double length)
{
Vector3d direction = new Vector3d(Math.Cos(rotation), Math.Sin(rotation), 0);
return position - (direction * length / 2);
}
// 计算杆件终点
private Point3d CalculateEndPoint(Point3d position, double rotation, double length)
{
Vector3d direction = new Vector3d(Math.Cos(rotation), Math.Sin(rotation), 0);
return position + (direction * length / 2);
}
// 删除原位置的杆件
private void DeleteOriginalBars(Database db, List<BarInfo> barInfos)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
foreach (BarInfo barInfo in barInfos)
{
BlockReference br = tr.GetObject(barInfo.Id, OpenMode.ForWrite) as BlockReference;
if (br != null)
{
br.Erase(true);
}
}
tr.Commit();
}
}
// 应用变换到实际对象
private void ApplyChanges(Database db, List<BarInfo> barInfos, Matrix3d displacementMatrix,
double newLength, int basePointMode, string componentPrefix, string componentLayer)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
string newBlockName = $"{componentPrefix}{newLength}mm";
// 确保新块已加载
if (!bt.Has(newBlockName))
{
// 使用嵌入式映射表加载块
if (EmbeddedBlockMap.ContainsKey(newBlockName))
{
if (!LoadBlockUsingQuickInsert(newBlockName))
{
// 对于斜拉杆,如果块不存在,尝试使用横杆块作为替代
if (componentPrefix == DiagonalBarPrefix)
{
string barBlockName = $"{BarPrefix}{newLength}mm";
if (bt.Has(barBlockName) || EmbeddedBlockMap.ContainsKey(barBlockName))
{
if (!bt.Has(barBlockName))
{
LoadBlockUsingQuickInsert(barBlockName);
}
// 复制横杆块作为斜拉杆块
CopyBlockDefinition(db, barBlockName, newBlockName);
}
else
{
ShowErrorDialog($"找不到{componentPrefix.Replace("ScaffoldPole", "")}块文件: {newBlockName}");
return;
}
}
else
{
ShowErrorDialog($"找不到{componentPrefix.Replace("ScaffoldPole", "")}块文件: {newBlockName}");
return;
}
}
}
else
{
ShowErrorDialog($"找不到{componentPrefix.Replace("ScaffoldPole", "")}块文件: {newBlockName}");
return;
}
}
ObjectId newBlockId = bt[newBlockName];
if (newBlockId.IsNull)
{
ShowErrorDialog($"无法加载{componentPrefix.Replace("ScaffoldPole", "")}块: {newBlockName}");
return;
}
foreach (BarInfo barInfo in barInfos)
{
// 计算新位置,确保基点对齐
Point3d originalBasePoint;
if (basePointMode == 0)
originalBasePoint = barInfo.OriginalStartPoint;
else if (basePointMode == 1)
originalBasePoint = barInfo.OriginalEndPoint;
else
originalBasePoint = barInfo.Position;
// 修正:使用Matrix3d的Translation属性获取位移向量
Vector3d displacement = displacementMatrix.Translation;
// 计算新基点
Point3d newBasePoint = originalBasePoint + displacement;
// 根据基点计算新的块插入点
Vector3d direction = new Vector3d(Math.Cos(barInfo.Rotation), Math.Sin(barInfo.Rotation), 0);
Point3d newPosition;
if (basePointMode == 0) // 左端点为基点
newPosition = newBasePoint + (direction * newLength / 2);
else if (basePointMode == 1) // 右端点为基点
newPosition = newBasePoint - (direction * newLength / 2);
else // 中心点为基点
newPosition = newBasePoint;
// 创建新的块引用
BlockReference newBr = new BlockReference(newPosition, newBlockId);
newBr.Layer = componentLayer; // 使用传入的图层
newBr.Rotation = barInfo.Rotation;
// 添加到模型空间
BlockTableRecord btr = tr.GetObject(SymbolUtilityServices.GetBlockModelSpaceId(db),
OpenMode.ForWrite) as BlockTableRecord;
btr.AppendEntity(newBr);
tr.AddNewlyCreatedDBObject(newBr, true);
}
tr.Commit();
}
}
// 横杆信息类
private class BarInfo
{
public ObjectId Id { get; set; }
public Point3d Position { get; set; }
public double Rotation { get; set; }
public double Length { get; set; }
public string Layer { get; set; }
public Point3d OriginalStartPoint { get; set; }
public Point3d OriginalEndPoint { get; set; }
}
// Jig类用于实时预览
private class ChangeComponentJig : DrawJig
{
private List<BarInfo> _barInfos;
private Point3d _basePoint;
private double _currentLength;
private Matrix3d _displacementMatrix;
private Point3d _dragPoint;
private string _keywordResult;
private int _basePointMode;
private string _componentPrefix;
public ChangeComponentJig(List<BarInfo> barInfos, Point3d basePoint, double currentLength, int basePointMode, string componentPrefix)
{
_barInfos = barInfos;
_basePoint = basePoint;
_currentLength = currentLength;
_basePointMode = basePointMode;
_componentPrefix = componentPrefix;
_displacementMatrix = Matrix3d.Identity;
_dragPoint = basePoint;
_keywordResult = null;
}
public Point3d BasePoint
{
get { return _basePoint; }
set { _basePoint = value; }
}
public double CurrentLength
{
get { return _currentLength; }
set { _currentLength = value; }
}
public int BasePointMode
{
get { return _basePointMode; }
set { _basePointMode = value; }
}
public string ComponentPrefix
{
get { return _componentPrefix; }
set { _componentPrefix = value; }
}
public Matrix3d DisplacementMatrix
{
get { return _displacementMatrix; }
}
public string KeywordResult
{
get { return _keywordResult; }
}
protected override SamplerStatus Sampler(JigPrompts prompts)
{
JigPromptPointOptions ppo = new JigPromptPointOptions("\n指定插入点或[长度(S)/拾取点(D)]: ");
ppo.Keywords.Add("S");
ppo.Keywords.Add("D");
ppo.Keywords.Default = "S";
ppo.BasePoint = _basePoint;
ppo.UseBasePoint = true;
ppo.Cursor = CursorType.RubberBand;
PromptPointResult ppr = prompts.AcquirePoint(ppo);
// 重置关键字结果
_keywordResult = null;
if (ppr.Status == PromptStatus.Keyword)
{
// 存储关键字结果供外部使用
_keywordResult = ppr.StringResult;
return SamplerStatus.NoChange;
}
else if (ppr.Status == PromptStatus.OK)
{
if (_dragPoint.DistanceTo(ppr.Value) < ToleranceValue)
{
return SamplerStatus.NoChange;
}
_dragPoint = ppr.Value;
return SamplerStatus.OK;
}
return SamplerStatus.Cancel;
}
protected override bool WorldDraw(WorldDraw draw)
{
// 计算位移矩阵
Vector3d moveVector = _dragPoint - _basePoint;
_displacementMatrix = Matrix3d.Displacement(moveVector);
// 绘制预览
foreach (BarInfo barInfo in _barInfos)
{
// 计算新基点位置
Point3d originalBasePoint;
if (_basePointMode == 0)
originalBasePoint = barInfo.OriginalStartPoint;
else if (_basePointMode == 1)
originalBasePoint = barInfo.OriginalEndPoint;
else
originalBasePoint = barInfo.Position;
Point3d newBasePoint = originalBasePoint + moveVector;
// 计算新的块插入点
Vector3d direction = new Vector3d(Math.Cos(barInfo.Rotation), Math.Sin(barInfo.Rotation), 0);
Point3d newPosition;
if (_basePointMode == 0) // 左端点为基点
newPosition = newBasePoint + (direction * _currentLength / 2);
else if (_basePointMode == 1) // 右端点为基点
newPosition = newBasePoint - (direction * _currentLength / 2);
else // 中心点为基点
newPosition = newBasePoint;
// 设置块表记录(使用当前长度)
string blockName = $"{_componentPrefix}{_currentLength}mm";
ObjectId blockId = ObjectId.Null;
// 获取数据库并检查块是否存在
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if (bt != null && bt.Has(blockName))
{
blockId = bt[blockName];
}
tr.Commit();
}
// 只有当块存在时才创建预览
if (!blockId.IsNull)
{
// 创建预览实体
BlockReference br = new BlockReference(newPosition, blockId);
br.Layer = barInfo.Layer;
br.Rotation = barInfo.Rotation;
// 绘制预览
draw.Geometry.Draw(br);
}
}
return true;
}
}
#endregion
#region 通用辅助方法及数据结构
private void ShowErrorDialog(string message)
{
Application.ShowAlertDialog(message);
}
private void HandleException(Editor ed, SysException ex)
{
string errorType = ".NET";
ed.WriteMessage($"\n{errorType}错误: {ex.Message}");
ShowErrorDialog($"发生{errorType}异常: {ex.Message}\n详细请查看命令行日志");
}
private void HandleException(Editor ed, AecException ex)
{
string errorType = "AutoCAD";
ed.WriteMessage($"\n{errorType}错误: {ex.Message} (状态: {ex.ErrorStatus})");
ShowErrorDialog($"发生{errorType}异常: {ex.Message}\n详细请查看命令行日志");
}
private class Segment
{
public List<Point3d> Points { get; set; } = new List<Point3d>();
}
private class Point3dComparer : IEqualityComparer<Point3d>
{
private readonly double _tolerance;
public Point3dComparer(double tolerance) => _tolerance = tolerance;
public bool Equals(Point3d p1, Point3d p2) =>
p1.DistanceTo(p2) < _tolerance;
public int GetHashCode(Point3d p) =>
p.X.GetHashCode() ^ p.Y.GetHashCode() ^ p.Z.GetHashCode();
}
private class EntityKeyComparer : IEqualityComparer<(string, Point3d, double)>
{
public bool Equals((string, Point3d, double) x, (string, Point3d, double) y) =>
x.Item1 == y.Item1 &&
x.Item2.DistanceTo(y.Item2) < SkipTolerance &&
Math.Abs(x.Item3 - y.Item3) < 0.01;
public int GetHashCode((string, Point3d, double) obj) =>
obj.Item1.GetHashCode() ^ obj.Item2.GetHashCode() ^ obj.Item3.GetHashCode();
}
private HashSet<(string blockName, Point3d pos, double angle)> _existingEntitiesCache;
#endregion
}
}
严重性 代码 说明 行 详细信息
错误(活动) CS1501 “Invoke”方法没有采用 4 个参数的重载 278
最新发布