summaryrefslogtreecommitdiff
path: root/Graph.py
diff options
context:
space:
mode:
Diffstat (limited to 'Graph.py')
-rw-r--r--Graph.py121
1 files changed, 121 insertions, 0 deletions
diff --git a/Graph.py b/Graph.py
new file mode 100644
index 0000000..49f0378
--- /dev/null
+++ b/Graph.py
@@ -0,0 +1,121 @@
+import math
+import random
+import pygame
+from parse import parse_input
+from Node import Node
+from globals import *
+
+def createColorFromString(s):
+ i = hash(s)
+ r = (i & 0xFF0000) >> 16
+ g = (i & 0x00FF00) >> 8
+ b = (i & 0x0000FF) + 125;
+ return (r,g,b%125 + 100)
+
+def generateRandomVelocity():
+ dx = random.uniform(NODE_MIN_VEL, NODE_MAX_VEL)
+ dy = random.uniform(NODE_MIN_VEL, NODE_MAX_VEL)
+ randomVelocity = (dx, dy)
+ return randomVelocity
+
+class Graph(object):
+ # A directed graph which contains nodes
+ def __init__(self, surface, nodes=[], links=[], file=""):
+ self.surface = surface
+ self.nodes = nodes
+ self.links = links
+ self.hashLink= {} # This will provide faster access to links
+ self.file = file
+ self.font = pygame.font.SysFont(None, 15)
+
+ self.nodesUnderMouse = []
+
+ def fromFile(self, initializeWithRandomVels=True):
+ # Parse from file
+ self.nodes, self.links = parse_input(self.file)
+
+ # Set the position of each node
+ square = math.ceil(math.sqrt(len(self.nodes)))
+ for i in range(square):
+ for j in range(square):
+ if (i*square + j < len(self.nodes)):
+ self.nodes[i*square + j].pos = (int((WIDTH)/(square) * i + 20), int((HEIGHT)/(square) * j + 20))
+ if (initializeWithRandomVels):
+ self.nodes[i*square + j].vel = generateRandomVelocity()
+ else:
+ self.nodes[i*square + j].vel = (0, 0)
+ self.nodes[i*square + j].color = createColorFromString(self.nodes[square*i + j].text)
+
+
+ def updateNodePositions(self, dt):
+ for i in self.nodes:
+ i.update(dt) # Update the position for velocity
+
+ def randomNodes(self):
+ # Populate nodes with random ones
+ for i in range(10):
+ for j in range(10):
+ position = (20 + i * 80, 20 + j * 80)
+ color=random.choice([RED,GREEN,BLUE])
+ radius=random.randint(5, 15)
+ text=random.choice(list("ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
+ self.nodes.append(Node(position, generateRandomVelocity(), color, radius, text))
+
+ def randomLinks(self):
+ for i in range(random.randint(1, 1000)):
+ # Each link is (source, destination, weight)
+ self.links.append((random.choice(self.nodes), random.choice(self.nodes), 1, "BRUH"))
+
+ def updateHashLinks(self):
+ # This will also calculate the radius for each node
+ for i in self.links:
+ # Hash links appear in the dictionary as:
+ # source_node : [(node1, weight1, description1), (node2, weight2, description2)]
+ if (i[0] not in self.hashLink.keys()):
+ self.hashLink[i[0]] = []
+ self.hashLink[i[0]].append((i[1], i[2], i[3]))
+ for i in self.nodes:
+ if (i in self.hashLink.keys()):
+ i.radius = max(min(len(self.hashLink[i]), NODE_MAX_RADIUS), NODE_MIN_RADIUS)
+ else:
+ # The node has no outer links
+ i.radius = NODE_MIN_RADIUS
+
+ def drawLinks(self, node):
+ # Draw all of the links from one node to all of its neighbors
+ if (node in self.hashLink.keys()):
+ for i in self.hashLink[node]:
+ pygame.gfxdraw.line(self.surface, int(node.pos[0]), int(node.pos[1]), int(i[0].pos[0]), int(i[0].pos[1]), RED)
+ midPoint = ((i[0].pos[0] + node.pos[0])/2, (i[0].pos[1] + node.pos[1])/2)
+ render=self.font.render(i[0].text, True, WHITE)
+ self.surface.blit(render, midPoint)
+ render=self.font.render(i[2], True, WHITE)
+ self.surface.blit(render, (midPoint[0] + 10, midPoint[1]+10))
+ else:
+ for i in self.links:
+ if i[0] == node:
+ pygame.gfxdraw.line(self.surface, int(node.pos[0]), int(node.pos[1]), int(i[1].pos[0]), int(i[1].pos[1]), RED)
+ midPoint = (abs(i[1].pos[0] + node.pos[0])/2, abs(i[1].pos[1] + node.pos[1])/2)
+ render=self.font.render(i[1].text, True, WHITE)
+ self.surface.blit(render, midPoint)
+ render=self.font.render(i[3], True, WHITE)
+ self.surface.blit(render, (midPoint[0] + 10, midPoint[1]+10))
+
+ def draw(self):
+ # Draw the graph for i in nodes:
+ mouseX = pygame.mouse.get_pos()[0]
+ mouseY = pygame.mouse.get_pos()[1]
+
+ if (self.nodesUnderMouse):
+ # If the node is under the mouse draw the links and the node
+ # content
+ for i in self.nodesUnderMouse:
+ self.drawLinks(i)
+ node=i
+ render=self.font.render(node.text, True, WHITE)
+ self.surface.blit(render, (node.pos[0]+node.radius, node.pos[1]+node.radius))
+
+ # Now we can finally draw the nodes!
+ for i in self.nodes:
+ i.draw(self.surface)
+