diff options
Diffstat (limited to 'bin/pychart/arrow.py')
| -rw-r--r-- | bin/pychart/arrow.py | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/bin/pychart/arrow.py b/bin/pychart/arrow.py new file mode 100644 index 00000000000..e0b931fb8a2 --- /dev/null +++ b/bin/pychart/arrow.py @@ -0,0 +1,184 @@ +# +# Copyright (C) 2000-2005 by Yasushi Saito (yasushi.saito@gmail.com) +# +# Jockey is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any +# later version. +# +# Jockey is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# for more details. +# +import line_style +import color +import chart_object +import object_set +import math +import arrow_doc +import canvas + +from pychart_types import * +from types import * +from scaling import * + +__doc__ = """ +Arrow is an optional component of a chart that draws line segments with +an arrowhead. To draw an arrow, one creates an arrow.T object, and calls +its "draw" method usually after area.draw() is called (otherwise, area.draw() +may overwrite the arrow). For example, the below code draws an arrow +from (10,10) to (20,30). + +ar = area.T(...) +a = arrow.T(head_style = 1) +ar.draw() +a.draw([(10,10), (20,30)]) +""" + +def draw_arrowhead(can, tailx, taily, tipx, tipy, thickness, head_len, style): + can.comment("ARROWHEAD tail=(%d,%d) tip=(%d,%d)\n" + % (tailx, taily, tipx, tipy)) + + halfthickness = thickness/2.0 + dx = tipx - tailx + dy = tipy - taily + arrow_len = math.sqrt(dx*dx + dy*dy) + angle = math.atan2(dy, dx) * 360 / (2*math.pi) + base = arrow_len - head_len + can.push_transformation((tailx, taily), None, angle) + + can.newpath() + if style == 0: + can.moveto(base, - halfthickness) + can.lineto(base, halfthickness) + can.lineto(arrow_len, 0) + can.closepath() + elif style == 1: + depth = head_len / 2.5 + can.moveto(base - depth, -halfthickness) + can.lineto(base, 0) + can.lineto(base - depth, halfthickness) + can.lineto(arrow_len, 0) + can.closepath() + elif style == 2: + can.moveto(base + head_len/2.0, 0) + can.path_arc(base + head_len / 2.0, 0, head_len / 2.0, 1.0, 0, 400) + elif style == 3: + can.moveto(base, 0) + can.lineto(base + head_len/2.0, -halfthickness) + can.lineto(arrow_len, 0) + can.lineto(base + head_len/2.0, halfthickness) + can.closepath() + else: + raise Exception, "Arrow style must be a number between 0 and 3." + can.fill() + can.pop_transformation() + can.comment("end ARROWHEAD.\n") + +def draw_arrowbody(can, tailx, taily, tipx, tipy, head_len): + dx = tipx - tailx + dy = tipy - taily + arrow_len = math.sqrt(dx*dx + dy*dy) + angle = math.atan2(dy, dx) * 360 / (2*math.pi) + base = arrow_len - head_len + can.push_transformation((tailx, taily), None, angle) + can.moveto(0, 0) + can.lineto(base+head_len*0.1, 0) + can.stroke() + can.pop_transformation() + + +class T(chart_object.T): + __doc__ = arrow_doc.doc + keys = { + "thickness" : (UnitType, 4, + "The width of the arrow head."), + "head_len": (UnitType, 8, + "The length of the arrow head."), + "head_color": (color.T, color.default, + "The color of the arrow head."), + "line_style": (line_style.T, line_style.default, + "Line style."), + "head_style": (IntType, 1, + "The value of 0 draws a triangular arrow head. The value of 1 draws a swallow-tail arrow head. The value of 2 draws a circular head. The value of 3 draws a diamond-shaped head.") + } +##AUTOMATICALLY GENERATED + +##END AUTOMATICALLY GENERATED + def draw(self, points, can = None): + """Parameter <points> specifies the + list of points the arrow traverses through. + It should contain at least two points, i.e., + the tail and tip. Parameter + <can> is an optional parameter that specifies the output. + <<canvas>> + """ + if can == None: can = canvas.default_canvas() + self.type_check() + xtip = points[-1][0] + ytip = points[-1][1] + + xtail = points[-2][0] + ytail = points[-2][1] + + can.newpath() + can.set_line_style(self.line_style) + if len(points) > 2: + can.moveto(points[0][0], points[0][1]) + for i in range(1, len(points)-1): + can.lineto(points[i][0], points[i][1]) + + draw_arrowbody(can, xscale(xtail), yscale(ytail), + yscale(xtip), yscale(ytip), + nscale(self.head_len)) + + can.set_fill_color(self.head_color) + draw_arrowhead(can, xscale(xtail), yscale(ytail), + xscale(xtip), yscale(ytip), + nscale(self.thickness), + nscale(self.head_len), + self.head_style) + + can.setbb(xtail, ytail) + can.setbb(xtip, ytip) + +standards = object_set.T() +def _intern(a): + global standards + standards.add(a) + return a + +a0 = _intern(T(head_style=0)) +a1 = _intern(T(head_style=1)) +a2 = _intern(T(head_style=2)) +a3 = _intern(T(head_style=3)) +gray0 = _intern(T(head_style=0, head_color = color.gray50, + line_style=line_style.T(color=color.gray50))) +gray1 = _intern(T(head_style=1, head_color = color.gray50, + line_style=line_style.T(color=color.gray50))) +gray2 = _intern(T(head_style=2, head_color = color.gray50, + line_style=line_style.T(color=color.gray50))) +gray3 = _intern(T(head_style=3, head_color = color.gray50, + line_style=line_style.T(color=color.gray50))) + +fat0 = _intern(T(head_style=0, head_len=12, thickness=10, line_style=line_style.T(width=2))) +fat1 = _intern(T(head_style=1, head_len=12, thickness=10, line_style=line_style.T(width=2))) +fat2 = _intern(T(head_style=2, head_len=12, thickness=10, line_style=line_style.T(width=2))) +fat3 = _intern(T(head_style=3, head_len=12, thickness=10, line_style=line_style.T(width=2))) +fatgray0 = _intern(T(head_style=0, head_len=12, thickness=10, + head_color = color.gray50, + line_style=line_style.T(width=2, color=color.gray50))) +fatgray1 = _intern(T(head_style=1, head_len=12, thickness=10, + head_color = color.gray50, + line_style=line_style.T(width=2, color=color.gray50))) +fatgray2 = _intern(T(head_style=2, head_len=12, thickness=10, + head_color = color.gray50, + line_style=line_style.T(width=2, color=color.gray50))) +fatgray3 = _intern(T(head_style=3, head_len=12, thickness=10, + head_color = color.gray50, + line_style=line_style.T(width=2, color=color.gray50))) + +default = a1 + + |
