GetAllModule.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. # -*- coding: UTF-8 -*-
  2. from pyautocad import Autocad, APoint
  3. from utils import conf,MovePath
  4. import math
  5. #这个true表示没有文件则打开一个,CAD有弹窗时会打开或者创建失败
  6. acad = Autocad(create_if_not_exists = False)
  7. # 组件实体点位置
  8. positoins={}
  9. currentPosition = {}
  10. # 组件使用点位置
  11. useAreaPositions={}
  12. # 组件与门距离
  13. distinceWithDoor = {}
  14. # 组件间距离
  15. distinceWithOthers={}
  16. # 旋转后需删除的组件
  17. needDeleteBlockReferences=[]
  18. scores=[]
  19. # 分别存储位置,雷达长度,入口与模块长度,模块间长度,撞点个数
  20. currentScore=[]
  21. # acad.prompt("Hello, Autocad from Python\n")
  22. # conf.myprint(acad.doc.Name)
  23. def printObjects():
  24. #遍历cad图形对象
  25. for obj in acad.iter_objects():
  26. conf.myprint(obj.ObjectName)
  27. def printBlockObjects():
  28. #遍历cad图形对象
  29. for obj in acad.iter_objects("BlockReference"):
  30. conf.myprint(obj.name,obj.HasAttributes)
  31. if obj.HasAttributes:
  32. attrs = obj.GetAttributes()
  33. for attrib in attrs:
  34. conf.myprint(" {}: {}".format(attrib.TagString, attrib.TextString))
  35. def printTheTypeObject(type):
  36. #按类型查找出所有某种图元
  37. for text in acad.iter_objects(type):
  38. conf.myprint(text.name)
  39. # 保存正确方案的分数
  40. def addCurrentScoreToScores(moveResult):
  41. conf.myprint("moveResult=",moveResult)
  42. if moveResult > 0:
  43. temp = []
  44. for item in currentScore:
  45. temp.append(item)
  46. scores.append(temp)
  47. # 获取列表的第二个元素
  48. def takeSecond(elem):
  49. return elem[1]
  50. # 根据scores给方案打分
  51. def scoreModule():
  52. moduleScores = []
  53. if len(scores)>0:
  54. tempLength = len(scores[0])-1
  55. else:
  56. conf.myprint("scores is empty")
  57. return
  58. # socres中目前存储 位置、入口雷达半径、入口与模块连线长度、模块间连线长度,入口与模块间撞点,模块与模块间撞点
  59. maxs = [0]*tempLength
  60. mins = [0]*tempLength
  61. detarLength = [0]*tempLength
  62. fullSocres = [10,10,10,5,5]
  63. fullSocresDirect = [1,-1,-1,-1,-1]
  64. # 先获取最大值和最小值
  65. for item in scores:
  66. for itemIndex in range(tempLength):
  67. if maxs[itemIndex]==0:
  68. maxs.pop(itemIndex)
  69. maxs.insert(itemIndex,item[itemIndex+1])
  70. if mins[itemIndex]==0:
  71. mins.pop(itemIndex)
  72. mins.insert(itemIndex,item[itemIndex+1])
  73. if item[itemIndex+1]>maxs[itemIndex]:
  74. maxs.pop(itemIndex)
  75. maxs.insert(itemIndex,item[itemIndex+1])
  76. if item[itemIndex+1]<mins[itemIndex]:
  77. mins.pop(itemIndex)
  78. mins.insert(itemIndex,item[itemIndex+1])
  79. for i in range(tempLength):
  80. detarLength[i] = maxs[i]-mins[i]
  81. conf.myprint("maxs=",maxs)
  82. conf.myprint("mins=",mins)
  83. conf.myprint("detarLength=",detarLength)
  84. for item in scores:
  85. tempScore = []
  86. tempScore.append(item[0])
  87. for itemIndex in range(tempLength):
  88. if detarLength[itemIndex] == 0:
  89. if fullSocresDirect[itemIndex] == 1:
  90. tempScore.append(fullSocres[itemIndex])
  91. else:
  92. tempScore.append(0)
  93. elif(fullSocresDirect[itemIndex] == 1):
  94. value = (item[itemIndex+1]-mins[itemIndex])*fullSocres[itemIndex]/detarLength[itemIndex]
  95. tempScore.append(round(value,2))
  96. else:
  97. value = fullSocres[itemIndex] - (item[itemIndex+1]-mins[itemIndex])*fullSocres[itemIndex]/detarLength[itemIndex]
  98. tempScore.append(round(value,2))
  99. tempTotalScore = 0;
  100. for i in range(1,len(tempScore)):
  101. tempTotalScore += tempScore[i]
  102. tempScore.insert(1,tempTotalScore)
  103. moduleScores.append(tempScore)
  104. conf.myprint("moduleScores=",moduleScores)
  105. moduleScores.sort(key=takeSecond,reverse=True)
  106. conf.myprint("moduleScores=",moduleScores)
  107. # 方案不合适返回0,否则返回方案评分
  108. def moveBlockReference(position):
  109. positoins.clear()
  110. useAreaPositions.clear()
  111. conf.myprint(conf.moduleLengths)
  112. currentScore.clear()
  113. currentScore.append("".join(position))
  114. moveResult = 1
  115. for blockReference in acad.iter_objects("BlockReference"):
  116. conf.myprint(blockReference.name)
  117. for item in conf.names:
  118. if(blockReference.name == item):
  119. currentPosition[0] = position
  120. currentPosition[1] = conf.names.index(item)
  121. result = moveBlockReferenceToWall(blockReference,position[conf.names.index(item)])
  122. if(result == 0):
  123. moveResult = result
  124. conf.myprint("currentScore size =",len(currentScore),",scores size=",len(scores))
  125. addCurrentScoreToScores(moveResult)
  126. conf.myprint("scores=",scores)
  127. for blockReference in needDeleteBlockReferences:
  128. blockReference.delete()
  129. needDeleteBlockReferences.clear()
  130. return moveResult
  131. def moveBlockReferenceToWall(blockReference,wallIndex):
  132. wallIndex = int(wallIndex)
  133. blockReference.rotate(APoint(blockReference.InsertionPoint),0.5*(wallIndex+1)*math.pi)
  134. blockIndex = conf.names.index(blockReference.name)
  135. conf.myprint("begin to put ",blockReference.name)
  136. if(wallIndex == 0):
  137. blockReference.move(APoint(blockReference.InsertionPoint),APoint(conf.roomLengths[0]-conf.roomUsedLengths[0],0))
  138. conf.roomUsedLengths[0] = conf.roomUsedLengths[0]+conf.moduleLengths[blockIndex];
  139. elif (wallIndex == 1):
  140. blockReference.move(APoint(blockReference.InsertionPoint),APoint(conf.roomLengths[0],conf.roomLengths[1]-conf.roomUsedLengths[1]))
  141. conf.roomUsedLengths[1] = conf.roomUsedLengths[1]+conf.moduleLengths[blockIndex];
  142. elif (wallIndex == 2):
  143. blockReference.move(APoint(blockReference.InsertionPoint),APoint(conf.roomUsedLengths[2],conf.roomLengths[1]))
  144. conf.roomUsedLengths[2] = conf.roomUsedLengths[2]+conf.moduleLengths[blockIndex];
  145. else:
  146. blockReference.move(APoint(blockReference.InsertionPoint),APoint(0,conf.roomLengths[1]-conf.roomUsedLengths[3]-conf.moduleLengths[blockIndex]))
  147. conf.roomUsedLengths[3] = conf.roomUsedLengths[3]+conf.moduleLengths[blockIndex];
  148. checkPositionIntersect = tempStoragePosition(blockReference.InsertionPoint[0],blockReference.InsertionPoint[1],wallIndex,blockIndex,blockReference)
  149. if(checkPositionIntersect == 0):
  150. conf.myprint("wallIndex=",wallIndex,blockReference.name," not walkable......")
  151. return 0
  152. else:
  153. return 1
  154. # 根据新顺序移动模块
  155. def moveBlockReferenceWithNewIndex(position,moduleIndex):
  156. moveResult = 1
  157. positoins.clear()
  158. useAreaPositions.clear()
  159. currentScore.clear()
  160. firstScoreItem = "".join(position)+"_"+ "".join([str(x) for x in moduleIndex])
  161. currentScore.append(firstScoreItem)
  162. conf.myprint(conf.moduleLengths)
  163. blockReferences = []
  164. for blockReference in acad.iter_objects("BlockReference"):
  165. conf.myprint(blockReference.name)
  166. for item in conf.names:
  167. if(blockReference.name == item):
  168. blockReferences.append(blockReference)
  169. for index in moduleIndex:
  170. currentPosition[0] = position
  171. currentPosition[1] = moduleIndex
  172. currentPosition[2] = moduleIndex.index(index)
  173. result = moveBlockReferenceToWall(blockReferences[index],position[moduleIndex.index(index)])
  174. if(result == 0):
  175. moveResult = result
  176. conf.myprint("currentScore size =",len(currentScore),",scores size=",len(scores))
  177. addCurrentScoreToScores(moveResult)
  178. conf.myprint("scores=",scores)
  179. for blockReference in needDeleteBlockReferences:
  180. blockReference.delete()
  181. needDeleteBlockReferences.clear()
  182. return moveResult
  183. # 重置已使用墙的长度
  184. def resetConfUsed():
  185. conf.roomUsedLengths=[0,0,0,0]
  186. # 对模块重新排序
  187. def changeConfModuleIndex(moduleIndex):
  188. names=[]
  189. moduleLengths=[]
  190. for index in range(len(conf.moduleLengths)):
  191. names.append(conf.names[moduleIndex[index]])
  192. moduleLengths.append(conf.moduleLengths[moduleIndex[index]])
  193. conf.names = names
  194. conf.moduleLengths = tuple(moduleLengths)
  195. # 重置模块顺序
  196. def resetModuleIndex():
  197. conf.names=['md_py','md_xs','md_rc']
  198. conf.moduleLengths = (800,1000,800)
  199. # 判断位置是否可行
  200. def isWorkable(position):
  201. resetConfUsed()
  202. conf.myprint("position=",position)
  203. needLength=[0]*4
  204. for positionIndex in range(len(position)):
  205. wallIndex = int(position[positionIndex])
  206. needLength[wallIndex]+=conf.moduleLengths[positionIndex]
  207. if(needLength[wallIndex]+conf.roomUsedLengths[wallIndex] > conf.roomWallLengths[wallIndex]):
  208. conf.myprint(needLength[wallIndex]+conf.roomUsedLengths[wallIndex],conf.roomLengths[math.floor(wallIndex/2)],wallIndex)
  209. return 0
  210. return 1
  211. # 获取组件的四点坐标
  212. def getCenterPoint(wallIndex, x, y, blockIndex):
  213. height = conf.moduleLengths[blockIndex]-conf.moduleLengthOffsets[blockIndex];
  214. width = conf.moduleHeights[blockIndex];
  215. useHeight = conf.moduleUseLength[blockIndex]
  216. useWidth = conf.humenLenght
  217. usePointPosition = conf.moduleUsePoint[blockIndex]
  218. useCenterPointPosition = conf.moduleUseCenterPoint[blockIndex]
  219. pointA = (x,y)
  220. conf.myprint("insertPoint=",x,y)
  221. if(wallIndex == 0):
  222. pointB = (x,y+width)
  223. pointC = (x-height,y+width)
  224. pointD = (x-height,y)
  225. centerPoint = (x-height/2,y+width/2)
  226. usePoint= (x-usePointPosition[1],y+usePointPosition[0])
  227. useCenterPoint= (x-useCenterPointPosition[1],y+useCenterPointPosition[0])
  228. centerPointOffset = (height,width)
  229. useCenterPointOffset = (useHeight,useWidth)
  230. elif(wallIndex == 1):
  231. pointB = (x-width,y)
  232. pointC = (x-width,y-height)
  233. pointD = (x,y-height)
  234. centerPoint = (x-width/2,y-height/2)
  235. usePoint= (x-usePointPosition[0],y-usePointPosition[1])
  236. useCenterPoint= (x-useCenterPointPosition[0],y-useCenterPointPosition[1])
  237. centerPointOffset = (width,height)
  238. useCenterPointOffset = (useWidth,useHeight)
  239. elif(wallIndex == 2):
  240. pointB = (x,y-width)
  241. pointC = (x+height,y-width)
  242. pointD = (x+height,y)
  243. centerPoint = (x+height/2,y-width/2)
  244. usePoint= (x+usePointPosition[1],y-usePointPosition[0])
  245. useCenterPoint= (x+useCenterPointPosition[1],y-useCenterPointPosition[0])
  246. centerPointOffset = (height,width)
  247. useCenterPointOffset = (useHeight,useWidth)
  248. else:
  249. pointB = (x+width,y)
  250. pointC = (x+width,y+height)
  251. pointD = (x,y+height)
  252. centerPoint = (x+width/2,y+height/2)
  253. usePoint= (x+usePointPosition[0],y+usePointPosition[1])
  254. useCenterPoint= (x+useCenterPointPosition[0],y+useCenterPointPosition[1])
  255. centerPointOffset = (width,height)
  256. useCenterPointOffset = (useWidth,useHeight)
  257. positoin = [centerPoint,centerPointOffset,usePoint,useCenterPoint,useCenterPointOffset];
  258. conf.myprint(wallIndex,width,height)
  259. # drawPointCircle((pointA, pointB, pointC, pointD, centerPoint, usePoint, useCenterPoint))
  260. conf.myprint(positoin)
  261. return positoin
  262. # 打印辅助点
  263. def drawPointCircle(points):
  264. for point in points:
  265. acad.model.AddCircle(APoint(point[0],point[1]), 50)
  266. # 判断可用区域是否超出房间
  267. def isUseAreaOverRoom(useCenterPosition,useCenterPositionOffset):
  268. if useCenterPosition[0]- useCenterPositionOffset[0]/2< 0 or useCenterPosition[0]+useCenterPositionOffset[0]/2>conf.roomLengths[0] or useCenterPosition[1]-useCenterPositionOffset[1]/2 < 0 or useCenterPosition[1]+useCenterPositionOffset[1]/2>conf.roomLengths[1]:
  269. return True
  270. return False
  271. # 从插入点开始顺时针记录已摆放的组件
  272. def tempStoragePosition(x,y,wallIndex,blockIndex,blockReference):
  273. position = getCenterPoint(wallIndex, x, y, blockIndex);
  274. # 判断可用区域中点是否超出房间
  275. if(isUseAreaOverRoom(position[3],position[4])):
  276. mirrorPy(blockReference,position)
  277. useCenterPosition = (position[3],position[4])
  278. doorFeasible = isPositionFeasibleWithDoor(position)
  279. conf.myprint("doorFeasible=",doorFeasible)
  280. if(doorFeasible == 0):
  281. return doorFeasible
  282. getDoorBeginAndModuleUsePointDistince(position,wallIndex)
  283. result = 1
  284. for item in positoins:
  285. # 判断实体是否相交
  286. result = isPositionFeasible(position,positoins[item],0)
  287. if(result == 1):
  288. # 判断当前实体是否与已摆放的可用区域相交
  289. result = isPositionFeasible(position,useAreaPositions[item],1)
  290. if(result == 1):
  291. # 判断可用区域是否与实体相交
  292. result = isPositionFeasible(useCenterPosition,positoins[item],1)
  293. if(result == 0):
  294. return result
  295. if(result == 1):
  296. positoins[len(positoins)] = position
  297. useAreaPositions[len(useAreaPositions)] = useCenterPosition
  298. return result
  299. # 计算位置是否可行type:0 实体 1可用区域
  300. def isPositionFeasible(position1,position2,type):
  301. areaName = "可用区域"
  302. if type==0:
  303. # acad.model.AddLine(APoint(position1[0][0],position1[0][1]),APoint(position2[0][0],position2[0][1]))
  304. # acad.model.AddCircle(APoint(position1[0][0],position1[0][1]), 50)
  305. areaName = "实体区域"
  306. # 画出实体区域间的可用点连线
  307. moduleIncludePoints = MovePath.getModuleMovePath(position1[0][0],position1[0][1],position1[1][0],position1[1][1],position1[2][0],position1[2][1],position2[0][0],position2[0][1],position2[1][0],position2[1][1],position2[2][0],position2[2][1])
  308. conf.myprint("moduleIncludePoints=",moduleIncludePoints)
  309. # 模块间距离
  310. moduleDistince = drawLines(moduleIncludePoints)
  311. if(len(currentScore) == 3):
  312. currentScore.append(moduleDistince)
  313. else:
  314. moduleDistince += currentScore.pop(3)
  315. currentScore.insert(3,moduleDistince)
  316. # 撞点个数
  317. knockPointNo = len(moduleIncludePoints)-2
  318. if(len(currentScore) == 4):
  319. currentScore.append(knockPointNo)
  320. else:
  321. knockPointNo += currentScore.pop(4)
  322. currentScore.insert(4,knockPointNo)
  323. if(abs(position1[0][0]-position2[0][0]) < (position1[1][0]+position2[1][0])/2 and abs(position1[0][1]-position2[0][1]) < (position1[1][1]+position2[1][1])/2):
  324. conf.myprint(areaName,"sorry! can not put here",currentPosition,"position1=",position1,"position2=",position2)
  325. return 0
  326. else:
  327. conf.myprint(areaName,"can put here")
  328. return 1
  329. # 计算实体位置是否与门使用区域相交
  330. def isPositionFeasibleWithDoor(position):
  331. length = conf.doorAlign[0]+conf.doorAlign[1]+conf.doorLength;
  332. width = conf.doorLength+conf.doorAlign[2];
  333. doorPosition = [(length/2,width/2),(length,width)]
  334. return isPositionFeasible(position,doorPosition,1)
  335. # 计算两点间距离
  336. def getDistince(point1,point2):
  337. detarX = point1[0]-point2[0]
  338. detarY = point1[1]-point2[1]
  339. return math.sqrt(detarX**2+detarY**2)
  340. def getDoorBeginPoint():
  341. return (conf.doorAlign[0]+conf.doorLength/2,0)
  342. def drawLines(includePoints):
  343. lineLength = 0;
  344. if(len(includePoints)>1):
  345. for item in range(len(includePoints)):
  346. if(item>0):
  347. acad.model.AddLine(APoint(includePoints[item-1][0],includePoints[item-1][1]),APoint(includePoints[item][0],includePoints[item][1]))
  348. lineLength += getDistince((includePoints[item-1][0],includePoints[item-1][1]),(includePoints[item][0],includePoints[item][1]))
  349. return lineLength
  350. def getDoorBeginAndModuleUsePointDistince(position,wallIndex):
  351. doorBeginPoint = getDoorBeginPoint()
  352. includePoints = MovePath.getDoorBeginAndModuleUsePointDistince(position[0][0],position[0][1],position[1][0],position[1][1],doorBeginPoint[0],doorBeginPoint[1])
  353. doorBeginAndModuleUsePointDistince = drawLines(includePoints)
  354. if(len(currentScore) == 1):
  355. currentScore.append(doorBeginAndModuleUsePointDistince)
  356. elif(currentScore[1] > doorBeginAndModuleUsePointDistince):
  357. currentScore.pop(1)
  358. currentScore.insert(1,doorBeginAndModuleUsePointDistince)
  359. includePoints = MovePath.getMovePath(position[0][0],position[0][1],position[1][0],position[1][1],doorBeginPoint[0],doorBeginPoint[1],position[2][0],position[2][1])
  360. moveLength = drawLines(includePoints)
  361. if(len(currentScore) == 2):
  362. currentScore.append(moveLength)
  363. else:
  364. moveLength += currentScore.pop(2)
  365. currentScore.insert(2,moveLength)
  366. # distinceWithDoor[len(distinceWithDoor)] = getDistince(doorBeginPoint,usePoint)
  367. # 以mirrorPoint和可用区域重点为对称抽翻转py
  368. def mirrorPy(py,position):
  369. insertPoint = py.InsertionPoint
  370. centerPoint = position[0]
  371. newCenterPoint = [position[3][0],position[3][1]]
  372. newUsePoint = [position[2][0],position[2][1]]
  373. conf.myprint("newUsePoint after mirror =",newUsePoint)
  374. if((insertPoint[0]-centerPoint[0])*(insertPoint[1]-centerPoint[1])>0):
  375. mirrorPoint = (insertPoint[0],centerPoint[1])
  376. direction = 1 if (insertPoint[1]-centerPoint[1])>0 else -1;
  377. newCenterPoint[1]=position[3][1]+position[4][1]*direction
  378. newUsePoint[1]=position[2][1]+position[1][1]*direction
  379. else:
  380. mirrorPoint = (centerPoint[0],insertPoint[1])
  381. direction = 1 if (insertPoint[0]-centerPoint[0])>0 else -1;
  382. newCenterPoint[0]=position[3][0]+position[4][0]*direction
  383. newUsePoint[0]=position[2][0]+position[1][0]*direction
  384. position[3] = newCenterPoint
  385. position[2] = newUsePoint
  386. conf.myprint("newUsePoint after mirror =",newUsePoint)
  387. py.mirror(APoint(mirrorPoint[0],mirrorPoint[1]),APoint(centerPoint[0],centerPoint[1]))
  388. conf.myprint("delete blockReference name",py.name)
  389. needDeleteBlockReferences.append(py)
  390. # printObjects()
  391. # printBlockObjects()
  392. # printTheTypeObject("BlockReference")
  393. # moveBlockReference('222')
  394. # a=[0,1,2]
  395. # moveBlockReferenceWithNewIndex('001',a)
  396. # conf.myprint(isWorkable('222'))
  397. # getCenterPoint(3,4162.85,0,2)
  398. # print(getDistince((0,3),(4,0)))
  399. # print(getDoorBeginPoint())