def accelerate(self, n): force = (0.0, 0.0) # attraction for m in n.adj: if n == m: continue delta = vec.sub(n.pos, m.pos) force = vec.sub(force, vec.mul(delta, ATTRACTION)) # repulsion for m in self.nodes: if n == m: continue delta = vec.sub(n.pos, m.pos) dist = vec.norm(delta) if dist <= KICK_DIST and id(n) < id(m): angle = random.uniform(0, 2 * math.pi) kick = vec.rotate2d((KICK_SIZE, 0), angle) n.vel = vec.add(n.vel, kick) m.vel = vec.sub(m.vel, kick) dist = max(dist, MIN_CLOSENESS) delta = vec.mul(delta, REPULSION / (dist ** 3)) force = vec.add(force, delta) n.force = force
def draw_edge(self, n, m, thickness, colour): z1 = self.project(n.pos) z2 = self.project(m.pos) if thickness <= 1: pygame.draw.aaline(self.screen, colour, z1, z2, 1) else: angle = math.atan2(z2[1] - z1[1], z2[0] - z1[0]) delta = vec.rotate2d((thickness / 2.0, 0), angle) delta = (-delta[0], delta[1]) p1 = vec.add(z1, delta) p2 = vec.sub(z1, delta) p3 = vec.sub(z2, delta) p4 = vec.add(z2, delta) pygame.gfxdraw.aapolygon(self.screen, (p1, p2, p3, p4), colour) pygame.gfxdraw.filled_polygon(self.screen, (p1, p2, p3, p4), colour)
def mouse_moved(self, event): if not self.mouse_down: return mouse_pos = pygame.mouse.get_pos() if self.selected_node == None: mouse_pos = vec.mul(mouse_pos, self.viewport.scale) self.viewport.pos = vec.sub(self.pan_grab_pos, mouse_pos) else: self.selected_node.pos = self.unproject(mouse_pos)
def find_node_at(self, pos): self.lock.acquire() try: for n in self.graph.nodes: if vec.norm(vec.sub( n.pos, pos)) <= n.style.value.radius * self.viewport.scale: return n return None finally: self.lock.release()
def project(self, v): viewport_pos = vec.sub(v, self.viewport.pos) return vec.int_round(vec.mul(viewport_pos, 1.0 / self.viewport.scale))