基于Autodesk Forge的DWG表格拖拽编辑功能实现技术咨询
基于Autodesk Forge实现DWG表格拖拽编辑方案
针对你开发阀门设计DWG处理应用的需求,核心思路是用Forge Viewer做前端交互预览,Design Automation做后端DWG文件的实际修改——因为Viewer本身仅负责可视化,无法直接编辑DWG的底层数据,必须结合Design Automation完成表格的插入、编辑和保存操作。以下是具体实现步骤和代码示例:
一、整体流程梳理
- 预先生成或动态创建表格DWG模板(作为可拖拽的组件)
- Viewer加载目标DWG,侧边栏展示表格模板,支持拖拽放置到图纸指定位置
- 收集放置坐标和表格信息,调用Design Automation将表格插入到目标DWG
- 在Viewer中选中表格后,弹出编辑面板修改数据,同步调用Design Automation更新表格内容
- 最终通过Design Automation保存修改后的DWG文件
二、具体实现步骤
1. 用Design Automation创建表格DWG模板
你可以用AutoCAD的.NET API在Design Automation中动态生成表格,示例C#代码如下(用于创建带初始数据的表格块):
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.Geometry; public class CreateTableBlock { public static void Run(Document doc) { using (Transaction tr = doc.TransactionManager.StartTransaction()) { // 获取块表和模型空间 BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 创建表格 Table table = new Table(); table.TableStyle = doc.Database.TableStyleId; table.SetSize(3, 4); // 3行4列 table.Position = new Point3d(0, 0, 0); // 设置表头和数据 table.Cells[0, 0].TextString = "阀门ID"; table.Cells[0, 1].TextString = "型号"; table.Cells[0, 2].TextString = "压力等级"; table.Cells[0, 3].TextString = "材质"; table.Cells[1, 0].TextString = "VAL-001"; table.Cells[1, 1].TextString = "Z41H-16C"; table.Cells[1, 2].TextString = "16MPa"; table.Cells[1, 3].TextString = "碳钢"; // 将表格添加到块表(作为可复用的块) BlockTableRecord tableBlock = new BlockTableRecord(); tableBlock.Name = "ValveSpecTable"; tableBlock.AppendEntity(table); bt.Add(tableBlock); tr.AddNewlyCreatedDBObject(tableBlock, true); tr.AddNewlyCreatedDBObject(table, true); tr.Commit(); } } }
将这段代码打包成Design Automation的活动(Activity),即可动态生成表格块模板。
2. Viewer中实现拖拽放置交互
在Viewer中,你可以通过监听鼠标事件完成拖拽定位,示例代码如下:
// 初始化Viewer后,添加拖拽监听 let selectedTableTemplate = null; let isDragging = false; // 侧边栏表格模板点击事件 document.getElementById('table-template-1').addEventListener('click', () => { selectedTableTemplate = 'ValveSpecTable'; }); // Viewer鼠标按下事件 viewer.addEventListener(Autodesk.Viewing.MOUSE_DOWN_EVENT, (e) => { if (selectedTableTemplate && !isDragging) { isDragging = true; } }); // Viewer鼠标移动事件 viewer.addEventListener(Autodesk.Viewing.MOUSE_MOVE_EVENT, (e) => { if (isDragging) { // 获取屏幕坐标对应的DWG世界坐标 const screenPoint = { x: e.clientX, y: e.clientY }; const result = viewer.hitTest(screenPoint.x, screenPoint.y); if (result) { const worldPoint = result.intersectPoint; // 这里可以在Viewer中显示临时预览的表格位置 } } }); // Viewer鼠标释放事件 viewer.addEventListener(Autodesk.Viewing.MOUSE_UP_EVENT, (e) => { if (isDragging && selectedTableTemplate) { const screenPoint = { x: e.clientX, y: e.clientY }; const result = viewer.hitTest(screenPoint.x, screenPoint.y); if (result) { const worldPoint = result.intersectPoint; // 调用后端API,传递表格模板名、放置坐标、目标DWG的URN insertTableToDWG(selectedTableTemplate, worldPoint.x, worldPoint.y, targetDWGURN); } isDragging = false; selectedTableTemplate = null; } });
3. 调用Design Automation插入表格到目标DWG
后端通过Design Automation API创建工作项(WorkItem),执行表格插入操作,示例代码(Node.js):
const { ForgeClient } = require('forge-apis'); async function insertTableToDWG(tableBlockName, x, y, dwgUrn) { const workItem = { ActivityId: 'InsertTableActivity', // 提前创建的活动ID Arguments: { InputDWG: { URN: dwgUrn, StorageProvider: 'OSS' }, TableBlockName: { Value: tableBlockName }, InsertPoint: { Value: `${x},${y},0` }, OutputDWG: { Verb: 'put', StorageProvider: 'OSS', Path: 'modified-dwg/valve_dwg_with_table.dwg' } } }; // 调用Design API创建工作项 const designAutomation = new ForgeClient.DesignAutomationApi(); const response = await designAutomation.createWorkItem(workItem, {}, oAuth2Client); // 轮询工作项状态,完成后更新Viewer预览 }
对应的Design Automation活动中,执行插入块的AutoCAD代码:
public class InsertTable { public static void Run(Document doc, string tableBlockName, string insertPointStr) { using (Transaction tr = doc.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord modelSpace = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; // 解析插入点 string[] coords = insertPointStr.Split(','); double x = double.Parse(coords[0]); double y = double.Parse(coords[1]); double z = double.Parse(coords[2]); Point3d insertPoint = new Point3d(x, y, z); // 插入表格块 if (bt.Has(tableBlockName)) { BlockReference blockRef = new BlockReference(insertPoint, bt[tableBlockName]); modelSpace.AppendEntity(blockRef); tr.AddNewlyCreatedDBObject(blockRef, true); } tr.Commit(); } } }
4. 实现表格数据编辑
当用户在Viewer中选中表格后,弹出编辑面板,收集修改后的数据,再调用Design Automation更新表格:
// Viewer选中事件 viewer.addEventListener(Autodesk.Viewing.SELECTION_CHANGED_EVENT, (e) => { if (e.dbIdArray.length === 1) { const dbId = e.dbIdArray[0]; // 判断选中的是否是表格(可以通过Viewer的getProperties获取对象类型) viewer.getProperties(dbId, (props) => { if (props.type === 'Table') { // 弹出编辑面板,加载当前表格数据 showTableEditPanel(props); } }); } }); // 编辑面板确认按钮事件 document.getElementById('save-table-btn').addEventListener('click', () => { const editedData = getEditedTableData(); // 获取用户修改的数据 const dbId = viewer.getSelection()[0]; // 获取表格的ObjectID(需要通过Viewer的getProperty获取对应的AutoCAD ObjectID) viewer.getProperties(dbId, (props) => { const objectId = props.properties.find(p => p.displayName === 'Object ID').value; updateTableData(objectId, editedData, targetDWGURN); }); });
Design Automation中更新表格数据的代码:
public class UpdateTableData { public static void Run(Document doc, string objectIdStr, List<List<string>> newData) { using (Transaction tr = doc.TransactionManager.StartTransaction()) { // 获取表格对象 ObjectId tableId = ObjectId.Parse(objectIdStr); Table table = tr.GetObject(tableId, OpenMode.ForWrite) as Table; // 更新单元格数据 for (int row = 0; row < newData.Count; row++) { for (int col = 0; col < newData[row].Count; col++) { if (row < table.Rows.Count && col < table.Columns.Count) { table.Cells[row, col].TextString = newData[row][col]; } // 如果是新增行,先添加行再设置数据 else if (row >= table.Rows.Count) { table.InsertRow(row); table.Cells[row, col].TextString = newData[row][col]; } } } tr.Commit(); } } }
三、关键注意事项
- 坐标转换:Viewer中的屏幕坐标需要通过
hitTest转换为DWG的世界坐标,确保表格插入位置准确。 - Design Automation权限:确保OSS bucket的权限设置正确,允许Design Automation读写文件。
- 表格样式:在创建表格时,指定合适的TableStyle,避免样式丢失。
- 工作项状态轮询:Design Automation工作项是异步执行的,需要轮询状态直到完成,再更新Viewer的预览。
内容的提问来源于stack exchange,提问作者Ajay Pratap Sing Rao
相关产品推荐
相关产品推荐

