You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

262 lines
6.8 KiB

3 years ago
  1. #!/usr/bin/python
  2. #Import required libraries
  3. import sys
  4. import os
  5. from PIL import Image, ImageDraw, ImageShow, ImageFont
  6. import math
  7. import psutil
  8. import time
  9. from collections import defaultdict
  10. class Node:
  11. def __init__(self, rect, colour, index, node_size):
  12. self.rect = [rect[0], rect[1], rect[0] + node_size, rect[1] + node_size]
  13. self.pos = ((self.rect[0] + self.rect[2])/2, (self.rect[1] + self.rect[3])/2)
  14. self.colour = colour
  15. self.index = index
  16. def colour(index):
  17. array = ["red", "blue", "green"]
  18. return array[index % len(array)]
  19. class Sxiv(ImageShow.UnixViewer):
  20. def get_command_ex(self, file, **options):
  21. return ("bspc rule -a \* -o state=floating focus=off && sxiv",) * 2
  22. node_size = 10
  23. m, n = 600, 600
  24. nodes = []
  25. num_nodes = 9
  26. assert(num_nodes % 3 == 0)
  27. ImageShow.register(Sxiv(), -1)
  28. font = ImageFont.truetype("Hack-Bold.ttf", node_size*3)
  29. im = Image.new('RGB', (m, n))
  30. draw = ImageDraw.Draw(im)
  31. draw.rectangle([0, 0, m, n], "white")
  32. x_step = math.floor(m / num_nodes) - 10
  33. y_step = math.floor(n / num_nodes) - 10
  34. centerX = math.floor(m/2)
  35. centerY = math.floor(n/2)
  36. step = -math.floor(360 / num_nodes)
  37. radius = math.floor(n/2.5)
  38. for i in range(0, num_nodes):
  39. angle = (i * step)
  40. coordinates = [centerX + radius*math.cos(math.radians(angle)), centerY + radius*math.sin(math.radians(angle))]
  41. nodes.append(Node(coordinates, colour(i), i, node_size))
  42. for i,node in enumerate(nodes):
  43. draw.rectangle(node.rect, fill=node.colour)
  44. draw.text(node.pos, str(node.index),font=font, fill="black")
  45. def connect_tuple(d, e):
  46. connect(d, e[0], e[1])
  47. def connect(d, v, w):
  48. d.line([v.pos, w.pos], fill="black", width=math.floor(node_size/4))
  49. def draw_tree(edges):
  50. local = im.copy()
  51. d = ImageDraw.Draw(local)
  52. for e in edges:
  53. connect(d, e[0], e[1])
  54. local.show()
  55. def sort_edges(edges):
  56. return sorted(edges, key = lambda x: (x[0].index, x[1].index))
  57. def to_indices(edge):
  58. return (edge[0].index, edge[1].index)
  59. def list_to_indices(edges):
  60. e = []
  61. for edge in edges:
  62. e.append(to_indices(edge))
  63. return e
  64. def has_crossing(edge, edges):
  65. new = to_indices(edge)
  66. if(new[0] > new[1]):
  67. new = new[::-1]
  68. for e in edges:
  69. exis = to_indices(e)
  70. if(exis[0] > exis[1]):
  71. exis = exis[::-1]
  72. if(exis[0] < new[0] < exis[1] and new[1] > exis[1]):
  73. return True
  74. if(exis[0] < new[1] < exis[1] and new[0] < exis[0]):
  75. return True
  76. return False
  77. def dfs(parents, visited, adj, node):
  78. visited.add(node)
  79. for adj_node in adj[node]:
  80. if adj_node not in visited:
  81. parents[adj_node] = node
  82. dfs(parents, visited, adj, adj_node)
  83. elif parents[node] != adj_node:
  84. return True
  85. def has_cycle(new_edge, edges):
  86. adj = defaultdict(set)
  87. es = [to_indices(e) for e in edges]
  88. es.append(to_indices(new_edge))
  89. for x, y in es:
  90. adj[x].add(y)
  91. adj[y].add(x)
  92. visited = set()
  93. parents = [None] * len(adj)
  94. if dfs(parents, visited, adj, to_indices(new_edge)[0]):
  95. return True
  96. return False
  97. def construct_neighbourhood(edges, index):
  98. neighbourhood = []
  99. i = 0
  100. #print(list_to_indices(edges))
  101. for e in edges:
  102. start = e[0].index
  103. #print("Testing: " + str(to_indices(e)))
  104. for new_target in range(start + 1, num_nodes):
  105. new_edge = (e[0], nodes[new_target])
  106. if(e == new_edge): continue
  107. cropped_edges = edges[:]
  108. cropped_edges.remove(e)
  109. #print(list_to_indices(cropped_edges))
  110. #print(to_indices(new_edge))
  111. #input()
  112. if(new_target % 3 == e[0].index % 3):
  113. #print("isn't bicolored")
  114. continue
  115. if(has_crossing(new_edge, cropped_edges)):
  116. #print("has_crossing")
  117. continue
  118. if(has_cycle(new_edge, cropped_edges)):
  119. #print("has_cycle")
  120. continue
  121. cropped_edges.append(new_edge)
  122. #print("Added: " + str(list_to_indices(cropped_edges)))
  123. neighbourhood.append(sort_edges(cropped_edges))
  124. if(i == index):
  125. return neighbourhood
  126. i = i + 1
  127. return neighbourhood
  128. def degree(edges):
  129. #print("degree...")
  130. l = len(construct_neighbourhood(edges, sys.maxsize))
  131. #print("done...")
  132. return l
  133. def get_jth_neighbour(edges, index):
  134. #print("Getting index: " + str(index))
  135. return construct_neighbourhood(edges, index)[index]
  136. def is_from_root(edge):
  137. return abs(edge[0] - edge[1]) == 1
  138. def get_largest_non_root_edge(edges):
  139. edges.reverse()
  140. print(edges)
  141. for e in edges:
  142. if not is_from_root(e):
  143. return e
  144. return edges
  145. def get_largest_missing_convex_edge(edges):
  146. difference = [e for e in root_tuples if e not in edges]
  147. return difference[-1]
  148. def get_parent(edges):
  149. sorted_edges = list_to_indices(sort_edges(edges))
  150. e = get_largest_non_root_edge(sorted_edges)
  151. if type(e) is list: return list_to_indices(edges)
  152. sorted_edges.remove(e)
  153. sorted_edges.append(get_largest_missing_convex_edge(sorted_edges))
  154. return sorted_edges
  155. def get_parent_in_nodes(edges):
  156. parent = get_parent(edges)
  157. p = []
  158. for e in parent:
  159. p.append((nodes[e[0]], nodes[e[1]]))
  160. return sort_edges(p)
  161. root = []
  162. for i in range(0, num_nodes - 1):
  163. root.append((nodes[i], nodes[i+1]))
  164. root_tuples = list_to_indices(root)
  165. draw_tree(root)
  166. assert(False)
  167. v = root
  168. j = 0
  169. count = 1
  170. while True:
  171. print("Current v: " + str(list_to_indices(v)))
  172. deg = degree(v)
  173. print(" degree = " + str(deg))
  174. while(j != deg):
  175. j = j + 1
  176. w = sort_edges(get_jth_neighbour(v, j - 1))
  177. if(sort_edges(get_parent_in_nodes(w)) == sort_edges(v)):
  178. print("\t " + str(list_to_indices(w)))
  179. print("\t parent: " + str(list_to_indices(get_parent_in_nodes(w))))
  180. v = w
  181. j = 0
  182. count = count + 1
  183. print(" Current w:" + str(list_to_indices(v)))
  184. print(" degree = " + str(deg) + " j = " + str(j))
  185. deg = degree(v)
  186. if(v != root):
  187. w = v
  188. v = get_parent_in_nodes(w)
  189. j = 0
  190. neighbours = construct_neighbourhood(v, sys.maxsize)
  191. n = neighbours[j]
  192. while(n != w):
  193. j = j + 1
  194. n = neighbours[j]
  195. input()
  196. if(v == root and j == degree(root)):
  197. print(list_to_indices(v))
  198. print(j)
  199. break
  200. #while True:
  201. # for tree in construct_neighbourhood(root, sys.maxsize):
  202. # im1 = im.copy()
  203. # d = ImageDraw.Draw(im1)
  204. # draw_tree(d, tree)
  205. # im1.show()
  206. #
  207. # input()
  208. # #for proc in psutil.process_iter():
  209. # # if proc.name() == "sxiv":
  210. # # proc.kill()
  211. # assert(False)