愿你出走半生,归来仍是少年!
环境:.NET FrameWork4.5、ObjectArx 2016 64bit、Entity Framework 6.
目录
1. 普通块引用的插入
2. 属性块引用的插入
3. 块参照的移动
在CAD中针对点的符号化通常使用块引用进行表达,在CAD中的对应Insert实体,在开发中对应的类为BlockReference。
所谓的普通块引用就是未带属性的块,熟悉CAD的应知道在CAD中的块对象是可以包含属性定义的。通过包含属性定义的块定义构造的块引用,也会包含对应的属性,并可以自行维护。
此处的参数“defineName”是在当前文档中的块定义的名称,当文档中包含此块定义时,块引用的插入才可能正常的完成。如何插入块定义,请点击进入传送门。
public static void InsertBlockReference(this string defineName, Point3d position,string layerName)
{
try
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (Transaction trans = doc.Database.TransactionManager.StartTransaction())
{
//当前文档块表
BlockTable blockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
//块表中存在该块表记录, 并且没有被删除
if (blockTable.Has(defineName) && !blockTable[defineName].IsErased)
{
ObjectId defineId = blockTable[defineName];
//模型空间
var mdlSpc = trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
//新建块参照
BlockReference blockReference = new BlockReference(position, defineId);
//图层名称
blockReference.Layer = layerName;
//在模型空间中追加此块参照
mdlSpc.AppendEntity(blockReference);
trans.AddNewlyCreatedDBObject(blockReference, true);
trans.Commit();
}
}
}
catch (Exception ex)
{
throw;
}
}
属性块的插入相较于普通块的插入,多了属性实体这部分。因此在插入过程中应当对块内的属性进行维护。
需要根据块定义获取是否存在属性定义,若存在进行属性定义的遍历。根据属性定义给块参照插入对应的属性参照。
///
/// 插入块引用
///
/// 块定义名称
/// 插入点
/// 要插入的图层名称
/// 属性值,不是属性块可直接设置null
public static void InsertBlockReference(this string defineName, Point3d position,string layerName, Dictionary vals)
{
try
{
Document doc = Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
using (DocumentLock acLckDoc = doc.LockDocument())
{
using (Transaction trans = doc.Database.TransactionManager.StartTransaction())
{
//当前文档块表
BlockTable blockTable = trans.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
//块表中存在该块表记录, 并且没有被删除
if (blockTable.Has(defineName) && !blockTable[defineName].IsErased)
{
//获取块定义的ID
ObjectId defineId = blockTable[defineName];
//获取块定义对象
BlockTableRecord defineObject = trans.GetObject(defineId, OpenMode.ForWrite) as BlockTableRecord;
//模型空间
var mdlSpc = trans.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
//新建块参照
BlockReference blockReference = new BlockReference(position, defineId);
//图层名称
blockReference.Layer = layerName;
//在模型空间中追加此块参照
mdlSpc.AppendEntity(blockReference);
trans.AddNewlyCreatedDBObject(blockReference, true);
if (vals != null)
{
//判断是否有属性定义,进行属性处理
if (defineObject.HasAttributeDefinitions)
{
//遍历块定义下的实体(属性定义也是实体)
foreach (var childId in defineObject)
{
//获取实体
var childEntity = trans.GetObject(childId, OpenMode.ForRead);
//判断是否为属性定义
if (childEntity is AttributeDefinition attDefine)
{
using (AttributeReference attRef = new AttributeReference())
{
attRef.SetAttributeFromBlock(attDefine, blockReference.BlockTransform);
attRef.Position = attDefine.Position.TransformBy(blockReference.BlockTransform);
attRef.Rotation = attDefine.Rotation;
//判断是否包含了指定的属性名称
if (vals.ContainsKey(attRef.Tag.ToUpper()))
{
//设置属性值
attRef.TextString = vals[attRef.Tag.ToUpper()].ToString();
}
blockReference.AttributeCollection.AppendAttribute(attRef);
trans.AddNewlyCreatedDBObject(attRef, true);
}
}
}
}
}
}
trans.Commit();
}
}
}
catch (Exception ex)
{
throw;
}
}
在实际的生产需求中,存在将块的位置进行变更的情况,即将块从点1移动到点2。通常的做法为直接给块设定新的位置。但是当块中存在属性参照的时候这个直接设定新位置的方式显然就行不通了,此时我们可通过点2相较于点1的偏移进行移动整个块参照,包括它的属性参照。
///
/// 平移块
///
///
///
/// 平移量
public static void Move(this BlockReference br, Transaction trans, Point3d offset)
{
try
{
br.UpgradeOpen();
br.Position = new Point3d(
br.Position.X + offset.X,
br.Position.Y + offset.Y,
br.Position.Z + offset.Z
);
br.DowngradeOpen();
var ids = br.AttributeCollection;
foreach (ObjectId tempId in ids)
{
var attrRef = (AttributeReference)trans.GetObject(tempId, OpenMode.ForWrite, false, true);
if (attrRef.Justify == AttachmentPoint.BaseLeft)
{
//左对齐时变更属性的位置
attrRef.Position = new Point3d(
attrRef.Position.X + offset.X,
attrRef.Position.Y + offset.Y,
attrRef.Position.Z + offset.Z
);
}
else {
//非左对齐时,变更属性的对齐点
attrRef.AlignmentPoint= new Point3d(
attrRef.AlignmentPoint.X + offset.X,
attrRef.AlignmentPoint.Y + offset.Y,
attrRef.AlignmentPoint.Z + offset.Z
);
}
}
}
catch (Exception ex)
{
throw ex;
}
}