solidworks自动标注-python实现
solidworks自动标注-python实现
- 正文
正文
标注前:

标注后:

标注逻辑:
1、打开solidworks工程图并选中一个视图:

2、执行代码
(执行时需要把swconst.py放在这段代码的文件同一目录下)
import time
import math
import pyautogui
import win32com.client as win32
import threading
import pythoncom
from swconst import constants as swconstswerrors = win32.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 3)
swwarnings = win32.VARIANT(pythoncom.VT_BYREF | pythoncom.VT_I4, 3)def getcirclesort(xpoint1,xcircle2,xcirclepoint2):#根据第一个参数的指数,从小到大排列三个参数,传入的后两个参数会被清空xcircleinfo = []xcircle3 = []xcirclepoint3 = []xpoint2 = []t = len(xpoint1)for i in range(t):xpoint1min = xpoint1[0]xpoint1minindex = 0for j in range(len(xpoint1)):if xpoint1[j] < xpoint1min:xpoint1min = xpoint1[j]xpoint1minindex = jxcircle3.append(xcircle2[xpoint1minindex])xcirclepoint3.append(xcirclepoint2[xpoint1minindex])xpoint2.append(xpoint1min)xcircle2.remove(xcircle2[xpoint1minindex])xcirclepoint2.remove(xcirclepoint2[xpoint1minindex])xpoint1.remove(xpoint1min)xcircleinfo.append(xcircle3)xcircleinfo.append(xcirclepoint3)xcircleinfo.append(xpoint2)return(xcircleinfo)def getonlyinfo(xcircle1,xcirclepoint1,index):#根据第二个参数去重onlyinfo = []xcircle2 = []xcirclepoint2 = []xpoint1 = []for i in range(len(xcircle1)):if xcirclepoint1[i][index] not in xpoint1:xpoint1.append(xcirclepoint1[i][index])xcircle2.append(xcircle1[i])xcirclepoint2.append(xcirclepoint1[i])#水平方向用y坐标小的点,竖直方向用x坐标大的点##########else:location = xpoint1.index(xcirclepoint1[i][index])if index == 0:if xcirclepoint1[i][1] < xcirclepoint1[location][1]:xpoint1[location] = xcirclepoint1[i][index]xcircle2[location] = xcircle1[i]xcirclepoint2[location] = xcirclepoint1[i]elif index == 1:if xcirclepoint1[i][0] > xcirclepoint1[location][0]:xpoint1[location] = xcirclepoint1[i][index]xcircle2[location] = xcircle1[i]xcirclepoint2[location] = xcirclepoint1[i]##################### onlyinfo.append(xcircle2)onlyinfo.append(xcirclepoint2)onlyinfo.append(xpoint1)return(onlyinfo)def getcirclesortinfo(closecircle,closecirclepoint):#孔排序circlesortinfo = []#x方向把孔坐标排序xcircle1 = []xcirclepoint1 = []for i in range(len(closecircle)):xcircle1.append(closecircle[i])xcirclepoint1.append(closecirclepoint[i])#去掉x坐标重复的点xonlyinfo = getonlyinfo(xcircle1,xcirclepoint1,0)xcircle2 = xonlyinfo[0]xcirclepoint2 = xonlyinfo[1]xpoint1 = xonlyinfo[2]#x坐标从小到大排序xcircleinfo = getcirclesort(xpoint1,xcircle2,xcirclepoint2)xcircle3 = xcircleinfo[0]xcirclepoint3 = xcircleinfo[1]xpoint2 = xcircleinfo[2]#y方向把孔坐标排序ycircle1 = []ycirclepoint1 = []for i in range(len(closecircle)):ycircle1.append(closecircle[i])ycirclepoint1.append(closecirclepoint[i])#去掉y坐标重复的点xonlyinfo = getonlyinfo(ycircle1,ycirclepoint1,1)ycircle2 = xonlyinfo[0]ycirclepoint2 = xonlyinfo[1]ypoint1 = xonlyinfo[2]#y坐标从小到大排序ycircleinfo = getcirclesort(ypoint1,ycircle2,ycirclepoint2)ycircle3 = ycircleinfo[0]ycirclepoint3 = ycircleinfo[1]ypoint2 = ycircleinfo[2]circlesortinfo.append(xcircle3)circlesortinfo.append(xcirclepoint3)circlesortinfo.append(xpoint2)circlesortinfo.append(ycircle3)circlesortinfo.append(ycirclepoint3)circlesortinfo.append(ypoint2)return(circlesortinfo)def getboundaryline(view,alllineinfo):boundarylineinfo = []xedge = alllineinfo[0]yedge = alllineinfo[1]xedgey = alllineinfo[2]yedgex = alllineinfo[3]#找出水平线最上和最下up = xedgey[0]lineup = xedge[0]for i in range(len(xedge)):if xedgey[i] > up:up = xedgey[i]lineup = xedge[i]down = xedgey[0]linedown = xedge[0]for i in range(len(xedge)):if xedgey[i] < down:down = xedgey[i]linedown = xedge[i]#找出竖直线最左和最右right = yedgex[0]lineright = yedge[0]for i in range(len(yedge)):if yedgex[i] > right:right = yedgex[i]lineright = yedge[i]left = yedgex[0]lineleft = yedge[0]for i in range(len(yedge)):if yedgex[i] < left:left = yedgex[i]lineleft = yedge[i]boundarylineinfo.append(lineup)boundarylineinfo.append(linedown)boundarylineinfo.append(lineleft)boundarylineinfo.append(lineright)boundarylineinfo.append(right)boundarylineinfo.append(left)boundarylineinfo.append(up)boundarylineinfo.append(down)return(boundarylineinfo)def getalledgeinfo(view,vedges):#输入:视图中的线段#返回:直线和圆弧信息#与solidworks通信alledgeinfo = []allline = []alllineparam = []allcircle = []allcircleparam1 = []allcircleparam2 = []for i in range(len(vedges)):swcurve = vedges[i].GetCurveif swcurve.IsLine:print('这是一条直线')allline.append(vedges[i])alllineparam.append(vedges[i].GetCurveParams2)elif swcurve.IsCircle:print('这是一个圆')allcircle.append(vedges[i])allcircleparam1.append(vedges[i].GetCurveParams2)allcircleparam2.append(swcurve.CircleParams)alledgeinfo.append(allline)alledgeinfo.append(alllineparam)alledgeinfo.append(allcircle)alledgeinfo.append(allcircleparam1)alledgeinfo.append(allcircleparam2)return(alledgeinfo)def getalllineinfo(view,alledgeinfo):alllineinfo = []allline = alledgeinfo[0]alllineparam = alledgeinfo[1]xedge = []yedge = []xedgey = []yedgex = []for i in range(len(alllineparam)):start = transform4(view,alllineparam[i][0],alllineparam[i][1],alllineparam[i][2])end = transform4(view,alllineparam[i][3],alllineparam[i][4],alllineparam[i][5])#线段两个端点x坐标相等,该线竖直if start[0] == end[0]:yedge.append(allline[i])yedgex.append(start[0])#线段两个端点y坐标相等,该线水平if start[1] == end[1]:xedge.append(allline[i])xedgey.append(start[1])alllineinfo.append(xedge)alllineinfo.append(yedge)alllineinfo.append(xedgey)alllineinfo.append(yedgex)return(alllineinfo)def getallcircleinfo(view,alledgeinfo):allcircleinfo = []allcircle = alledgeinfo[2]allcircleparam1 = alledgeinfo[3]allcircleparam2 = alledgeinfo[4]closecircle = []closecircleR = []closecirclepoint = []for i in range(len(allcircle)):start = transform4(view,round(allcircleparam1[i][0],4),round(allcircleparam1[i][1],4),round(allcircleparam1[i][2],4))end = transform4(view,round(allcircleparam1[i][3],4),round(allcircleparam1[i][4],4),round(allcircleparam1[i][5],4))if start == end:startangle = math.degrees(allcircleparam1[i][6])endangle = math.degrees(allcircleparam1[i][7])if startangle - endangle == 360 or startangle - endangle == -360:circleR = allcircleparam2[i][6]center = transform4(view,round(allcircleparam2[i][0],4),round(allcircleparam2[i][1],4),round(allcircleparam2[i][2],4))center.remove(center[2])closecircle.append(allcircle[i])closecircleR.append(circleR)closecirclepoint.append(center)allcircleinfo.append(closecircle)allcircleinfo.append(closecircleR)allcircleinfo.append(closecirclepoint)return(allcircleinfo)def dimensionxcircle(part,scale,vbounds,xcirclepoint3,xcircle3,xmin,xmax,ymin,ymax,lineleft,lineright,yoffset2):#标注水平方向孔位置尺寸xpos = (xcirclepoint3[0][0] + xmin)/2 * scale + vbounds[0] + xoffsetypos = ymin * scale + vbounds[1] + yoffset - yoffset2part.ClearSelection2(True)lineleft.Select4(True,arg_Nothing)xcircle3[0].Select4(True,arg_Nothing)part.AddVerticalDimension2(xpos,ypos,0)for i in range(len(xcircle3)-1):xpos = (xcirclepoint3[i][0] + xcirclepoint3[i+1][0])/2 * scale + vbounds[0] + xoffsetypos = ymin * scale + vbounds[1] + yoffset - yoffset2part.ClearSelection2(True)xcircle3[i].Select4(True,arg_Nothing)xcircle3[i+1].Select4(True,arg_Nothing)part.AddHorizontalDimension2(xpos,ypos,0)def dimensionxmax(part,scale,vbounds,xmin,xmax,ymin,ymax,lineleft,lineright,yoffset2):xpos = (xmax + xmin)/2 * scale + vbounds[0] + xoffsetypos = ymin * scale + vbounds[1] + yoffset - yoffset2part.ClearSelection2(True)lineleft.Select4(True,arg_Nothing)lineright.Select4(True,arg_Nothing)part.AddVerticalDimension2(xpos,ypos,0)def dimensionycircle(part,scale,vbounds,ycirclepoint3,ycircle3,xmin,xmax,ymin,ymax,lineup,linedown,xoffset2):#标注竖直方向孔位置尺寸xpos = xmax * scale + vbounds[0] + xoffset + xoffset2ypos = (ycirclepoint3[0][1] + ymin)/2 * scale + vbounds[1] + yoffsetpart.ClearSelection2(True)linedown.Select4(True,arg_Nothing)ycircle3[0].Select4(True,arg_Nothing)part.AddHorizontalDimension2(xpos,ypos,0)for i in range(len(ycircle3)-1):xpos = xmax * scale + vbounds[0] + xoffset + xoffset2ypos = (ycirclepoint3[i][1] + ycirclepoint3[i+1][1])/2 * scale + vbounds[1] + yoffsetpart.ClearSelection2(True)ycircle3[i].Select4(True,arg_Nothing)ycircle3[i+1].Select4(True,arg_Nothing)part.AddVerticalDimension2(xpos,ypos,0)def dimensionymax(part,scale,vbounds,xmin,xmax,ymin,ymax,lineup,linedown,xoffset2):#标注竖直最大尺寸xpos = xmax * scale + vbounds[0] + xoffset + xoffset2ypos = (ymax + ymin)/2 * scale + vbounds[1] + yoffsetpart.ClearSelection2(True)lineup.Select4(True,arg_Nothing)linedown.Select4(True,arg_Nothing)part.AddHorizontalDimension2(xpos,ypos,0)def getpointsort(allclosecirclepointx1xy3,t):allclosecirclepointx1xy = []if t == 0:q =1elif t == 1:q = 0for i in range(len(allclosecirclepointx1xy3)):allclosecirclepointx1xy3[i].sort(key=lambda x: (x[t],x[q]))allclosecirclepointx1xy.append(allclosecirclepointx1xy3[i])return(allclosecirclepointx1xy)def transform4(view,x,y,z):point = swMathUtil.CreatePointpoint.ArrayData=win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x,y,z))swviewxform = view.ModelToViewTransformviewpoint = point.MultiplyTransform(swviewxform)viewpoint1 = []viewpoint1.append(round(viewpoint.ArrayData[0],4))viewpoint1.append(round(viewpoint.ArrayData[1],4))viewpoint1.append(round(viewpoint.ArrayData[2],4))return(viewpoint1)def autodimension(): #自动标注global swappglobal xoffsetglobal yoffsetglobal arg_Nothingglobal swMathUtil#连接solidworksprint('正在连接solidworks')#swapp = win32.Dispatch("Sldworks.application") #引入sldworks接口sw_edition = 2016swapp = win32.Dispatch('SldWorks.Application.{}'.format(sw_edition - 1992))swapp.Visible = TrueswMathUtil = swapp.GetMathUtilityarg_Nothing = win32.VARIANT(pythoncom.VT_DISPATCH, None) #转义VBA中不同变量nothingprint('成功连接solidworks') part = swapp.ActiveDoc###part.SketchManager.AddToDB = True#设置不弹出输入尺寸值对话框swapp.SetUserPreferenceToggle(swconst.swInputDimValOnCreate, False)###swselectmgr = part.SelectionManagerview = swselectmgr.GetSelectedObject5(1)view=win32.Dispatch(view)#vbounds = view.GetOutlinevbounds = [0,0,0]#视图比例#viewscale = view.ScaleRatio#scale = viewscale[0]/viewscale[1]scale = 1#偏移#xoffset = 0.005#yoffset = 0.005xoffset = 0yoffset = 0vcomps = view.GetVisibleComponentsvedges = view.GetVisibleEntities(vcomps[0],1)#遍历视图中的线段,返回:直线列表,圆列表alledgeinfo = getalledgeinfo(view,vedges)#处理直线信息,返回:水平直线,竖直直线,水平直线y坐标,竖直直线x坐标alllineinfo = getalllineinfo(view,alledgeinfo)#处理圆弧信息,返回:整圆,半径,圆心allcircleinfo = getallcircleinfo(view,alledgeinfo)closecircle = allcircleinfo[0]closecircleR = allcircleinfo[1]closecirclepoint = allcircleinfo[2]xedge = alllineinfo[0]yedge = alllineinfo[1]xedgey = alllineinfo[2]yedgex = alllineinfo[3]#找出边界线boundarylineinfo = getboundaryline(view,alllineinfo)lineup = boundarylineinfo[0]linedown = boundarylineinfo[1]lineleft = boundarylineinfo[2]lineright = boundarylineinfo[3]xmax = boundarylineinfo[4]xmin = boundarylineinfo[5]ymax = boundarylineinfo[6]ymin = boundarylineinfo[7]onlyR = []for i in range(len(closecircleR)):if round(closecircleR[i],6) not in onlyR:onlyR.append(round(closecircleR[i],6))print('半径')print(round(closecircleR[i],6))allclosecircle = []allclosecirclepoint = []closecirclemaxx = []closecirclemaxy = []for i in range(len(onlyR)):closecirclei = []closecirclepointi = []for j in range(len(closecircleR)):if round(closecircleR[j],6) == onlyR[i]:closecirclei.append(closecircle[j])closecirclepointi.append(closecirclepoint[j])allclosecircle.append(closecirclei)allclosecirclepoint.append(closecirclepointi)maxxi = closecirclepointi[0][0]maxyi = closecirclepointi[0][1]for j in range(len(closecirclepointi)):if closecirclepointi[j][0] > maxxi:maxxi = closecirclepointi[j][0]if closecirclepointi[j][1] > maxyi:maxyi = closecirclepointi[j][1]closecirclemaxx.append(maxxi)closecirclemaxy.append(maxyi)allclosecircle1 = []allclosecirclepoint1 = []for i in range(len(allclosecircle)):allclosecircle1.append(allclosecircle[i])allclosecirclepoint1.append(allclosecirclepoint[i])allclosecircleinfox = getcirclesort(closecirclemaxx,allclosecircle,allclosecirclepoint)allclosecircleinfoy = getcirclesort(closecirclemaxy,allclosecircle1,allclosecirclepoint1)#x方向allclosecirclemaxx1 = allclosecircleinfox[2]allclosecirclex1 = allclosecircleinfox[0]allclosecirclepointx1 = allclosecircleinfox[1]allclosecirclepointx1xy3 = [] #存放圆心坐标的x值和y值for i in range(len(allclosecirclepointx1)):circlepointj = []for j in range(len(allclosecirclepointx1[i])):circlepointi = []circlepointi.append(allclosecirclepointx1[i][j][0])circlepointi.append(allclosecirclepointx1[i][j][1])circlepointj.append(circlepointi)allclosecirclepointx1xy3.append(circlepointj)#y方向allclosecirclemaxy1 = allclosecircleinfoy[2]allclosecircley1 = allclosecircleinfoy[0]allclosecirclepointy1 = allclosecircleinfoy[1]allclosecirclepointy1xy3 = [] #存放圆心坐标的x值和y值for i in range(len(allclosecirclepointy1)):circlepointj = []for j in range(len(allclosecirclepointy1[i])):circlepointi = []circlepointi.append(allclosecirclepointy1[i][j][0])circlepointi.append(allclosecirclepointy1[i][j][1])circlepointj.append(circlepointi)allclosecirclepointy1xy3.append(circlepointj)#xy方向去重#这里插入一个函数,将allclosecirclepointx1xy按照x方向排序,allclosecirclepointy1xy安装y方向排序#处理allclosecirclepointx1xy3和allclosecirclepointy1xy3allclosecirclepointx1xy = getpointsort(allclosecirclepointx1xy3,0)allclosecirclepointy1xy = getpointsort(allclosecirclepointy1xy3,1)#####################################allclosecirclepointxy1 = []allclosecirclemaxx = []allclosecirclex = []allclosecirclepointx = []for i in range(len(allclosecirclepointx1)):if allclosecirclepointx1xy[i] not in allclosecirclepointxy1:allclosecirclepointxy1.append(allclosecirclepointx1xy[i])allclosecirclemaxx.append(allclosecirclemaxx1[i])allclosecirclex.append(allclosecirclex1[i])allclosecirclepointx.append(allclosecirclepointx1[i])allclosecirclepointxy2 = []allclosecirclemaxy = []allclosecircley = []allclosecirclepointy = []for i in range(len(allclosecirclepointy1)):if allclosecirclepointy1xy[i] not in allclosecirclepointxy2:allclosecirclepointxy2.append(allclosecirclepointy1xy[i])allclosecirclemaxy.append(allclosecirclemaxy1[i])allclosecircley.append(allclosecircley1[i])allclosecirclepointy.append(allclosecirclepointy1[i])#####################################yoffset2 = float(e13.get())/1000#yoffset2step = float(e13.get())/1000yoffset2 = 10/1000yoffset2step = 10/1000for i in range(len(allclosecirclemaxx)):circlesortinfo = getcirclesortinfo(allclosecirclex[i],allclosecirclepointx[i])xcircle3 = circlesortinfo[0]xcirclepoint3 = circlesortinfo[1]xpoint2 = circlesortinfo[2]ycircle3 = circlesortinfo[3]ycirclepoint3 = circlesortinfo[4]ypoint2 = circlesortinfo[5]#标注水平方向孔位置尺寸dimensionxcircle(part,scale,vbounds,xcirclepoint3,xcircle3,xmin,xmax,ymin,ymax,lineleft,lineright,yoffset2)yoffset2 = yoffset2+yoffset2step#标注水平最大尺寸dimensionxmax(part,scale,vbounds,xmin,xmax,ymin,ymax,lineleft,lineright,yoffset2)#xoffset2 = float(e13.get())/1000#xoffset2step = float(e13.get())/1000xoffset2 = 10/1000xoffset2step = 10/1000for i in range(len(allclosecirclemaxy)):circlesortinfo = getcirclesortinfo(allclosecircley[i],allclosecirclepointy[i])xcircle3 = circlesortinfo[0]xcirclepoint3 = circlesortinfo[1]xpoint2 = circlesortinfo[2]ycircle3 = circlesortinfo[3]ycirclepoint3 = circlesortinfo[4]ypoint2 = circlesortinfo[5]#标注竖直方向孔位置尺寸dimensionycircle(part,scale,vbounds,ycirclepoint3,ycircle3,xmin,xmax,ymin,ymax,lineup,linedown,xoffset2)xoffset2 = xoffset2+xoffset2step#标注竖直最大尺寸dimensionymax(part,scale,vbounds,xmin,xmax,ymin,ymax,lineup,linedown,xoffset2)#设置弹出输入尺寸值对话框swapp.SetUserPreferenceToggle(swconst.swInputDimValOnCreate, True)#运行中开启这个选项更快part.SketchManager.AddToDB = Falseautodimension()
即可完成以下逻辑:
①:遍历选中视图中的线条,存入列表备用
②:遍历线条,按照直线和圆弧,分别存入列表备用
③:遍历直线,找出最上、最下、最左、最右的直线,存入常量备用
④:遍历圆弧,找出完整的圆,存入列表备用
⑤:圆弧按照半径分类,按照水平和竖直方向排序,分别存入列表备用
⑥:同心圆组成的列表子项去重
⑦:自动标注所有孔的位置尺寸,不同类型的孔分层标注
注:上面代码有一些无意义的操作,例如传递的vbounds和scale两个参数,懒得改了
但是在运行过程中有几个问题没有解决:
一、例如xy平面内有一个圆形,这个圆形在xz平面内会投影成一条直线,这条直线虽然在视图中看起来是一条直线,遍历的时候solidworks api会把它识别成一个圆,会导致多一些没有意义的标注尺寸,如下图:

二、代码连接solidworks2016sp5时运行很快,符合预期,但是在solidworks2018sp5和solidworks2019sp4这两个版本中运行相当慢,相比solidworks2016sp5慢了十倍以上(我暂时只用到这三个版本的solidworks),这就导致我无法正常使用这段代码,因为手动标注比自动标注更快。
这个思路是我在工作中一点点摸索出来的,前前后后搞了一年多才到这个程度,有路过的大佬一起讨论一下,指点一下这两个问题如何解决,感激
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
