1、需求
插入外部文件中指定的块。
2、思路
将外部dwg文件加载到临时数据库中,把外部dwg文件中自定义的命名块复制到当前文档的数据库中;新建指定块的块参照加入到当前块表记录。
3、环境
AutoCAD 2018/vs2015
4、步骤:
(1) 新建一个临时图形数据库
Database tempDB = new Database(false, true);
(2) 调用Database类的 WblockCloneObjects()方法复制块
(3) 新建一个块参照:BlockReference
public BlockReference(Point3d position, ObjectId blockTableRecord);
(4) 把块参照添加到块表记录中
BlockTableRecord.AppendEntity()
Transaction.AddNewlyCreatedDBObject();
关键代码:
/// <summary>
/// 复制块文件
/// </summary>
/// <param name="TargetDB"></param>
/// <param name="FileName">动态块文件路径</param>
/// <param name="BlockName">动态块名称</param>
/// <param name="Method"></param>
public static void CopyBlockFromFile(this Database TargetDB, string FileName, string BlockName, DuplicateRecordCloning Method = DuplicateRecordCloning.Replace)
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(FileName, FileShare.ReadWrite, true, "");
ObjectIdCollection ids = new ObjectIdCollection();
ObjectIdCollection newoids = new ObjectIdCollection();
IdMapping im = new IdMapping();
using (Transaction tr = db.TransactionManager.StartTransaction())
{
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, true, true);
ids.Add(bt[BlockName]);
tr.Commit();
}
try
{
//db.WblockCloneObjects(ids, TargetDB.BlockTableId, im, DuplicateRecordCloning.Ignore, true);
db.WblockCloneObjects(ids, TargetDB.BlockTableId, im, DuplicateRecordCloning.Replace, false);
}
catch (Exception ex)
{
}
}
}
/// <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 InsertBlockrefenceModelSpace(this ObjectId spaceId, string blockName, Point3d postion, Scale3d scale, double rotateAngle, Dictionary<string, Dictionary<string, string>> attNameValues, Dictionary<string, Dictionary<string, string>> attDNameValues, bool isRoate = false)
{
// 获取数据库对象
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]);
//DynamicBlockReferencePropertyCollection properties= br.DynamicBlockReferencePropertyCollection;
br.ScaleFactors = scale;
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);
}
}
}
if (isRoate )
{
br.TransformBy(Matrix3d.Rotation(GeTools.DegreeToRadian(180), Vector3d.YAxis, postion));
}
ChangeDynamicValue(br, attDNameValues);
db.TransactionManager.AddNewlyCreatedDBObject(br, true);
return br.ObjectId;//返回添加的快参照的ID
}
说明:
Dictionary<string, Dictionary<string, string>> : Dictionary<属性设置值, Dictionary<属性名称, 类型(string\double)>>
/// <summary>
///设置自定义属性值
/// </summary>
/// <param name="br"></param>
/// <param name="attDNameValues"></param>
public static void ChangeDynamicValue(BlockReference br, Dictionary<string, Dictionary<string,string>> attDNameValues)
{
if (br != null && br.IsDynamicBlock)
{
DynamicBlockReferencePropertyCollection pc = br.DynamicBlockReferencePropertyCollection;
AttributeCollection ar = br.AttributeCollection;
foreach (DynamicBlockReferenceProperty prop in pc)
{
if (attDNameValues.Keys.Contains(prop.PropertyName) && !prop.ReadOnly)
{
try
{
Dictionary<string, string> dic = attDNameValues[prop.PropertyName];
List<string> values = dic.Keys.ToList();
List<string> types = dic.Values.ToList();
switch(types[0].ToLower())
{
case "double":
string[] sp = prop.PropertyName.Split('_');
if (sp != null)
{
//if(sp[sp.Length-1]=="mm")
// prop.Value = double.Parse(values[0])/1000;
//else
prop.Value = double.Parse(values[0]);
}
break;
case "string":
prop.Value = values[0];
break;
}
//prop.Value = attDNameValues[prop.PropertyName];
}
catch (System.Exception ex)
{
}
}
else
{
continue;
}
}
}
}