Advertisement
Guest User

нр

a guest
May 25th, 2019
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.25 KB | None | 0 0
  1. # поиск ограничений методом find_origin_ends
  2. # make_plane_view не работает
  3.  
  4. import sys
  5. import math
  6. import numpy
  7. import random
  8. from PyQt5.QtCore import Qt, QPoint, QRectF
  9. from PyQt5.QtGui import QPainter, QPen, QBrush
  10. from PyQt5.QtWidgets import QMainWindow, QWidget, QApplication
  11.  
  12.  
  13. class MyMainWindow(QMainWindow):
  14. def __init__(self):
  15. super().__init__()
  16. self.setWindowTitle("Построение выпуклых многоугольников")
  17. self.setGeometry(180, 100, 600, 600) # начало в экр., ширина, высота
  18. palette = self.palette()
  19. palette.setColor(self.backgroundRole(), Qt.white)
  20. self.setPalette(palette)
  21. self.form_widget = MyFormWidget()
  22. self.setCentralWidget(self.form_widget)
  23.  
  24.  
  25. class MyFormWidget(QWidget):
  26. def __init__(self):
  27. super().__init__()
  28. self.poly_1_true = {'bottom1': [(200, 200, 0), (250, 150, 50), (100, 200, 0)], # bottom
  29. 'back1': [(250, 150, 50), (150, 100, 0), (100, 200, 0)], # back
  30. 'right1': [(200, 200, 0), (250, 150, 50), (150, 100, 0)], # right
  31. 'front1': [(100, 200, 0), (200, 200, 0), (150, 100, 0)]} # front
  32.  
  33. self.poly_2_true = {'left2': [(200, 150, 0), (200, 50, 0), (250, 20, 100), (250, 120, 100)], # left
  34. 'bottom2': [(200, 150, 0), (300, 150, 0), (350, 120, 100), (250, 120, 100)], # bottom
  35. 'back2': [(350, 120, 100), (350, 20, 100), (250, 20, 100), (250, 120, 100)], # back
  36. 'top2': [(200, 50, 0), (300, 50, 0), (350, 20, 100), (250, 20, 100)], # top
  37. 'right2': [(300, 50, 0), (300, 150, 0), (350, 120, 100), (350, 20, 100)], # right
  38. 'front2': [(200, 150, 0), (200, 50, 0), (300, 50, 0), (300, 150, 0)]} # front
  39.  
  40. self.polys_sides_with_coef = {} # (A, B, C, D) : poly_true[side] for BOTH polygons
  41. self.polys_sides_with_coef_1 = {} # (A, B, C, D) : poly_true[side] for FIRST polygons
  42. self.polys_sides_with_coef_2 = {} # (A, B, C, D) : poly_true[side] for SECOND polygons
  43. self.side_color = {} # side: color
  44. self.bones_on_side = {} # bones: (A, B, C, D)
  45.  
  46. def paintEvent(self, QPaintEvent):
  47. self.qp = QPainter()
  48. self.qp.begin(self)
  49. self.find_side_coef(self.poly_1_true, self.polys_sides_with_coef_1)
  50. self.find_side_coef(self.poly_2_true, self.polys_sides_with_coef_2)
  51. self.compare_polys_side()
  52. print(self.polys_sides_with_coef)
  53. self.set_color()
  54. # self.bones_founder_once() # каждое ребро один раз (первый)
  55. self.bones_founder_all_sides() # ребро с каждой гранью, которой оно принадлежит
  56. self.y_min, self.y_max = self.get_min_max_y()
  57. # print(self.y_min, self.y_max)
  58.  
  59. stra_with_ends, stra_on_side, straights = self.make_plane_view(200)
  60. print('stra w ends : ' + str(stra_with_ends))
  61. print('2: ' + str(stra_on_side))
  62. print('3 ' + str(straights))
  63. # ends = self.find_straights_ends((0, -5000, -5000, 1000000), 200, self.polys_sides_with_coef_1)
  64. # print('MAIN ENDS: ' + str(ends))
  65.  
  66. # print('STRA W ENDS: ' + str(stra_with_ends))
  67. # print('STRA ON SIDE' + str(stra_on_side))
  68. # print('STRA' + str(straights))
  69. # for stra in stra_on_side.keys():
  70. # print(str(stra) + ': ' + str(self.polys_sides_with_coef[stra_on_side[stra]]) + ' -- ' + str(stra_with_ends[stra]))
  71. #----------------------
  72. # self.worker_2_1()
  73. # self.segm_painter()
  74. # print(self.polys_sides_with_coef)
  75. self.true_painter()
  76. self.qp.end()
  77.  
  78. def find_side_coef(self, polygon, into_polys_side_w_coef):
  79. # Ax + By + Cz + D = 0
  80. for side in polygon.keys():
  81. u, v, w = polygon[side][0], polygon[side][1], polygon[side][2]
  82. A = v[1] * w[2] - v[1] * u[2] - u[1] * w[2] + u[1] * v[2] - w[1] * v[2] + w[1] * u[2]
  83. B = -(v[0] * w[2] - v[0] * u[2] - u[0] * w[2] + u[0] * v[2] - w[0] * v[2] + w[0] * u[2])
  84. C = v[0] * w[1] - v[0] * u[1] - u[0] * w[1] + u[0] * v[1] - w[0] * v[1] + w[0] * u[1]
  85. D = -u[0] * A - u[1] * B - u[2] * C
  86. into_polys_side_w_coef[(A, B, C, D)] = polygon[side]
  87.  
  88. def compare_polys_side(self):
  89. for side_coef_1 in self.polys_sides_with_coef_1.keys():
  90. self.polys_sides_with_coef[side_coef_1] = self.polys_sides_with_coef_1[side_coef_1]
  91. for side_coef_2 in self.polys_sides_with_coef_2.keys():
  92. self.polys_sides_with_coef[side_coef_2] = self.polys_sides_with_coef_2[side_coef_2]
  93.  
  94. def set_color(self):
  95. d_color = {1: Qt.darkYellow, 2: Qt.darkRed, 3: Qt.darkCyan, 4: Qt.darkGreen,
  96. 5: Qt.darkBlue, 6: Qt.darkGray, 7: Qt.darkMagenta, 8: Qt.black, 9: Qt.blue,
  97. 10: Qt.red, 11: Qt.green}
  98. for side_coef in self.polys_sides_with_coef:
  99. n_color = random.randrange(1, 11)
  100. self.side_color[side_coef] = d_color[n_color]
  101.  
  102. def bones_founder_once(self):
  103. for side_coef in self.polys_sides_with_coef.keys():
  104. tmp_b = self.find_sides(self.polys_sides_with_coef[side_coef])
  105. for bone in tmp_b:
  106. if (bone[1], bone[0]) in self.bones_on_side.keys() or bone in self.bones_on_side.keys():
  107. continue
  108. else:
  109. self.bones_on_side[bone] = side_coef
  110.  
  111. def bones_founder_all_sides(self):
  112. for side_coef in self.polys_sides_with_coef.keys():
  113. tmp_b = self.find_sides(self.polys_sides_with_coef[side_coef])
  114. for bone in tmp_b:
  115. self.bones_on_side[bone] = side_coef
  116.  
  117. def find_sides(self, vertex):
  118. return [(vertex[i], vertex[i - 1]) for i in range(len(vertex))]
  119.  
  120. def planes_intersection(self, y, side_coef):
  121. # return tuple of coeff of plane equation and of straight equation
  122. # Ax + By + Cz + D = 0 --> A'x + C'z + D = 0
  123. D_shift = side_coef[3] + y * side_coef[1]
  124. return (side_coef[0], side_coef[2], D_shift)
  125.  
  126. def get_vertex(self, poly):
  127. vertex = set()
  128. for side in poly.keys():
  129. for x in poly[side]:
  130. vertex.add(x)
  131. return [*vertex]
  132.  
  133. def local_min_max_y(self, vertex):
  134. return min(v[1] for v in vertex), max(v[1] for v in vertex)
  135.  
  136. def get_min_max_y(self):
  137. poly_vert_1 = self.get_vertex(self.poly_1_true)
  138. poly_vert_2 = self.get_vertex(self.poly_2_true)
  139. y_min_1, y_max_1 = self.local_min_max_y(poly_vert_1)
  140. y_min_2, y_max_2 = self.local_min_max_y(poly_vert_2)
  141. return min(y_min_1, y_min_2), max(y_max_1, y_max_2)
  142.  
  143. def have_intersection(self, y, side):
  144. bones = self.find_sides(side)
  145. for bone in bones:
  146. if (bone[0][1] <= y <= bone[1][1]) or (bone[1][1] <= y <= bone[0][1]):
  147. return bones
  148. return []
  149.  
  150. def find_origin_ends(self, side_coef, polygon):
  151. X = polygon[side_coef] # coordinates of side
  152. # print('X: ' + str(X))
  153. x_set = set()
  154. z_set = set()
  155. for x, _, z in X:
  156. x_set.add(x)
  157. z_set.add(z)
  158. x_min = min(x_set)
  159. x_max = max(x_set)
  160. z_min = min(z_set)
  161. z_max = max(z_set)
  162. return x_min, x_max, z_min, z_max
  163.  
  164. def find_straights_ends(self, side_coef, y, polygon):
  165. x_min, x_max, z_min, z_max = self.find_origin_ends(side_coef, polygon)
  166. ends = set()
  167. for side_coef_2 in polygon.keys():
  168. main_coef_det = round(numpy.linalg.det([[0, 1, 0], [side_coef[0], side_coef[1], side_coef[2]],
  169. [side_coef_2[0], side_coef_2[1], side_coef_2[2]]]))
  170. if main_coef_det:
  171. x_det = round(numpy.linalg.det([[y, 1, 0], [-side_coef[3], side_coef[1], side_coef[2]],
  172. [-side_coef_2[3], side_coef_2[1], side_coef_2[2]]]))
  173. z_det = round(numpy.linalg.det([[0, 1, y], [side_coef[0], side_coef[1], -side_coef[3]],
  174. [side_coef_2[0], side_coef_2[1], -side_coef_2[3]]]))
  175. # print('x_det: ' + str(x_det))
  176. # print('z_det: ' + str(z_det))
  177. # x_det = round(numpy.linalg.det([[y, 0, 1], [-side_coef[3], side_coef[1], side_coef[2]],
  178. # [-side_coef_2[3], side_coef_2[1], side_coef_2[2]]]))
  179. # z_det = round(numpy.linalg.det([[0, 1, y], [side_coef[0], side_coef[1], -side_coef[3]],
  180. # [side_coef_2[0], side_coef_2[1], -side_coef_2[3]]]))
  181. # print('x_det ff: ' + str(x_det))
  182. # print('z_det ff: ' + str(z_det))
  183. x_coord_intersection = int(round(x_det / main_coef_det))
  184. z_coord_intersection = int(round(z_det / main_coef_det))
  185. x_c_i = 0 if x_coord_intersection == -0 else x_coord_intersection
  186. z_c_i = 0 if z_coord_intersection == -0 else z_coord_intersection
  187. if x_min <= x_c_i <= x_max and z_min <= z_c_i <= z_max:
  188. ends.append((x_c_i, z_c_i))
  189. if len(ends) == 2:
  190. return ends
  191. else:
  192. return []
  193.  
  194. def make_plane_view(self, y):
  195. straights_on_side = {}
  196. straights_with_ends = {}
  197. straights = []
  198. for side_coef in self.polys_sides_with_coef.keys():
  199.  
  200. flag_found = False
  201. for side_coef_t in self.polys_sides_with_coef_1.keys():
  202. if side_coef_t == side_coef:
  203. polygon = self.polys_sides_with_coef_1
  204. flag_found = True
  205. if flag_found:
  206. break
  207. if not flag_found:
  208. for side_coef_2t in self.polys_sides_with_coef_2.keys():
  209. if side_coef_2t == side_coef:
  210. polygon = self.polys_sides_with_coef_2
  211. flag_found = True
  212. if flag_found:
  213. break
  214.  
  215. bones = self.have_intersection(y, self.polys_sides_with_coef[side_coef])
  216. if bones:
  217. # print('side: ' + str(self.polys_sides_with_coef[side_coef]))
  218. # print('side coef: ' + str(side_coef))
  219. # print('bones: ' + str(bones))
  220. end_list= self.find_straights_ends(side_coef, y, polygon)
  221. if end_list:
  222. straight_coef = self.planes_intersection(y, side_coef)
  223. straights.append(straight_coef) # shouldnt be here !!!!!!! надо добавлять, когда точно будет 2 конца отрезка
  224. straights_on_side[straight_coef] = side_coef # аналогично
  225. straights_with_ends[straight_coef] = end_list
  226. return straights_with_ends, straights_on_side, straights
  227.  
  228. def find_2_straights_inters(self, stra1, stra2):
  229. # point of intersection of 2 straight (use in next)
  230. main_det = round(numpy.linalg.det([[stra1[0], stra1[1]], [stra2[0], stra2[1]]]))
  231. if main_det:
  232. x_det = round(numpy.linalg.det([[-stra1[2], stra1[1]], [-stra2[2], stra2[1]]]))
  233. z_det = round(numpy.linalg.det([[stra1[0], -stra1[2]], [stra2[0], -stra2[2]]]))
  234. x_c = int(round(x_det / main_det))
  235. z_c = int(round(z_det / main_det))
  236. x_c_i = 0 if x_c == -0 else x_c
  237. z_c_i = 0 if z_c == -0 else z_c
  238. return x_c_i, z_c_i
  239. return None
  240.  
  241. def is_between(self, end_p_1, end_p_2, point):
  242. return (end_p_1[0] <= point[0] <= end_p_2[0] or end_p_2[0] <= point[0] <= end_p_1[0]) and \
  243. (end_p_1[1] <= point[1] <= end_p_2[1] or end_p_2[1] <= point[1] <= end_p_1[1])
  244.  
  245. def find_all_plane_points(self, straights, stra_w_ends):
  246. intersections = set()
  247. for i in range(len(straights)):
  248. for j in range(len(straights)):
  249. inter_v = self.find_2_straights_inters(straights[i], straights[j])
  250. if inter_v:
  251. a, b = stra_w_ends[straights[i]]
  252. if self.is_between(a, b, inter_v):
  253. c, d = stra_w_ends[straights[j]]
  254. if self.is_between(c, d, inter_v):
  255. intersections.add(inter_v)
  256. return intersections
  257.  
  258. def collect_z_for_x(self, x, stra_w_ends):
  259. z_set = set()
  260. stra_dict_for_z = {}
  261. for stra in stra_w_ends.keys():
  262. if stra_w_ends[stra][0][0] <= x <= stra_w_ends[stra][1][0] or \
  263. stra_w_ends[stra][1][0] <= x <= stra_w_ends[stra][0][0]:
  264. try:
  265. z_for_x = -round((stra[0] * x + stra[2]) / stra[1])
  266. z_set.add(z_for_x)
  267. if not z_for_x in stra_dict_for_z.keys():
  268. stra_dict_for_z[z_for_x] = [stra]
  269. else:
  270. stra_dict_for_z[z_for_x].append(stra)
  271. except ZeroDivisionError:
  272. continue
  273. return z_set, stra_dict_for_z
  274.  
  275. def get_segm_for_paint(self, y, points, stra_w_ends, str_on_side):
  276. for i in range(len(points) - 1):
  277. x_1 = points[i][0]
  278. x_2 = points[i + 1][0]
  279. z_1_set, stra_dict_for_x1 = self.collect_z_for_x(x_1, stra_w_ends)
  280. z_2_set, stra_dict_for_x2 = self.collect_z_for_x(x_2, stra_w_ends)
  281. z_1_list = [z for z in z_1_set]
  282. z_2_list = [z for z in z_2_set]
  283. z_1_list.sort()
  284. z_2_list.sort()
  285. z_p_1 = -1
  286. z_p_2 = -1
  287. flag_end = False
  288. for tz_1 in z_1_list:
  289. for tz_2 in z_2_list:
  290. common_stra = list(set(stra_dict_for_x1[tz_1]) & set(stra_dict_for_x2[tz_2]))
  291. if common_stra:
  292. color = self.side_color[str_on_side[common_stra]]
  293. flag_end = True
  294. break
  295. if flag_end:
  296. break
  297. if z_p_1 > -1 and z_p_2 > -1:
  298. self.segments_for_paint[((x_1, y), (x_2, y))] = color
  299.  
  300. def worker_2_1(self):
  301. self.segments_for_paint = {} # segment: color
  302. for y in range(self.y_min, self.y_max):
  303. straights_with_ends, str_on_side, straights = self.make_plane_view(y)
  304. all_viewier_points = self.find_all_plane_points(straights, straights_with_ends)
  305. all_points_sorted = sorted(all_viewier_points, key=lambda p: (p[1], p[0]))
  306. self.get_segm_for_paint(y, all_points_sorted, straights_with_ends, str_on_side)
  307.  
  308. def segm_painter(self):
  309. for p1, p2 in self.segments_for_paint.keys():
  310. self.qp.setPen(QPen(self.segments_for_paint[(p1, p2)], 2))
  311. self.qp.drawLine(p1[0], p1[1], p2[0], p2[1])
  312.  
  313. def true_painter(self):
  314. poly_1_true = {Qt.darkMagenta: [(200, 200, 0), (250, 150, 50), (100, 200, 0)], # bottom
  315. Qt.darkYellow: [(250, 150, 50), (150, 100, 0), (100, 200, 0)], # back
  316. Qt.darkBlue: [(200, 200, 0), (250, 150, 50), (150, 100, 0)], # right
  317. Qt.darkGray: [(100, 200, 0), (200, 200, 0), (150, 100, 0)]} # front
  318.  
  319. poly_2_true = {Qt.darkMagenta: [(200, 150, 0), (200, 50, 0), (250, 20, 100), (250, 120, 100)], # left
  320. Qt.darkBlue: [(200, 150, 0), (300, 150, 0), (350, 120, 100), (250, 120, 100)], # bottom
  321. Qt.blue: [(350, 120, 100), (350, 20, 100), (250, 20, 100), (250, 120, 100)], # back
  322. Qt.darkYellow: [(200, 50, 0), (300, 50, 0), (350, 20, 100), (250, 20, 100)], # top
  323. Qt.darkRed: [(300, 50, 0), (300, 150, 0), (350, 120, 100), (350, 20, 100)], # right
  324. Qt.darkGreen: [(200, 150, 0), (200, 50, 0), (300, 50, 0), (300, 150, 0)]} # front
  325.  
  326. for side in poly_1_true.keys():
  327. self.qp.setPen(QPen(side, 2))
  328. self.qp.setBrush(QBrush(side))
  329. self.qp.drawPolygon(QPoint(poly_1_true[side][0][0], poly_1_true[side][0][1]),
  330. QPoint(poly_1_true[side][1][0], poly_1_true[side][1][1]),
  331. QPoint(poly_1_true[side][2][0], poly_1_true[side][2][1]))
  332.  
  333. for side in poly_2_true.keys():
  334. self.qp.setPen(QPen(side, 2))
  335. self.qp.setBrush(QBrush(side))
  336. self.qp.drawPolygon(QPoint(poly_2_true[side][0][0], poly_2_true[side][0][1]),
  337. QPoint(poly_2_true[side][1][0], poly_2_true[side][1][1]),
  338. QPoint(poly_2_true[side][2][0], poly_2_true[side][2][1]),
  339. QPoint(poly_2_true[side][3][0], poly_2_true[side][3][1]))
  340.  
  341.  
  342. if __name__ == '__main__':
  343. app = QApplication(sys.argv)
  344. window = MyMainWindow()
  345. window.show()
  346. sys.exit(app.exec_())
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement