终于考完了
昨天终于把驾照给考出来了。说起来真正考试过程倒是并不复杂,每个科目都是一次过了,但整个过程还是略显艰辛。……
[TOC]
(1)线局部重合、重叠
不仅仅包括直线段的重叠,同时包含有弧线的重合
(2)平行线
(1) 分区域
基于各个分块图形都具有一定区间,分块处理后互相不再打扰。每个图块外围会生成一个浅蓝色矩形框。
(2)去重线
(3)获交点
上述两步是为后续找外轮廓线奠定基础
(4)找外轮廓线
这里所采用的是这个算法闭合线段找最外围线段
(5)合并外轮廓线
此步可做可不做
将exe文件和同名lsp文件放到同一个文件夹中,然后在cad中加载该lsp文件。进而输入命令 2265(此命令可以自己在lsp文件中更改),在弹出的命令窗口提示”请选择图形“后在选择所需要处理的图形即可进行处理。此时会弹出窗口提示处理进程。若出现提示“第n未闭合”,则表明存在需要手动处理的图形,相应图形颜色会标红。当提示“多余线处理完成”后,程序执行完毕。对于弹出的窗口,按回车键可关闭。在程序处理过程中,cad中不建议执行其他操作,否则程序会报错。
遇到有闪退,一般重新运行两次即可。
如下图所示:
目前角度相差超过1e-1或与原点距离差大于1mm的并不会赋予粉色.如下图中右边两条尽管看似平行,但由于与原点距离偏差距离较大(超过3mm),并未赋予粉红色。因此除了图中显色粉色的线外,尚有必要手动检查下其他线。
其余正常处理后的图形中,绿色线表示已消除重线。
对于标红需要手动处理的图形,其原因主要在于各处理环节中精度控制的大小。在目前所取的精度下,对于设计部方面所提供的两个案例cad图纸,图1共1385个图块,程序处理1381个,剩余4个需要手动处理,完成率达到99.71%;图2共1269个图块,程序处理1261个,剩余8个需要手动处理,完成率达到99.37%。
'''
2023/3/14 星期二 天气晴
本程序用于对CAD零件图进行处理
版本1.1
'''
import math
from pyautocad import Autocad, APoint, aDouble, ACAD
from mycad61 import Line, AllLine
A1 = Autocad(create_if_not_exists=True)
def get_layer(acad, la_name): # 顶级对象 图层名称
'''
获取所要设置图层是否存在
'''
ret = []
la_all = acad.doc.layers # 得到全部图层
la_name_li = [obj.name for obj in la_all] # 获取所有图层名称
ret.append(la_name in la_name_li) # 返回该图层是否存在
if la_name in la_name_li: # 假如存在
ret.append(la_all.item(la_name)) # 返回该图层对象
return ret # 返回一序列,第一个值表征其是否存在,第二个为图层名称
def set_layer(acad, la_name, la_color1=255, la_color2=255, la_color3=255):
'''
设置图层
'''
ret = get_layer(acad, la_name) # 获取当前图层是否存在
if ret[0]: # 假如存在所要设置图层
acad.doc.Activelayer = ret[1] # 设置当前图层
else:
ac_layer = acad.doc.layers.add(la_name) # 添加所要图层
acad.doc.Activelayer = ac_layer # 设置当前图层
version_str = acad.app.Version[0:4]
progid = version_str[:2]
cc = acad.app.GetInterfaceObject('AutoCAD.AcCmColor.'+ progid)
# 获取一个AcCmColor对象,这里progid代表版本号,需要根据CAD版本变化而调整
cc.setrgb(la_color1, la_color2, la_color3)
ac_layer.TrueColor = cc
round_no = 6
snap = A1.doc.GetVariable("OSMODE") # 清除所有捕捉
A1.doc.SetVariable("OSMODE", 0)
# 读取坐标
selSets = A1.doc.SelectionSets
for obj in selSets:
print(obj)
obj.delete()
gg = selSets.add("Wall")
gg.SelectOnScreen()
i = 0
L = 0
p1li = []
p2li = []
pli = []
ac_layer = A1.doc.Activelayer
cc = ac_layer.TrueColor #这里得到了一个AcCmColor对象
cc.setrgb(0, 255, 255)
num = 0
lines = []
angleLi = []
dLi = []
# obj.ObjectName=="AcDbArc"
for obj in gg:
#print(obj.ObjectName)
if (obj.ObjectName == "AcDbLine" or obj.ObjectName == "AcDbArc") and\
(obj.Layer == 'Part' or obj.Layer == '0'):
line1 = Line(obj)
lines.append(line1)
num += 1
#print(line1.angle,line1.p1,line1.p2)
#L+=obj.Length
print('共'+str(num)+'条线\n')
gg.delete()
print('1----图形分块')
Al = AllLine(lines)
i = 0
for obj1 in Al.Lines:
aa = []
for obj2 in Al.Lines:
if obj1 == obj2:
pass
else:
if max(obj1.rec[0], obj2.rec[0]) <= min(obj1.rec[2], obj2.rec[2]) and\
max(obj1.rec[1], obj2.rec[1]) <= min(obj1.rec[3], obj2.rec[3]):
obj1.coinLines.append(obj2)
#print(obj1.coinLines)
i += 1
RecAll = []
L2 = Al.Lines
#L2[0].L.TrueColor=cc
i = 0
while len(L2) != 0:
Lw0 = [L2[0]]+L2[0].coinLines
LwSearch = L2[0].coinLines
while len(LwSearch) != 0:
#print('第一次')
#print(len(LwSearch))
aa = []
for obj2 in LwSearch:
#print(len(obj2.coinLines))
for obj3 in obj2.coinLines:
if obj3 in Lw0:
pass
else:
if obj3 not in aa:
aa.append(obj3)
Lw0.append(obj3)
#print(len(aa))
LwSearch = aa
RecAll.append(AllLine(Lw0))
for obj4 in Lw0:
L2.remove(obj4)
i += 1
#print('第'+str(i)+'个')
print('共'+str(i)+'个图形')
#print(L2)
set_layer(A1, '外框图层', 0, 255, 255)
for obj1 in RecAll:
minX = obj1.Lines[0].rec[0]
minY = obj1.Lines[0].rec[1]
maxX = obj1.Lines[0].rec[2]
maxY = obj1.Lines[0].rec[3]
for obj2 in obj1.Lines[1:]:
#print(obj2.rec)
minX = min(obj2.rec[0], minX)
minY = min(obj2.rec[1], minY)
maxX = max(obj2.rec[2], maxX)
maxY = max(obj2.rec[3], maxY)
dd = [minX, minY, 0]+[minX, maxY, 0]+[maxX, maxY, 0]+[maxX, minY, 0]+[minX, minY, 0]
ee = aDouble(dd)
L = A1.model.AddPolyline(ee)
print('图形分块完成\n')
print('2---处理重线')
## 这里有个问题是如果内部有环的话,但好像也没有问题,正好适合开洞
cc.setrgb(0, 255, 0)
set_layer(A1, '0')
ff = ac_layer.TrueColor #这里得到了一个AcCmColor对象
ff.setrgb(255, 0, 255)
##去重
newRecAll = []
for AL in RecAll:
flag = 1
lines = AL.Ls
while flag == 1:
delL = []
appL = []
for i, line1 in enumerate(lines):
#print(line1.angle)
for line2 in lines[i+1:]:
#print(line1.angle,line2.angle)
if abs(line1.p1[1]-line1.p2[1]) <= 1e-6:# 水平线
d = abs(line1.p1[1]-line2.p1[1])
elif abs(line1.p1[0]-line1.p2[0]) <= 1e-6:# 竖直线
d = abs(line1.p1[0]-line2.p1[0])
else:
d = abs(line1.d0-line2.d0)
x12 = max(abs(line1.p2[0]-line2.p1[0]), abs(line1.p1[0]-line2.p2[0]))
y12 = max(abs(line1.p2[1]-line2.p1[1]), abs(line1.p1[1]-line2.p2[1]))
if abs(line1.angle-line2.angle) < 1e-6: # 角度相同
#print('i='+str(i))
#print('d',d)
if d < 1e-6:# 共线 (如果是多条共线?)
if (math.sqrt(x12*x12+y12*y12)-line1.len-line2.len) > 1e-3:
pass
# print('无重合段')
else:
if line1.L.ObjectName == "AcDbArc":
pc = APoint(line1.L.Center[0], line1.L.Center[1])
l1 = A1.model.AddArc(pc, line1.L.Radius, line1.L.StartAngle, line1.L.EndAngle)
else:
#print('aa')
aa = [line1.p1, line1.p2]
if line2.p1 not in aa:
aa.append(line2.p1)
if line2.p2 not in aa:
aa.append(line2.p2)
aa = sorted(aa, key=lambda x: (x[1], x[0]))
x1 = aa[0][0]
y1 = aa[0][1]
x2 = aa[-1][0]
y2 = aa[-1][1]
p1 = APoint(x1, y1)
p2 = APoint(x2, y2)
#print(aa)
l1 = A1.model.addLine(p1, p2)
l1.TrueColor = cc
#Al.mat[no][2].L.TrueColor =cc
#Al.mat[i][2].L.TrueColor =cc
delL += [line1, line2]
appL.append(Line(l1))
print('发现重叠线')
break # 找到一条就跳出
#print(len(appL))
elif d<0.1:
if (math.sqrt(x12*x12+y12*y12)-line1.len-line2.len) > 1e-3:
pass
else:
line1.L.TrueColor =ff
line2.L.TrueColor =ff
elif abs(line1.angle-line2.angle) < 1e-3 or abs(abs(line1.angle-line2.angle)-math.pi)<1e-3 : #角度相差较小
if d<0.1:
if (math.sqrt(x12*x12+y12*y12)-line1.len-line2.len) > 1e-3:
pass
else:
line1.L.TrueColor =ff
line2.L.TrueColor =ff
#print('gh',len(delL))
if len(delL) != 0:
for line in delL:
if line in lines:
line.L.Delete()
lines.remove(line)
#print(len(lines))
for line in appL:
lines.append(line)
else:
flag = 0
newRecAll.append(AllLine(lines))
print('重线处理完成\n')
print('3---处理交线')
### 求交点,暂时仅考虑对直线相交的处理
newRecAll2 = []
for Al in newRecAll:
new_Ls = []
for line in Al.Ls:
line.new_lines = [[line.p1[0], line.p1[1]], [line.p2[0], line.p2[1]]]
#print(line.new_lines)
for i, line1 in enumerate(Al.Ls):
for line2 in Al.Ls[i+1:]:
RetVal = line1.L.IntersectWith(line2.L, ACAD.acExtendNone)
if len(RetVal) == 3:#有交点
inP = [round(RetVal[0], round_no), round(RetVal[1], round_no)] # 相交点
#print(inP)
flag = 1
for obj in line1.new_lines:
#print(abs(obj[0]-inP[0]),abs(obj[1]-inP[1]))
if abs(obj[0]-inP[0]) < 1e-4 and abs(obj[1]-inP[1]) < 1e-4:
flag = 0
break
if flag != 0:
line1.new_lines.append(inP)
#print(line1.new_lines)
flag = 1
for obj in line2.new_lines:
if abs(obj[0]-inP[0]) < 1e-4 and abs(obj[1]-inP[1]) < 1e-4:
flag = 0
break
if flag != 0:
line2.new_lines.append(inP)
for line in Al.Ls:
new_line = line.new_lines
#print(new_line)
#print('aa')
if len(new_line) == 2:
new_Ls.append(line)
else:
#print('aa')
if line.angle<1e-6:
new_line = sorted(new_line, key=lambda x: (x[0]))
else:
new_line = sorted(new_line, key=lambda x: (x[1], x[0]))
#print(new_line)
line.L.Delete()
for j in range(len(new_line)-1):
x1 = new_line[j][0]
y1 = new_line[j][1]
x2 = new_line[j+1][0]
y2 = new_line[j+1][1]
p1 = APoint(x1, y1)
p2 = APoint(x2, y2)
l1 = A1.model.addLine(p1, p2)
new_Ls.append(Line(l1))
Al2 = AllLine(new_Ls)
newRecAll2.append(Al2)
print('交线处理完成\n')
print('4---寻找最外圈闭合框')
def drawRec(AL):
minX = AL.Lines[0].rec[0]
minY = AL.Lines[0].rec[1]
maxX = AL.Lines[0].rec[2]
maxY = AL.Lines[0].rec[3]
for obj2 in AL.Lines[1:]:
#print(obj2.rec)
minX = min(obj2.rec[0], minX)
minY = min(obj2.rec[1], minY)
maxX = max(obj2.rec[2], maxX)
maxY = max(obj2.rec[3], maxY)
dd = [minX, minY, 0]+[minX, maxY, 0]+[maxX, maxY, 0]+[maxX, minY, 0]+[minX, minY, 0]
ee = aDouble(dd)
L = A1.model.AddPolyline(ee)
jj = 0
for Al in newRecAll2:
#print(Al.pDL.p)
pDL = Al.pDL
Pos = Al.Pos
ret = pDL.L0 # 得到
#print(ret[1].p)
OutLines = []
#print('L0',pDL)
#print(ret)
#print(len(Al.Ls))
if ret != 0:
set_layer(A1, '外框图层')
Point = APoint(pDL.p[0], pDL.p[1])
A1.model.AddPoint(Point)
set_layer(A1, '0')
else:
#print('跳出')
jj += 1
i = 1
while ret != 0:
OutLines.append(ret[0])
#ret[0].L.TrueColor =ee
pStart = ret[1]
L0 = ret[0]
ret = pStart.L1(L0)
i += 1
#print(ret)
#print(ret[1].p[0]-pDL.p[0],ret[1].p[1]-pDL.p[1])
#print(ret[1] == pDL)
#print(ret)
if ret != 0 and abs(ret[1].p[0] - pDL.p[0]) < 1e-6 and abs(ret[1].p[1] - pDL.p[1]) < 1e-6:
#ret[0].L.TrueColor = ee
OutLines.append(ret[0])
#print('闭合')
break
if ret != 0 and i > 2*len(Al.Ls):
ret = 0
#print('陷入死循环')
break
if ret == 0:
jj += 1
if ret == 0:
print('第'+str(jj)+'未闭合')
set_layer(A1, '问题图形', 255, 0, 0)
drawRec(Al)
'''
for obj in Al.Ls:
obj.L.TrueColor = ee
'''
else:
print('闭合')
for obj in Al.Ls:
if obj not in OutLines:
obj.L.Delete()
print('最外圈闭合框寻找完成\n')
A1.doc.SetVariable("OSMODE", snap) # 设置捕捉
input('按 Enter 退出…')
import math
import numpy as np
class Point():
def __init__(self,p):
self.__p = p
self.Ls = []
@property
def p(self):
return self.__p
@property
def L0(self):
if len(self.Ls)==1:
#print('cc')
return 0
else:
angle = math.pi
for obj in self.Ls:
if obj.p1 == self.p:
if obj.angle <angle:
angle = obj.angle
ret = obj
p2 = obj.Po2
else:
angle = math.pi
break
if angle < round(math.pi/2,6):
#print('angle',angle)
return ret,p2
else:
return 0
def L1(self,L0):
if len(self.Ls)==1:
return 0
else:
if L0.p1 == self.p: #如果线段起点即为此点
angle1 = L0.angle
else:
angle1 = L0.angle +math.pi
dangle = 0
#print('angle1')
#print(angle1)
#print(len(self.Ls))
for obj in self.Ls:
if obj == L0:
pass
else:
if obj.p1 == self.p: #如果线段起点即为此点:
angle2 = obj.angle
p2p = obj.Po2
else:
angle2 = obj.angle+math.pi
p2p = obj.Po1
if angle2<=angle1:
dangle2 = angle1-angle2
else:
dangle2 = math.pi*2-(angle2-angle1)
#print('angle2')
#print(angle2)
#print(p2p.p)
#print(dangle2)
if dangle2 >= dangle:
dangle = dangle2
ret = obj
p2 = p2p
#print(p2.p)
return ret,p2
class Line():
def __init__(self,L):
self.__tol = 1 # 矩形搜索范围两侧1mm
self.__L = L
round_no= 6
p1 = [round(L.StartPoint[0],round_no),round(L.StartPoint[1],round_no)]
p2 = [round(L.EndPoint[0],round_no),round(L.EndPoint[1],round_no)]
#p1 = [L.StartPoint[0],L.StartPoint[1]]
#p2 = L.EndPoint[0],L.EndPoint[1]]
[x1,y1] = p1
[x2,y2] = p2
if abs(p1[1]-p2[1])<=1e-6:
self.__d = p1[1]
#print(self.__d)
elif abs(p1[0]-p2[0])<=1e-6:
self.__d = p1[0]
else:
a = 1/(x2-x1)
b = -1/(y2-y1)
c = -x1/(x2-x1)+y1/(y2-y1)
if a>0:
pass
else:
a= -a
b =-b
c= -c
if c/b>=0:
self.__d = abs(c/math.sqrt(a*a+b*b))
else:
self.__d = -abs(c/math.sqrt(a*a+b*b))
self.__abc =[a,b,c]
if L.ObjectName=="AcDbLine":
self.__angle = L.angle
self.__len = L.Length
else:
self.__len=math.sqrt((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1))
if abs(x2-x1)<1e-6:
self.__angle = math.pi/2
else:
self.__angle = math.atan((y2-y1)/(x2-x1))+math.pi
'''
if aa >= math.pi-1e-6 and aa<2*math.pi-1e-6:
self.__angle = aa - math.pi
elif aa>=2*math.pi -1e-6:
self.__angle = aa - 2*math.pi
else:
self.__angle = aa
if self.__angle<0:
self.__angle =-self.__angle
self.__angle = round(self.__angle,6)
'''
if y1<y2:
self.__p1 = p1
self.__p2 = p2
elif y1>y2:
self.__angle = self.__angle- math.pi
self.__p1 = p2
self.__p2 = p1
else:
if x1<x2:
self.__p1 = p1
self.__p2 = p2
else:
self.__angle = self.__angle - math.pi
self.__p1 = p2
self.__p2 = p1
if abs(self.__angle - math.pi)< 1e-6:
self.__angle = self.__angle -math.pi
aa = self.__p1
self.__p1 = self.__p2
self.__p2 = aa
if abs(self.__angle -2*math.pi)< 1e-6:
self.__angle = self.__angle -2*math.pi
self.__angle = round(self.__angle,round_no)
self.__minX = min(x1,x2)
self.__maxX = max(x1,x2)
self.__minY = min(y1,y2)
self.__maxY = max(y1,y2)
self.coinLines = []
#print(self.__p1)
self.new_lines =[]
self.Po1 =Point([0,0])
self.Po2 =Point([0,0])
@property
def L(self):
return self.__L
@property
def angle(self):
return self.__angle
@property
def abc(self):
return self.__abc
@property
def d0(self):
return self.__d
@property
def p1(self):
return self.__p1
@property
def p2(self):
return self.__p2
@property
def len(self):
return self.__len
@property
def rec0(self):
return [self.__minX,self.__minY,self.__maxX,self.__maxY]
@property
def rec(self):
return [self.__minX-self.__tol,self.__minY-self.__tol,self.__maxX+self.__tol,self.__maxY+self.__tol]
class AllLine():
def __init__(self,Ls):
self.Ls = Ls
self.__ps =[]
for obj in self.Ls:
if obj.p1 not in self.__ps:
self.__ps.append(obj.p1)
if obj.p2 not in self.__ps:
self.__ps.append(obj.p2)
@property
def Lines(self):
ret = []
for obj in self.mat:
ret.append(obj[2])
return ret
@property
def mat(self):
ret =[]
#print(self.Ls)
for obj in self.Ls:
ret.append([obj.angle,obj.d0,obj,obj.p1[1],obj.p1[0]])
ret = sorted(ret,key=lambda x: (x[0], -x[1],x[4],x[3]))
return ret
# 所有点
@property
def ps(self):
return self.__ps
@property
def pDL(self):
ret = self.Pos[0]
for obj in self.Pos[1:]:
if obj.p[1]<ret.p[1] and obj.L0!=0:
ret = obj
elif obj.p[1] == ret.p[1] and obj.L0!=0:
if obj.p[0] < ret.p[0]:
ret = obj
return ret
@property
def Pos(self):
ps = self.__ps
ret =[]
for obj in ps:
ret.append(Point(obj))
for obj in self.Ls:
if ps.count(obj.p1)==1:
no = ps.index(obj.p1)
ret[no].Ls.append(obj)
obj.Po1 = ret[no]
if ps.count(obj.p2)==1:
no = ps.index(obj.p2)
ret[no].Ls.append(obj)
obj.Po2 = ret[no]
return ret
class SepRecs():
def __init__(self,lines):
self.Lines = lines
self.outLines0 = []
self.inLines0 = []
;;;; 2023-3-7 星期二 天气晴
;;;; kiritanimirei.cn
(defun c:2265() ;;;自定义函数名
(startapp "qx.exe")
)