Advertisement
trishLEX

LAB_5

Apr 25th, 2017
366
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 20.29 KB | None | 0 0
  1. import glfw
  2. from OpenGL.GL import *
  3.  
  4.  
  5. class Vertex:
  6.     def __init__(self, point):
  7.         self.coords = point
  8.         self.isIntersectionPoint = False
  9.         self.isEntry = False
  10.         self.isHole = False
  11.  
  12.     def __len__(self):
  13.         return 1
  14.  
  15.  
  16. class Polygon:
  17.     isSbjReady = False
  18.     isHolesReady = False
  19.     listOfEntries = []
  20.  
  21.     def __init__(self):
  22.         self.points = []
  23.         self.sizes = []
  24.         self.size = 0
  25.  
  26.     def insert(self, x, i):
  27.         for j in x:
  28.             self.points[i].append(j)
  29.         self.sizes[i] += len(x)
  30.  
  31.     def append(self, x):
  32.         self.points.append(x)
  33.         self.sizes.append(len(x))
  34.         self.size += 1
  35.  
  36.     def isEmpty(self):
  37.         if self.size == 0 and self.points == [] and self.sizes == []:
  38.             return True
  39.         else:
  40.             return False
  41.  
  42.     def clear(self):
  43.         self.isSbjReady = False
  44.         self.isHolesReady = False
  45.         self.listOfEntries = []
  46.         self.points = []
  47.         self.sizes = []
  48.         self.size = 0
  49.  
  50.  
  51. class Clip:
  52.     isClipReady = False
  53.  
  54.     def __init__(self):
  55.         self.points = []
  56.         self.size = 0
  57.  
  58.     def append(self, x):
  59.         self.points.append(x)
  60.         self.size += 1
  61.  
  62.     def isEmpty(self):
  63.         if self.size:
  64.             return False
  65.         else:
  66.             return True
  67.  
  68.     def clear(self):
  69.         self.points = []
  70.         self.size = 0
  71.         self.isClipReady = False
  72.  
  73.  
  74. class IntersectionShapes:
  75.     isIntersectionMade = False
  76.  
  77.     def __init__(self):
  78.         self.points = []
  79.         self.sizes = []
  80.         self.size = 0
  81.         self.boolIntersectionList = []
  82.  
  83.     def insert(self, x, i):
  84.         for j in x:
  85.             self.points[i].append(j)
  86.         self.sizes[i] += len(x)
  87.  
  88.     def append(self, x):
  89.         self.points.append(x)
  90.         self.sizes.append(len(x))
  91.         self.size += 1
  92.  
  93.     def isEmpty(self):
  94.         if self.size == 0 and self.points == [] and self.sizes == []:
  95.             return True
  96.         else:
  97.             return False
  98.  
  99.     def clear(self):
  100.         self.isIntersectionMade = False
  101.         self.points = []
  102.         self.sizes = []
  103.         self.size = 0
  104.  
  105.  
  106. global startPoint
  107. startPoint = False
  108.  
  109.  
  110. def mouseCallback(window, button, action, mods):
  111.     global startPoint
  112.     if button == glfw.MOUSE_BUTTON_1 and action:
  113.         mouse = glfw.get_cursor_pos(window)
  114.         mouse = [int(mouse[0]), 480 - int(mouse[1])]
  115.         p = Vertex(mouse)
  116.         if not polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
  117.             if polygon.isEmpty():
  118.                 if not startPoint:
  119.                     startPoint = True
  120.                     polygon.append([p])
  121.             else:
  122.                 polygon.insert([p], 0)
  123.         if polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
  124.             if not startPoint:
  125.                 startPoint = True
  126.                 p.isHole = True
  127.                 polygon.append([p])
  128.             else:
  129.                 p.isHole = True
  130.                 polygon.insert([p], polygon.size - 1)
  131.         if polygon.isSbjReady and polygon.isHolesReady and not clip.isClipReady:
  132.             clip.append(p)
  133.  
  134.  
  135. def keyCallback(window, key, scancode, action, mods):
  136.     global startPoint
  137.     if key == glfw.KEY_SPACE and action:
  138.         if not polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
  139.             startPoint = False
  140.             polygon.isSbjReady = True
  141.             print("PRESS SPACE TO SKIP DRAWING HOLES")
  142.         elif polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
  143.             startPoint = False
  144.             polygon.isHolesReady = True
  145.         elif polygon.isSbjReady and polygon.isHolesReady and not clip.isClipReady:
  146.             clip.isClipReady = True
  147.     if key == glfw.KEY_H and action:
  148.         polygon.isHolesReady = False
  149.     if key == glfw.KEY_ENTER and action:
  150.         makeIntersection()
  151.     if key == glfw.KEY_DELETE and action:
  152.         polygon.clear()
  153.         clip.clear()
  154.         intersectionShapes.clear()
  155.         startPoint = False
  156.  
  157.  
  158. def makeEntryList(points, count):
  159.     entry = checkForEntry(points[0], clip.points)
  160.  
  161.     for i in range(count):
  162.         if points[i].isIntersectionPoint:
  163.             k = clip.points.index(points[i])
  164.             points[i].isEntry = entry
  165.             clip.points[k].isEntry = entry
  166.             entry = not entry
  167.  
  168.  
  169. def makeIntersection():
  170.     global isWhite
  171.  
  172.     searchForIntersections()
  173.  
  174.     checkIntersections() ###список в каких контурах есть пересечение
  175.  
  176.     holesInside = []
  177.     isCompleted = False
  178.  
  179.     if not intersectionShapes.boolIntersectionList[0] and insideInClip(polygon.points[0]):
  180.         print("polygon inside clip")
  181.         isCompleted = True
  182.         intersectionShapes.points = polygon.points
  183.         intersectionShapes.size = polygon.size
  184.         intersectionShapes.sizes = polygon.sizes
  185.  
  186.     for i in range(1, polygon.size):
  187.         if not intersectionShapes.boolIntersectionList[i] and insideInClip(polygon.points[i]):
  188.             print("holes is inside clip")
  189.             holesInside.append(polygon.points[i])
  190.  
  191.     bool = False
  192.  
  193.     for i in intersectionShapes.boolIntersectionList:
  194.         bool = bool or i
  195.  
  196.     isWhite = False
  197.  
  198.     if not bool and not isCompleted:
  199.         for i in range(1, polygon.size):
  200.             if inPolygon(clip.points[0].coords[0], clip.points[0].coords[1], [j.coords[0] for j in polygon.points[i]],
  201.                          [j.coords[1] for j in polygon.points[i]]):
  202.                 print("clip is inside hole")
  203.                 isWhite = True
  204.                 break
  205.  
  206.         intersectionShapes.points.append(clip.points)
  207.         intersectionShapes.size = 1
  208.         intersectionShapes.sizes = [clip.size]
  209.         isCompleted = True
  210.  
  211.     for i in range(polygon.size):
  212.         makeEntryList(polygon.points[i], polygon.sizes[i])
  213.     for i in clip.points:
  214.         if i.isIntersectionPoint and i.isEntry:
  215.             polygon.listOfEntries.append(i)
  216.  
  217.     print("list of entries", [i.coords for i in polygon.listOfEntries])
  218.     print("polygon coords", [j.coords for i in polygon.points for j in i])
  219.     print("clip coords", [i.coords for i in clip.points])
  220.  
  221.     if not isCompleted:
  222.         print("intersection is not completed")
  223.         makeIntersectionShapes()
  224.  
  225.     for i in holesInside:
  226.         intersectionShapes.points.append(i)
  227.         intersectionShapes.sizes.append(len(i))
  228.         intersectionShapes.size += 1
  229.  
  230.  
  231. def searchForIntersections():
  232.     newSbjPoints = []
  233.     newClipPoints = []
  234.  
  235.     newSbjSizes = []
  236.     newSbjSize = 0
  237.     newClipSize = 0
  238.  
  239.     for i in range(polygon.size):
  240.         points = []
  241.         size = 0
  242.         for k in range(polygon.sizes[i]):
  243.             points.append(polygon.points[i][k])
  244.             size += 1
  245.             intersectionPoints = []
  246.             intersectionPointsCount = 0
  247.             for j in range(clip.size):
  248.                 if clip.points[j] not in newClipPoints:
  249.                     newClipPoints.append(clip.points[j])
  250.                     newClipSize += 1
  251.                 I = intersectionFound(
  252.                     [polygon.points[i][k].coords, polygon.points[i][(k + 1) % polygon.sizes[i]].coords],
  253.                     [clip.points[j].coords, clip.points[(j + 1) % clip.size].coords])
  254.                 if I:
  255.                     intersectionPointsCount += 1
  256.                     p = Vertex(I)
  257.                     p.isIntersectionPoint = True
  258.                     if i:
  259.                         p.isHole = True
  260.                     intersectionPoints.append(p)
  261.                     intersectionPointsCount += 1
  262.                     newClipPoints.append(p)
  263.                     newClipSize += 1
  264.             intersectionPoints = makeOrder(intersectionPoints, polygon.points[i][k],
  265.                                            polygon.points[i][(k + 1) % polygon.sizes[i]])
  266.             if intersectionPoints != []:
  267.                 for l in intersectionPoints:
  268.                     points.append(l)
  269.                     size += 1
  270.         newSbjPoints.append(points)
  271.         newSbjSize += 1
  272.         newSbjSizes.append(size)
  273.  
  274.     newClipSize = 0
  275.     newClipPoints = []
  276.  
  277.     for j in range(clip.size):
  278.         newClipPoints.append(clip.points[j])
  279.         newClipSize += 1
  280.         intersectionPoints = []
  281.         intersectionPointsCount = 0
  282.         for i in range(polygon.size):
  283.             for k in range(polygon.sizes[i]):
  284.                 I = intersectionFound(
  285.                     [polygon.points[i][k].coords, polygon.points[i][(k + 1) % polygon.sizes[i]].coords],
  286.                     [clip.points[j].coords, clip.points[(j + 1) % clip.size].coords])
  287.                 if I:
  288.                     intersectionPointsCount += 1
  289.                     for m in newSbjPoints:
  290.                         for n in m:
  291.                             if I == n.coords:
  292.                                 p = n
  293.                     intersectionPoints.append(p)
  294.                     intersectionPointsCount += 1
  295.         intersectionPoints = makeOrder(intersectionPoints, clip.points[j], clip.points[(j + 1) % clip.size])
  296.         if intersectionPoints != []:
  297.             for l in intersectionPoints:
  298.                 newClipPoints.append(l)
  299.                 newClipSize += 1
  300.  
  301.     polygon.points = newSbjPoints
  302.     polygon.sizes = newSbjSizes
  303.     polygon.size = newSbjSize
  304.  
  305.     clip.points = newClipPoints
  306.     clip.size = newClipSize
  307.  
  308.  
  309. def checkIntersections():
  310.     intersectionShapes.boolIntersectionList = [False for i in range(polygon.size)]
  311.  
  312.     for i in range(polygon.size):
  313.         for j in range(polygon.sizes[i]):
  314.             if polygon.points[i][j].isIntersectionPoint:
  315.                 intersectionShapes.boolIntersectionList[i] = True
  316.                 break
  317.  
  318.  
  319. def intersectionFound(edge1, edge2):
  320.     if checkForBelonging(edge1[0], edge2) or checkForBelonging(edge1[1], edge2) or checkForBelonging(edge2[0], edge1) \
  321.             or checkForBelonging(edge2[1], edge1):
  322.         return False
  323.     A = edge1[0]
  324.     C = edge2[0]
  325.     c = [C[0] - A[0], C[1] - A[1]]
  326.     b = [edge1[1][0] - edge1[0][0], edge1[1][1] - edge1[0][1]]
  327.     d = [edge2[1][0] - edge2[0][0], edge2[1][1] - edge2[0][1]]
  328.     dVert = [-d[1], d[0]]
  329.     bVert = [-b[1], b[0]]
  330.     m = dVert[0] * c[0] + dVert[1] * c[1]
  331.     n = dVert[0] * b[0] + dVert[1] * b[1]
  332.     if n == 0:
  333.         return False
  334.     t = m / n
  335.     q = bVert[0] * c[0] + bVert[1] * c[1]
  336.     u = q / n
  337.     if t < 0 or t > 1 or u < 0 or u > 1:
  338.         return False
  339.     pr = [b[0] * t, b[1] * t]
  340.     I = [A[0] + pr[0], A[1] + pr[1]]
  341.     return I
  342.  
  343.  
  344. def makeIntersectionShapes():
  345.     points = []
  346.     size = 0
  347.     goToListOfEntries = False
  348.     startPoint = False
  349.     polygon.listOfEntries.reverse()
  350.     entryPoint = False
  351.  
  352.     while polygon.listOfEntries:
  353.         if not entryPoint:
  354.             a = polygon.listOfEntries.pop()                                              ###новая точка входа в новую фигуру
  355.         else:
  356.             print("entry point coords", entryPoint.coords)                               ###новая точка вхожа в старую фигуру
  357.             a = polygon.listOfEntries.pop(polygon.listOfEntries.index(entryPoint))                                      
  358.             entryPoint = False
  359.         if not startPoint:
  360.             startPoint = a
  361.         for i in range(polygon.size):
  362.             if goToListOfEntries:
  363.                 break
  364.             for j in range(polygon.sizes[i]):
  365.                 if goToListOfEntries:
  366.                     break
  367.                 if a == polygon.points[i][j]:
  368.                     points.append(a)                                                     ###добавляем точку входа
  369.                     print("points1", [r.coords for r in points])
  370.                     size += 1
  371.                     print("size =", size)
  372.                     for x in range(j + 1, j + polygon.sizes[i]):
  373.                         if goToListOfEntries:
  374.                             break
  375.                         p = polygon.points[i][x % polygon.sizes[i]]
  376.                         print("p", p.coords, "index =", x % polygon.sizes[i], "x =", x)
  377.                         if not p.isIntersectionPoint:                                    ###добавляем всё до точки выхода
  378.                             points.append(p)
  379.                             size += 1
  380.                             print("points2", [r.coords for r in points])
  381.                             print("size =", size)
  382.                         else:                                                            ###переходим на отсекатель
  383.                             print("GG WP")
  384.                             z = clip.points.index(p)
  385.                             points.append(p)
  386.                             size += 1
  387.                             print("points3", [r.coords for r in points])
  388.                             print("size =", size)
  389.                             print("p index in clip", z)
  390.                             for y in range(z + 1, z + clip.size):
  391.                                 point = clip.points[y % clip.size]
  392.                                 # size += 1
  393.                                 print(point.coords, "isIntersection?", point.isIntersectionPoint)
  394.                                 if not point.isIntersectionPoint:                         ###добавляем всё до точки входа
  395.                                     points.append(point)
  396.                                     size += 1
  397.                                     print("points4", [r.coords for r in points])
  398.                                     print("size =", size)
  399.                                 else:                                                     ###переходим опять на список вершин входа
  400.                                     goToListOfEntries = True
  401.                                     if point == startPoint:                               ###отсечённый многоугольник завершён
  402.                                         print("points are adding to shapes", [r.coords for r in points])
  403.                                         intersectionShapes.points.append(points)
  404.                                         intersectionShapes.size += 1
  405.                                         intersectionShapes.sizes.append(size)
  406.                                         points = []
  407.                                         size = 0
  408.                                         startPoint = False
  409.                                     else:                                                 ###многоугольник не завершён, начинаем с текущей точки входа
  410.                                         entryPoint = point
  411.                                     break
  412.         if goToListOfEntries:
  413.             goToListOfEntries = False
  414.  
  415.  
  416. def inPolygon(x, y, xp, yp):
  417.     c = False
  418.     for i in range(len(xp)):
  419.         if ((yp[i] <= y < yp[i - 1]) or (yp[i - 1] <= y < yp[i])) and (
  420.                     x > (xp[i - 1] - xp[i]) * (y - yp[i]) / (yp[i - 1] - yp[i]) + xp[i]):
  421.             c = not c
  422.     return c
  423.  
  424.  
  425. def checkForEntry(point, points):
  426.     xp = [i.coords[0] for i in points]
  427.     yp = [i.coords[1] for i in points]
  428.  
  429.     if inPolygon(point.coords[0], point.coords[1], xp, yp):
  430.         return False
  431.     else:
  432.         return True
  433.  
  434.  
  435. def insideInClip(points):
  436.     result = True
  437.  
  438.     for i in points:
  439.         result = result and inPolygon(i.coords[0], i.coords[1], [j.coords[0] for j in clip.points],
  440.                                       [j.coords[1] for j in clip.points])
  441.  
  442.     return result
  443.  
  444.  
  445. def insideHoles():
  446.     res = [[], [], 0]
  447.  
  448.     for i in range(1, polygon.size):
  449.         if insideInClip(polygon.points[i]):
  450.             res[0].append(polygon.points[i])
  451.             res[1].append(polygon.sizes[i])
  452.             res[2] += 1
  453.  
  454.     return res
  455.  
  456.  
  457. def checkForBelonging(point, edge):  ###edge = [[x1, y1], [x2, y2]]
  458.     maxX = max(edge[0][0], edge[1][0])
  459.     minX = min(edge[0][0], edge[1][0])
  460.     maxY = max(edge[0][1], edge[1][1])
  461.     minY = min(edge[0][1], edge[1][1])
  462.  
  463.     if maxX >= point[0] >= minX and maxY >= point[1] >= minY:
  464.         if not ((point[0] - edge[0][0]) * (edge[1][1] - edge[0][1]) - (point[1] - edge[0][1]) * (
  465.                     edge[1][0] - edge[0][0])):
  466.             return True
  467.         else:
  468.             return False
  469.     else:
  470.         return False
  471.  
  472.  
  473. def sign(a, b):
  474.     if a < b:
  475.         return 1
  476.     elif a == b:
  477.         return 0
  478.     else:
  479.         return -1
  480.  
  481.  
  482. def makeOrder(points, point1, point2):
  483.     intersectionPoints = points
  484.     sx = sign(point1.coords[0], point2.coords[0])
  485.     sy = sign(point1.coords[1], point2.coords[1])
  486.     if sx > 0:
  487.         intersectionPoints.sort(key=lambda x: x.coords[0])
  488.     elif sx < 0:
  489.         intersectionPoints.sort(key=lambda x: -x.coords[0])
  490.     else:
  491.         if sy > 0:
  492.             intersectionPoints.sort(key=lambda x: x.coords[1])
  493.         else:
  494.             intersectionPoints.sort(key=lambda x: -x.coords[1])
  495.     return intersectionPoints
  496.  
  497.  
  498. def background():
  499.     glClearColor(1.0, 1.0, 1.0, 1.0)
  500.     glClear(GL_COLOR_BUFFER_BIT)
  501.  
  502.  
  503. def chngCoordf(point):
  504.     width = 640
  505.     height = 480
  506.  
  507.     x = point[0] * 2 / width - 1
  508.     y = point[1] * 2 / height - 1
  509.  
  510.     return x, y
  511.  
  512.  
  513. def drawShape(points, pointsCount, color, type):
  514.     glBegin(type)
  515.  
  516.     glColor3f(color[0], color[1], color[2])
  517.  
  518.     for i in range(pointsCount):
  519.         x, y = chngCoordf(points[i].coords)
  520.         glVertex(x, y)
  521.  
  522.     glEnd()
  523.  
  524.  
  525. def drawLines(points, count, color):
  526.     glBegin(GL_LINE_STRIP)
  527.     glColor3f(color[0], color[1], color[2])
  528.  
  529.     for i in range(count):
  530.         x, y = chngCoordf(points[i].coords)
  531.         glVertex2f(x, y)
  532.  
  533.     glEnd()
  534.  
  535.  
  536. def drawLine(point1, point2, color):
  537.     x1, y1 = chngCoordf(point1.coords)
  538.     x2, y2 = chngCoordf(point2.coords)
  539.  
  540.     glBegin(GL_LINES)
  541.  
  542.     glColor3f(color[0], color[1], color[2])
  543.     glVertex2f(x1, y1)
  544.     glVertex2f(x2, y2)
  545.  
  546.     glEnd()
  547.  
  548.  
  549. def draw():
  550.     glPointSize(1)
  551.     glLineWidth(3)
  552.  
  553.     if not polygon.isEmpty():
  554.         if polygon.size == 1:
  555.             if polygon.isSbjReady:
  556.                 drawShape(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0], GL_POLYGON)
  557.             else:
  558.                 drawLines(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0])
  559.         else:
  560.             drawShape(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0], GL_POLYGON)
  561.             if polygon.isHolesReady:
  562.                 for i in range(1, polygon.size):
  563.                     drawShape(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0], GL_POLYGON)
  564.             else:
  565.                 for i in range(1, polygon.size - 1):
  566.                     drawShape(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0], GL_POLYGON)
  567.                 for i in range(polygon.size - 1, polygon.size):
  568.                     drawLines(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0])
  569.     if not clip.isEmpty():
  570.         if clip.isClipReady:
  571.             for i in range(clip.size):
  572.                 drawLine(clip.points[i], clip.points[(i + 1) % clip.size], [0, 0, 1.0])
  573.         else:
  574.             for i in range(clip.size):
  575.                 drawLines(clip.points, clip.size, [0.0, 0.0, 1.0])
  576.     if not intersectionShapes.isEmpty():
  577.         if not isWhite:
  578.             for i in range(intersectionShapes.size):
  579.                 drawShape(intersectionShapes.points[i], intersectionShapes.sizes[i], [1.0, 0.0, 0.0], GL_LINE_LOOP)
  580.  
  581.  
  582. class Drawer:
  583.     window = False
  584.  
  585.     def __init__(self):
  586.         if not glfw.init():
  587.             return
  588.  
  589.         self.window = glfw.create_window(640, 480, "Lab5", None, None)
  590.         if not self.window:
  591.             glfw.terminate()
  592.             return
  593.  
  594.         glfw.make_context_current(self.window)
  595.  
  596.         glfw.set_mouse_button_callback(self.window, mouseCallback)
  597.         glfw.set_key_callback(self.window, keyCallback)
  598.  
  599.     def startLoop(self):
  600.         while not glfw.window_should_close(self.window):
  601.             background()
  602.             draw()
  603.  
  604.             glfw.swap_buffers(self.window)
  605.             glfw.poll_events()
  606.  
  607.         glfw.terminate()
  608.  
  609.  
  610. polygon = Polygon()
  611. clip = Clip()
  612. intersectionShapes = IntersectionShapes()
  613. drawer = Drawer()
  614. drawer.startLoop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement