class Line(Lines): def __init__(self, x, y, formatter=None): super(Line, self).__init__(x, y, formatter=formatter) def __repr__(self): return 'Line at <%s>' % id(self) def __len__(self): return len(self.objects) @property def origin(self): self.coord = Coordinates(self.x, self.y) return self.coord @property def end(self): x = self.objects[-1].coord.x y = self.objects[-1].coord.y self.coord = Coordinates(x, y) return self.coord @property def length(self): return len(self) def add_point(self, p): self.objects.add(p) def update_graph(self, w=1, h=1): self.graph = Graph(w=w, h=h) origin = self.origin for obj in self.objects: obj.coord -= origin self.graph.add_graph(obj)
class Canvas(GraphicObject): def __init__(self, w, h): super(Canvas, self).__init__() self.draw = Draw(self) self.w = w self.h = h self.reset() def add_object(self, obj, x=None, y=None, coord=None): if not coord is None: obj.set_coordinates(coord) elif x is not None and y is not None: obj.set_coordinates(x, y) self.objects.add(obj) def remove_object(self, key): self.objects.remove(key) def reset(self): self.objects = GraphicObjectArray() self.reset_graph() def reset_graph(self): self.graph = Graph(w=self.w, h=self.h) def show(self, axes=False, frame=False, frame_formatter=None): self.update_graph() self.graph.print(axes=axes, frame=frame, frame_formatter=frame_formatter) def undo(self): self.objects.remove(-1) def update_graph(self): self.reset_graph() for obj in self.objects: try: obj.update() except: pass self.graph.add_objects(self.objects)
class Route(Lines): def __init__(self, transparent=True): super(Route, self).__init__(transparent=transparent) self.objects = GraphicObjectArray() def __repr__(self): return 'Route at <%s>' % id(self) def __len__(self): return len(self.objects) @property def origin(self): x = min([obj.coord.x for obj in self.objects]) y = min([obj.coord.y for obj in self.objects]) return Coordinates(x, y) @property def h(self): return (max([obj.coord.y for obj in self.objects]) - min([obj.coord.y for obj in self.objects]) + 1) @property def w(self): return (max([obj.coord.x for obj in self.objects]) - min([obj.coord.x for obj in self.objects]) + 1) def add_point(self, p): self.objects.add(p) def create_route(self, *points, marker='.', origin_marker='.', formatter=None, origin_formatter=None): for point, next_point in zip(points[0:-1], points[1:]): point.set_marker(marker) point.set_formatter(formatter) self.connect(point, next_point) # edit origins self.objects[0].set_marker(origin_marker) self.objects[0].set_formatter(origin_formatter) self.objects[-1].set_marker(origin_marker) self.objects[-1].set_formatter(origin_formatter) self.coord = self.origin self.update() def connect(self, p1, p2): current_point = p1 target_point = p2 arrived = current_point == target_point self.add_point(current_point) while not arrived: next_points = [current_point + m for m in movements] distances = [calc_distance(p, target_point) for p in next_points] idx = distances.index(min(distances)) current_point += movements[idx] self.add_point(current_point) arrived = current_point == target_point def update(self): self.graph = Graph(w=self.w, h=self.h) origin = self.origin for obj in self.objects: obj.coord -= origin self.graph.add_graph(obj)
def update_graph(self, w=1, h=1): self.graph = Graph(w=w, h=h) origin = self.origin for obj in self.objects: obj.coord -= origin self.graph.add_graph(obj)
def update(self): self.graph = Graph(w=self.w, h=self.h) origin = self.origin for obj in self.objects: obj.coord -= origin self.graph.add_graph(obj)
def reset_graph(self): self.graph = Graph(w=self.w, h=self.h)
def update_graph(self): self.graph = Graph(w=self.w, h=self.h) for obj in self.objects: self.graph.add_graph(obj)
class Text(GraphicObject): def __init__(self, x=0, y=0, transparent=True, formatter=None, alignment='center', text=None): super(Text, self).__init__(x, y, transparent) self.formatter = formatter self.objects = GraphicObjectArray() self.alignment = alignment if text is not None: self.write(text) @property def origin(self): self.coord = Coordinates(self.x, self.y) return self.coord def add_point(self, p): self.objects.add(p) def align(self, alignment=None): def calc_offset(w, sz): if self.alignment == 'center': return int((w - sz) / 2) elif self.alignment == 'right': return w - sz elif self.alignment == 'left': return 0 if alignment is None: alignment = self.alignment else: self.alignment = alignment w = self.w h = self.h objects_list = [[obj for obj in self.objects if obj.y == i] for i in range(h)] for lst in objects_list: x0 = lst[0].x sz = len(lst) offset = calc_offset(w, sz) - x0 for obj in lst: obj.coord.x += offset self.update_graph() def format_text(self, formatter=None): if formatter is not None: self.formatter = formatter for obj in self.objects: obj.set_formatter(self.formatter) self.update_graph() def update_graph(self): self.graph = Graph(w=self.w, h=self.h) for obj in self.objects: self.graph.add_graph(obj) def write(self, text): if isinstance(text, (list, tuple)): w = max([len(t) for t in text]) h = len(text) self.set_y(self.y - (h - 1)) for j, txt in enumerate(text): j_ = (h - 1) - j for i, t in enumerate(txt): p = Point(i, j_, marker=t) self.add_point(p) elif isinstance(text, str): w = len(text) h = 1 for i, t in enumerate(text): p = Point(i, 0, marker=t) self.add_point(p) else: raise TypeError("'text' must be s string or a list of strings") self.w = w self.h = h self.format_text() self.align()
def set_marker(self, marker): self.marker = marker[0] self.graph = Graph(self.formatter.format(self.marker))