C#基于Autocad的二次开发(2.块的插入)

开始之前确保已完成步骤1创建解决方案和类库项目,并在对应项目中安装nuget包

开始插入块操作之前,首先在ACD.Domain项目中创建”点位类”,”插入块类”。Autocad中所有图形绘制以及操作都基于点位,插入块也需要一个插入点,以及插入块的块文件,并且在插入时也需要指定将该块插入到某一图层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 /// <summary>
/// 点位类
/// </summary>
public class ACDPoint3D
{
public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }

public ACDPoint3D() { }

public ACDPoint3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/// <summary>
/// 插入块类
/// </summary>
public class InsertBlockParam
{
/// <summary>
/// 图层名称
/// </summary>
public string LayerName { get; set; }
/// <summary>
/// 块名称
/// </summary>
public string BlockName { get; set; }
/// <summary>
/// 块物理路径
/// </summary>
public string BlockPath { get; set; }
/// <summary>
/// 块插入坐标
/// </summary>
public ACDPoint3D InsertPoint { get; set; }

public InsertBlockParam() { }

public InsertBlockParam(string layerName, string blockName, string blockPath, ACDPoint3D insertPoint)
{
LayerName = layerName;
BlockName = blockName;
BlockPath = blockPath;
InsertPoint = insertPoint;
}
}

ACD.Application项目中封装常用的扩展方法,新建类文件Extensions.Validate.cs内容如下,partial修饰为分部类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public static partial class Extensions
{
/// <summary>
/// 检测对象是否为null
/// </summary>
/// <param name="obj">对象</param>
/// <returns></returns>
public static bool IsNull(this object obj) => obj == null;

/// <summary>
/// 是否为空
/// </summary>
/// <param name="value"></param>
public static bool IsEmpty(this string value)
{
return string.IsNullOrWhiteSpace(value);
}

/// <summary>
/// 是否为空
/// </summary>
/// <param name="value"></param>
public static bool IsEmpty(this Guid value)
{
return value == Guid.Empty;
}

/// <summary>
/// 是否为空
/// </summary>
/// <param name="value"></param>
public static bool IsEmpty(this Guid? value)
{
if (value == null)
return true;
return value == Guid.Empty;
}

/// <summary>
/// 是否为空
/// </summary>
/// <param name="value"></param>
public static bool IsEmpty<T>(this IEnumerable<T> value)
{
if (value == null)
return true;
return !value.Any();
}
}

ACD.CadCore项目中创建ACDOperation.cs类文件,通过partial修饰为分部类,并实现为单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public partial class ACDOperation 
{
private ACDOperation() { }

private static ACDOperation _instance = null;

private static readonly object _locker = new object();

public static ACDOperation Instance
{
get
{
if (_instance == null)
{
lock (_locker)
{
if (_instance == null)
{
_instance = new ACDOperation();
}
}
}
return _instance;
}
}

/// <summary>
/// 校验路径
/// </summary>
/// <param name="dwgFilePath"></param>
/// <param name="newFilePath"></param>
/// <exception cref="NotFoundException"></exception>
private void CheckFilePath(string dwgFilePath, string newFilePath)
{
if (!File.Exists(dwgFilePath)) throw new NotFoundException($"文件{dwgFilePath}不存在");

string directoryPath = Path.GetDirectoryName(newFilePath);

if (!Directory.Exists(directoryPath)) Directory.CreateDirectory(directoryPath);
}
}

ACD.CadCore项目中接着创建ACDOperation.InsertBlock.cs类文件,实现Autocad插入块的操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
public partial class ACDOperation
{
public bool InsertBlock(string dwgFilePath, string newFilePath, IEnumerable<InsertBlockParam> blocks)
{
bool result = true;

CheckFilePath(dwgFilePath, newFilePath);

File.Copy(dwgFilePath, newFilePath, true);

using (Database blockDb = new Database(false, true))
{
blockDb.ReadDwgFile(newFilePath, FileOpenMode.OpenForReadAndWriteNoShare, true, null);
blockDb.CloseInput(true);

result = InsertBlock(blockDb, blocks);
}

if (!result) File.Delete(newFilePath);

return result;
}

public bool InsertBlock(IDynamicMetaObjectProvider database, IEnumerable<InsertBlockParam> blocks)
{
bool result = true;

LayerTable layers;
Database wblockDb;
ObjectId wblockId;
Point3d insertPoint;
BlockTable currblockTable;
LayerTableRecord layer;
BlockReference blockReference;
BlockTableRecord currblockTableRecord;

Database currdb = database as Database;

// 启动事务
using (Transaction currtransaction = currdb.TransactionManager.StartTransaction())
{
try
{
currblockTable = currtransaction.GetObject(currdb.BlockTableId, OpenMode.ForRead) as BlockTable;

currblockTableRecord = currtransaction.GetObject(currblockTable[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;

layers = currtransaction.GetObject(currdb.LayerTableId, OpenMode.ForRead) as LayerTable;

foreach (var param in blocks)
{
using (wblockDb = new Database(false, true))
{
wblockDb.ReadDwgFile(param.BlockPath, FileOpenMode.OpenForReadAndWriteNoShare, true, null);
wblockDb.CloseInput(true);

// 插入外部块
wblockId = currdb.Insert(param.BlockName, wblockDb, false);
}

insertPoint = new Point3d(param.InsertPoint.X, param.InsertPoint.Y, param.InsertPoint.Z);
// 创建块引用
blockReference = new BlockReference(insertPoint, wblockId);

if (layers.Has(param.LayerName))
{
layer = currtransaction.GetObject(layers[param.LayerName], OpenMode.ForWrite) as LayerTableRecord;
//设置块引用的图层
blockReference.LayerId = layer.Id;
}
// 将块引用添加到模型空间
currblockTableRecord.AppendEntity(blockReference);

currtransaction.AddNewlyCreatedDBObject(blockReference, true);
}
// 提交事务
currtransaction.Commit();
}
catch (Exception)
{
currtransaction.Abort();

result = false;
}
}
return result;
}
}

块的插入操作在Autocad中需要有一个被插入的外部块文件,和一个插入的目标图形文件,目标图形文件可以是当前工作文档空间,也可以是一个指定的文件路径(最终也是通过文件路径打开工作文档空间),插入过程中会读取外部块文件,将外部块文件在当前工作文档空间中创建块引用并指定插入点位以及图层


C#基于Autocad的二次开发(2.块的插入)
https://wangyuangen.github.io/2024/05/20/CsharpAutocad2/
作者
Yuangen Wang
发布于
2024年5月20日
许可协议