CAD C# 批量替换当前图中块
本案例功能为选择当前文档中一个块(旧块),然后选择新图元(新块),运行插件后新块将替换图中所有的旧块。
效果如下:
public static class Class1
{
//选取对象替换块定义
[CommandMethod("TT")]
public static void BLKREDEF()
{
Document doc =Z.doc;
Database db = doc.Database;
Editor ed = doc.Editor;
ed.WriteMessage("图块编辑替换 BK");
//提示选择块
PromptEntityOptions peo = new PromptEntityOptions("\n请选择需要编辑的块");
peo.SetRejectMessage("\n你选择的不是块");
peo.AddAllowedClass(typeof(BlockReference), true); //只让选择块
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) { return; }
ObjectId blockID = per.ObjectId;
string blockName;
Point3d blockInPt;
double blockAngle;
Matrix3d blockMatri, blockInMatri;
using (Transaction trans = doc.TransactionManager.StartTransaction())
{
BlockReference blockref = (BlockReference)trans.GetObject(blockID, OpenMode.ForRead); //块参照
blockName = blockref.Name; //块名
blockInPt = blockref.Position; //块插入点
blockAngle = blockref.Rotation; //块旋转
blockMatri = blockref.BlockTransform;
blockInMatri = blockMatri.Inverse(); //逆矩阵
}
ed.WriteMessage("\n您编辑的块名为: " + blockName);
//提示选择对象
PromptSelectionOptions pso = new PromptSelectionOptions();
pso.MessageForAdding = "请选择需要生成块的图形";
pso.RejectObjectsOnLockedLayers = true; //不能选在锁定图层上的
PromptSelectionResult psr = ed.GetSelection(pso);
if (psr.Status != PromptStatus.OK) { return; }
SelectionSet ss = psr.Value;
//新对象的基点
//注意交互下的坐标都是UCS,需要处理
PromptPointOptions ppo = new PromptPointOptions("请选择新块基点:");
ppo.UseBasePoint = true;
ppo.BasePoint = blockInPt.TransformBy(ed.CurrentUserCoordinateSystem.Inverse());
PromptPointResult ppr = ed.GetPoint(ppo);
if (ppr.Status != PromptStatus.OK) { return; }
Point3d blockInPtN = ppr.Value;
Point3d inPtNWCS = blockInPtN.TransformBy(ed.CurrentUserCoordinateSystem);
//坐标系变换,从UCS转换到WCS
Vector3d vt = blockInPt - inPtNWCS;
Matrix3d matMove = Matrix3d.Displacement(vt); //平移
using (Transaction trans = doc.TransactionManager.StartTransaction())
{
//获取块参照的定义
BlockReference blockRef = (BlockReference)trans.GetObject(blockID, OpenMode.ForWrite);
BlockTableRecord btr = (BlockTableRecord)blockRef.BlockTableRecord.GetObject(OpenMode.ForWrite);
//遍历删除原块内所有对象
foreach (ObjectId id in btr)
{
Entity ent = (Entity)trans.GetObject(id, OpenMode.ForWrite);
ent.Erase();
}
//实体列表加入新建的块表记录中
foreach (ObjectId id in ss.GetObjectIds())
{
Entity ent = (Entity)trans.GetObject(id, OpenMode.ForWrite);
//要排除自身嵌套Bug
if (ent is BlockReference)
{
if (((BlockReference)ent).Name == blockName)
{
continue;
}
}
IdMapping mapping = new IdMapping();
Entity ent1 = (Entity)ent.Clone(); //复制新的并加入块
// Entity ent1 = (Entity)ent.DeepClone(ent, mapping, false);
//块定义以时候会以(0,0,0)为基点
//插入的时候坐标会以飞一个相对(0,0,0)到inPt的距离,这里要处理一下。
//预先把对象移到原点
ent1.TransformBy(blockInMatri * (matMove));
btr.AppendEntity(ent1);
trans.AddNewlyCreatedDBObject(ent1, true);
//ent.Erase(); //删除原来的
}
//通知事务处理
//trans.AddNewlyCreatedDBObject(bt, true);
//刷新块显示
//blockRef.RecordGraphicsModified(true);
//模型空间打开块表
BlockTable bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);
//打开指定块名的块表记录
BlockTableRecord btr1 = (BlockTableRecord)trans.GetObject(bt[blockName], OpenMode.ForRead);
//获取指定块名的块参照集合的Id
ObjectIdCollection blockIds = btr1.GetBlockReferenceIds(false, true);
foreach (ObjectId id in blockIds) // 遍历块参照的Id
{
//获取块参照
BlockReference block = (BlockReference)trans.GetObject(id, OpenMode.ForWrite);
block.Visible = block.Visible;
}
trans.Commit();
}
}
}