最近比较忙,一直没有更新内容,周末有个网友询问他遇到的一个问题,问题是他使用CreateSpline函数时无法生成相应的样条曲线,让我帮帮看看是否能解决,周末没有时间处理,今天早上来试了下,确实是有问题,不过也有解决办法,这里将解决办法记录以下,有类似需求或问题的朋友可以参考下。
网友的问题是他在CreateSpline方法时,并没有按照要求创建出需要的样条曲线,网友怀疑是数据没有被正确传递,让我看看是否能帮忙解决。
CreateSpline在VBA中的定义如下:
Function CreateSpline( _
ByVal PointData As System.Object _
) As SketchSegment
PointData : 是一个双精度的坐标数组
CreatePoint在makepy.py生成的文件中定义如下
def CreateSpline(self, PointData=defaultNamedNotOptArg):
'Create a sketch spline'
ret = self._oleobj_.InvokeTypes(37, LCID, 1, (9, 0), ((12, 1),),PointData
)
if ret is not None:
ret = Dispatch(ret, 'CreateSpline', '{83A33DBF-27C5-11CE-BFD4-00400513BB57}')
return ret
可以看到VBA和Python 中两个的定义是一样的,这样看来应该不会出问题,也很容易解决问题,实际则不然
方法本身使用不难,于是就在Python 中简单写了如下测试代码:
import win32com.client
import pythoncom
def main():
sldver=2018
swApp=win32com.client.Dispatch(f'SldWorks.Application.{sldver-1992}')
swApp.CommandInProgress =True
swApp.Visible =True
# 注意此处当前文档是工程图文档
swModel = swApp.ActiveDoc
Nothing=win32com.client.VARIANT(9,None)
boolstatus = swModel.Extension.SelectByID2("上视基准面", "PLANE", 0, 0, 0, False, 0, Nothing, 0)
swModel.SketchManager.InsertSketch(True)
swModel.ClearSelection2(True)
# 样条线的2D数据点
points=(0.05,0,0,0.1,0.1,0,0.3,0.5,0,0.8,0.2,0)
pointArray=win32com.client.VARIANT(12,points)
skSegment = swModel.SketchManager.CreateSpline(pointArray)
swModel.SketchManager.InsertSketch(True)
if __name__ == '__main__':
main()
运行以后出现如下错误:
‘NoneType’ object is not callable
出现问题的语句是:
skSegment = swModel.SketchManager.CreateSpline(pointArray)
错误提示是说CreateSpline的是个空类型,没法当函数调用,那这样就没法输入数据点了,也就无法生成相应的样条曲线,所以此方法有问题,不能用,再看看是否还有其他解决措施
其实CreateSpline方法是个过时的方法,已经用CreateSpline3方法替代(2018版如此),那我们就用最新的方法重新调用下,看是否能解决,以下是更改为CreateSpline3的代码:
import win32com.client
import pythoncom
def main():
sldver=2018
swApp=win32com.client.Dispatch(f'SldWorks.Application.{sldver-1992}')
swApp.CommandInProgress =True
swApp.Visible =True
# 注意此处当前文档是工程图文档
swModel = swApp.ActiveDoc
Nothing=win32com.client.VARIANT(9,None)
boolstatus = swModel.Extension.SelectByID2("上视基准面", "PLANE", 0, 0, 0, False, 0, Nothing, 0)
swModel.SketchManager.InsertSketch(True)
swModel.ClearSelection2(True)
status=win32com.client.VARIANT(16396,None)
# 样条线的2D数据点
points=(0.05,0,0,0.1,0.1,0,0.3,0.5,0,0.8,0.2,0)
pointArray=win32com.client.VARIANT(12,points)
skSegment = swModel.SketchManager.CreateSpline3(pointArray,Nothing,Nothing,True,status)
swModel.SketchManager.InsertSketch(True)
if __name__ == '__main__':
main()
按照以上代码运行后,代码不报错,但是依然没有生成相关的样条曲线,这样看来问题就出在CreateSpline3的参数定义上,可是对照参数发现没有问题,再仔细一想问题肯定出在CreateSpline3的第一个参数定义,之前就有过类似的情况,第一个参数实际需要的数组点,那就需要将points转换为数组点,之前的《Python SolidWorks 二次开发—SolidWorks中IMathUtility对象的CreatePoint方法踩坑》就使用过此种赋值,具体如下:
此句代码修改:
pointArray=win32com.client.VARIANT(12,points)
修改后的代码如下:
pointArray=win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,points)
再运行后已经可以生成样条曲线,问题解决,问题原因也正如网友怀疑的一样,传递的数据格式不正确
完整代码如下:
import win32com.client
import pythoncom
def main():
sldver=2018
swApp=win32com.client.Dispatch(f'SldWorks.Application.{sldver-1992}')
swApp.CommandInProgress =True
swApp.Visible =True
# 注意此处当前文档是工程图文档
swModel = swApp.ActiveDoc
Nothing=win32com.client.VARIANT(9,None)
boolstatus = swModel.Extension.SelectByID2("上视基准面", "PLANE", 0, 0, 0, False, 0, Nothing, 0)
swModel.SketchManager.InsertSketch(True)
swModel.ClearSelection2(True)
status=win32com.client.VARIANT(16396,None)
# 样条线的2D数据点
points=(0.05,0,0,0.1,0.1,0,0.3,0.5,0,0.8,0.2,0)
pointArray=win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8,points)
skSegment = swModel.SketchManager.CreateSpline3(pointArray,Nothing,Nothing,True,status)
swModel.SketchManager.InsertSketch(True)
if __name__ == '__main__':
main()
其实出现这样的问题大多都是由于数据传输的时候格式不正确,输入正确的格式后问题都会迎刃而解,以下是可能遇到的一些数据类型的转换,记录以下,方便以后查阅
def vtPoint(x, y, z):
# 坐标点转化为浮点数
return VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))
def vtObj(obj):
# 转化为对象数组
return VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, obj)
def vtFloat(list):
# 列表转化为浮点数
return VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, list)
def vtInt(list):
# 列表转化为整数
return VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_I2, list)
def vtVariant(list):
# 列表转化为变体
return VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_VARIANT, list)