AutoCAD打印模型的图元的基本组成是“块”,其存储于内部数据库中的块表之中。
目录
访问内部数据库的方法
访问块表的方法
块表、模型空间
绘制、插入图形
插入块
访问内部数据库的方法
var db = HostApplicationServices.WorkingDatabase
或者通过document访问:
var doc = Application.DocumentManager.MdiActiveDocument;
var db = doc.Database;
区别是前者不需要AutoCAD的运行环境。
访问块表的方法
AutoCAD内部数据库中的信息的查询(get)操作都可以通过Transaction.GetObject方法获得ObjectId,块表也不例外。
通常这样写以自动释放资源:
using(var tran = db.TransactionManager.StartTransaction())
{
var blockTable = tran.GetObject(db.BlockTableId,OpenMode.Read) as BlockTable;
// 其他操作
tran.Commit(); // 最后要提交数据库操作
}
块表、模型空间
块表blockTable的每一条记录BlockTableRecord就是一个块,所有的BlockTableRecord记录中有一条特殊的记录叫做ModelSpace(模型空间),就是我们常规的绘图用的空间。
var modelSpace = tran.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
绘制、插入图形
得到模型空间的块表记录后,向其中AppendEntity,即可在模型空间中添加图形,所添加的entity(实体)可以是二维(线、圆等等)、三维图形(三维实体)、块等等。
resultObjectId = modelSpace.AppendEntity(entity);// 返回添加的实体id
tran.AddNewlyCreatedDBObject(entity, true);// 向数据库中添加实体,true是增加,false是删除
插入块
不少地方在讲插入块时是通过外部文件的方式链接进来(Xref),这里推荐使用数据库自带的Insert方法来模拟AutoCAD本身的insert命令。
前文讲明所有的块包括整个模型空间都是块表的一条记录(Record),这些“块”的记录和模型空间中实例化的块模型,显然不是一个东西。前者叫BlockTableRecord,后者叫BlockReference,换言之,前者叫“块定义”,后者叫“块参照”。
类似的还有“块属性定义(AttributeDefinition)”和“属性(AttributeReference)”。
如下代码简单的演示了如何模拟AutoCAD的insert命令从其他文件插入块,并选择插入点。
public class CommandClass
{
[CommandMethod(nameof(MyCommand))]
public void MyCommand()
{
var doc = Application.DocumentManager.MdiActiveDocument;
// 让用户决定插入点
var pointPickResult = doc.Editor.GetPoint(new PromptPointOptions("请输入插入点"));
if (pointPickResult.Status == PromptStatus.Cancel) return;
var insertPoint = pointPickResult.Value;
AddBlock2ModelSpace("xx/xx.dwg",insertPoint);
}
private static ObjectId AddBlock2ModelSpace(string blockFilePath, Point3d insertPoint)
{
var db = HostApplicationServices.WorkingDatabase;
var resultObjectId = ObjectId.Null;
using (var transaction = db.TransactionManager.StartTransaction())
{
var blockTable = transaction.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
if (blockTable != null)
{
BlockReference br = default;
var blockFileName = Path.GetFileNameWithoutExtension(blockFilePath);
// 模拟CAD的insert块操作,无的从blockFilePath导入,有的直接读取块名
if (blockTable.Has(blockFileName))
{
// blockTable[blockFileName]读取块记录,并将其转化为块参照
br = new BlockReference(insertPoint, blockTable[blockFileName]);
}
else
{
// 没有记录的,从其他dwg文件导入
var sourceDb = new Database(false, false);
// 这里假定dwg文件是一个纯粹的放置块的dwg,否则需要过滤掉一些不需要的东西
sourceDb.ReadDwgFile(blockFilePath, FileShare.Read, true, "");
var btrId = db.Insert(blockFileName, sourceDb, true);
if (!btrId.IsNull) br = new BlockReference(insertPoint, btrId);
}
if (br == null) return resultObjectId;
// 导入模型空间
var modelSpace =
transaction.GetObject(blockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
if (modelSpace != null)
{
resultObjectId = modelSpace.AppendEntity(br);
transaction.AddNewlyCreatedDBObject(br, true);
}
// 添加块属性
var blockTableRecord =
transaction.GetObject(blockTable[blockFileName], OpenMode.ForRead) as BlockTableRecord;
if (blockTableRecord != null)
// 遍历块记录,寻找块属性定义AttributeDefinition
foreach (var objectId in blockTableRecord)
if (transaction.GetObject(objectId, OpenMode.ForRead) is AttributeDefinition ad)
// 块属性定义如果被定义为常数是不可以修改的
if (!ad.Constant)
// 块定义↔块参照,类比,块属性定义↔块属性参照
using (var ar = new AttributeReference())
{
ar.SetAttributeFromBlock(ad, br.BlockTransform);
ar.Position = ad.Position.TransformBy(br.BlockTransform);
ar.TextString = ad.TextString; // 这里改属性值
br.AttributeCollection.AppendAttribute(ar);
transaction.AddNewlyCreatedDBObject(ar, true);
}
}
transaction.Commit();
}
return resultObjectId;
}
}