Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import glfw
- from OpenGL.GL import *
- class Vertex:
- def __init__(self, point):
- self.coords = point
- self.isIntersectionPoint = False
- self.isEntry = False
- self.isHole = False
- def __len__(self):
- return 1
- class Polygon:
- isSbjReady = False
- isHolesReady = False
- listOfEntries = []
- def __init__(self):
- self.points = []
- self.sizes = []
- self.size = 0
- def insert(self, x, i):
- for j in x:
- self.points[i].append(j)
- self.sizes[i] += len(x)
- def append(self, x):
- self.points.append(x)
- self.sizes.append(len(x))
- self.size += 1
- def isEmpty(self):
- if self.size == 0 and self.points == [] and self.sizes == []:
- return True
- else:
- return False
- def clear(self):
- self.isSbjReady = False
- self.isHolesReady = False
- self.listOfEntries = []
- self.points = []
- self.sizes = []
- self.size = 0
- class Clip:
- isClipReady = False
- def __init__(self):
- self.points = []
- self.size = 0
- def append(self, x):
- self.points.append(x)
- self.size += 1
- def isEmpty(self):
- if self.size:
- return False
- else:
- return True
- def clear(self):
- self.points = []
- self.size = 0
- self.isClipReady = False
- class IntersectionShapes:
- isIntersectionMade = False
- def __init__(self):
- self.points = []
- self.sizes = []
- self.size = 0
- self.boolIntersectionList = []
- def insert(self, x, i):
- for j in x:
- self.points[i].append(j)
- self.sizes[i] += len(x)
- def append(self, x):
- self.points.append(x)
- self.sizes.append(len(x))
- self.size += 1
- def isEmpty(self):
- if self.size == 0 and self.points == [] and self.sizes == []:
- return True
- else:
- return False
- def clear(self):
- self.isIntersectionMade = False
- self.points = []
- self.sizes = []
- self.size = 0
- global startPoint
- startPoint = False
- def mouseCallback(window, button, action, mods):
- global startPoint
- if button == glfw.MOUSE_BUTTON_1 and action:
- mouse = glfw.get_cursor_pos(window)
- mouse = [int(mouse[0]), 480 - int(mouse[1])]
- p = Vertex(mouse)
- if not polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
- if polygon.isEmpty():
- if not startPoint:
- startPoint = True
- polygon.append([p])
- else:
- polygon.insert([p], 0)
- if polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
- if not startPoint:
- startPoint = True
- p.isHole = True
- polygon.append([p])
- else:
- p.isHole = True
- polygon.insert([p], polygon.size - 1)
- if polygon.isSbjReady and polygon.isHolesReady and not clip.isClipReady:
- clip.append(p)
- def keyCallback(window, key, scancode, action, mods):
- global startPoint
- if key == glfw.KEY_SPACE and action:
- if not polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
- startPoint = False
- polygon.isSbjReady = True
- print("PRESS SPACE TO SKIP DRAWING HOLES")
- elif polygon.isSbjReady and not polygon.isHolesReady and not clip.isClipReady:
- startPoint = False
- polygon.isHolesReady = True
- elif polygon.isSbjReady and polygon.isHolesReady and not clip.isClipReady:
- clip.isClipReady = True
- if key == glfw.KEY_H and action:
- polygon.isHolesReady = False
- if key == glfw.KEY_ENTER and action:
- makeIntersection()
- if key == glfw.KEY_DELETE and action:
- polygon.clear()
- clip.clear()
- intersectionShapes.clear()
- startPoint = False
- def makeEntryList(points, count):
- entry = checkForEntry(points[0], clip.points)
- for i in range(count):
- if points[i].isIntersectionPoint:
- k = clip.points.index(points[i])
- points[i].isEntry = entry
- clip.points[k].isEntry = entry
- entry = not entry
- def makeIntersection():
- global isWhite
- searchForIntersections()
- checkIntersections() ###список в каких контурах есть пересечение
- holesInside = []
- isCompleted = False
- if not intersectionShapes.boolIntersectionList[0] and insideInClip(polygon.points[0]):
- print("polygon inside clip")
- isCompleted = True
- intersectionShapes.points = polygon.points
- intersectionShapes.size = polygon.size
- intersectionShapes.sizes = polygon.sizes
- for i in range(1, polygon.size):
- if not intersectionShapes.boolIntersectionList[i] and insideInClip(polygon.points[i]):
- print("holes is inside clip")
- holesInside.append(polygon.points[i])
- bool = False
- for i in intersectionShapes.boolIntersectionList:
- bool = bool or i
- isWhite = False
- if not bool and not isCompleted:
- for i in range(1, polygon.size):
- if inPolygon(clip.points[0].coords[0], clip.points[0].coords[1], [j.coords[0] for j in polygon.points[i]],
- [j.coords[1] for j in polygon.points[i]]):
- print("clip is inside hole")
- isWhite = True
- break
- intersectionShapes.points.append(clip.points)
- intersectionShapes.size = 1
- intersectionShapes.sizes = [clip.size]
- isCompleted = True
- for i in range(polygon.size):
- makeEntryList(polygon.points[i], polygon.sizes[i])
- for i in clip.points:
- if i.isIntersectionPoint and i.isEntry:
- polygon.listOfEntries.append(i)
- print("list of entries", [i.coords for i in polygon.listOfEntries])
- print("polygon coords", [j.coords for i in polygon.points for j in i])
- print("clip coords", [i.coords for i in clip.points])
- if not isCompleted:
- print("intersection is not completed")
- makeIntersectionShapes()
- for i in holesInside:
- intersectionShapes.points.append(i)
- intersectionShapes.sizes.append(len(i))
- intersectionShapes.size += 1
- def searchForIntersections():
- newSbjPoints = []
- newClipPoints = []
- newSbjSizes = []
- newSbjSize = 0
- newClipSize = 0
- for i in range(polygon.size):
- points = []
- size = 0
- for k in range(polygon.sizes[i]):
- points.append(polygon.points[i][k])
- size += 1
- intersectionPoints = []
- intersectionPointsCount = 0
- for j in range(clip.size):
- if clip.points[j] not in newClipPoints:
- newClipPoints.append(clip.points[j])
- newClipSize += 1
- I = intersectionFound(
- [polygon.points[i][k].coords, polygon.points[i][(k + 1) % polygon.sizes[i]].coords],
- [clip.points[j].coords, clip.points[(j + 1) % clip.size].coords])
- if I:
- intersectionPointsCount += 1
- p = Vertex(I)
- p.isIntersectionPoint = True
- if i:
- p.isHole = True
- intersectionPoints.append(p)
- intersectionPointsCount += 1
- newClipPoints.append(p)
- newClipSize += 1
- intersectionPoints = makeOrder(intersectionPoints, polygon.points[i][k],
- polygon.points[i][(k + 1) % polygon.sizes[i]])
- if intersectionPoints != []:
- for l in intersectionPoints:
- points.append(l)
- size += 1
- newSbjPoints.append(points)
- newSbjSize += 1
- newSbjSizes.append(size)
- newClipSize = 0
- newClipPoints = []
- for j in range(clip.size):
- newClipPoints.append(clip.points[j])
- newClipSize += 1
- intersectionPoints = []
- intersectionPointsCount = 0
- for i in range(polygon.size):
- for k in range(polygon.sizes[i]):
- I = intersectionFound(
- [polygon.points[i][k].coords, polygon.points[i][(k + 1) % polygon.sizes[i]].coords],
- [clip.points[j].coords, clip.points[(j + 1) % clip.size].coords])
- if I:
- intersectionPointsCount += 1
- for m in newSbjPoints:
- for n in m:
- if I == n.coords:
- p = n
- intersectionPoints.append(p)
- intersectionPointsCount += 1
- intersectionPoints = makeOrder(intersectionPoints, clip.points[j], clip.points[(j + 1) % clip.size])
- if intersectionPoints != []:
- for l in intersectionPoints:
- newClipPoints.append(l)
- newClipSize += 1
- polygon.points = newSbjPoints
- polygon.sizes = newSbjSizes
- polygon.size = newSbjSize
- clip.points = newClipPoints
- clip.size = newClipSize
- def checkIntersections():
- intersectionShapes.boolIntersectionList = [False for i in range(polygon.size)]
- for i in range(polygon.size):
- for j in range(polygon.sizes[i]):
- if polygon.points[i][j].isIntersectionPoint:
- intersectionShapes.boolIntersectionList[i] = True
- break
- def intersectionFound(edge1, edge2):
- if checkForBelonging(edge1[0], edge2) or checkForBelonging(edge1[1], edge2) or checkForBelonging(edge2[0], edge1) \
- or checkForBelonging(edge2[1], edge1):
- return False
- A = edge1[0]
- C = edge2[0]
- c = [C[0] - A[0], C[1] - A[1]]
- b = [edge1[1][0] - edge1[0][0], edge1[1][1] - edge1[0][1]]
- d = [edge2[1][0] - edge2[0][0], edge2[1][1] - edge2[0][1]]
- dVert = [-d[1], d[0]]
- bVert = [-b[1], b[0]]
- m = dVert[0] * c[0] + dVert[1] * c[1]
- n = dVert[0] * b[0] + dVert[1] * b[1]
- if n == 0:
- return False
- t = m / n
- q = bVert[0] * c[0] + bVert[1] * c[1]
- u = q / n
- if t < 0 or t > 1 or u < 0 or u > 1:
- return False
- pr = [b[0] * t, b[1] * t]
- I = [A[0] + pr[0], A[1] + pr[1]]
- return I
- def makeIntersectionShapes():
- points = []
- size = 0
- goToListOfEntries = False
- startPoint = False
- polygon.listOfEntries.reverse()
- entryPoint = False
- while polygon.listOfEntries:
- if not entryPoint:
- a = polygon.listOfEntries.pop() ###новая точка входа в новую фигуру
- else:
- print("entry point coords", entryPoint.coords) ###новая точка вхожа в старую фигуру
- a = polygon.listOfEntries.pop(polygon.listOfEntries.index(entryPoint))
- entryPoint = False
- if not startPoint:
- startPoint = a
- for i in range(polygon.size):
- if goToListOfEntries:
- break
- for j in range(polygon.sizes[i]):
- if goToListOfEntries:
- break
- if a == polygon.points[i][j]:
- points.append(a) ###добавляем точку входа
- print("points1", [r.coords for r in points])
- size += 1
- print("size =", size)
- for x in range(j + 1, j + polygon.sizes[i]):
- if goToListOfEntries:
- break
- p = polygon.points[i][x % polygon.sizes[i]]
- print("p", p.coords, "index =", x % polygon.sizes[i], "x =", x)
- if not p.isIntersectionPoint: ###добавляем всё до точки выхода
- points.append(p)
- size += 1
- print("points2", [r.coords for r in points])
- print("size =", size)
- else: ###переходим на отсекатель
- print("GG WP")
- z = clip.points.index(p)
- points.append(p)
- size += 1
- print("points3", [r.coords for r in points])
- print("size =", size)
- print("p index in clip", z)
- for y in range(z + 1, z + clip.size):
- point = clip.points[y % clip.size]
- # size += 1
- print(point.coords, "isIntersection?", point.isIntersectionPoint)
- if not point.isIntersectionPoint: ###добавляем всё до точки входа
- points.append(point)
- size += 1
- print("points4", [r.coords for r in points])
- print("size =", size)
- else: ###переходим опять на список вершин входа
- goToListOfEntries = True
- if point == startPoint: ###отсечённый многоугольник завершён
- print("points are adding to shapes", [r.coords for r in points])
- intersectionShapes.points.append(points)
- intersectionShapes.size += 1
- intersectionShapes.sizes.append(size)
- points = []
- size = 0
- startPoint = False
- else: ###многоугольник не завершён, начинаем с текущей точки входа
- entryPoint = point
- break
- if goToListOfEntries:
- goToListOfEntries = False
- def inPolygon(x, y, xp, yp):
- c = False
- for i in range(len(xp)):
- if ((yp[i] <= y < yp[i - 1]) or (yp[i - 1] <= y < yp[i])) and (
- x > (xp[i - 1] - xp[i]) * (y - yp[i]) / (yp[i - 1] - yp[i]) + xp[i]):
- c = not c
- return c
- def checkForEntry(point, points):
- xp = [i.coords[0] for i in points]
- yp = [i.coords[1] for i in points]
- if inPolygon(point.coords[0], point.coords[1], xp, yp):
- return False
- else:
- return True
- def insideInClip(points):
- result = True
- for i in points:
- result = result and inPolygon(i.coords[0], i.coords[1], [j.coords[0] for j in clip.points],
- [j.coords[1] for j in clip.points])
- return result
- def insideHoles():
- res = [[], [], 0]
- for i in range(1, polygon.size):
- if insideInClip(polygon.points[i]):
- res[0].append(polygon.points[i])
- res[1].append(polygon.sizes[i])
- res[2] += 1
- return res
- def checkForBelonging(point, edge): ###edge = [[x1, y1], [x2, y2]]
- maxX = max(edge[0][0], edge[1][0])
- minX = min(edge[0][0], edge[1][0])
- maxY = max(edge[0][1], edge[1][1])
- minY = min(edge[0][1], edge[1][1])
- if maxX >= point[0] >= minX and maxY >= point[1] >= minY:
- if not ((point[0] - edge[0][0]) * (edge[1][1] - edge[0][1]) - (point[1] - edge[0][1]) * (
- edge[1][0] - edge[0][0])):
- return True
- else:
- return False
- else:
- return False
- def sign(a, b):
- if a < b:
- return 1
- elif a == b:
- return 0
- else:
- return -1
- def makeOrder(points, point1, point2):
- intersectionPoints = points
- sx = sign(point1.coords[0], point2.coords[0])
- sy = sign(point1.coords[1], point2.coords[1])
- if sx > 0:
- intersectionPoints.sort(key=lambda x: x.coords[0])
- elif sx < 0:
- intersectionPoints.sort(key=lambda x: -x.coords[0])
- else:
- if sy > 0:
- intersectionPoints.sort(key=lambda x: x.coords[1])
- else:
- intersectionPoints.sort(key=lambda x: -x.coords[1])
- return intersectionPoints
- def background():
- glClearColor(1.0, 1.0, 1.0, 1.0)
- glClear(GL_COLOR_BUFFER_BIT)
- def chngCoordf(point):
- width = 640
- height = 480
- x = point[0] * 2 / width - 1
- y = point[1] * 2 / height - 1
- return x, y
- def drawShape(points, pointsCount, color, type):
- glBegin(type)
- glColor3f(color[0], color[1], color[2])
- for i in range(pointsCount):
- x, y = chngCoordf(points[i].coords)
- glVertex(x, y)
- glEnd()
- def drawLines(points, count, color):
- glBegin(GL_LINE_STRIP)
- glColor3f(color[0], color[1], color[2])
- for i in range(count):
- x, y = chngCoordf(points[i].coords)
- glVertex2f(x, y)
- glEnd()
- def drawLine(point1, point2, color):
- x1, y1 = chngCoordf(point1.coords)
- x2, y2 = chngCoordf(point2.coords)
- glBegin(GL_LINES)
- glColor3f(color[0], color[1], color[2])
- glVertex2f(x1, y1)
- glVertex2f(x2, y2)
- glEnd()
- def draw():
- glPointSize(1)
- glLineWidth(3)
- if not polygon.isEmpty():
- if polygon.size == 1:
- if polygon.isSbjReady:
- drawShape(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0], GL_POLYGON)
- else:
- drawLines(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0])
- else:
- drawShape(polygon.points[0], polygon.sizes[0], [0.0, 0.0, 0.0], GL_POLYGON)
- if polygon.isHolesReady:
- for i in range(1, polygon.size):
- drawShape(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0], GL_POLYGON)
- else:
- for i in range(1, polygon.size - 1):
- drawShape(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0], GL_POLYGON)
- for i in range(polygon.size - 1, polygon.size):
- drawLines(polygon.points[i], polygon.sizes[i], [1.0, 1.0, 1.0])
- if not clip.isEmpty():
- if clip.isClipReady:
- for i in range(clip.size):
- drawLine(clip.points[i], clip.points[(i + 1) % clip.size], [0, 0, 1.0])
- else:
- for i in range(clip.size):
- drawLines(clip.points, clip.size, [0.0, 0.0, 1.0])
- if not intersectionShapes.isEmpty():
- if not isWhite:
- for i in range(intersectionShapes.size):
- drawShape(intersectionShapes.points[i], intersectionShapes.sizes[i], [1.0, 0.0, 0.0], GL_LINE_LOOP)
- class Drawer:
- window = False
- def __init__(self):
- if not glfw.init():
- return
- self.window = glfw.create_window(640, 480, "Lab5", None, None)
- if not self.window:
- glfw.terminate()
- return
- glfw.make_context_current(self.window)
- glfw.set_mouse_button_callback(self.window, mouseCallback)
- glfw.set_key_callback(self.window, keyCallback)
- def startLoop(self):
- while not glfw.window_should_close(self.window):
- background()
- draw()
- glfw.swap_buffers(self.window)
- glfw.poll_events()
- glfw.terminate()
- polygon = Polygon()
- clip = Clip()
- intersectionShapes = IntersectionShapes()
- drawer = Drawer()
- drawer.startLoop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement