2025年【工业软件开发学习——AnyCAD篇】事务(Transaction)与撤销(Undo)、重做(Redo)机制

【工业软件开发学习——AnyCAD篇】事务(Transaction)与撤销(Undo)、重做(Redo)机制引子 前一阵基于 AnyCAD 做了些小项目 发现 SDK 中不少与文档 Document 元素构件 Element 相关的概念和 Revit 等 BIM 软件有一定相似度 这在进行业务开发时有很大用处 但不知为何目前官方在这方面的文档比较少 也未提供太多具体示例

大家好,我是讯享网,很高兴认识大家。

引子

前一阵基于AnyCAD做了些小项目,发现SDK中不少与文档(Document)、元素构件(Element)相关的概念和Revit等BIM软件有一定相似度,这在进行业务开发时有很大用处,但不知为何目前官方在这方面的文档比较少,也未提供太多具体示例,所以准备选取一些Highlight简单写些小教程。工业软件SDK或二次开发接口大多使用相似的架构和理念,一方面借此作为自己学习和开发的基础,另一方面也希望可以帮助到从事相关工作的朋友。

概述

AnyCAD图形平台主要提供一系列造型、显示、以及一些工业领域应用的脚手架,gitee上有不少官方提供的示例仓库:

  • rapid.net.starter
  • anycad.rapid.net.sample
  • RapidCAX

还不熟悉此平台的朋友可以先从官网和上面的例子入门,这里不作过多展开。

在大多例子中,AnyCAD创建和操作的对象都仅仅用于显示,但复杂的CAD软件往往需要具备数据管理功能,所有针对数据对象的增删查改都应可回退或重做(Undo/Redo),AnyCAD也提供了这些基础功能,在官方开发指南数据管理这一节介绍了基本概念和用法,本文fork了rapid.net.starter这一仓库进行了一些修改,需要参考的朋友可以把代码pull到本地直接运行(安装相关依赖的前提下,具体依赖请参考官方提供的教程)。

准备工作

AnyCAD提供的应用框架AppFramework能够让开发者以MVVM的模式快速搭建应用,我们这里也借助它来完成应用与文档的初始化;安装nuget包后新建一个MainViewModelImpl.cs文件,创建一个从AnyCAD.NX.ViewModel.WpfMainViewModel继承的类即可:

public partial class MainViewModelImpl : WpfMainViewModel { 
    public MainViewModelImpl(IRenderView viewer) : base(viewer) { 
    } } 

讯享网

接着在MainWindow的构造函数中实例化MainViewModelImpl:

讯享网public MainWindow() { 
    InitializeComponent(); var viewModel = new MainViewModelImpl(mRenderCtrl); this.DataContext = viewModel; } 

并在已经注册的ViewerReady事件函数中初始化viewModel:

private void mRenderCtrl_ViewerReady() { 
    // 初始化 ViewModel.Initialize(mRenderCtrl); } 

此时编译运行程序将会得到一个已初始化文档对象的窗口:

image-20240106165200909
讯享网

在事务中创建对象

参照开发指南里的示例代码,我们增加一个菜单项用于创建包含圆柱体形状的ShapeElement,并将这部分代码包含在UndoTransaction的Start与Commit之间:

讯享网// MainWindow.xaml <Metro:MetroWindow.RightWindowCommands> <Metro:WindowCommands ShowSeparators="False"> <Menu Margin="50,2,0,0" Background="#00000000"> <MenuItem Header="创建" Background="#00000000"> <MenuItem Header="圆柱体" Command="{Binding NewCylinderCommand}"/> </MenuItem> </Menu> </Metro:WindowCommands> </Metro:MetroWindow.RightWindowCommands> // MainViewModelImpl.cs [RelayCommand] void OnNewCylinder() // 该方法与xaml中的创建圆柱体命令绑定 { 
    UndoTransaction undo = new(Document); // 实例化UndoTransaction对象 undo.Start("create.cylinder"); // 开启事务 var shape = ShapeBuilder.MakeCylinder(GP.XOY(), 10, 20, 0); // 创建圆柱体shape var shapeElement = ShapeElement.Create(Document); // 在文档中创建ShapeElement对象 shapeElement.SetShape(shape); // 将构造好的shape赋予ShapeElement对象 undo.Commit(); // 提交事务 } 

运行后通过菜单项便可创建圆柱体:

image-20240106170040096

Undo/Redo操作

目前为止和rapid.net.starter原本所展示的内容似乎并无区别,但实际上新建圆柱体这一操作已经能够进行回退操作了,由于SDK并没有自带回退与重做键盘事件的绑定,我们需要在MainWindow.xaml自行绑定:

<Metro:MetroWindow.InputBindings> <KeyBinding Key="Z" Command="{Binding UndoCommand}" Modifiers="Control" /> <KeyBinding Key="Y" Command="{Binding RedoCommand}" Modifiers="Control" /> </Metro:MetroWindow.InputBindings> 

或者也可以增加菜单项来执行这两个命令:

讯享网<MenuItem Header="事务" Background="#00000000"> <MenuItem Header="回退" Command="{Binding ExecuteSystemCommand}" CommandParameter="Undo"/> <MenuItem Header="重做" Command="{Binding ExecuteSystemCommand}" CommandParameter="Redo"/> </MenuItem> 

那么这时我们再创建圆柱体之后就可以通过快捷键或菜单项进行Undo/Redo操作了:

img

在事务中编辑对象

同时,后续对已创建对象的编辑也同样支持在事务中进行,以进行Undo/Redo操作,AnyCAD也提供了移动/旋转物体的小控件,调用"MoveInstance/RotateInstance"命令即可唤起:

<MenuItem Header="编辑" Background="#00000000"> <MenuItem Header="移动" Command="{Binding ExecuteSystemCommand}" CommandParameter="MoveInstance"></MenuItem> <MenuItem Header="旋转" Command="{Binding ExecuteSystemCommand}" CommandParameter="RotateInstance"></MenuItem> </MenuItem> 

并且,通过这两个小控件进行的编辑操作已经被包含在了事务中,不再需要开发者去操作UndoTransaction对象(不过截止文章撰写时,这里需要两次Undo才能回到编辑前的状态,已report issue给平台,想必后续会修复这个问题):

img

总结

数据管理是开发复杂CAD应用的重要功能,AnyCAD帮助开发者实现了一部分核心内容,这大大提升了业务实现的效率。后续我将结合自己的经历撰写更多工业软件开发的小文章,欢迎大家阅读与指正。

小讯
上一篇 2025-02-24 12:22
下一篇 2025-03-01 20:16

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/20155.html