src/reportlab/graphics/charts/utils.py
author robin <robin@reportlab.com>
Tue, 07 Mar 2017 10:00:34 +0000
changeset 4330 617ffa6bbdc8
parent 4252 fe660f227cac
child 4370 823a8c33ce43
permissions -rw-r--r--
changes for release 3.4.0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
4330
617ffa6bbdc8 changes for release 3.4.0
robin <robin@reportlab.com>
parents: 4252
diff changeset
     1
#Copyright ReportLab Europe Ltd. 2000-2017
1555
a0c3e76acdb6 Headers+versioning
rgbecker
parents: 1367
diff changeset
     2
#see license.txt for license details
2332
2a7ab4405e18 Remove $Header:, fix CopyRight & history
rgbecker
parents: 1683
diff changeset
     3
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/charts/utils.py
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3019
diff changeset
     4
4252
fe660f227cac changes for release 3.3.0
robin
parents: 4116
diff changeset
     5
__version__='3.3.0'
3032
22224b1b4d24 New docstrings mainly for module titles
damian
parents: 3019
diff changeset
     6
__doc__="Utilities used here and there."
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
     7
from time import mktime, gmtime, strftime
3566
63166bfc6267 charts/utils.py: use hypot for xyDist
rgbecker
parents: 3534
diff changeset
     8
from math import log10, pi, floor, sin, cos, sqrt, hypot
3534
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
     9
import weakref
4116
cf49463fc067 Fix a bunch of undefined names. Mostly typos or missing imports.
Matthew Duggan <mgithub@guarana.org>
parents: 3721
diff changeset
    10
from reportlab.graphics.shapes import transformPoint, transformPoints, inverse, Ellipse, Group, String, Path, numericXShift
3534
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
    11
from reportlab.lib.utils import flatten
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
    12
from reportlab.pdfbase.pdfmetrics import stringWidth
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    13
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    14
### Dinu's stuff used in some line plots (likely to vansih).
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    15
def mkTimeTuple(timeString):
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    16
    "Convert a 'dd/mm/yyyy' formatted string to a tuple for use in the time module."
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    17
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    18
    list = [0] * 9
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
    19
    dd, mm, yyyy = list(map(int, timeString.split('/')))
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    20
    list[:3] = [yyyy, mm, dd]
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
    21
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    22
    return tuple(list)
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    23
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    24
def str2seconds(timeString):
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    25
    "Convert a number of seconds since the epoch into a date string."
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    26
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    27
    return mktime(mkTimeTuple(timeString))
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    28
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    29
def seconds2str(seconds):
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    30
    "Convert a date string into the number of seconds since the epoch."
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    31
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    32
    return strftime('%Y-%m-%d', gmtime(seconds))
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    33
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    34
### Aaron's rounding function for making nice values on axes.
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    35
def nextRoundNumber(x):
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    36
    """Return the first 'nice round number' greater than or equal to x
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    37
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    38
    Used in selecting apropriate tick mark intervals; we say we want
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    39
    an interval which places ticks at least 10 points apart, work out
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    40
    what that is in chart space, and ask for the nextRoundNumber().
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    41
    Tries the series 1,2,5,10,20,50,100.., going up or down as needed.
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    42
    """
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
    43
827
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    44
    #guess to nearest order of magnitude
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    45
    if x in (0, 1):
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    46
        return x
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    47
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    48
    if x < 0:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    49
        return -1.0 * nextRoundNumber(-x)
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    50
    else:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    51
        lg = int(log10(x))
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    52
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    53
        if lg == 0:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    54
            if x < 1:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    55
                base = 0.1
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    56
            else:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    57
                base = 1.0
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    58
        elif lg < 0:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    59
            base = 10.0 ** (lg - 1)
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    60
        else:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    61
            base = 10.0 ** lg    # e.g. base(153) = 100
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    62
        # base will always be lower than x
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    63
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    64
        if base >= x:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    65
            return base * 1.0
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    66
        elif (base * 2) >= x:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    67
            return base * 2.0
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    68
        elif (base * 5) >= x:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    69
            return base * 5.0
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    70
        else:
be88a17f65ca Moved utility functions into new module utils.py.
dinu_gherman
parents:
diff changeset
    71
            return base * 10.0
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    72
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    73
_intervals=(.1, .2, .25, .5)
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    74
_j_max=len(_intervals)-1
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    75
def find_interval(lo,hi,I=5):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    76
    'determine tick parameters for range [lo, hi] using I intervals'
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    77
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    78
    if lo >= hi:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    79
        if lo==hi:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    80
            if lo==0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    81
                lo = -.1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    82
                hi =  .1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    83
            else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    84
                lo = 0.9*lo
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    85
                hi = 1.1*hi
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    86
        else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
    87
            raise ValueError("lo>hi")
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    88
    x=(hi - lo)/float(I)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    89
    b= (x>0 and (x<1 or x>10)) and 10**floor(log10(x)) or 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    90
    b = b
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    91
    while 1:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    92
        a = x/b
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    93
        if a<=_intervals[-1]: break
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    94
        b = b*10
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    95
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    96
    j = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    97
    while a>_intervals[j]: j = j + 1
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
    98
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
    99
    while 1:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   100
        ss = _intervals[j]*b
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   101
        n = lo/ss
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   102
        l = int(n)-(n<0)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   103
        n = ss*l
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   104
        x = ss*(l+I)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   105
        a = I*ss
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   106
        if n>0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   107
            if a>=hi:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   108
                n = 0.0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   109
                x = a
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   110
        elif hi<0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   111
            a = -a
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   112
            if lo>a:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   113
                n = a
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   114
                x = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   115
        if hi<=x and n<=lo: break
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   116
        j = j + 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   117
        if j>_j_max:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   118
            j = 0
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   119
            b = b*10
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   120
    return n, x, ss, lo - n + x - hi
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
   121
1331
dee677d0c6a7 Allow for forceable grid override
rgbecker
parents: 832
diff changeset
   122
def find_good_grid(lower,upper,n=(4,5,6,7,8,9), grid=None):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   123
    if grid:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   124
        t = divmod(lower,grid)[0] * grid
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   125
        hi, z = divmod(upper,grid)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   126
        if z>1e-8: hi = hi+1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   127
        hi = hi*grid
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   128
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   129
        try:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   130
            n[0]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   131
        except TypeError:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   132
            n = range(max(1,n-2),max(n+3,2))
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
   133
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   134
        w = 1e308
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   135
        for i in n:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   136
            z=find_interval(lower,upper,i)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   137
            if z[3]<w:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   138
                t, hi, grid = z[:3]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   139
                w=z[3]
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   140
    return t, hi, grid
832
fe4f27b7d484 Added Robin's stuff from rgb_ticks.py.
dinu_gherman
parents: 827
diff changeset
   141
3412
8f046ab1b050 axes.py: add support for labelVOffset to AdjYValueAxis
rgbecker
parents: 3393
diff changeset
   142
def ticks(lower, upper, n=(4,5,6,7,8,9), split=1, percent=0, grid=None, labelVOffset=0):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   143
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   144
    return tick positions and labels for range lower<=x<=upper
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   145
    n=number of intervals to try (can be a list or sequence)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   146
    split=1 return ticks then labels else (tick,label) pairs
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   147
    '''
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   148
    t, hi, grid = find_good_grid(lower, upper, n, grid)
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   149
    power = floor(log10(grid))
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   150
    if power==0: power = 1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   151
    w = grid/10.**power
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   152
    w = int(w)!=w
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   153
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   154
    if power > 3 or power < -3:
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3032
diff changeset
   155
        format = '%+'+repr(w+7)+'.0e'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   156
    else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   157
        if power >= 0:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   158
            digits = int(power)+w
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3032
diff changeset
   159
            format = '%' + repr(digits)+'.0f'
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   160
        else:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   161
            digits = w-int(power)
3326
ce725978d11c Initial Python3 compatibility fixes
damian
parents: 3032
diff changeset
   162
            format = '%'+repr(digits+2)+'.'+repr(digits)+'f'
1683
7fa753e4420a Removed all trailing whitespace
andy_robinson
parents: 1677
diff changeset
   163
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   164
    if percent: format=format+'%%'
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   165
    T = []
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   166
    n = int(float(hi-t)/grid+0.1)+1
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   167
    if split:
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   168
        labels = []
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   169
        for i in range(n):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   170
            v = t+grid*i
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   171
            T.append(v)
3412
8f046ab1b050 axes.py: add support for labelVOffset to AdjYValueAxis
rgbecker
parents: 3393
diff changeset
   172
            labels.append(format % (v+labelVOffset))
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   173
        return T, labels
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   174
    else:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   175
        for i in range(n):
1677
1450177dd19e Exterminated all tab characters and added a test to make sure
andy_robinson
parents: 1557
diff changeset
   176
            v = t+grid*i
3412
8f046ab1b050 axes.py: add support for labelVOffset to AdjYValueAxis
rgbecker
parents: 3393
diff changeset
   177
            T.append((v, format % (v+labelVOffset)))
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   178
        return T
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   179
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   180
def findNones(data):
3019
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   181
    m = len(data)
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   182
    if None in data:
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   183
        b = 0
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   184
        while b<m and data[b] is None:
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   185
            b += 1
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   186
        if b==m: return data
3019
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   187
        l = m-1
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   188
        while data[l] is None:
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   189
            l -= 1
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   190
        l+=1
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   191
        if b or l: data = data[b:l]
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   192
        I = [i for i in range(len(data)) if data[i] is None]
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   193
        for i in I:
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   194
            data[i] = 0.5*(data[i-1]+data[i+1])
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   195
        return b, l, data
3019
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   196
    return 0,m,data
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   197
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   198
def pairFixNones(pairs):
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   199
    Y = [x[1] for x in pairs]
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   200
    b,l,nY = findNones(Y)
3019
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   201
    m = len(Y)
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   202
    if b or l<m or nY!=Y:
e303fc5232dd utild.py: fix broken moving average func
rgbecker
parents: 2964
diff changeset
   203
        if b or l<m: pairs = pairs[b:l]
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   204
        pairs = [(x[0],y) for x,y in zip(pairs,nY)]
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   205
    return pairs
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   206
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   207
def maverage(data,n=6):
2847
437c2e2335f2 graphics: fix utils and factorize some axis behaviour
rgbecker
parents: 2846
diff changeset
   208
    data = (n-1)*[data[0]]+data
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   209
    data = [float(sum(data[i-n:i]))/n for i in range(n,len(data)+1)]
2846
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   210
    return data
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   211
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   212
def pairMaverage(data,n=6):
d2ce0e707ba9 charts: added axes skipEndL and some utilities
rgbecker
parents: 2332
diff changeset
   213
    return [(x[0],s) for x,s in zip(data, maverage([x[1] for x in data],n))]
3385
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   214
3387
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   215
class DrawTimeCollector(object):
3385
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   216
    '''
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   217
    generic mechanism for collecting information about nodes at the time they are about to be drawn
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   218
    '''
3388
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   219
    def __init__(self,formats=['gif']):
3385
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   220
        self._nodes = weakref.WeakKeyDictionary()
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   221
        self.clear()
3387
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   222
        self._pmcanv = None
3393
1a1c9637d79f graphics: minor changes to drawTimeCollector support
rgbecker
parents: 3390
diff changeset
   223
        self.formats = formats
1a1c9637d79f graphics: minor changes to drawTimeCollector support
rgbecker
parents: 3390
diff changeset
   224
        self.disabled = False
3385
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   225
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   226
    def clear(self):
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   227
        self._info = []
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   228
        self._info_append = self._info.append
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   229
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   230
    def record(self,func,node,*args,**kwds):
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   231
        self._nodes[node] = (func,args,kwds)
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   232
        node.__dict__['_drawTimeCallback'] = self
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   233
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   234
    def __call__(self,node,canvas,renderer):
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   235
        func = self._nodes.get(node,None)
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   236
        if func:
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   237
            func, args, kwds = func
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   238
            i = func(node,canvas,renderer, *args, **kwds)
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   239
            if i is not None: self._info_append(i)
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   240
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   241
    @staticmethod
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   242
    def rectDrawTimeCallback(node,canvas,renderer,**kwds):
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   243
        A = getattr(canvas,'ctm',None)
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   244
        if not A: return
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   245
        x1 = node.x
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   246
        y1 = node.y
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   247
        x2 = x1 + node.width
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   248
        y2 = y1 + node.height
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   249
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   250
        D = kwds.copy()
3387
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   251
        D['rect']=DrawTimeCollector.transformAndFlatten(A,((x1,y1),(x2,y2)))
3385
e45ca0b2053c graphics: start on run time callback support
rgbecker
parents: 3326
diff changeset
   252
        return D
3387
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   253
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   254
    @staticmethod
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   255
    def transformAndFlatten(A,p):
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   256
        ''' transform an flatten a list of points
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   257
        A   transformation matrix
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   258
        p   points [(x0,y0),....(xk,yk).....]
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   259
        '''
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   260
        if tuple(A)!=(1,0,0,1,0,0):
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   261
            iA = inverse(A)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   262
            p = transformPoints(iA,p)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   263
        return tuple(flatten(p))
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   264
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   265
    @property
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   266
    def pmcanv(self):
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   267
        if not self._pmcanv:
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   268
            import renderPM
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   269
            self._pmcanv = renderPM.PMCanvas(1,1)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   270
        return self._pmcanv
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   271
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   272
    def wedgeDrawTimeCallback(self,node,canvas,renderer,**kwds):
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   273
        A = getattr(canvas,'ctm',None)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   274
        if not A: return
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   275
        if isinstance(node,Ellipse):
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   276
            c = self.pmcanv
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   277
            c.ellipse(node.cx, node.cy, node.rx,node.ry)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   278
            p = c.vpath
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   279
            p = [(x[1],x[2]) for x in p]
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   280
        else:
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   281
            p = node.asPolygon().points
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   282
            p = [(p[i],p[i+1]) for i in range(0,len(p),2)]
3387
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   283
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   284
        D = kwds.copy()
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   285
        D['poly'] = self.transformAndFlatten(A,p)
52dc490767e9 graphics: add wedgeRecord support
rgbecker
parents: 3385
diff changeset
   286
        return D
3388
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   287
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   288
    def save(self,fnroot):
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   289
        '''
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   290
        save the current information known to this collector
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   291
        fnroot is the root name of a resource to name the saved info
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   292
        override this to get the right semantics for your collector
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   293
        '''
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   294
        import pprint
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   295
        f=open(fnroot+'.default-collector.out','w')
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   296
        try:
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   297
            pprint.pprint(self._info,f)
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   298
        finally:
793d353cbc08 shapes.py, utils.py more support for draw time collector
rgbecker
parents: 3387
diff changeset
   299
            f.close()
3532
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   300
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   301
def xyDist(xxx_todo_changeme, xxx_todo_changeme1 ):
3532
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   302
    '''return distance between two points'''
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   303
    (x0,y0) = xxx_todo_changeme
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   304
    (x1,y1) = xxx_todo_changeme1
3566
63166bfc6267 charts/utils.py: use hypot for xyDist
rgbecker
parents: 3534
diff changeset
   305
    return hypot((x1-x0),(y1-y0))
3532
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   306
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   307
def lineSegmentIntersect(xxx_todo_changeme2, xxx_todo_changeme3, xxx_todo_changeme4, xxx_todo_changeme5
3532
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   308
                ):
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   309
    (x00,y00) = xxx_todo_changeme2
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   310
    (x01,y01) = xxx_todo_changeme3
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   311
    (x10,y10) = xxx_todo_changeme4
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   312
    (x11,y11) = xxx_todo_changeme5
3532
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   313
    p = x00,y00
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   314
    r = x01-x00,y01-y00
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   315
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   316
    
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   317
    q = x10,y10
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   318
    s = x11-x10,y11-y10
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   319
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   320
    rs = float(r[0]*s[1]-r[1]*s[0])
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   321
    qp = q[0]-p[0],q[1]-p[1]
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   322
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   323
    qpr = qp[0]*r[1]-qp[1]*r[0]
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   324
    qps = qp[0]*s[1]-qp[1]*s[0]
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   325
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   326
    if abs(rs)<1e-8:
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   327
        if abs(qpr)<1e-8: return 'collinear'
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   328
        return None
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   329
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   330
    t = qps/rs
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   331
    u = qpr/rs
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   332
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   333
    if 0<=t<=1 and 0<=u<=1:
8f3fe2729f66 charts/utils.py: added xyDist & lineSegmentIntersect
rgbecker
parents: 3412
diff changeset
   334
        return p[0]+t*r[0], p[1]+t*r[1]
3534
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   335
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   336
def makeCircularString(x, y, radius, angle, text, fontName, fontSize, inside=0, G=None,textAnchor='start'):
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   337
    '''make a group with circular text in it'''
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   338
    if not G: G = Group()
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   339
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   340
    angle %= 360
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   341
    pi180 = pi/180
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   342
    phi = angle*pi180
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   343
    width = stringWidth(text, fontName, fontSize)
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   344
    sig = inside and -1 or 1
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   345
    hsig = sig*0.5
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   346
    sig90 = sig*90
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   347
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   348
    if textAnchor!='start':
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   349
        if textAnchor=='middle':
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   350
            phi += sig*(0.5*width)/radius
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   351
        elif textAnchor=='end':
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   352
            phi += sig*float(width)/radius
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   353
        elif textAnchor=='numeric':
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   354
            phi += sig*float(numericXShift(textAnchor,text,width,fontName,fontSize,None))/radius
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   355
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   356
    for letter in text:
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   357
        width = stringWidth(letter, fontName, fontSize)
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   358
        beta = float(width)/radius
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   359
        h = Group()
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   360
        h.add(String(0, 0, letter, fontName=fontName,fontSize=fontSize,textAnchor="start"))
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   361
        h.translate(x+cos(phi)*radius,y+sin(phi)*radius)    #translate to radius and angle
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   362
        h.rotate((phi-hsig*beta)/pi180-sig90)               # rotate as needed
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   363
        G.add(h)                                            #add to main group
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   364
        phi -= sig*beta                                     #increment
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   365
956dcd489c78 charts/utils.py: add makeCircularString
rgbecker
parents: 3532
diff changeset
   366
    return G
3645
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   367
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   368
class CustomDrawChanger:
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   369
    '''
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   370
    a class to simplify making changes at draw time
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   371
    '''
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   372
    def __init__(self):
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   373
        self.store = None
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   374
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   375
    def __call__(self,change,obj):
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   376
        if change:
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   377
            self.store = self._changer(obj)
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   378
            assert isinstance(self.store,dict), '%s.changer should return a dict of changed attributes' % self.__class__.__name__
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   379
        elif self.store is not None:
3721
0c93dd8ff567 initial changes from 2to3-3.3
rptlab
parents: 3645
diff changeset
   380
            for a,v in self.store.items():
3645
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   381
                setattr(obj,a,v)
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   382
            self.store = None
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   383
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   384
    def _changer(self,obj):
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   385
        '''
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   386
        When implemented this method should return a dictionary of
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   387
        original attribute values so that a future self(False,obj)
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   388
        can restore them.
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   389
        '''
388ffb1a42df graphics/charts: added CustomDrawChanger class
robin
parents: 3617
diff changeset
   390
        raise RuntimeError('Abstract method _changer called')