summaryrefslogtreecommitdiff
path: root/sandbox/cliechti/aafigure/aa.py
blob: 69d62b4fd02589f072b2de58958e71f8627ad702 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
"""
Simple ASCII output of the rendered image.
Think of it as a low resolution black and white image.

(C) 2006 Chris Liechti <cliechti@gmx.net>
"""

import sys

class AsciiOutputVisitor:
    """Render a list of shapes as ASCII art.
       Scaled, think of it as a low resolution black and white image
    """
    
    def __init__(self, scale=3):
        self.image = {}
        self.scale = scale
    
    def visit(self, aa_image):
        for shape in aa_image.shapes:
            shape_name = shape.__class__.__name__.lower()
            visitor_name = 'visit_%s' % shape_name
            if hasattr(self, visitor_name):
                getattr(self, visitor_name)(shape)
            else:
                print "don't know how to handle shape %r" % shape

    def visit_point(self, point):
        self.image[point.x*self.scale, point.y*self.scale] = '#'

    def visit_line(self, line):
        x1, x2 = line.start.x*self.scale, line.end.x*self.scale
        y1, y2 = line.start.y*self.scale, line.end.y*self.scale
        if x1 > x2: x1, x2 = x2, x1
        if y1 > y2: y1, y2 = y2, y1
        dx = x2 - x1
        dy = y2 - y1
        if dx > dy:
            y = y1
            if dx:
                m = float(dy)/dx
            else:
                m = 0
            for x in range(x1, x2+1):
                self.image[x,int(y)] = '#'
            y += m
        else:
            x = x1
            if dy:
                m = float(dx)/dy
            else:
                m = 0
            for y in range(y1, y2+1):
                self.image[int(x),y] = '#'
            x += m
        if line.start_style:
            self.image[line.start.x*self.scale,line.start.y*self.scale] = 'O'
        if line.end_style:
            self.image[line.end.x*self.scale,line.end.y*self.scale] = 'O'

    def visit_rectangle(self, rectangle):
        x1, x2 = rectangle.p1.x*self.scale, rectangle.p2.x*self.scale
        y1, y2 = rectangle.p1.y*self.scale, rectangle.p2.y*self.scale
        if x1 > x2: x1, x2 = x2, x1
        if y1 > y2: y1, y2 = y2, y1
        for y in range(y1, y2):
            for x in range(x1, x2):
                self.image[x,y] = '#'
        
    def visit_label(self, label):
        x, y = label.position.x*self.scale, label.position.y*self.scale
        for character in label.text:
            self.image[x, y] = character
            x += 1

    def __str__(self):
        """return a cropped image"""
        #find out size
        min_x = min_y = sys.maxint
        max_x = max_y = -sys.maxint
        for x,y in self.image:
            min_x = min(min_x, x)
            max_x = max(max_x, x)
            min_y = min(min_y, y)
            max_y = max(max_y, y)
        #render image to lines of text, fill unused fields with a dot
        result = []
        for y in range(min_y, max_y+1):
            line = []
            for x in range(min_x, max_x+1):
                line.append(self.image.get((x,y), '.'))
            result.append(''.join(line))
        return '\n'.join(result)