csharp
复制代码
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System;
using App = Autodesk.AutoCAD.ApplicationServices.Application;
namespace AutoBlockManager
{
public class BlockManager
{
// 块配置常量
private const string BLOCK_NAME = "firstBlock";
private const double OUTER_SQUARE_SIZE = 100.0;
private const double DEFAULT_SPACING = 150.0;
[CommandMethod("inFB")]
public void CreateAndInsertFirstBlock()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 步骤1: 检查块是否存在
bool blockExists = CheckBlockExists(db);
// 步骤2: 如果不存在,先创建块
if (!blockExists)
{
ed.WriteMessage("\n⚠ 块 'firstBlock' 不存在,正在创建...");
CreateFirstBlock(db, ed);
ed.WriteMessage("\n✓ 块创建完成!");
}
else
{
ed.WriteMessage("\n✓ 检测到现有块 'firstBlock'");
}
// 步骤3: 获取用户输入并插入10个块
if (GetUserInput(ed, out Point3d startPoint, out double spacing))
{
InsertTenBlocks(db, ed, startPoint, spacing);
ed.WriteMessage($"\n✅ 成功插入10个'firstBlock'块!");
ed.WriteMessage($"\n起始点: ({startPoint.X:F2}, {startPoint.Y:F2})");
ed.WriteMessage($"\n间距: {spacing:F2}");
}
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n❌ 错误: {ex.Message}");
}
}
/// <summary>
/// 检查块是否存在
/// </summary>
private bool CheckBlockExists(Database db)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
bool exists = bt.Has(BLOCK_NAME);
tr.Commit();
return exists;
}
}
/// <summary>
/// 创建firstBlock块定义
/// </summary>
private void CreateFirstBlock(Database db, Editor ed)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
// 检查是否已存在同名块(再次确认)
if (bt.Has(BLOCK_NAME))
{
// 先删除现有的块定义
DeleteExistingBlock(bt, tr, ed);
}
// 创建块表记录
BlockTableRecord btr = new BlockTableRecord();
btr.Name = BLOCK_NAME;
// 创建几何图形
CreateGeometricShapes(btr);
// 添加到数据库
ObjectId blockId = bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
tr.Commit();
}
}
/// <summary>
/// 删除已存在的块定义
/// </summary>
private void DeleteExistingBlock(BlockTable bt, Transaction tr, Editor ed)
{
try
{
ObjectId blockId = bt[BLOCK_NAME];
if (!blockId.IsErased)
{
BlockTableRecord existingBtr = tr.GetObject(blockId, OpenMode.ForWrite) as BlockTableRecord;
// 检查是否有块引用
ObjectIdCollection refIds = existingBtr.GetBlockReferenceIds(true,true);
if (refIds != null && refIds.Count > 0)
{
ed.WriteMessage($"\n⚠ 块 '{BLOCK_NAME}' 有 {refIds.Count} 个引用,需要清理...");
// 删除所有引用
foreach (ObjectId refId in refIds)
{
if (!refId.IsErased)
{
Entity ent = tr.GetObject(refId, OpenMode.ForWrite) as Entity;
ent.Erase();
}
}
}
// 删除块定义
existingBtr.Erase();
ed.WriteMessage($"\n🗑️ 已删除现有块 '{BLOCK_NAME}',重新创建...");
}
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n⚠ 删除现有块时出错: {ex.Message}");
// 继续创建新块
}
}
/// <summary>
/// 创建所有几何图形
/// </summary>
private void CreateGeometricShapes(BlockTableRecord btr)
{
// 外层正方形
double halfSize = OUTER_SQUARE_SIZE / 2;
Polyline outerSquare = new Polyline();
outerSquare.AddVertexAt(0, new Point2d(-halfSize, -halfSize), 0, 0, 0);
outerSquare.AddVertexAt(1, new Point2d(halfSize, -halfSize), 0, 0, 0);
outerSquare.AddVertexAt(2, new Point2d(halfSize, halfSize), 0, 0, 0);
outerSquare.AddVertexAt(3, new Point2d(-halfSize, halfSize), 0, 0, 0);
outerSquare.Closed = true;
outerSquare.ColorIndex = 1;
btr.AppendEntity(outerSquare);
// 内切圆
double circleRadius = halfSize;
Circle innerCircle = new Circle(Point3d.Origin, Vector3d.ZAxis, circleRadius);
innerCircle.ColorIndex = 3;
btr.AppendEntity(innerCircle);
// 内接正方形
Polyline innerSquare = new Polyline();
innerSquare.AddVertexAt(0, new Point2d(0, circleRadius), 0, 0, 0);
innerSquare.AddVertexAt(1, new Point2d(circleRadius, 0), 0, 0, 0);
innerSquare.AddVertexAt(2, new Point2d(0, -circleRadius), 0, 0, 0);
innerSquare.AddVertexAt(3, new Point2d(-circleRadius, 0), 0, 0, 0);
innerSquare.Closed = true;
innerSquare.ColorIndex = 5;
btr.AppendEntity(innerSquare);
// 三角形
double triangleRadius = circleRadius * 0.4; // 调整大小
Polyline triangle = new Polyline();
for (int i = 0; i < 3; i++)
{
double angle = (Math.PI / 2) - (i * 2 * Math.PI / 3);
double x = triangleRadius * Math.Cos(angle);
double y = triangleRadius * Math.Sin(angle);
triangle.AddVertexAt(i, new Point2d(x, y), 0, 0, 0);
}
triangle.Closed = true;
triangle.ColorIndex = 2;
btr.AppendEntity(triangle);
// 中心标记
Line centerX = new Line(new Point3d(-5, 0, 0), new Point3d(5, 0, 0));
centerX.ColorIndex = 7;
btr.AppendEntity(centerX);
Line centerY = new Line(new Point3d(0, -5, 0), new Point3d(0, 5, 0));
centerY.ColorIndex = 7;
btr.AppendEntity(centerY);
}
/// <summary>
/// 获取用户输入 - 修正后的方法
/// </summary>
private bool GetUserInput(Editor ed, out Point3d startPoint, out double spacing)
{
startPoint = Point3d.Origin;
spacing = DEFAULT_SPACING;
try
{
// 方法1:使用 GetDistance 获取距离
PromptPointOptions ppo = new PromptPointOptions("\n选择第一个插入点: ");
PromptPointResult ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return false;
startPoint = ppr.Value;
// 正确使用 PromptDistanceOptions 和 GetDistance
PromptDistanceOptions pdo = new PromptDistanceOptions("\n输入块之间的间距: ");
pdo.BasePoint = startPoint;
pdo.UseBasePoint = true;
pdo.DefaultValue = DEFAULT_SPACING;
pdo.AllowNegative = false;
pdo.AllowZero = false;
pdo.UseDefaultValue = true;
PromptDoubleResult pdr = ed.GetDistance(pdo); // 注意:这里是 GetDistance,不是 GetDouble
if (pdr.Status != PromptStatus.OK) return false;
spacing = pdr.Value;
return true;
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n⚠ 输入错误: {ex.Message}");
return false;
}
}
/// <summary>
/// 获取用户输入的替代方法(更简单的方式)
/// </summary>
private bool GetUserInputAlternative(Editor ed, out Point3d startPoint, out double spacing)
{
startPoint = Point3d.Origin;
spacing = DEFAULT_SPACING;
try
{
// 获取插入点
PromptPointOptions ppo = new PromptPointOptions("\n选择第一个插入点: ");
PromptPointResult ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) return false;
startPoint = ppr.Value;
// 方法2:使用 GetDouble 获取数值(更简单)
PromptDoubleOptions pdo = new PromptDoubleOptions("\n输入块之间的间距 <" + DEFAULT_SPACING + ">: ");
pdo.DefaultValue = DEFAULT_SPACING;
pdo.AllowNegative = false;
pdo.AllowZero = false;
pdo.UseDefaultValue = true;
PromptDoubleResult pdr = ed.GetDouble(pdo); // 直接获取数值
if (pdr.Status != PromptStatus.OK) return false;
spacing = pdr.Value;
return true;
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n⚠ 输入错误: {ex.Message}");
return false;
}
}
/// <summary>
/// 插入10个块
/// </summary>
private void InsertTenBlocks(Database db, Editor ed, Point3d startPoint, double spacing)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord modelSpace = tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
) as BlockTableRecord;
// 再次确认块存在
if (!bt.Has(BLOCK_NAME))
{
ed.WriteMessage($"\n❌ 错误: 块 '{BLOCK_NAME}' 不存在!");
return;
}
ObjectId blockId = bt[BLOCK_NAME];
for (int i = 0; i < 10; i++)
{
// 计算位置
Point3d insertPoint = new Point3d(
startPoint.X + i * spacing,
startPoint.Y,
startPoint.Z
);
// 创建块引用
BlockReference blockRef = new BlockReference(insertPoint, blockId);
// 添加旋转效果(可选)
if (i % 2 == 0)
{
blockRef.Rotation = 15 * Math.PI / 180; // 15度
}
modelSpace.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
// 添加编号
AddBlockNumber(tr, modelSpace, insertPoint, i);
}
tr.Commit();
}
}
/// <summary>
/// 添加块编号文字
/// </summary>
private void AddBlockNumber(Transaction tr, BlockTableRecord modelSpace, Point3d insertPoint, int index)
{
DBText text = new DBText();
text.Position = new Point3d(insertPoint.X, insertPoint.Y - 60, 0);
text.Height = 10;
text.TextString = $"FB-{index + 1}";
text.ColorIndex = 7;
text.HorizontalMode = TextHorizontalMode.TextCenter;
text.VerticalMode = TextVerticalMode.TextBottom;
text.AlignmentPoint = text.Position;
modelSpace.AppendEntity(text);
tr.AddNewlyCreatedDBObject(text, true);
}
/// <summary>
/// 辅助命令:检查块状态
/// </summary>
[CommandMethod("CheckFB")]
public void CheckFirstBlockStatus()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
bool exists = CheckBlockExists(db);
if (exists)
{
ed.WriteMessage("\n✅ 块 'firstBlock' 存在,可以使用 inFB 命令插入。");
}
else
{
ed.WriteMessage("\n❌ 块 'firstBlock' 不存在。");
ed.WriteMessage("\n 运行 inFB 命令将自动创建并插入该块。");
}
}
/// <summary>
/// 辅助命令:删除块定义
/// </summary>
[CommandMethod("DeleteFB")]
public void DeleteFirstBlock()
{
Document doc = App.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForWrite) as BlockTable;
if (bt.Has(BLOCK_NAME))
{
ObjectId blockId = bt[BLOCK_NAME];
BlockTableRecord btr = tr.GetObject(blockId, OpenMode.ForWrite) as BlockTableRecord;
// 检查是否有块引用
bool hasReferences = false;
ObjectIdCollection refIds = btr.GetBlockReferenceIds(true, true);
if (refIds != null && refIds.Count > 0)
{
hasReferences = true;
ed.WriteMessage($"\n⚠ 块 '{BLOCK_NAME}' 有 {refIds.Count} 个引用。");
// 询问用户是否删除引用
PromptKeywordOptions pko = new PromptKeywordOptions(
$"\n是否删除所有 {refIds.Count} 个块引用?[是(Y)/否(N)] <N>: ");
pko.Keywords.Add("Y");
pko.Keywords.Add("N");
pko.Keywords.Default = "N";
PromptResult pr = ed.GetKeywords(pko);
if (pr.StringResult == "Y")
{
// 删除所有块引用
foreach (ObjectId refId in refIds)
{
if (!refId.IsErased)
{
Entity ent = tr.GetObject(refId, OpenMode.ForWrite) as Entity;
ent.Erase();
}
}
hasReferences = false;
ed.WriteMessage($"\n✓ 已删除 {refIds.Count} 个块引用。");
}
}
if (!hasReferences)
{
// 删除块定义
btr.Erase();
ed.WriteMessage($"\n🗑️ 已删除块 '{BLOCK_NAME}' 定义。");
}
else
{
ed.WriteMessage($"\n⚠ 保留块定义(引用未删除)。");
}
}
else
{
ed.WriteMessage($"\n⚠ 块 '{BLOCK_NAME}' 不存在,无需删除。");
}
tr.Commit();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage($"\n❌ 删除失败: {ex.Message}");
}
}
/// <summary>
/// 辅助命令:插入块并设置参数
/// </summary>
[CommandMethod("inFB2")]
public void InsertFirstBlockWithOptions()
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
try
{
// 确保块存在
if (!CheckBlockExists(db))
{
ed.WriteMessage("\n⚠ 块 'firstBlock' 不存在,正在创建...");
CreateFirstBlock(db, ed);
}
// 获取用户输入(使用替代方法)
if (GetUserInputAlternative(ed, out Point3d startPoint, out double spacing))
{
// 获取旋转角度
double rotation = GetRotationAngle(ed);
// 获取缩放比例
double scale = GetScaleFactor(ed);
// 插入块
InsertBlocksWithParameters(db, ed, startPoint, spacing, rotation, scale);
ed.WriteMessage($"\n✅ 成功插入10个'firstBlock'块!");
ed.WriteMessage($"\n参数: 间距={spacing:F2}, 旋转={rotation:F1}°, 缩放={scale:F2}");
}
}
catch (System.Exception ex)
{
ed.WriteMessage($"\n❌ 错误: {ex.Message}");
}
}
/// <summary>
/// 获取旋转角度
/// </summary>
private double GetRotationAngle(Editor ed)
{
PromptDoubleOptions pdo = new PromptDoubleOptions("\n输入旋转角度(度) <0>: ");
pdo.DefaultValue = 0.0;
pdo.AllowNegative = true;
pdo.AllowZero = true;
pdo.UseDefaultValue = true;
PromptDoubleResult pdr = ed.GetDouble(pdo);
if (pdr.Status == PromptStatus.OK)
{
return pdr.Value * Math.PI / 180.0; // 转换为弧度
}
return 0.0;
}
/// <summary>
/// 获取缩放比例
/// </summary>
private double GetScaleFactor(Editor ed)
{
PromptDoubleOptions pdo = new PromptDoubleOptions("\n输入缩放比例 <1.0>: ");
pdo.DefaultValue = 1.0;
pdo.AllowNegative = false;
pdo.AllowZero = false;
pdo.UseDefaultValue = true;
PromptDoubleResult pdr = ed.GetDouble(pdo);
if (pdr.Status == PromptStatus.OK)
{
return pdr.Value;
}
return 1.0;
}
/// <summary>
/// 插入块并应用参数
/// </summary>
private void InsertBlocksWithParameters(Database db, Editor ed, Point3d startPoint,
double spacing, double rotation, double scale)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord modelSpace = tr.GetObject(
bt[BlockTableRecord.ModelSpace],
OpenMode.ForWrite
) as BlockTableRecord;
ObjectId blockId = bt[BLOCK_NAME];
for (int i = 0; i < 10; i++)
{
Point3d insertPoint = new Point3d(
startPoint.X + i * spacing,
startPoint.Y,
startPoint.Z
);
BlockReference blockRef = new BlockReference(insertPoint, blockId);
// 应用旋转
blockRef.Rotation = rotation;
// 应用缩放
blockRef.ScaleFactors = new Scale3d(scale, scale, scale);
// 可选:交替旋转
if (i % 2 == 1)
{
blockRef.Rotation += 15 * Math.PI / 180;
}
modelSpace.AppendEntity(blockRef);
tr.AddNewlyCreatedDBObject(blockRef, true);
// 添加编号
AddBlockNumber(tr, modelSpace, insertPoint, i);
}
tr.Commit();
}
}
}
}