本文描述在SCDM中开发参数化脚本的基本流程。
1 脚本录制 在进行脚本参数化之前,可以进行脚本录制。不过脚本录制工作不是必须的,如果对SCDM的脚本API比较熟悉的话,也可以直接编写代码。不过对于一般的工程人员,还是建议采用录制的方式获取代码。
这里以一个简单的案例进行演示。
启动SCDM,选择文件 → 新建 → 脚本 创建一个新脚本文件 脚本编辑器如下图所示,默认情况下为录制状态,用户的所有操作均会作为脚本被记录下来 def GenerateGeo (length=30 , width =12 , height=10 ) : # 设置新草绘 result = SketchHelper.StartConstraintSketching() # 设置草绘平面 sectionPlane = Plane.PlaneXY result = ViewHelper.SetSketchPlane(sectionPlane, Info1) # 设置新草绘 result = SketchHelper.StartConstraintSketching() # 草绘矩形 point1 = Point2D.Create(MM(0 ),MM(0 )) point2 = Point2D.Create(MM(length),MM(0 )) point3 = Point2D.Create(MM(length),MM(width)) result = SketchRectangle.Create(point1, point2, point3) # 实体化草绘 mode = InteractionMode.Solid result = ViewHelper.SetViewMode(mode, Info2) # 拉伸 1 个面 selection = Face1 options = ExtrudeFaceOptions() options.ExtrudeType = ExtrudeType.Add result = ExtrudeFaces.Execute(selection, MM(height), options, Info3)
脚本编制完毕后,可以利用脚本编辑器右上方的运行按钮执行脚本。
如删除所有几何后,在脚本编辑器中添加代码:
GenerateGeo(40 ,20 ,50 )
点击运行 按钮即可在图形窗口中生成一个40×20×50 mm的几何体。
此时参数化工作基本完成。不过为了操作方便,可以考虑做一个GUI界面。
2 关于IronPython SCDM采用IronPython进行脚本编程。
注: IronPython是一种在NET和Mono上实现的 Python 语言,由 Jim Hugunin(同时也是Jython创造者)所创造。1.0 版于2006年9月5日发布。随后,在 2007 年,开发者决定改写构架,使用动态类型系统以让更多脚本语言能很容易地移植到NET Framework上。2008 年,随着微软发布 NET Framework3.0/3.5、Silverlight之后,IronPython也发布了 2.0 版,最新版本是 2.7,于 2011年3月发布,支持.NET Framework 4.0。
——来自搜狗百科
” IronPython已经很久没有更新了,这真不是个好主意,Python大量新特性无法在IronPython中得以体现。更悲剧的是Visual Studio 2019中已经不再支持利用IronPython进行WinForm界面设计(只能采用代码的方式设计GUI界面,无法使用拖拽控件的形式),仅支持WPF界面设计。想要利用IronPython进行WinForm界面设计,只能采用老版本的Visual Studio,或者使用老版本的SharpDevelop(新版本也已经不支持IronPython)。相比较Python的火爆,IronPython几乎冷清到无人问津,这可以从网络上的教程资料多寡间接体现出来。不过好在IronPython的语法与Python大体相同。
这里采用SharpDevelop进行图形界面开发。注意较高版本的SharpDevelop取消了对IronPython的支持,这里选用4.4版本。SharpDevelop是开源软件,可以在网络上随便下载。
启动SharpDevelop,选择菜单文件 → 新建 → 解决方案… 打开解决方案创建对话框 选择模板类型为Windows 应用程序 ,设置名称与位置,如下图所示创建新项目 为控件命名,利用属性设置面板将长度输入框命名为tb_length,宽度输入框命名为tb_width,高度输入框命名为tb_height,创建模型按钮命名为btn_GenerateGeo,SharpDevelop会自动调整控件名称,在人工命名的前面加上_
,如下图所示 双击设计界面中的创建模型
按钮,软件自动创建回调函数Btn_GenerateGeoClick
,源代码中如下图所示 def Btn_GenerateGeoClick (self, sender, e) : length = (float)(self._tb_Length.Text) width = (float)(self._tb_Width.Text) height=(float)(self._tb_Height.Text)
完整代码如下所示。
import System.Drawingimport System.Windows.Formsfrom System.Drawing import *from System.Windows.Forms import * class MainForm (Form) : def __init__ (self) : self.InitializeComponent() def InitializeComponent (self) : self._label1 = System.Windows.Forms.Label() self._tb_Length = System.Windows.Forms.TextBox() self._label2 = System.Windows.Forms.Label() self._label3 = System.Windows.Forms.Label() self._tb_Width = System.Windows.Forms.TextBox() self._label4 = System.Windows.Forms.Label() self._label5 = System.Windows.Forms.Label() self._tb_Height = System.Windows.Forms.TextBox() self._label6 = System.Windows.Forms.Label() self._btn_GenerateGeo = System.Windows.Forms.Button() self.SuspendLayout() # # label1 # self._label1.Location = System.Drawing.Point(10 , 36 ) self._label1.Name = "label1" self._label1.Size = System.Drawing.Size(46 , 23 ) self._label1.TabIndex = 0 self._label1.Text = "长度:" self._label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight # # tb_Length # self._tb_Length.Location = System.Drawing.Point(63 , 37 ) self._tb_Length.Name = "tb_Length" self._tb_Length.Size = System.Drawing.Size(157 , 23 ) self._tb_Length.TabIndex = 1 self._tb_Length.Text = "30" # # label2 # self._label2.Location = System.Drawing.Point(227 , 35 ) self._label2.Name = "label2" self._label2.Size = System.Drawing.Size(43 , 23 ) self._label2.TabIndex = 2 self._label2.Text = "mm" # # label3 # self._label3.Location = System.Drawing.Point(10 , 74 ) self._label3.Name = "label3" self._label3.Size = System.Drawing.Size(46 , 23 ) self._label3.TabIndex = 0 self._label3.Text = "宽度:" self._label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight # # tb_Width # self._tb_Width.Location = System.Drawing.Point(63 , 75 ) self._tb_Width.Name = "tb_Width" self._tb_Width.Size = System.Drawing.Size(157 , 23 ) self._tb_Width.TabIndex = 2 self._tb_Width.Text = "20" # # label4 # self._label4.Location = System.Drawing.Point(227 , 73 ) self._label4.Name = "label4" self._label4.Size = System.Drawing.Size(43 , 23 ) self._label4.TabIndex = 2 self._label4.Text = "mm" # # label5 # self._label5.Location = System.Drawing.Point(10 , 115 ) self._label5.Name = "label5" self._label5.Size = System.Drawing.Size(46 , 23 ) self._label5.TabIndex = 0 self._label5.Text = "高度:" self._label5.TextAlign = System.Drawing.ContentAlignment.MiddleRight # # tb_Height # self._tb_Height.Location = System.Drawing.Point(63 , 116 ) self._tb_Height.Name = "tb_Height" self._tb_Height.Size = System.Drawing.Size(157 , 23 ) self._tb_Height.TabIndex = 3 self._tb_Height.Text = "50" # # label6 # self._label6.Location = System.Drawing.Point(227 , 114 ) self._label6.Name = "label6" self._label6.Size = System.Drawing.Size(43 , 23 ) self._label6.TabIndex = 2 self._label6.Text = "mm" # # btn_GenerateGeo # self._btn_GenerateGeo.Location = System.Drawing.Point(63 , 160 ) self._btn_GenerateGeo.Name = "btn_GenerateGeo" self._btn_GenerateGeo.Size = System.Drawing.Size(82 , 23 ) self._btn_GenerateGeo.TabIndex = 3 self._btn_GenerateGeo.Text = "创建模型" self._btn_GenerateGeo.UseVisualStyleBackColor = True self._btn_GenerateGeo.Click += self.Btn_GenerateGeoClick # # MainForm # self.ClientSize = System.Drawing.Size(284 , 204 ) self.Controls.Add(self._btn_GenerateGeo) self.Controls.Add(self._label6) self.Controls.Add(self._label4) self.Controls.Add(self._label2) self.Controls.Add(self._tb_Height) self.Controls.Add(self._label5) self.Controls.Add(self._tb_Width) self.Controls.Add(self._label3) self.Controls.Add(self._tb_Length) self.Controls.Add(self._label1) self.Font = System.Drawing.Font("微软雅黑" , 9 , System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, 134 ) self.Name = "MainForm" self.Text = "几何建模示例" self.ResumeLayout(False ) self.PerformLayout() def Btn_GenerateGeoClick (self, sender, e) : length = (float)(self._tb_Length.Text) width = (float)(self._tb_Width.Text) height=(float)(self._tb_Height.Text)
3 修改脚本代码 直接执行代码会报错,需要对代码进行修改。
点击执行脚本
按钮,程序并没有报错,然而也没有什么反应,此时应当在代码末尾添加代码将对话框显示出来 form = MainForm() form.ShowDialog()
如下图所示。
修改函数Btn_GenerateGeoClick
,实现程序功能 为了避免脚本创建的几何相互重叠,这里在几何创建函数中添加清除几何函数Clear All
,如下图所示 点击运行按钮,此时弹出对话框,设置数据后点击创建模型
按钮,此时在图形窗口中显示按输入的尺寸创建的几何模型,如下图所示 注: 后期调用脚本时可能会提示什么info1,info2未定义,此时可以将脚本文件中的info1,info2等直接删除掉。还有就是录制脚本中的一些鼠标选择项,可能会在后续的运行过程中提示错误,此时应当修改为利用几何遍历的方式选择。
” 最终的完整代码如下(代码经过精简):
# Python Script, API Version = V19 def GenerateGeo (length=30 , width =12 , height=10 ) : ClearAll() # 设置新草绘 result = SketchHelper.StartConstraintSketching() # 设置草绘平面 sectionPlane = Plane.PlaneXY result = ViewHelper.SetSketchPlane(sectionPlane) # 设置新草绘 result = SketchHelper.StartConstraintSketching() # 草绘矩形 point1 = Point2D.Create(MM(0 ),MM(0 )) point2 = Point2D.Create(MM(length),MM(0 )) point3 = Point2D.Create(MM(length),MM(width)) result = SketchRectangle.Create(point1, point2, point3) # 实体化草绘 mode = InteractionMode.Solid result = ViewHelper.SetViewMode(mode) # 拉伸 1 个面 selection = Selection.Create(GetRootPart().Bodies[0 ].Faces) options = ExtrudeFaceOptions() options.ExtrudeType = ExtrudeType.Add result = ExtrudeFaces.Execute(selection, MM(height), options) import clr clr.AddReference('System.Drawing' ) clr.AddReference('System.Windows.Forms' )from System.Drawing import *from System.Windows.Forms import * class MainForm (Form) : def __init__ (self) : self.InitializeComponent() def InitializeComponent (self) : self._label1 =Label() self._tb_Length =TextBox() self._label2 =Label() self._label3 = Label() self._tb_Width = TextBox() self._label4 = Label() self._label5 = Label() self._tb_Height = TextBox() self._label6 = Label() self._btn_GenerateGeo = Button() self.SuspendLayout() # # label1 # self._label1.Location = Point(10 , 36 ) self._label1.Name = "label1" self._label1.Size = Size(46 , 23 ) self._label1.TabIndex = 0 self._label1.Text = "长度:" self._label1.TextAlign = ContentAlignment.MiddleRight # # tb_Length # self._tb_Length.Location = Point(63 , 37 ) self._tb_Length.Name = "tb_Length" self._tb_Length.Size = Size(157 , 23 ) self._tb_Length.TabIndex = 1 self._tb_Length.Text = "30" # # label2 # self._label2.Location = Point(227 , 35 ) self._label2.Name = "label2" self._label2.Size = Size(43 , 23 ) self._label2.TabIndex = 2 self._label2.Text = "mm" # # label3 # self._label3.Location = Point(10 , 74 ) self._label3.Name = "label3" self._label3.Size = Size(46 , 23 ) self._label3.TabIndex = 0 self._label3.Text = "宽度:" self._label3.TextAlign = ContentAlignment.MiddleRight # # tb_Width # self._tb_Width.Location = Point(63 , 75 ) self._tb_Width.Name = "tb_Width" self._tb_Width.Size = Size(157 , 23 ) self._tb_Width.TabIndex = 2 self._tb_Width.Text = "20" # # label4 # self._label4.Location = Point(227 , 73 ) self._label4.Name = "label4" self._label4.Size = Size(43 , 23 ) self._label4.TabIndex = 2 self._label4.Text = "mm" # # label5 # self._label5.Location = Point(10 , 115 ) self._label5.Name = "label5" self._label5.Size = Size(46 , 23 ) self._label5.TabIndex = 0 self._label5.Text = "高度:" self._label5.TextAlign = ContentAlignment.MiddleRight # # tb_Height # self._tb_Height.Location = Point(63 , 116 ) self._tb_Height.Name = "tb_Height" self._tb_Height.Size = Size(157 , 23 ) self._tb_Height.TabIndex = 3 self._tb_Height.Text = "50" # # label6 # self._label6.Location = Point(227 , 114 ) self._label6.Name = "label6" self._label6.Size = Size(43 , 23 ) self._label6.TabIndex = 2 self._label6.Text = "mm" # # btn_GenerateGeo # self._btn_GenerateGeo.Location = Point(63 , 160 ) self._btn_GenerateGeo.Name = "btn_GenerateGeo" self._btn_GenerateGeo.Size = Size(82 , 23 ) self._btn_GenerateGeo.TabIndex = 3 self._btn_GenerateGeo.Text = "创建模型" self._btn_GenerateGeo.UseVisualStyleBackColor = True self._btn_GenerateGeo.Click += self.Btn_GenerateGeoClick # # MainForm # self.ClientSize = Size(284 , 204 ) self.Controls.Add(self._btn_GenerateGeo) self.Controls.Add(self._label6) self.Controls.Add(self._label4) self.Controls.Add(self._label2) self.Controls.Add(self._tb_Height) self.Controls.Add(self._label5) self.Controls.Add(self._tb_Width) self.Controls.Add(self._label3) self.Controls.Add(self._tb_Length) self.Controls.Add(self._label1) self.Font = Font("微软雅黑" , 9 , FontStyle.Regular, GraphicsUnit.Point, 134 ) self.Name = "MainForm" self.Text = "几何建模示例" self.ResumeLayout(False ) self.PerformLayout() def Btn_GenerateGeoClick (self, sender, e) : length = (float)(self._tb_Length.Text) width = (float)(self._tb_Width.Text) height=(float)(self._tb_Height.Text) GenerateGeo(length,width,height) form = MainForm() form.ShowDialog()
利用脚本编辑器中的保存按钮保存脚本文件。
4 脚本发布 脚本调试完毕后,可以保存代码或将功能发布为按钮。
发布脚本
按钮下包含两种:
发布为组
:将脚本发布为群组,后续需要使用时直接在群组列表中选取并运行发布为工具
:将脚本发布为工具栏按钮,可以直接点击调用。而且在SCDM关闭后再启动,此工具按钮依然会存在选择发布为工具(Beta) ,点击按钮发布工具 打开设置对话框,如下图所示,设置脚本名称及图标路径,点击确定 按钮发布工具 注: 这里的图标尺寸为32*32。
” 工具发布完毕后,在工具栏中会多出如下图所示的按钮,点击该按钮会运行该脚本工具 此时点击按钮即可运行脚本。
5 一点想法 在工程中对现有软件进行二次开发有利于知识保存,同时也有利于提高工作效率。
SCDM是基于Windows的软件,其选用IronPython进行脚本开发无可厚非,但个人认为这是非常大的一个败笔。IronPython的开发早已陷入停滞,基本已经可以宣称死亡了,就连微软自己都不怎么待见这玩意儿。
SCDM的插件开发是基于C#的,也许这个才是正途吧。不过脚本开发比较轻便,录制和编程都可以在极短的时间内完成,或许将IronPython改成Python也是不错的选择,毕竟Python的GUI库也不少,开发效率也并不比IronPython低。
文中程序代码: