CadParamPluging/Readme.md

707 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 0. 目标 & 新流程说明
### 0.1 功能目标
基于 **AutoCAD 2014** 开发一个插件,实现:
1. 在 AutoCAD 中**新建图纸后**,打开插件面板;
2. 用户在插件面板中**输入一组模板相关参数**(如图纸类别、项目类型、图幅、比例等),
插件根据这些参数**自动匹配模板**DWT/DWG中的某个图纸
3. 用户再输入**出图相关的其它参数**(构件数量、尺寸、布置方式等,开发时再定);
4. 插件结合**选中的模板 + 业务参数**,自动在 CAD 中生成图形;
5. 生成后通过插件提供的“保存”功能,让用户选择保存位置和文件名。
### 0.2 使用体验要求(不走命令行)
- 使用人员只通过 **侧边面板 UI** 操作,不需要输入命令;
- 插件加载后自动显示面板;
- 整个流程:填写参数 → 预览/确定模板 → 生成图纸 → 保存,全部在 UI 中完成;
- 命令行入口可以保留一个隐藏命令用于调试,但**不要求普通用户使用**。
---
## 1. 技术选型与项目结构
### 1.1 环境 & 依赖
- 操作系统Windows 7
- AutoCADAutoCAD 2014x86 或 x64
- .NET Framework建议 4.5
- IDEVisual Studio 2012 / 2013+
AutoCAD 引用:
- `AcCoreMgd.dll`
- `AcDbMgd.dll`
- `AcMgd.dll`
(从 AutoCAD 2014 安装目录或 ARX SDK 中引用)
### 1.2 解决方案结构(建议)
```text
Solution: AutoCADParamDrawing
├─ AutoCADParamDrawing.Plugin // 插件宿主 + UI + CAD 操作
├─ AutoCADParamDrawing.Domain // 业务模型 + 参数校验 + 出图算法
├─ AutoCADParamDrawing.Data // 模板配置、系统配置等数据访问
├─ AutoCADParamDrawing.Common // 日志、配置工具、通用扩展方法
```
- **Plugin**:与 AutoCAD、UI 直接打交道;
- **Domain**:只关心“参数”和“图形逻辑”,不关心 UI/配置文件细节;
- **Data**:负责加载模板配置、系统参数(从 config/JSON/数据库等);
- **Common**:基础设施。
---
## 2. 用户业务流程 & UI 设计
### 2.1 用户操作流程(从用户视角)
1. 打开 AutoCAD**新建一个空白图纸**(或默认新建图);
2. AutoCAD 启动时插件自动加载,右侧弹出**“参数化出图”面板**
3. 用户在面板中完成三步:
- **步骤 1填写模板参数**
- 项目类型(结构 / 给排水 / …)
- 图纸类型(基础平面 / 楼层平面 / 剖面等)
- 图幅A1 / A2 / A3 …)
- 比例1:50 / 1:100…
- 其他模板选型相关参数(开发时定)
点击【匹配模板】按钮,面板显示匹配到的模板名称与路径。
- **步骤 2填写出图参数**
- 构件类别 / 数量
- 尺寸参数(长宽高、标高、层数……)
- 出图规则选项(是否生成某些视图/明细等)
> 具体参数由开发阶段根据业务确定。
- **步骤 3生成图纸 & 保存**
- 点击【生成图纸】按钮:
- 插件根据模板参数,找到模板文件;
- 根据出图参数计算几何布置;
- 调用 AutoCAD API 在图中生成图形(可选:自动基于模板新建一个新图窗体);
- **(新特性) 参数保存**:生成图纸的同时,系统会将当前界面的所有参数自动保存到 DWG 的内部扩展字典中。
- 出图完成后弹出提示,并提供【保存为…】按钮:
- 打开文件保存对话框,让用户选择 DWG 名称和目录;
- 插件内部调用 `Database.SaveAs()` 完成保存,**参数数据会随文件一起保存**。
4. 用户后续可手工调整图纸或继续用插件对同一模板重复生成。
### 2.2 插件主面板结构
**ParamDrawingPanel**WinForms UserControl建议布局
1. **区域一模板参数Template Parameters**
- ComboBox项目类型ProjectType
- ComboBox图纸类型DrawingType
- ComboBox图幅SheetSize
- ComboBox / TextBox比例Scale
- 预留若干 TextBox/ComboBox 用于其它模板判断参数
- 按钮:`匹配模板`Match Template
- Label显示“已选模板XXX.dwt”或“未找到匹配模板”
2. **区域二出图参数Drawing Parameters**
- 若干 TextBox/ComboBox具体字段开发时确定比如
- 轴线数量、层数、构件高度等
- 可以采用简单表格控件展示不同构件列表(可选)
3. **区域三:操作按钮**
- `生成图纸`Generate Drawing
- `保存当前图纸…`Save Drawing As…
- `打开配置`(打开模板配置/系统配置窗口)
4. **区域四:日志/提示**
- 多行 TextBox 或 ListBox 用于显示:
- 模板匹配结果;
- 参数校验信息;
- 出图进度、错误提示等。
---
## 3. 模块划分与职责
### 3.1 Plugin 层
主要命名空间(示例):
- `AutoCADParamDrawing.Plugin.Entry`
- 插件入口,实现 `IExtensionApplication`
- 初始化 PaletteSet & Panel
- `AutoCADParamDrawing.Plugin.UI`
- `ParamDrawingPanel`:主面板
- 可选其它对话框,如“配置窗口”
- `AutoCADParamDrawing.Plugin.Cad`
- `CadContext`:封装 Transaction / Document
- `CadDrawingService`:封装 AutoCAD 绘图操作(画线、插块、文字、图层、布局等)
- `CadDrawingService`:封装 AutoCAD 绘图操作(画线、插块、文字、图层、布局等)
- `TemplateDrawingService`:处理“基于模板新建图纸”的逻辑
- `DictionaryHelper`:封装 Extension Dictionary (NOD) 的读写操作,用于保存参数
**职责总结:**
- 与 AutoCAD 交互Document、Database、锁定、事务
- 与用户交互UI 事件);
- 将 UI 输入转为 Domain 模型;
- 调用 Domain 层完成校验和绘图。
---
### 3.2 Domain 层
建议基础模型结构如下(字段仅示意):
```csharp
public class TemplateParams
{
public string ProjectType { get; set; }
public string DrawingType { get; set; }
public string SheetSize { get; set; }
public string Scale { get; set; }
// 其他用于模板选择的参数,开发时补充
}
public class DrawingParams
{
// 出图相关参数(构件、尺寸等),开发时定义
// 示例:
// public int FloorCount { get; set; }
// public double ColumnWidth { get; set; }
// ...
}
public class TemplateInfo
{
public string Name { get; set; }
public string FilePath { get; set; }
public string Description { get; set; }
}
```
Domain 入口类(示例):
```csharp
public static class DomainFacade
{
public static TemplateInfo SelectTemplate(TemplateParams tplParams)
{
// 调用 Data 层TemplateRepository.FindTemplate(tplParams)
// 并对结果做业务校验(是否唯一等)
}
public static void ValidateParameters(TemplateParams tplParams, DrawingParams drawParams)
{
// 对必填项、数值范围等进行校验
// 可抛出 BusinessException 反馈给 UI
}
public static void DrawByParams(
TemplateInfo template,
DrawingParams drawParams,
CadDrawingService cadService)
{
// 真正的业务绘图逻辑:
// 1. 根据模板信息,配置图层/样式(如需要)
// 2. 根据 drawParams 计算几何位置
// 3. 调用 cadService 画线、插块、标注、文字等
// 4. 可封装不同图纸类型的策略类BeamDrawingStrategy、ColumnDrawingStrategy 等
}
}
```
职责:
- 参数模型和校验;
- 模板选择规则(+ Data 层配置);
- 绘图算法与布置规则。
---
### 3.3 Data 层
Data 层主要处理 **模板配置 & 系统配置**,例如:
```csharp
public class TemplateDefinition
{
public string Id { get; set; } // 内部唯一 ID
public string ProjectType { get; set; }
public string DrawingType { get; set; }
public string SheetSize { get; set; }
public string Scale { get; set; }
public string FilePath { get; set; } // 模板文件路径
public string Description { get; set; }
}
```
模板仓储接口:
```csharp
public interface ITemplateRepository
{
TemplateDefinition FindTemplate(TemplateParams tplParams);
IEnumerable<TemplateDefinition> GetAll();
}
```
实现可以是:
- 读取 app.config / JSON 文件 / XML 文件等;
- 配置格式示例JSON 形式,具体由开发时确定):
```json
[
{
"ProjectType": "结构",
"DrawingType": "基础平面",
"SheetSize": "A1",
"Scale": "1:50",
"FilePath": "C:\\CadTemplates\\Stru_Base_A1_50.dwt",
"Description": "结构基础平面 A1 1:50"
}
]
```
> 具体字段和匹配策略可以开发时再细化,这里只定义架构和职责。
---
### 3.4 Common 层
- 日志工具:`Logger.Info/Error`(写文本或者 log4net 等);
- 配置读取:读取 app.config 或 JSON 路径;
- 通用异常类型:`BusinessException` 用于业务错误提示用户。
---
## 4. 核心技术实现示意
### 4.1 插件入口 & PaletteSet 创建
```csharp
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Windows;
namespace AutoCADParamDrawing.Plugin.Entry
{
public class PluginEntry : IExtensionApplication
{
private static PaletteSet _palette;
public void Initialize()
{
CreateAndShowPalette();
}
public void Terminate()
{
// 可记录日志等
}
private void CreateAndShowPalette()
{
if (_palette == null)
{
_palette = new PaletteSet("参数化出图")
{
Style = PaletteSetStyles.ShowCloseButton |
PaletteSetStyles.ShowAutoHideButton |
PaletteSetStyles.Snappable
};
var panel = new UI.ParamDrawingPanel();
_palette.Add("主面板", panel);
_palette.MinimumSize = new System.Drawing.Size(320, 400);
}
_palette.Visible = true;
}
// 可选:用于调试/恢复面板
[CommandMethod("PARAM_PANEL")]
public void ShowPanelCommand()
{
CreateAndShowPalette();
}
}
}
```
### 4.2 CadContext & CadDrawingService
```csharp
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
namespace AutoCADParamDrawing.Plugin.Cad
{
public class CadContext : IDisposable
{
public Document Document { get; }
public Database Database => Document.Database;
public Transaction Transaction { get; private set; }
public CadContext(Document doc)
{
Document = doc;
Transaction = Database.TransactionManager.StartTransaction();
}
public void Commit()
{
Transaction?.Commit();
}
public void Dispose()
{
Transaction?.Dispose();
Transaction = null;
}
}
public class CadDrawingService
{
private readonly CadContext _ctx;
public CadDrawingService(CadContext ctx)
{
_ctx = ctx;
}
// 示例:画线
public ObjectId DrawLine(Point3d start, Point3d end)
{
var db = _ctx.Database;
var tr = _ctx.Transaction;
var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
var btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
var line = new Line(start, end);
var id = btr.AppendEntity(line);
tr.AddNewlyCreatedDBObject(line, true);
return id;
}
// TODO: 插块、文字、标注、图层等方法开发时补充
}
}
```
### 4.3 基于模板新建图纸(可选方案)
两种方式,二选一:
1. **直接在当前新建图中绘图**
- 只用模板来参考图层/样式规则,但不真正打开模板文件;
2. **真正基于模板新建一个图纸 Document**(推荐):
示例(在 UI 的“生成图纸”里调用):
```csharp
public Document CreateDocumentFromTemplate(TemplateInfo tpl)
{
// template.FilePath 来自 Data 层配置
var newDoc = Autodesk.AutoCAD.ApplicationServices.Application
.DocumentManager.Add(tpl.FilePath);
// 设为当前活动文档
Autodesk.AutoCAD.ApplicationServices.Application
.DocumentManager.MdiActiveDocument = newDoc;
return newDoc;
}
```
之后:
```csharp
var tplInfo = DomainFacade.SelectTemplate(templateParams);
DomainFacade.ValidateParameters(templateParams, drawingParams);
var newDoc = TemplateDrawingService.CreateDocumentFromTemplate(tplInfo);
using (newDoc.LockDocument())
using (var ctx = new CadContext(newDoc))
{
var cadService = new CadDrawingService(ctx);
DomainFacade.DrawByParams(tplInfo, drawingParams, cadService);
ctx.Commit();
}
```
### 4.4 UI 面板核心逻辑示意ParamDrawingPanel
```csharp
public partial class ParamDrawingPanel : UserControl
{
private TemplateInfo _selectedTemplate;
public ParamDrawingPanel()
{
InitializeComponent();
}
private TemplateParams CollectTemplateParamsFromUI()
{
return new TemplateParams
{
ProjectType = cbProjectType.Text,
DrawingType = cbDrawingType.Text,
SheetSize = cbSheetSize.Text,
Scale = cbScale.Text
// 更多字段开发时补充
};
}
private DrawingParams CollectDrawingParamsFromUI()
{
var p = new DrawingParams();
// 从文本框/下拉框收集各类出图参数
return p;
}
private void btnMatchTemplate_Click(object sender, EventArgs e)
{
try
{
var tplParams = CollectTemplateParamsFromUI();
_selectedTemplate = DomainFacade.SelectTemplate(tplParams);
lblTemplateInfo.Text = $"已匹配模板: {_selectedTemplate.Name}";
AppendLog($"模板: {_selectedTemplate.FilePath}");
}
catch (BusinessException bex)
{
AppendLog($"模板选择错误: {bex.Message}");
}
catch (Exception ex)
{
AppendLog($"异常: {ex.Message}");
Logger.Error("MatchTemplate", ex);
}
}
private void btnGenerate_Click(object sender, EventArgs e)
{
if (_selectedTemplate == null)
{
AppendLog("请先匹配模板。");
return;
}
try
{
var tplParams = CollectTemplateParamsFromUI();
var drawingParams = CollectDrawingParamsFromUI();
DomainFacade.ValidateParameters(tplParams, drawingParams);
// 创建基于模板的新图纸并绘图
var newDoc = TemplateDrawingService.CreateDocumentFromTemplate(_selectedTemplate);
using (newDoc.LockDocument())
using (var ctx = new CadContext(newDoc))
{
var cadService = new CadDrawingService(ctx);
DomainFacade.DrawByParams(_selectedTemplate, drawingParams, cadService);
ctx.Commit();
}
AppendLog("图纸生成完成。");
}
catch (BusinessException bex)
{
AppendLog($"参数错误: {bex.Message}");
}
catch (Exception ex)
{
AppendLog($"生成失败: {ex.Message}");
Logger.Error("GenerateDrawing", ex);
}
}
private void btnSaveAs_Click(object sender, EventArgs e)
{
var doc = Autodesk.AutoCAD.ApplicationServices.Application
.DocumentManager.MdiActiveDocument;
using var dlg = new SaveFileDialog
{
Filter = "AutoCAD Drawing (*.dwg)|*.dwg",
FileName = "新图纸.dwg"
};
if (dlg.ShowDialog() == DialogResult.OK)
{
doc.Database.SaveAs(dlg.FileName, true, DwgVersion.Current, doc.Database.SecurityParameters);
AppendLog($"图纸已保存到: {dlg.FileName}");
}
}
private void AppendLog(string msg)
{
txtLog.AppendText(msg + Environment.NewLine);
}
}
```
### 4.5 新模板出图逻辑隔离(新增模板开发流程)
为保证每个模板的**生成图纸逻辑隔离**,出图逻辑按模板拆分为独立生成器:
**核心机制**
- 每个模板由 `TemplateKey` 唯一标识(由 `TemplateKeyBuilder.Build(ProjectType, DrawingType, SheetSize, Scale)` 生成)。
- 出图时根据 `TemplateKey``TemplateDrawingRegistry` 解析到对应生成器;
- 公共流程(清理模板、附注/表格替换、标题栏更新、参数保存)仍在 `ParamDrawingPanel` 中执行,
**只有“图形绘制 + 预期尺寸计算”由各生成器负责**
**新增模板流程(开发者指引)**
1. **新增生成器类**
- 目录:`Cad/Drawers/`
- 实现 `ITemplateDrawingGenerator` 或继承 `TemplateDrawingGeneratorBase`
- 指定 `TemplateKey`,与模板参数绑定配置完全一致。
```csharp
public sealed class NewTemplateGenerator : TemplateDrawingGeneratorBase
{
public static readonly string Key = TemplateKeyBuilder.Build("交付状态", "工艺方法", "结构特征", "特殊条件");
public override string TemplateKey => Key;
// 如需特殊尺寸预估,重写此方法
public override FeatureDrivenDrawer.ExpectedDrawingSize CalculateExpectedSize(ParamBag bag, TemplateParams templateParams)
{
return base.CalculateExpectedSize(bag, templateParams);
}
// 如需自定义出图逻辑,重写此方法
public override void Draw(CadContext ctx, ParamBag bag, TemplateParams templateParams, Point3d center, double scaleFactor)
{
// 自定义绘图逻辑
}
}
```
2. **注册生成器**
-`TemplateDrawingRegistry` 的静态构造函数中注册:
```csharp
Register(new NewTemplateGenerator());
```
3. **配置模板参数绑定**
-`模板参数绑定` 界面新增模板定义(或在 `TemplateSchemaDefaults` 中加入默认项)。
- 确保 `ProjectType / DrawingType / SheetSize / Scale` 与生成器 `TemplateKey` 完全一致。
4. **参数与附注**
- 在模板绑定里选择该模板需要的参数;
- 配置附注模板文本与占位符绑定(若需要)。
**说明**
- 现有模板生成器示例位于 `Cad/Drawers/`,可直接参考扩展;
- 若某模板需要完全不同的绘图算法,可在生成器中自行实现,不影响其他模板。
> 具体 UI 控件命名、字段等开发时根据实际参数调整。
---
## 5. 开发步骤(执行指引)
### 步骤 1创建解决方案 & 项目
1. 新建 VS 解决方案 `AutoCADParamDrawing`
2. 创建四个项目Plugin / Domain / Data / Common
3. Plugin 项目引用 AutoCAD DLL
4. Common 项目实现基础配置/日志工具类。
### 步骤 2定义参数模型Domain
1. 定义 `TemplateParams`, `DrawingParams`, `TemplateInfo` 等类;
2. 类上用注释说明这些属性将对应到 UI 控件;
3. 定义 `DomainFacade` 入口方法:
- `SelectTemplate`
- `ValidateParameters`
- `DrawByParams`
### 步骤 3实现模板配置Data 层)
1. 确定模板配置文件格式(建议 JSON / XML方便非程序员维护
2. 实现 `TemplateRepository`
- 从配置文件加载所有模板定义;
- 提供按 `TemplateParams` 匹配模板的方法;
3.`DomainFacade.SelectTemplate` 中调用 `TemplateRepository` 并处理找不到/多条等情况。
### 步骤 4实现 Domain 的基本绘图算法
1. 先实现**简单版本**
- 根据一两个简单参数(比如构件数量/长度)画出一些线条/框,验证流程;
2. 后续逐步细化:
- 按不同图纸类型拆分策略类;
- 完善图层、标注、文字等。
### 步骤 5实现 Plugin 层的 CadContext & CadDrawingService
1. 封装事务和 Document 操作;
2. 实现画线/插块/文字/标注等基础方法;
3. 后续根据业务增加更多方法。
### 步骤 6实现 UI 面板ParamDrawingPanel
1. 设计界面布局(模板参数区 + 出图参数区 + 操作区 + 日志区);
2. 编写事件处理逻辑:
- 参数收集 → 模板匹配 → 参数校验 → 调用生成图纸;
3. 实现 `btnSaveAs` 保存功能。
### 步骤 7实现插件入口IExtensionApplication
1.`PluginEntry.Initialize` 中创建 PaletteSet添加 ParamDrawingPanel
2. 编译后在 AutoCAD 中 `NETLOAD` 测试:
- 确认启动时自动出现面板;
- 按步骤能生成一张简单测试图。
### 步骤 8迭代完善业务细节
- 与业务方确认参数列表 & 模板规则;
- 丰富模板配置;
- 封装真实业务绘图算法;
- 扩展功能:
- 多图纸批量生成;
- 一键生成并保存到指定目录等。
---
## 6. 测试要点(开发自测参考)
1. **模板匹配**
- 输入各种模板参数组合;
- 检查模板是否正确匹配,找不到/多条时提示是否合理。
2. **参数校<E695B0><E6A0A1>**
- 有必填项为空时,能在 UI 上提示具体字段;
- 数值异常(负数、格式错误)能被拦截。
3. **绘图结果**
- 图形是否根据参数变化;
- 图层/文字/标注是否按模板和规则创建。
4. **保存**
- “保存为…”是否成功输出 DWG 文件;
- 再次打开是否正常显示。
---
## 7. 部署与使用说明(给实施/最终用户)
1. 将编译后的 `AutoCADParamDrawing.Plugin.dll` 及其它依赖拷贝至指定目录(如:`C:\CadPlugins\ParamDrawing\`)。
2. 建议做成 AutoCAD `.bundle` 插件,实现自动加载;或者由实施人员在启动脚本中设置 `NETLOAD`
3. 用户启动 AutoCAD 后:
- 看到右侧“参数化出图”面板;
- 按“模板参数 → 匹配模板 → 出图参数 → 生成图纸 → 保存”流程使用即可。
---