本文描述在SCDM中开发参数化脚本的基本流程。
1 脚本录制
在进行脚本参数化之前,可以进行脚本录制。不过脚本录制工作不是必须的,如果对SCDM的脚本API比较熟悉的话,也可以直接编写代码。不过对于一般的工程人员,还是建议采用录制的方式获取代码。
这里以一个简单的案例进行演示。
-
启动SCDM,选择文件 → 新建 → 脚本创建一个新脚本文件
-
脚本编辑器如下图所示,默认情况下为录制状态,用户的所有操作均会作为脚本被记录下来
-
在XY草图平面上绘制一个30×12 mm的矩形
-
此时脚本窗口中录制形成的脚本程序如下图所示
-
拉伸距离10mm后形成三维几何
-
此时增加的脚本代码如下所示
-
将代码封装成函数,将尺寸作为函数参数
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 应用程序,设置名称与位置,如下图所示创建新项目
-
点击设计选项卡进入界面设计
-
采用拖拽控件的方式创建GUI界面,如下图所示
-
为控件命名,利用属性设置面板将长度输入框命名为tb_length,宽度输入框命名为tb_width,高度输入框命名为tb_height,创建模型按钮命名为btn_GenerateGeo,SharpDevelop会自动调整控件名称,在人工命名的前面加上 _
,如下图所示
-
双击设计界面中的 创建模型
按钮,软件自动创建回调函数Btn_GenerateGeoClick
,源代码中如下图所示
-
修改 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.Drawing
import 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 = 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)
-
拷贝所有代码到SCDM的脚本编辑器中
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低。
文中程序代码:
本篇文章来源于微信公众号: CFD之道
评论前必须登录!
注册