def test_diff(self): x1, y1 = 42, 24 x2, y2 = 0.1, -0.3 a = Point(x1, y1) b = Point(x2, y2) self.assertEqual((x1 - x2, y1 - y2), a - b)
def test_sum(self): x1, y1 = 42, 24 x2, y2 = 0.1, -0.3 a = Point(x1, y1) b = Point(x2, y2) self.assertEqual((x1 + x2, y1 + y2), a + b)
def reset(self): super(SpringLayout, self).reset() # set random initial positions for vertex in range(len(self._graph.vertices)): self.set_unlocked_location( vertex, Point(self.size.x * random.random(), self.size.y * random.random())) self._velocities = dict.fromkeys( list(range(len(self._graph.vertices))), Point())
def _on_drag(self, event): if self._click is not None: if self._click_id is not None: picked = self._picked_state.get_picked() if picked: for vertex in picked: self._canvas.move_vertex(vertex, Point(event.x, event.y) - self._click) self._click = Point(event.x, event.y) else: x0, x1 = graph.ordered_pair(self._selection.x, event.x) y0, y1 = graph.ordered_pair(self._selection.y, event.y) self._canvas.coords(self._selection_rect, x0, y0, x1, y1)
def step(self, time_step=0.2): """Calculates position of vertices after a lapse of `time_step' after last position. """ for vertex in range(len(self._graph.vertices)): force = Point() # repulsion between vertices for other in range(len(self._graph.vertices)): if other == vertex: continue force += self._repulsion_force(vertex, other) # attraction between edges' ends for other in self._graph.neighbors(vertex): force += self._attraction_force(vertex, other) # border contact force def transform_force(coord, right_border, f): if coord == 0: return max(0, f) if coord == right_border: return min(0, f) return f force = Point( transform_force(self[vertex].x, self.size.x, force.x), transform_force(self[vertex].y, self.size.y, force.y)) vel = self._damping * (self._velocities[vertex] + time_step * force) vel = Point(transform_force(self[vertex].x, self.size.x, vel.x), transform_force(self[vertex].y, self.size.y, vel.y)) # here we constrain maximal speed step_distance_x = math.fabs(vel.x) * time_step if step_distance_x > self.size.x * 0.1: vel *= 0.1 * self.size.x / step_distance_x step_distance_y = math.fabs(vel.y) * time_step if step_distance_y > self.size.y * 0.1: vel *= 0.1 * self.size.x / step_distance_y self._velocities[vertex] = vel # this is to prevent going behind borders: fx = lambda a: min(max(0, a), self.size.x) fy = lambda b: min(max(0, b), self.size.y) p = self[vertex] + time_step * vel # next position of vertex self.set_unlocked_location(vertex, Point(fx(p.x), fy(p.y)))
def move_vertex(self, vertex, v): """Move `vertex' by vector `v' """ id = vertex.shape.id self.move(id, v.x, v.y) canvas_location = self._get_shape_center(id) layout_location = self._convert_canvas_location(canvas_location) self._layout[self.graph.index(vertex.value)] = layout_location self._update_vertex_label_location(vertex) # move edges ends for edge in vertex.incident: if vertex is edge.start: self._move_edge(edge, v, Point()) else: self._move_edge(edge, Point(), v)
def test_mult(self): x, y = 4.2, 2.4 a = Point(x, y) c = 10 self.assertEqual((float(x) * c, float(y) * c), a * c) self.assertEqual((float(x) * c, float(y) * c), c * a)
def test_setLocation(self): self.assertEquals((0.42, 0.42), self.layout[0]) self.layout[1] = Point(1, 1) self.assertEquals((1, 1), self.layout[1]) self.layout.reset() self.assertEquals((0.42, 0.42), self.layout[1])
def __getitem__(self, vertex): if vertex not in self.__locations: self.set_unlocked_location( vertex, Point(self.size.x * random.random(), self.size.y * random.random())) return self.__locations[vertex]
def reset(self): super(CircleLayout, self).reset() step = 2 * math.pi / len(self.graph.vertices) r = self._radius for i in range(len(self._graph.vertices)): v = Point(math.sin(step * i), math.cos(step * i)) self.set_unlocked_location(i, self._center + r * v)
def _on_configure(self): """Updates layout space size so that it fits the canvas. Called on every change of canvas size. """ self._layout.size = Point(self.winfo_width() - 2 * self.__margin, self.winfo_height() - 2 * self.__margin) if self._caption: self.coords(self._caption, 10, self.winfo_height() - 10)
def _on_press(self, event): self._click = Point(event.x, event.y) self._click_id = None id = self._canvas.get_object_id_by_location(self._click) if self._canvas.is_vertex(id): self._click_id = id vertex = self._canvas._get_vertex_by_shape_id(id) if (not self._picked_state.is_picked(vertex) and not event.state & 1): self._picked_state.clear() self._picked_state.pick(vertex) else: if not event.state & 1: self._picked_state.clear() self._selection = Point(event.x, event.y) self._selection_rect = self._canvas.create_rectangle( event.x, event.y, event.x, event.y, **SELECTION_KW)
def get_label_vector(self, vertex): """Returns identity vector locating the side of vertex where the density of edges is the least. """ default = Point(0, 1) edgeVec = lambda neighbor: (self[vertex] - self[neighbor]).identity() return reduce(lambda x, y: x + y, list(map(edgeVec, self._graph.neighbors(vertex))), default).identity()
def __init__(self, canvas, radius, location=Point(), **kw): super(CircleShape, self).__init__(canvas) r = radius self._radius = radius x, y = location.x, location.y self._id = canvas.create_oval(x - r, y - r, x + r, y + r, fill="white", **kw)
def _repulsion_force(self, vertex, other): r = (self[vertex] - self[other]).square() if r == 0.0: return Point() #random(), random()) c = 10**6 * self._electric_rate / (r**1.5) return (self[vertex] - self[other]) * c
def test_scalar_product(self): a = Point(2, 3) b = Point(0.1, 0.2) self.assertEqual(a.x * b.x + a.y * b.y, a * b)
def __init__(self, graph, r, center=(50, 50), **kw): super(CircleLayout, self).__init__(graph, **kw) self._center = Point(*center) self._radius = r self.reset()
def __init__(self, graph, default_location=Point(), width=400, height=400): self.size = Point(width, height) self._locked = set() self._graph = graph self.__locations = dict() self._defaultLocation = default_location
def _get_shape_center(self, id): x, y, x1, y1 = self.coords(id) return (Point(x, y) + Point(x1, y1)) / 2
def _get_shape_radius(self, id): x, y, x1, y1 = self.bbox(id) return (Point(x1, y1) - Point(x, y)).square()**0.5 / 2
def test_div(self): x, y = 3, 4 a = Point(x, y) c = 2 self.assertEqual((float(x) / c, float(y) / c), a / c)
def _update_layout_size(self): """Updates layout space size so that it fits the canvas. Called on every change of canvas size. """ self._layout.size = Point(self.winfo_width() - 2 * self.__margin, self.winfo_height() - 2 * self.__margin)
def _attraction_force(self, vertex, other): r = (self[vertex] - self[other]).square()**0.5 if r == 0.0: return Point() c = 10 * self._spring_rate * (self._spring_length - r) / r return (self[vertex] - self[other]) * c
def test_neg(self): x, y = 1, 2 a = Point(x, y) self.assertEqual((-x, -y), -a)
def _convert_layout_location(self, location): """Converts layout coordinates to canvas coordinates """ margin = self.__margin return Point(margin + location.x, margin + location.y)
def _convert_canvas_location(self, location): """Converts canvas coordinates to layout coordinates """ x, y = location margin = self.__margin return Point(x - margin, y - margin)
def test_square(self): a = Point(4, 5) self.assertEqual(a.x * a.x + a.y * a.y, a.square())