标注前:
标注后:
标注逻辑:
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 swconst
swerrors = 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 = 0
for j in range(len(xpoint1)):
if xpoint1[j] < xpoint1min:
xpoint1min = xpoint1[j]
xpoint1minindex = j
xcircle3.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].GetCurve
if 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] + xoffset
ypos = ymin * scale + vbounds[1] + yoffset - yoffset2
part.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] + xoffset
ypos = ymin * scale + vbounds[1] + yoffset - yoffset2
part.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] + xoffset
ypos = ymin * scale + vbounds[1] + yoffset - yoffset2
part.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 + xoffset2
ypos = (ycirclepoint3[0][1] + ymin)/2 * scale + vbounds[1] + yoffset
part.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 + xoffset2
ypos = (ycirclepoint3[i][1] + ycirclepoint3[i+1][1])/2 * scale + vbounds[1] + yoffset
part.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 + xoffset2
ypos = (ymax + ymin)/2 * scale + vbounds[1] + yoffset
part.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 =1
elif t == 1:
q = 0
for 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.CreatePoint
point.ArrayData=win32.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x,y,z))
swviewxform = view.ModelToViewTransform
viewpoint = 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 swapp
global xoffset
global yoffset
global arg_Nothing
global swMathUtil
#连接solidworks
print('正在连接solidworks')
#swapp = win32.Dispatch("Sldworks.application") #引入sldworks接口
sw_edition = 2016
swapp = win32.Dispatch('SldWorks.Application.{}'.format(sw_edition - 1992))
swapp.Visible = True
swMathUtil = swapp.GetMathUtility
arg_Nothing = win32.VARIANT(pythoncom.VT_DISPATCH, None) #转义VBA中不同变量nothing
print('成功连接solidworks')
part = swapp.ActiveDoc
###
part.SketchManager.AddToDB = True
#设置不弹出输入尺寸值对话框
swapp.SetUserPreferenceToggle(swconst.swInputDimValOnCreate, False)
###
swselectmgr = part.SelectionManager
view = swselectmgr.GetSelectedObject5(1)
view=win32.Dispatch(view)
#vbounds = view.GetOutline
vbounds = [0,0,0]
#视图比例
#viewscale = view.ScaleRatio
#scale = viewscale[0]/viewscale[1]
scale = 1
#偏移
#xoffset = 0.005
#yoffset = 0.005
xoffset = 0
yoffset = 0
vcomps = view.GetVisibleComponents
vedges = 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和allclosecirclepointy1xy3
allclosecirclepointx1xy = 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())/1000
yoffset2 = 10/1000
yoffset2step = 10/1000
for 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())/1000
xoffset2 = 10/1000
xoffset2step = 10/1000
for 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 = False
autodimension()
'''
即可完成以下逻辑:
①:遍历选中视图中的线条,存入列表备用
②:遍历线条,按照直线和圆弧,分别存入列表备用
③:遍历直线,找出最上、最下、最左、最右的直线,存入常量备用
④:遍历圆弧,找出完整的圆,存入列表备用
⑤:圆弧按照半径分类,按照水平和竖直方向排序,分别存入列表备用
⑥:同心圆组成的列表子项去重
⑦:自动标注所有孔的位置尺寸,不同类型的孔分层标注
注:上面代码有一些无意义的操作,例如传递的vbounds和scale两个参数,懒得改了
但是在运行过程中有几个问题没有解决:
一、例如xy平面内有一个圆形,这个圆形在xz平面内会投影成一条直线,这条直线虽然在视图中看起来是一条直线,遍历的时候solidworks api会把它识别成一个圆,会导致多一些没有意义的标注尺寸,如下图:
二、代码连接solidworks2016sp5时运行很快,符合预期,但是在solidworks2018sp5和solidworks2019sp4这两个版本中运行相当慢,相比solidworks2016sp5慢了十倍以上(我暂时只用到这三个版本的solidworks),这就导致我无法正常使用这段代码,因为手动标注比自动标注更快。
这个思路是我在工作中一点点摸索出来的,前前后后搞了一年多才到这个程度,有路过的大佬一起讨论一下,指点一下这两个问题如何解决,感激