在CAD中块是一个非常重要的知识点,今天我会为大家做一些块的分类和介绍,以及块的定义和引用。
1. 概念
1.1 块定义
块由多个在逻辑上相关的图形对象所定义的整体。优点就是可以统一作业标准、提高作业效率,因为生活中的物体不是简单的一个单元,可能有多个单元统一构成,块就可以很好地表示这种结构。
块的本质是存储于块表记录中的实体对象集合。
1.2 属性块定义
属性块是有构成的实体和附加信息(属性)组成的,属性块中块的定义与简单块中块的定义一样,而属性的定义主要是通过属性的AttributeDefinition类的有关属性和函数来实现的。具体实现有:
- AttributeDefinition类的实例并设置对象的属性值;
- 由于块的属性定义也可以看做是块中的实体,可以通过块表记录类的成员函数AppendEntity将属性定义附加到块中。
其中,属性定义的属性值主要有:
- 文字的插入点、高度、旋转角度、对齐方式和宽度;
- 属性的默认值;
- 属性的模式,如不可见方式Invisible、常量方式Constant、验证方式Verify、预置方式Preset;
- 属性标签名。
1.3 动态块定义
动态块允许我们创建具有高度灵活性和可定制性的块。因为传统的块一旦插入到图纸中,其尺寸、形状和位置通常是固定的。而动态块则不同,它们可以通过用户界面的交互(如拖拽动作柄)来调整其几何属性,而无需重新定义整个块或手动编辑其组成部分。
1.4 块分类和操作
块主要分为简单块,属性块,动态块。对于块,主要有块定义操作和块引用操作(也就是块插入操作),块编辑。
2. 块定义
2.1 块定义
无论是什么块,他们的定义大致是统一的(属性块需要添加属性对象),具体步骤如下:
- 用Transaction类的GetObject()函数获得块表对象;
- 创建BlockTableRecord对象并设置块名称;
- 创建组成块的实体对象;
- 调用BlockTableRecord类的AppendEntity函数将组成块的实体写入块表记录中;
- 调用BlockTable类的Add函数将创建的块表记录写入当前图形的块表中。
具体代码如下:
public static ObjectId AddBlockThroughDB(this Database db, string blockName, List<Entity> ents)
{
//声明ObjectId,用于返回
ObjectId entId = ObjectId.Null;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForWrite);
BlockTableRecord btr = new BlockTableRecord();
btr.Name = blockName;
for (int ii = 0; ii < ents.Count; ii++)
{
Entity ent = ents[ii];
btr.AppendEntity(ent);
}
entId = bt.Add(btr);
tr.AddNewlyCreatedDBObject(btr, true);
tr.Commit();
}
return entId;
}
2.2 属性块定义
上面只是简单块的定义,属性块的话,顾名思义,就得需要定义块中属性字段(我们就可以理解为定义属性变量,当引用的时候需要将其转成具体变量值)。
属性块定义,我们可以通过属性添加的方式为其进行属性添加。
/// <summary>
/// 块添加属性
/// </summary>
/// <param name="blockId"></param>
/// <param name="atts"></param>
public static void AddAttsToBlocks(this ObjectId blockId, List<AttributeDefinition> atts)
{
Database db = blockId.Database;//获取数据库对象
BlockTableRecord btr = blockId.GetObject(OpenMode.ForWrite) as BlockTableRecord;
foreach (AttributeDefinition att in atts)
{
btr.AppendEntity(att);
db.TransactionManager.AddNewlyCreatedDBObject(att, true);
}
btr.DowngradeOpen();
}
public static void AddAttsToBlocks(this ObjectId blockId, params AttributeDefinition[] atts)
{
blockId.AddAttsToBlocks(atts.ToList());
}
为指定的块定义进行属性添加。我们在使用的时候可以这样:
//属性添加
AttributeDefinition attr1 = new AttributeDefinition(Point3d.Origin, "箱变", "箱变编号", "请输入箱变编号", ObjectId.Null);
AttributeDefinition attr2 = new AttributeDefinition(Point3d.Origin + new Vector3d(0, 0.25, 0),
"变电站", "变电站编号", "请输入变电站编号", ObjectId.Null);
//然后将这两个属性加入到集合,再调用上面的方法即可。
参数说明如下:
- Point3d position:这是属性定义的位置,以三维坐标的形式给出。即使你的设计工作在二维平面上,也需要提供一个三维坐标点,Z值通常设为0。
- string value:这是属性定义的默认值。当块被插入时,如果没有提供特定的属性值,就使用这个默认值。
- string tag:这是属性定义的标签,也就是它的唯一标识符。当块被插入时,可以通过这个标签来引用和修改属性值。
- string prompt:这是属性的提示信息,当用户在插入块时需要输入属性值时,会显示这个提示信息。如果不需要用户输入,则可以留空。
- ObjectId style:这是字体样式的对象ID。在AutoCAD中,字体样式决定了属性文本的外观,包括字体、大小、宽度比例等。这个参数必须是一个有效的字体样式对象的ID,否则可能会抛出异常。
2.3 动态块定义
动态块的定义是需要属性块的基础上使用DynamicBlockReferencePropertyCollection
类对属性进行约束。
3. 块引用(块插入)
3.1 普通块插入
public void Insert()
{
Database db = HostApplicationServices.WorkingDatabase;
using (Transaction trans = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
BlockTableRecord space = db.CurrentSpaceId.GetObject(OpenMode.ForWrite) as BlockTableRecord;
//判断名为“块1”的块是否存在
if(! bt["块1"].IsNull)
{
BlockReference br = new BlockReference(Point3d.Origin, bt["块1"]);
br.ScaleFactors = new Scale3d(2.0);//设置尺寸为原来2倍
space.AppendEntity(br);
trans.AddNewlyCreatedDBObject(br, true);
trans.Commit();
}
else
{
return;
}
}
}
3.2 属性块插入
块参照中的属性实体由DatabaseServices命名空间中的AttibuteReference类表示,它其实是一个单行文本对象,由DBText类派生。为块参照添加属性的步骤如下:
- 打开块参照所属的块表记录对象;
- 对块表记录中的实体进行循环遍历,如果实体是属性定义的对象,则根据它的标识为块参照属性对象设置属性值;
- 获取块参照对象的属性集合对象来为块参照添加新创建的属性参照对象。属性集合对象由BlockReference的AttributeCollection 属性标识,调用它的AppendAttribute函数就可以完成块参照的属性添加。
/// <summary>
/// 插入带属性的参照快
/// </summary>
/// <param name="spaceId">空间的ID</param>
/// <param name="layer">块要加入的图层名</param>
/// <param name="blockName">快参照所属的快名</param>
/// <param name="postion">插入点</param>
/// <param name="scale">缩放比例</param>
/// <param name="rotateAngle">旋转角度</param>
/// <param name="attNameValues">属性名称与取值</param>
/// <returns></returns>
public static ObjectId InsertBlockrefence(this ObjectId spaceId, string layer, string blockName, Point3d postion, Scale3d scale, double rotateAngle, Dictionary<string, string> attNameValues)
{
// 获取数据库对象
Database db = spaceId.Database;
//以读的方式打开块表
BlockTable bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
//如果没有blockName d的块,则程序返回
if (!bt.Has(blockName))
return ObjectId.Null;//如果没有blockName的块,程序返回
//以写的模式打开空间
BlockTableRecord space = (BlockTableRecord)spaceId.GetObject(OpenMode.ForWrite);
//获取块表的记录ID
ObjectId btrId = bt[blockName];
//打开块表记录
BlockTableRecord record = btrId.GetObject(OpenMode.ForRead) as BlockTableRecord;
//创建一个快参照并设置插入点
BlockReference br = new BlockReference(postion, bt[blockName]);
br.ScaleFactors = scale;
br.Layer = layer;
br.Rotation = rotateAngle;
space.AppendEntity(br);
//判断块表记录是否包含属性定义
if (record.HasAttributeDefinitions)
{
//若包含,则遍历属性定义
foreach (ObjectId id in record)
{
//检查是否是属性定义
AttributeDefinition attDef = id.GetObject(OpenMode.ForRead) as AttributeDefinition;
if (attDef != null)
{
//创建一个新的属性对象
AttributeReference attribute = new AttributeReference();
//从属性定义获取属性对象的对象特性
attribute.SetAttributeFromBlock(attDef, br.BlockTransform);
attribute.Rotation = attDef.Rotation;
attribute.Position = attDef.Position.TransformBy(br.BlockTransform);
attribute.AdjustAlignment(db);
//判断是否包含指定的属性名称
if (attNameValues.ContainsKey(attDef.Tag.ToUpper()))
{
//设置属性值
attribute.TextString = attNameValues[attDef.Tag.ToUpper()].ToString();
}
// 向块参照添加属性对象
br.AttributeCollection.AppendAttribute(attribute);
db.TransactionManager.AddNewlyCreatedDBObject(attribute, true);
}
}
}
db.TransactionManager.AddNewlyCreatedDBObject(br, true);
return br.ObjectId;//返回添加的快参照的ID
}
上面的有些参数也可以不需要,比如缩放比例和插入比例。
3.3 属性修改
/// <summary>
/// 更新属性名称与取值
/// </summary>
/// <param name="blockRefId"></param>
/// <param name="attNameValues"></param>
public static void UpdateAttributesInBlock(this ObjectId blockRefId, Dictionary<string, string> attNameValues)
{
BlockReference blockRef = blockRefId.GetObject(OpenMode.ForRead) as BlockReference;
if (blockRef != null)
{
foreach (ObjectId id in blockRef.AttributeCollection)
{
AttributeReference attref = id.GetObject(OpenMode.ForRead) as AttributeReference;
if (attNameValues.ContainsKey(attref.Tag.ToUpper()))
{
attref.UpgradeOpen();
//设置属性值
attref.TextString = attNameValues[attref.Tag.ToUpper()].ToString();
attref.DowngradeOpen();
}
}
}
}