SHARE
TWEET

too_much

a guest May 25th, 2019 78 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # много отрезков из метода make_plan_view
  2. # при y = 200 должен быть 1
  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.         self.set_color()
  53.         # self.bones_founder_once() # каждое ребро один раз (первый)
  54.         self.bones_founder_all_sides() # ребро с каждой гранью, которой оно принадлежит
  55.         self.y_min, self.y_max = self.get_min_max_y()
  56.         # print(self.y_min, self.y_max)
  57.  
  58.         stra_with_ends, stra_on_side, straights = self.make_plane_view(200)
  59.         print('stra w ends: ' + str(stra_with_ends))
  60.         # ends = self.find_straights_ends((0, -5000, -5000, 1000000), 200, self.polys_sides_with_coef_1)
  61.         # print('MAIN ENDS: ' + str(ends))
  62.  
  63.         # print('STRA W ENDS: ' + str(stra_with_ends))
  64.         # print('STRA ON SIDE' + str(stra_on_side))
  65.         # print('STRA' + str(straights))
  66.         # for stra in stra_on_side.keys():
  67.         #     print(str(stra) + ': ' + str(self.polys_sides_with_coef[stra_on_side[stra]]) + ' -- ' + str(stra_with_ends[stra]))
  68.         #----------------------
  69.         # self.worker_2_1()
  70.         # self.segm_painter()
  71.         # print(self.polys_sides_with_coef)
  72.         self.true_painter()
  73.         self.qp.end()
  74.  
  75.     def find_side_coef(self, polygon, into_polys_side_w_coef):
  76.         # Ax + By + Cz + D = 0
  77.         for side in polygon.keys():
  78.             u, v, w = polygon[side][0], polygon[side][1], polygon[side][2]
  79.             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]
  80.             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])
  81.             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]
  82.             D = -u[0] * A - u[1] * B - u[2] * C
  83.             into_polys_side_w_coef[(A, B, C, D)] = polygon[side]
  84.  
  85.     def compare_polys_side(self):
  86.         for side_coef_1 in self.polys_sides_with_coef_1.keys():
  87.             self.polys_sides_with_coef[side_coef_1] = self.polys_sides_with_coef_1[side_coef_1]
  88.         for side_coef_2 in self.polys_sides_with_coef_2.keys():
  89.                     self.polys_sides_with_coef[side_coef_2] = self.polys_sides_with_coef_2[side_coef_2]
  90.  
  91.     def set_color(self):
  92.         d_color = {1: Qt.darkYellow, 2: Qt.darkRed, 3: Qt.darkCyan, 4: Qt.darkGreen,
  93.                    5: Qt.darkBlue, 6: Qt.darkGray, 7: Qt.darkMagenta, 8: Qt.black, 9: Qt.blue,
  94.                    10: Qt.red, 11: Qt.green}
  95.         for side_coef in self.polys_sides_with_coef:
  96.             n_color = random.randrange(1, 11)
  97.             self.side_color[side_coef] = d_color[n_color]
  98.  
  99.     def bones_founder_once(self):
  100.         for side_coef in self.polys_sides_with_coef.keys():
  101.             tmp_b = self.find_sides(self.polys_sides_with_coef[side_coef])
  102.             for bone in tmp_b:
  103.                 if (bone[1], bone[0]) in self.bones_on_side.keys() or bone in self.bones_on_side.keys():
  104.                     continue
  105.                 else:
  106.                     self.bones_on_side[bone] = side_coef
  107.  
  108.     def bones_founder_all_sides(self):
  109.             for side_coef in self.polys_sides_with_coef.keys():
  110.                 tmp_b = self.find_sides(self.polys_sides_with_coef[side_coef])
  111.                 for bone in tmp_b:
  112.                     self.bones_on_side[bone] = side_coef
  113.  
  114.     def find_sides(self, vertex):
  115.         return [(vertex[i], vertex[i - 1]) for i in range(len(vertex))]
  116.  
  117.     def planes_intersection(self, y, side_coef):
  118.         # return tuple of coeff of plane equation and of straight equation
  119.         # Ax + By + Cz + D = 0  --> A'x + C'z + D = 0
  120.         D_shift = side_coef[3] + y * side_coef[1]
  121.         return (side_coef[0], side_coef[2], D_shift)
  122.  
  123.     def get_vertex(self, poly):
  124.         vertex = set()
  125.         for side in poly.keys():
  126.             for x in poly[side]:
  127.                 vertex.add(x)
  128.         return [*vertex]
  129.  
  130.     def local_min_max_y(self, vertex):
  131.         return min(v[1] for v in vertex), max(v[1] for v in vertex)
  132.  
  133.     def get_min_max_y(self):
  134.         poly_vert_1 = self.get_vertex(self.poly_1_true)
  135.         poly_vert_2 = self.get_vertex(self.poly_2_true)
  136.         y_min_1, y_max_1 = self.local_min_max_y(poly_vert_1)
  137.         y_min_2, y_max_2 = self.local_min_max_y(poly_vert_2)
  138.         return min(y_min_1, y_min_2), max(y_max_1, y_max_2)
  139.  
  140.     def have_intersection(self, y, side):
  141.         bones = self.find_sides(side)
  142.         for bone in bones:
  143.             if (bone[0][1] <= y <= bone[1][1]) or (bone[1][1] <= y <= bone[0][1]):
  144.                 return bones
  145.         return []
  146.  
  147.     def find_straights_ends(self, side_coef, y, polygon):
  148.         ends = []
  149.         for side_coef_2 in polygon.keys():
  150.             main_coef_det = round(numpy.linalg.det([[0, 1, 0], [side_coef[0], side_coef[1], side_coef[2]],
  151.                                                     [side_coef_2[0], side_coef_2[1], side_coef_2[2]]]))
  152.             # print('side_coef_2: ' + str(side_coef_2))
  153.             # print('main_dev: ' + str(main_coef_det))
  154.             if main_coef_det:
  155.                 x_det = round(numpy.linalg.det([[y, 1, 0], [-side_coef[3], side_coef[1], side_coef[2]],
  156.                                                 [-side_coef_2[3], side_coef_2[1], side_coef_2[2]]]))
  157.                 z_det = round(numpy.linalg.det([[0, 1, y], [side_coef[0], side_coef[1], -side_coef[3]],
  158.                                                [side_coef_2[0], side_coef_2[1], -side_coef_2[3]]]))
  159.                 # print('x_det: ' + str(x_det))
  160.                 # print('z_det: ' + str(z_det))
  161.                 # x_det = round(numpy.linalg.det([[y, 0, 1], [-side_coef[3], side_coef[1], side_coef[2]],
  162.                 #                                 [-side_coef_2[3], side_coef_2[1], side_coef_2[2]]]))
  163.                 # z_det = round(numpy.linalg.det([[0, 1, y], [side_coef[0], side_coef[1], -side_coef[3]],
  164.                 #                                 [side_coef_2[0], side_coef_2[1], -side_coef_2[3]]]))
  165.                 # print('x_det ff: ' + str(x_det))
  166.                 # print('z_det ff: ' + str(z_det))
  167.                 x_coord_intersection = int(round(x_det / main_coef_det))
  168.                 z_coord_intersection = int(round(z_det / main_coef_det))
  169.                 x_c_i = 0 if x_coord_intersection == -0 else x_coord_intersection
  170.                 z_c_i = 0 if z_coord_intersection == -0 else z_coord_intersection
  171.                 print(x_c_i, z_c_i)
  172.                 ends.append((x_c_i, z_c_i))
  173.         return ends
  174.  
  175.     def make_plane_view(self, y):
  176.         straights_on_side = {}
  177.         straights_with_ends = {}
  178.         straights = []
  179.         for side_coef in self.polys_sides_with_coef.keys():
  180.             # polygon = {}
  181.             flag_found = False
  182.             for side_coef_t in self.polys_sides_with_coef_1.keys():
  183.                 if side_coef_t == side_coef:
  184.                     print('here1')
  185.                     print(side_coef)
  186.                     polygon = self.polys_sides_with_coef_1
  187.                     flag_found = True
  188.                 if flag_found:
  189.                     break
  190.             if not flag_found:
  191.                 for side_coef_2t in self.polys_sides_with_coef_2.keys():
  192.                     if side_coef_2t == side_coef:
  193.                         polygon = self.polys_sides_with_coef_2
  194.                         flag_found = True
  195.                     if flag_found:
  196.                         break
  197.  
  198.             bones = self.have_intersection(y, self.polys_sides_with_coef[side_coef])
  199.             if bones:
  200.                 print('side: ' + str(self.polys_sides_with_coef[side_coef]))
  201.                 print('side coef: ' + str(side_coef))
  202.                 print('bones: ' + str(bones))
  203.                 straight_coef = self.planes_intersection(y, side_coef)
  204.                 print('stra: ' + str(straight_coef))
  205.                 straights.append(straight_coef) # shouldnt be here !!!!!!! надо добавлять, когда точно будет 2 конца отрезка
  206.                 straights_on_side[straight_coef] = side_coef # аналогично
  207.                 print('polygon: ' + str(polygon))
  208.                 end_list = self.find_straights_ends(side_coef, y, polygon)
  209.                 print('ends: ' + str(end_list))
  210.                 straights_with_ends[straight_coef] = end_list
  211.         return straights_with_ends, straights_on_side, straights
  212.  
  213.     def find_2_straights_inters(self, stra1, stra2):
  214.         # point of intersection of 2 straight (use in next)
  215.         main_det = round(numpy.linalg.det([[stra1[0], stra1[1]], [stra2[0], stra2[1]]]))
  216.         if main_det:
  217.             x_det = round(numpy.linalg.det([[-stra1[2], stra1[1]], [-stra2[2], stra2[1]]]))
  218.             z_det = round(numpy.linalg.det([[stra1[0], -stra1[2]], [stra2[0], -stra2[2]]]))
  219.             x_c = int(round(x_det / main_det))
  220.             z_c = int(round(z_det / main_det))
  221.             x_c_i = 0 if x_c == -0 else x_c
  222.             z_c_i = 0 if z_c == -0 else z_c
  223.             return x_c_i, z_c_i
  224.         return None
  225.  
  226.     def is_between(self, end_p_1, end_p_2, point):
  227.         return (end_p_1[0] <= point[0] <= end_p_2[0] or end_p_2[0] <= point[0] <= end_p_1[0]) and \
  228.                (end_p_1[1] <= point[1] <= end_p_2[1] or end_p_2[1] <= point[1] <= end_p_1[1])
  229.  
  230.     def find_all_plane_points(self, straights, stra_w_ends):
  231.         intersections = set()
  232.         for i in range(len(straights)):
  233.             for j in range(len(straights)):
  234.                 inter_v = self.find_2_straights_inters(straights[i], straights[j])
  235.                 if inter_v:
  236.                     a, b = stra_w_ends[straights[i]]
  237.                     if self.is_between(a, b, inter_v):
  238.                         c, d = stra_w_ends[straights[j]]
  239.                         if self.is_between(c, d, inter_v):
  240.                             intersections.add(inter_v)
  241.         return intersections
  242.  
  243.     def collect_z_for_x(self, x, stra_w_ends):
  244.         z_set = set()
  245.         stra_dict_for_z = {}
  246.         for stra in stra_w_ends.keys():
  247.             if stra_w_ends[stra][0][0] <= x <= stra_w_ends[stra][1][0] or \
  248.                                     stra_w_ends[stra][1][0] <= x <= stra_w_ends[stra][0][0]:
  249.                 try:
  250.                     z_for_x = -round((stra[0] * x + stra[2]) / stra[1])
  251.                     z_set.add(z_for_x)
  252.                     if not z_for_x in stra_dict_for_z.keys():
  253.                         stra_dict_for_z[z_for_x] = [stra]
  254.                     else:
  255.                         stra_dict_for_z[z_for_x].append(stra)
  256.                 except ZeroDivisionError:
  257.                     continue
  258.         return z_set, stra_dict_for_z
  259.  
  260.     def get_segm_for_paint(self, y, points, stra_w_ends, str_on_side):
  261.         for i in range(len(points) - 1):
  262.             x_1 = points[i][0]
  263.             x_2 = points[i + 1][0]
  264.             z_1_set, stra_dict_for_x1 = self.collect_z_for_x(x_1, stra_w_ends)
  265.             z_2_set, stra_dict_for_x2 = self.collect_z_for_x(x_2, stra_w_ends)
  266.             z_1_list = [z for z in z_1_set]
  267.             z_2_list = [z for z in z_2_set]
  268.             z_1_list.sort()
  269.             z_2_list.sort()
  270.             z_p_1 = -1
  271.             z_p_2 = -1
  272.             flag_end = False
  273.             for tz_1 in z_1_list:
  274.                 for tz_2 in z_2_list:
  275.                     common_stra = list(set(stra_dict_for_x1[tz_1]) & set(stra_dict_for_x2[tz_2]))
  276.                     if common_stra:
  277.                         color = self.side_color[str_on_side[common_stra]]
  278.                         flag_end = True
  279.                         break
  280.                 if flag_end:
  281.                     break
  282.             if z_p_1 > -1 and z_p_2 > -1:
  283.                 self.segments_for_paint[((x_1, y), (x_2, y))] = color
  284.  
  285.     def worker_2_1(self):
  286.         self.segments_for_paint = {}  # segment: color
  287.         for y in range(self.y_min, self.y_max):
  288.             straights_with_ends, str_on_side, straights = self.make_plane_view(y)
  289.             all_viewier_points = self.find_all_plane_points(straights, straights_with_ends)
  290.             all_points_sorted = sorted(all_viewier_points, key=lambda p: (p[1], p[0]))
  291.             self.get_segm_for_paint(y, all_points_sorted, straights_with_ends, str_on_side)
  292.  
  293.     def segm_painter(self):
  294.         for p1, p2 in self.segments_for_paint.keys():
  295.             self.qp.setPen(QPen(self.segments_for_paint[(p1, p2)], 2))
  296.             self.qp.drawLine(p1[0], p1[1], p2[0], p2[1])
  297.  
  298.     def true_painter(self):
  299.         poly_1_true = {Qt.darkMagenta: [(200, 200, 0), (250, 150, 50), (100, 200, 0)],  # bottom
  300.                        Qt.darkYellow: [(250, 150, 50), (150, 100, 0), (100, 200, 0)],  # back
  301.                        Qt.darkBlue: [(200, 200, 0), (250, 150, 50), (150, 100, 0)],  # right
  302.                        Qt.darkGray: [(100, 200, 0), (200, 200, 0), (150, 100, 0)]}  # front
  303.  
  304.         poly_2_true = {Qt.darkMagenta: [(200, 150, 0), (200, 50, 0), (250, 20, 100), (250, 120, 100)],  # left
  305.                        Qt.darkBlue: [(200, 150, 0), (300, 150, 0), (350, 120, 100), (250, 120, 100)],  # bottom
  306.                        Qt.blue: [(350, 120, 100), (350, 20, 100), (250, 20, 100), (250, 120, 100)],  # back
  307.                        Qt.darkYellow: [(200, 50, 0), (300, 50, 0), (350, 20, 100), (250, 20, 100)],  # top
  308.                        Qt.darkRed: [(300, 50, 0), (300, 150, 0), (350, 120, 100), (350, 20, 100)],  # right
  309.                        Qt.darkGreen: [(200, 150, 0), (200, 50, 0), (300, 50, 0), (300, 150, 0)]}  # front
  310.  
  311.         for side in poly_1_true.keys():
  312.             self.qp.setPen(QPen(side, 2))
  313.             self.qp.setBrush(QBrush(side))
  314.             self.qp.drawPolygon(QPoint(poly_1_true[side][0][0], poly_1_true[side][0][1]),
  315.                                 QPoint(poly_1_true[side][1][0], poly_1_true[side][1][1]),
  316.                                 QPoint(poly_1_true[side][2][0], poly_1_true[side][2][1]))
  317.  
  318.         for side in poly_2_true.keys():
  319.             self.qp.setPen(QPen(side, 2))
  320.             self.qp.setBrush(QBrush(side))
  321.             self.qp.drawPolygon(QPoint(poly_2_true[side][0][0], poly_2_true[side][0][1]),
  322.                                 QPoint(poly_2_true[side][1][0], poly_2_true[side][1][1]),
  323.                                 QPoint(poly_2_true[side][2][0], poly_2_true[side][2][1]),
  324.                                 QPoint(poly_2_true[side][3][0], poly_2_true[side][3][1]))
  325.  
  326.  
  327. if __name__ == '__main__':
  328.     app = QApplication(sys.argv)
  329.     window = MyMainWindow()
  330.     window.show()
  331.     sys.exit(app.exec_())
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top