author | robin <robin@reportlab.com> |
Tue, 07 Mar 2017 10:00:34 +0000 | |
changeset 4330 | 617ffa6bbdc8 |
parent 4252 | fe660f227cac |
child 4332 | b9b7e096842f |
permissions | -rw-r--r-- |
4330 | 1 |
#Copyright ReportLab Europe Ltd. 2000-2017 |
817 | 2 |
#see license.txt for license details |
2332 | 3 |
#history http://www.reportlab.co.uk/cgi-bin/viewcvs.cgi/public/reportlab/trunk/reportlab/graphics/charts/piecharts.py |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
4 |
# experimental pie chart script. Two types of pie - one is a monolithic |
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
5 |
#widget with all top-level properties, the other delegates most stuff to |
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
6 |
#a wedges collection whic lets you customize the group or every individual |
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
7 |
#wedge. |
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
8 |
|
4252 | 9 |
__version__='3.3.0' |
3032 | 10 |
__doc__="""Basic Pie Chart class. |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
11 |
|
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
12 |
This permits you to customize and pop out individual wedges; |
909
a5ee7d2bdb17
Extracted validator functions into lib.validators.
dinu_gherman
parents:
907
diff
changeset
|
13 |
supports elliptical and circular pies. |
a5ee7d2bdb17
Extracted validator functions into lib.validators.
dinu_gherman
parents:
907
diff
changeset
|
14 |
""" |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
15 |
|
3818 | 16 |
import copy, functools |
907 | 17 |
from math import sin, cos, pi |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
18 |
|
909
a5ee7d2bdb17
Extracted validator functions into lib.validators.
dinu_gherman
parents:
907
diff
changeset
|
19 |
from reportlab.lib import colors |
1620 | 20 |
from reportlab.lib.validators import isColor, isNumber, isListOfNumbersOrNone,\ |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
21 |
isListOfNumbers, isColorOrNone, isString,\ |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
22 |
isListOfStringsOrNone, OneOf, SequenceOf,\ |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
23 |
isBoolean, isListOfColors, isNumberOrNone,\ |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
24 |
isNoneOrListOfNoneOrStrings, isTextAnchor,\ |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
25 |
isNoneOrListOfNoneOrNumbers, isBoxAnchor,\ |
2431
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
26 |
isStringOrNone, NoneOr |
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
27 |
from reportlab.graphics.widgets.markers import uSymbol2Symbol, isSymbol |
948 | 28 |
from reportlab.lib.attrmap import * |
909
a5ee7d2bdb17
Extracted validator functions into lib.validators.
dinu_gherman
parents:
907
diff
changeset
|
29 |
from reportlab.pdfgen.canvas import Canvas |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
30 |
from reportlab.graphics.shapes import Group, Drawing, Ellipse, Wedge, String, STATE_DEFAULTS, ArcPath, Polygon, Rect, PolyLine, Line |
916
de1bbc3958c3
Made more consistent use of typed collections.
dinu_gherman
parents:
909
diff
changeset
|
31 |
from reportlab.graphics.widgetbase import Widget, TypedPropertyCollection, PropHolder |
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
32 |
from reportlab.graphics.charts.areas import PlotArea |
2856
2225ac76e622
charts: fix unicode labels using _objStr (bug from Sebastian Ware sebastian@urbantalk.se)
rgbecker
parents:
2835
diff
changeset
|
33 |
from reportlab.graphics.charts.legends import _objStr |
3580 | 34 |
from reportlab.graphics.charts.textlabels import Label |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
35 |
|
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
36 |
_ANGLE2BOXANCHOR={0:'w', 45:'sw', 90:'s', 135:'se', 180:'e', 225:'ne', 270:'n', 315: 'nw', -45: 'nw'} |
2520 | 37 |
_ANGLE2RBOXANCHOR={0:'e', 45:'ne', 90:'n', 135:'nw', 180:'w', 225:'sw', 270:'s', 315: 'se', -45: 'se'} |
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
38 |
|
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
39 |
_ANGLELO = 1e-7 |
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
40 |
_ANGLEHI = 360.0 - _ANGLELO |
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
41 |
|
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
42 |
class WedgeLabel(Label): |
2028 | 43 |
def _checkDXY(self,ba): |
44 |
pass |
|
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
45 |
def _getBoxAnchor(self): |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
46 |
ba = self.boxAnchor |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
47 |
if ba in ('autox','autoy'): |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
48 |
na = (int((self._pmv%360)/45.)*45)%360 |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
49 |
if not (na % 90): # we have a right angle case |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
50 |
da = (self._pmv - na) % 360 |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
51 |
if abs(da)>5: |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
52 |
na += (da>0 and 45 or -45) |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
53 |
ba = (getattr(self,'_anti',None) and _ANGLE2RBOXANCHOR or _ANGLE2BOXANCHOR)[na] |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
54 |
self._checkDXY(ba) |
2028 | 55 |
return ba |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
56 |
|
916
de1bbc3958c3
Made more consistent use of typed collections.
dinu_gherman
parents:
909
diff
changeset
|
57 |
class WedgeProperties(PropHolder): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
58 |
"""This holds descriptive information about the wedges in a pie chart. |
1683 | 59 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
60 |
It is not to be confused with the 'wedge itself'; this just holds |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
61 |
a recipe for how to format one, and does not allow you to hack the |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
62 |
angles. It can format a genuine Wedge object for you with its |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
63 |
format method. |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
64 |
""" |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
65 |
_attrMap = AttrMap( |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
66 |
strokeWidth = AttrMapValue(isNumber,desc='Width of the wedge border'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
67 |
fillColor = AttrMapValue(isColorOrNone,desc='Filling color of the wedge'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
68 |
strokeColor = AttrMapValue(isColorOrNone,desc='Color of the wedge border'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
69 |
strokeDashArray = AttrMapValue(isListOfNumbersOrNone,desc='Style of the wedge border, expressed as a list of lengths of alternating dashes and blanks'), |
3271 | 70 |
strokeLineCap = AttrMapValue(OneOf(0,1,2),desc="Line cap 0=butt, 1=round & 2=square"), |
71 |
strokeLineJoin = AttrMapValue(OneOf(0,1,2),desc="Line join 0=miter, 1=round & 2=bevel"), |
|
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
72 |
strokeMiterLimit = AttrMapValue(isNumber,desc='Miter limit control miter line joins'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
73 |
popout = AttrMapValue(isNumber,desc="How far of centre a wedge to pop"), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
74 |
fontName = AttrMapValue(isString,desc='Name of the font of the label text'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
75 |
fontSize = AttrMapValue(isNumber,desc='Size of the font of the label text in points'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
76 |
fontColor = AttrMapValue(isColorOrNone,desc='Color of the font of the label text'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
77 |
labelRadius = AttrMapValue(isNumber,desc='Distance between the center of the label box and the center of the pie, expressed in times the radius of the pie'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
78 |
label_dx = AttrMapValue(isNumber,desc='X Offset of the label'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
79 |
label_dy = AttrMapValue(isNumber,desc='Y Offset of the label'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
80 |
label_angle = AttrMapValue(isNumber,desc='Angle of the label, default (0) is horizontal, 90 is vertical, 180 is upside down'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
81 |
label_boxAnchor = AttrMapValue(isBoxAnchor,desc='Anchoring point of the label'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
82 |
label_boxStrokeColor = AttrMapValue(isColorOrNone,desc='Border color for the label box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
83 |
label_boxStrokeWidth = AttrMapValue(isNumber,desc='Border width for the label box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
84 |
label_boxFillColor = AttrMapValue(isColorOrNone,desc='Filling color of the label box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
85 |
label_strokeColor = AttrMapValue(isColorOrNone,desc='Border color for the label text'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
86 |
label_strokeWidth = AttrMapValue(isNumber,desc='Border width for the label text'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
87 |
label_text = AttrMapValue(isStringOrNone,desc='Text of the label'), |
3270 | 88 |
label_leading = AttrMapValue(isNumberOrNone,desc=''), |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
89 |
label_width = AttrMapValue(isNumberOrNone,desc='Width of the label'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
90 |
label_maxWidth = AttrMapValue(isNumberOrNone,desc='Maximum width the label can grow to'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
91 |
label_height = AttrMapValue(isNumberOrNone,desc='Height of the label'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
92 |
label_textAnchor = AttrMapValue(isTextAnchor,desc='Maximum height the label can grow to'), |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
93 |
label_visible = AttrMapValue(isBoolean,desc="True if the label is to be drawn"), |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
94 |
label_topPadding = AttrMapValue(isNumber,'Padding at top of box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
95 |
label_leftPadding = AttrMapValue(isNumber,'Padding at left of box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
96 |
label_rightPadding = AttrMapValue(isNumber,'Padding at right of box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
97 |
label_bottomPadding = AttrMapValue(isNumber,'Padding at bottom of box'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
98 |
label_simple_pointer = AttrMapValue(isBoolean,'Set to True for simple pointers'), |
2543 | 99 |
label_pointer_strokeColor = AttrMapValue(isColorOrNone,desc='Color of indicator line'), |
100 |
label_pointer_strokeWidth = AttrMapValue(isNumber,desc='StrokeWidth of indicator line'), |
|
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
101 |
label_pointer_elbowLength = AttrMapValue(isNumber,desc='Length of final indicator line segment'), |
2543 | 102 |
label_pointer_edgePad = AttrMapValue(isNumber,desc='pad between pointer label and box'), |
103 |
label_pointer_piePad = AttrMapValue(isNumber,desc='pad between pointer label and pie'), |
|
3270 | 104 |
swatchMarker = AttrMapValue(NoneOr(isSymbol), desc="None or makeMarker('Diamond') ...",advancedUsage=1), |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
105 |
visible = AttrMapValue(isBoolean,'Set to false to skip displaying'), |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
106 |
) |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
107 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
108 |
def __init__(self): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
109 |
self.strokeWidth = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
110 |
self.fillColor = None |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
111 |
self.strokeColor = STATE_DEFAULTS["strokeColor"] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
112 |
self.strokeDashArray = STATE_DEFAULTS["strokeDashArray"] |
3227
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
113 |
self.strokeLineJoin = 1 |
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
114 |
self.strokeLineCap = 0 |
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
115 |
self.strokeMiterLimit = 0 |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
116 |
self.popout = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
117 |
self.fontName = STATE_DEFAULTS["fontName"] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
118 |
self.fontSize = STATE_DEFAULTS["fontSize"] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
119 |
self.fontColor = STATE_DEFAULTS["fillColor"] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
120 |
self.labelRadius = 1.2 |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
121 |
self.label_dx = self.label_dy = self.label_angle = 0 |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
122 |
self.label_text = None |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
123 |
self.label_topPadding = self.label_leftPadding = self.label_rightPadding = self.label_bottomPadding = 0 |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
124 |
self.label_boxAnchor = 'autox' |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
125 |
self.label_boxStrokeColor = None #boxStroke |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
126 |
self.label_boxStrokeWidth = 0.5 #boxStrokeWidth |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
127 |
self.label_boxFillColor = None |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
128 |
self.label_strokeColor = None |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
129 |
self.label_strokeWidth = 0.1 |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
130 |
self.label_leading = self.label_width = self.label_maxWidth = self.label_height = None |
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
131 |
self.label_textAnchor = 'start' |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
132 |
self.label_simple_pointer = 0 |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
133 |
self.label_visible = 1 |
2543 | 134 |
self.label_pointer_strokeColor = colors.black |
135 |
self.label_pointer_strokeWidth = 0.5 |
|
136 |
self.label_pointer_elbowLength = 3 |
|
137 |
self.label_pointer_edgePad = 2 |
|
138 |
self.label_pointer_piePad = 3 |
|
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
139 |
self.visible = 1 |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
140 |
|
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
141 |
def _addWedgeLabel(self,text,angle,labelX,labelY,wedgeStyle,labelClass=WedgeLabel): |
2017 | 142 |
# now draw a label |
143 |
if self.simpleLabels: |
|
144 |
theLabel = String(labelX, labelY, text) |
|
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
145 |
if not self.sideLabels: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
146 |
theLabel.textAnchor = "middle" |
3580 | 147 |
else: |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
148 |
if (abs(angle) < 90 ) or (angle >270 and angle<450) or (-450< angle <-270): |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
149 |
theLabel.textAnchor = "start" |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
150 |
else: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
151 |
theLabel.textAnchor = "end" |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
152 |
theLabel._pmv = angle |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
153 |
theLabel._simple_pointer = 0 |
2017 | 154 |
else: |
2028 | 155 |
theLabel = labelClass() |
2017 | 156 |
theLabel._pmv = angle |
157 |
theLabel.x = labelX |
|
158 |
theLabel.y = labelY |
|
159 |
theLabel.dx = wedgeStyle.label_dx |
|
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
160 |
if not self.sideLabels: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
161 |
theLabel.dy = wedgeStyle.label_dy |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
162 |
theLabel.boxAnchor = wedgeStyle.label_boxAnchor |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
163 |
else: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
164 |
if wedgeStyle.fontSize is None: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
165 |
sideLabels_dy = self.fontSize / 2.5 |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
166 |
else: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
167 |
sideLabels_dy = wedgeStyle.fontSize / 2.5 |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
168 |
if wedgeStyle.label_dy is None: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
169 |
theLabel.dy = sideLabels_dy |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
170 |
else: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
171 |
theLabel.dy = wedgeStyle.label_dy + sideLabels_dy |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
172 |
if (abs(angle) < 90 ) or (angle >270 and angle<450) or (-450< angle <-270): |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
173 |
theLabel.boxAnchor = 'w' |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
174 |
else: |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
175 |
theLabel.boxAnchor = 'e' |
2017 | 176 |
theLabel.angle = wedgeStyle.label_angle |
177 |
theLabel.boxStrokeColor = wedgeStyle.label_boxStrokeColor |
|
178 |
theLabel.boxStrokeWidth = wedgeStyle.label_boxStrokeWidth |
|
179 |
theLabel.boxFillColor = wedgeStyle.label_boxFillColor |
|
180 |
theLabel.strokeColor = wedgeStyle.label_strokeColor |
|
181 |
theLabel.strokeWidth = wedgeStyle.label_strokeWidth |
|
182 |
_text = wedgeStyle.label_text |
|
183 |
if _text is None: _text = text |
|
184 |
theLabel._text = _text |
|
185 |
theLabel.leading = wedgeStyle.label_leading |
|
186 |
theLabel.width = wedgeStyle.label_width |
|
187 |
theLabel.maxWidth = wedgeStyle.label_maxWidth |
|
188 |
theLabel.height = wedgeStyle.label_height |
|
189 |
theLabel.textAnchor = wedgeStyle.label_textAnchor |
|
190 |
theLabel.visible = wedgeStyle.label_visible |
|
191 |
theLabel.topPadding = wedgeStyle.label_topPadding |
|
192 |
theLabel.leftPadding = wedgeStyle.label_leftPadding |
|
193 |
theLabel.rightPadding = wedgeStyle.label_rightPadding |
|
194 |
theLabel.bottomPadding = wedgeStyle.label_bottomPadding |
|
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
195 |
theLabel._simple_pointer = wedgeStyle.label_simple_pointer |
2017 | 196 |
theLabel.fontSize = wedgeStyle.fontSize |
197 |
theLabel.fontName = wedgeStyle.fontName |
|
198 |
theLabel.fillColor = wedgeStyle.fontColor |
|
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
199 |
return theLabel |
2017 | 200 |
|
201 |
def _fixLabels(labels,n): |
|
202 |
if labels is None: |
|
203 |
labels = [''] * n |
|
204 |
else: |
|
205 |
i = n-len(labels) |
|
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
206 |
if i>0: labels = list(labels)+['']*i |
2017 | 207 |
return labels |
208 |
||
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
209 |
class AbstractPieChart(PlotArea): |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
210 |
|
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
211 |
def makeSwatchSample(self, rowNo, x, y, width, height): |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
212 |
baseStyle = self.slices |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
213 |
styleIdx = rowNo % len(baseStyle) |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
214 |
style = baseStyle[styleIdx] |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
215 |
strokeColor = getattr(style, 'strokeColor', getattr(baseStyle,'strokeColor',None)) |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
216 |
fillColor = getattr(style, 'fillColor', getattr(baseStyle,'fillColor',None)) |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
217 |
strokeDashArray = getattr(style, 'strokeDashArray', getattr(baseStyle,'strokeDashArray',None)) |
2431
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
218 |
strokeWidth = getattr(style, 'strokeWidth', getattr(baseStyle, 'strokeWidth',None)) |
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
219 |
swatchMarker = getattr(style, 'swatchMarker', getattr(baseStyle, 'swatchMarker',None)) |
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
220 |
if swatchMarker: |
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
221 |
return uSymbol2Symbol(swatchMarker,x+width/2.,y+height/2.,fillColor) |
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
222 |
return Rect(x,y,width,height,strokeWidth=strokeWidth,strokeColor=strokeColor, |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
223 |
strokeDashArray=strokeDashArray,fillColor=fillColor) |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
224 |
|
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
225 |
def getSeriesName(self,i,default=None): |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
226 |
'''return series name i or default''' |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
227 |
try: |
2856
2225ac76e622
charts: fix unicode labels using _objStr (bug from Sebastian Ware sebastian@urbantalk.se)
rgbecker
parents:
2835
diff
changeset
|
228 |
text = _objStr(self.labels[i]) |
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
229 |
except: |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
230 |
text = default |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
231 |
if not self.simpleLabels: |
2431
84617376d454
charts: minor adjustments to legends/swatches for pies/barcharts
rgbecker
parents:
2427
diff
changeset
|
232 |
_text = getattr(self.slices[i],'label_text','') |
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
233 |
if _text is not None: text = _text |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
234 |
return text |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
235 |
|
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
236 |
def boundsOverlap(P,Q): |
3580 | 237 |
return not(P[0]>Q[2]-1e-2 or Q[0]>P[2]-1e-2 or P[1]>(0.5*(Q[1]+Q[3]))-1e-2 or Q[1]>(0.5*(P[1]+P[3]))-1e-2) |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
238 |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
239 |
def _findOverlapRun(B,i,wrap): |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
240 |
'''find overlap run containing B[i]''' |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
241 |
n = len(B) |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
242 |
R = [i] |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
243 |
while 1: |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
244 |
i = R[-1] |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
245 |
j = (i+1)%n |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
246 |
if j in R or not boundsOverlap(B[i],B[j]): break |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
247 |
R.append(j) |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
248 |
while 1: |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
249 |
i = R[0] |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
250 |
j = (i-1)%n |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
251 |
if j in R or not boundsOverlap(B[i],B[j]): break |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
252 |
R.insert(0,j) |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
253 |
return R |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
254 |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
255 |
def findOverlapRun(B,wrap=1): |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
256 |
'''determine a set of overlaps in bounding boxes B or return None''' |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
257 |
n = len(B) |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
258 |
if n>1: |
3721 | 259 |
for i in range(n-1): |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
260 |
R = _findOverlapRun(B,i,wrap) |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
261 |
if len(R)>1: return R |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
262 |
return None |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
263 |
|
3580 | 264 |
def fixLabelOverlaps(L, sideLabels=False): |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
265 |
nL = len(L) |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
266 |
if nL<2: return |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
267 |
B = [l._origdata['bounds'] for l in L] |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
268 |
OK = 1 |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
269 |
RP = [] |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
270 |
iter = 0 |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
271 |
mult = 1. |
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
272 |
|
3580 | 273 |
if not sideLabels: |
274 |
while iter<30: |
|
275 |
R = findOverlapRun(B) |
|
276 |
if not R: break |
|
277 |
nR = len(R) |
|
278 |
if nR==nL: break |
|
279 |
if not [r for r in RP if r in R]: |
|
280 |
mult = 1.0 |
|
281 |
da = 0 |
|
282 |
r0 = R[0] |
|
283 |
rL = R[-1] |
|
284 |
bi = B[r0] |
|
285 |
taa = aa = _360(L[r0]._pmv) |
|
286 |
for r in R[1:]: |
|
287 |
b = B[r] |
|
288 |
da = max(da,min(b[3]-bi[1],bi[3]-b[1])) |
|
289 |
bi = b |
|
290 |
aa += L[r]._pmv |
|
291 |
aa = aa/float(nR) |
|
292 |
utaa = abs(L[rL]._pmv-taa) |
|
293 |
ntaa = _360(utaa) |
|
294 |
da *= mult*(nR-1)/ntaa |
|
295 |
||
296 |
for r in R: |
|
297 |
l = L[r] |
|
298 |
orig = l._origdata |
|
299 |
angle = l._pmv = _360(l._pmv+da*(_360(l._pmv)-aa)) |
|
300 |
rad = angle/_180_pi |
|
301 |
l.x = orig['cx'] + orig['rx']*cos(rad) |
|
302 |
l.y = orig['cy'] + orig['ry']*sin(rad) |
|
303 |
B[r] = l.getBounds() |
|
304 |
RP = R |
|
305 |
mult *= 1.05 |
|
306 |
iter += 1 |
|
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
307 |
|
3580 | 308 |
else: |
309 |
while iter<30: |
|
310 |
R = findOverlapRun(B) |
|
311 |
if not R: break |
|
312 |
nR = len(R) |
|
313 |
if nR == nL: break |
|
314 |
l1 = L[-1] |
|
315 |
orig1 = l1._origdata |
|
316 |
bounds1 = orig1['bounds'] |
|
317 |
for i,r in enumerate(R): |
|
318 |
l = L[r] |
|
319 |
orig = l._origdata |
|
320 |
bounds = orig['bounds'] |
|
321 |
diff1 = 0 |
|
322 |
diff2 = 0 |
|
323 |
if not i == nR-1: |
|
324 |
if not bounds == bounds1: |
|
325 |
if bounds[3]>bounds1[1] and bounds1[1]<bounds[1]: |
|
326 |
diff1 = bounds[3]-bounds1[1] |
|
327 |
if bounds1[3]>bounds[1] and bounds[1]<bounds1[1]: |
|
328 |
diff2 = bounds1[3]-bounds[1] |
|
329 |
if diff1 > diff2: |
|
330 |
l.y +=0.5*(bounds1[3]-bounds1[1]) |
|
331 |
elif diff2 >= diff1: |
|
332 |
l.y -= 0.5*(bounds1[3]-bounds1[1]) |
|
333 |
B[r] = l.getBounds() |
|
334 |
iter += 1 |
|
335 |
||
2543 | 336 |
def intervalIntersection(A,B): |
337 |
x,y = max(min(A),min(B)),min(max(A),max(B)) |
|
338 |
if x>=y: return None |
|
339 |
return x,y |
|
340 |
||
341 |
def _makeSideArcDefs(sa,direction): |
|
342 |
sa %= 360 |
|
343 |
if 90<=sa<270: |
|
344 |
if direction=='clockwise': |
|
345 |
a = (0,90,sa),(1,-90,90),(0,-360+sa,-90) |
|
346 |
else: |
|
347 |
a = (0,sa,270),(1,270,450),(0,450,360+sa) |
|
348 |
else: |
|
349 |
offs = sa>=270 and 360 or 0 |
|
350 |
if direction=='clockwise': |
|
351 |
a = (1,offs-90,sa),(0,offs-270,offs-90),(1,-360+sa,offs-270) |
|
352 |
else: |
|
353 |
a = (1,sa,offs+90),(0,offs+90,offs+270),(1,offs+270,360+sa) |
|
354 |
return tuple([a for a in a if a[1]<a[2]]) |
|
355 |
||
3818 | 356 |
def _keyFLA(x,y): |
357 |
return cmp(y[1]-y[0],x[1]-x[0]) |
|
358 |
_keyFLA = functools.cmp_to_key(_keyFLA) |
|
359 |
||
2543 | 360 |
def _findLargestArc(xArcs,side): |
361 |
a = [a[1] for a in xArcs if a[0]==side and a[1] is not None] |
|
362 |
if not a: return None |
|
3818 | 363 |
if len(a)>1: a.sort(key=_keyFLA) |
2543 | 364 |
return a[0] |
365 |
||
366 |
def _fPLSide(l,width,side=None): |
|
367 |
data = l._origdata |
|
368 |
if side is None: |
|
369 |
li = data['li'] |
|
370 |
ri = data['ri'] |
|
371 |
if li is None: |
|
372 |
side = 1 |
|
373 |
i = ri |
|
374 |
elif ri is None: |
|
375 |
side = 0 |
|
376 |
i = li |
|
377 |
elif li[1]-li[0]>ri[1]-ri[0]: |
|
378 |
side = 0 |
|
379 |
i = li |
|
380 |
else: |
|
381 |
side = 1 |
|
382 |
i = ri |
|
383 |
w = data['width'] |
|
384 |
edgePad = data['edgePad'] |
|
385 |
if not side: #on left |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
386 |
l._pmv = 180 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
387 |
l.x = edgePad+w |
2543 | 388 |
i = data['li'] |
389 |
else: |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
390 |
l._pmv = 0 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
391 |
l.x = width - w - edgePad |
2543 | 392 |
i = data['ri'] |
393 |
mid = data['mid'] = (i[0]+i[1])*0.5 |
|
394 |
data['smid'] = sin(mid/_180_pi) |
|
395 |
data['cmid'] = cos(mid/_180_pi) |
|
396 |
data['side'] = side |
|
397 |
return side,w |
|
398 |
||
3818 | 399 |
#key functions |
400 |
def _fPLCF(a,b): |
|
3828 | 401 |
return cmp(b._origdata['smid'],a._origdata['smid']) |
3818 | 402 |
_fPLCF = functools.cmp_to_key(_fPLCF) |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
403 |
|
3818 | 404 |
def _arcCF(a): |
405 |
return a[1] |
|
2543 | 406 |
|
407 |
def _fixPointerLabels(n,L,x,y,width,height,side=None): |
|
408 |
LR = [],[] |
|
409 |
mlr = [0,0] |
|
410 |
for l in L: |
|
411 |
i,w = _fPLSide(l,width,side) |
|
412 |
LR[i].append(l) |
|
413 |
mlr[i] = max(w,mlr[i]) |
|
414 |
mul = 1 |
|
415 |
G = n*[None] |
|
416 |
mel = 0 |
|
417 |
hh = height*0.5 |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
418 |
yhh = y+hh |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
419 |
m = max(mlr) |
2543 | 420 |
for i in (0,1): |
421 |
T = LR[i] |
|
422 |
if T: |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
423 |
B = [] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
424 |
aB = B.append |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
425 |
S = [] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
426 |
aS = S.append |
3818 | 427 |
T.sort(key=_fPLCF) |
2543 | 428 |
p = 0 |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
429 |
yh = y+height |
2543 | 430 |
for l in T: |
431 |
data = l._origdata |
|
432 |
inc = x+mul*(m-data['width']) |
|
433 |
l.x += inc |
|
434 |
G[data['index']] = l |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
435 |
ly = yhh+data['smid']*hh |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
436 |
b = data['bounds'] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
437 |
b2 = (b[3]-b[1])*0.5 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
438 |
if ly+b2>yh: ly = yh-b2 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
439 |
if ly-b2<y: ly = y+b2 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
440 |
data['bounds'] = b = (b[0],ly-b2,b[2],ly+b2) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
441 |
aB(b) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
442 |
l.y = ly |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
443 |
aS(max(0,yh-ly-b2)) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
444 |
yh = ly-b2 |
2543 | 445 |
p = max(p,data['edgePad']+data['piePad']) |
446 |
mel = max(mel,abs(data['smid']*(hh+data['elbowLength']))-hh) |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
447 |
aS(yh-y) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
448 |
|
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
449 |
iter = 0 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
450 |
nT = len(T) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
451 |
while iter<30: |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
452 |
R = findOverlapRun(B,wrap=0) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
453 |
if not R: break |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
454 |
nR = len(R) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
455 |
if nR==nT: break |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
456 |
j0 = R[0] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
457 |
j1 = R[-1] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
458 |
jl = j1+1 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
459 |
sAbove = sum(S[:j0+1]) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
460 |
sFree = sAbove+sum(S[jl:]) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
461 |
sNeed = sum([b[3]-b[1] for b in B[j0:jl]])+jl-j0-(B[j0][3]-B[j1][1]) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
462 |
if sNeed>sFree: break |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
463 |
yh = B[j0][3]+sAbove*sNeed/sFree |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
464 |
for r in R: |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
465 |
l = T[r] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
466 |
data = l._origdata |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
467 |
b = data['bounds'] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
468 |
b2 = (b[3]-b[1])*0.5 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
469 |
yh -= 0.5 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
470 |
ly = l.y = yh-b2 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
471 |
B[r] = data['bounds'] = (b[0],ly-b2,b[2],yh) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
472 |
yh = ly - b2 - 0.5 |
2543 | 473 |
mlr[i] = m+p |
474 |
mul = -1 |
|
475 |
return G, mlr[0], mlr[1], mel |
|
476 |
||
3580 | 477 |
def theta0(data, direction): |
478 |
fac = (2*pi)/sum(data) |
|
479 |
rads = [d*fac for d in data] |
|
480 |
||
481 |
r0 = 0 |
|
482 |
hrads = [] |
|
483 |
for r in rads: |
|
484 |
hrads.append(r0+r*0.5) |
|
485 |
r0 += r |
|
486 |
||
487 |
vstar = len(data)*1e6 |
|
488 |
rstar = 0 |
|
489 |
delta = pi/36.0 |
|
3721 | 490 |
for i in range(36): |
3580 | 491 |
r = i*delta |
492 |
v = sum([abs(sin(r+a)) for a in hrads]) |
|
493 |
if v < vstar: |
|
494 |
if direction == 'clockwise': |
|
495 |
rstar=-r |
|
496 |
else: |
|
497 |
rstar=r |
|
498 |
vstar = v |
|
499 |
return rstar*180/pi |
|
500 |
||
501 |
||
3387 | 502 |
class AngleData(float): |
503 |
'''use this to carry the data along with the angle''' |
|
504 |
def __new__(cls,angle,data): |
|
505 |
self = float.__new__(cls,angle) |
|
506 |
self._data = data |
|
507 |
return self |
|
508 |
||
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
509 |
class Pie(AbstractPieChart): |
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
510 |
_attrMap = AttrMap(BASE=AbstractPieChart, |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
511 |
data = AttrMapValue(isListOfNumbers, desc='List of numbers defining wedge sizes; need not sum to 1'), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
512 |
labels = AttrMapValue(isListOfStringsOrNone, desc="Optional list of labels to use for each data point"), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
513 |
startAngle = AttrMapValue(isNumber, desc="Angle of first slice; 0 is due East"), |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
514 |
direction = AttrMapValue(OneOf('clockwise', 'anticlockwise'), desc="'clockwise' or 'anticlockwise'"), |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
515 |
slices = AttrMapValue(None, desc="Collection of wedge descriptor objects"), |
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
516 |
simpleLabels = AttrMapValue(isBoolean, desc="If true(default) use a simple String not an advanced WedgeLabel. A WedgeLabel is customisable using the properties prefixed label_ in the collection slices."), |
3270 | 517 |
other_threshold = AttrMapValue(isNumber, desc='A value for doing threshholding, not used yet.',advancedUsage=1), |
518 |
checkLabelOverlap = AttrMapValue(isBoolean, desc="If true check and attempt to fix\n standard label overlaps(default off)",advancedUsage=1), |
|
519 |
pointerLabelMode = AttrMapValue(OneOf(None,'LeftRight','LeftAndRight'), desc='',advancedUsage=1), |
|
520 |
sameRadii = AttrMapValue(isBoolean, desc="If true make x/y radii the same(default off)",advancedUsage=1), |
|
521 |
orderMode = AttrMapValue(OneOf('fixed','alternate'),advancedUsage=1), |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
522 |
xradius = AttrMapValue(isNumberOrNone, desc="X direction Radius"), |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
523 |
yradius = AttrMapValue(isNumberOrNone, desc="Y direction Radius"), |
3671 | 524 |
innerRadiusFraction = AttrMapValue(isNumberOrNone, desc="fraction of radii to start wedges at"), |
3387 | 525 |
wedgeRecord = AttrMapValue(None, desc="callable(wedge,*args,**kwds)",advancedUsage=1), |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
526 |
sideLabels = AttrMapValue(isBoolean, desc="If true attempt to make piechart with labels along side and pointers"), |
3586 | 527 |
sideLabelsOffset = AttrMapValue(isNumber, desc="The fraction of the pie width that the labels are situated at from the edges of the pie"), |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
528 |
) |
2019 | 529 |
other_threshold=None |
1683 | 530 |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
531 |
def __init__(self,**kwd): |
2543 | 532 |
PlotArea.__init__(self) |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
533 |
self.x = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
534 |
self.y = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
535 |
self.width = 100 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
536 |
self.height = 100 |
2427
1de04210b407
charts: autolegending in place, legend now has boxAnchor
rgbecker
parents:
2420
diff
changeset
|
537 |
self.data = [1,2.3,1.7,4.2] |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
538 |
self.labels = None # or list of strings |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
539 |
self.startAngle = 90 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
540 |
self.direction = "clockwise" |
1961
eb03e38caf87
Allow for proper labels in piechart and some clean ups
rgbecker
parents:
1937
diff
changeset
|
541 |
self.simpleLabels = 1 |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
542 |
self.checkLabelOverlap = 0 |
2543 | 543 |
self.pointerLabelMode = None |
544 |
self.sameRadii = False |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
545 |
self.orderMode = 'fixed' |
3671 | 546 |
self.xradius = self.yradius = self.innerRadiusFraction = None |
3580 | 547 |
self.sideLabels = 0 |
3586 | 548 |
self.sideLabelsOffset = 0.1 |
1683 | 549 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
550 |
self.slices = TypedPropertyCollection(WedgeProperties) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
551 |
self.slices[0].fillColor = colors.darkcyan |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
552 |
self.slices[1].fillColor = colors.blueviolet |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
553 |
self.slices[2].fillColor = colors.blue |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
554 |
self.slices[3].fillColor = colors.cyan |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
555 |
self.slices[4].fillColor = colors.pink |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
556 |
self.slices[5].fillColor = colors.magenta |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
557 |
self.slices[6].fillColor = colors.yellow |
916
de1bbc3958c3
Made more consistent use of typed collections.
dinu_gherman
parents:
909
diff
changeset
|
558 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
559 |
def demo(self): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
560 |
d = Drawing(200, 100) |
1683 | 561 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
562 |
pc = Pie() |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
563 |
pc.x = 50 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
564 |
pc.y = 10 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
565 |
pc.width = 100 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
566 |
pc.height = 80 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
567 |
pc.data = [10,20,30,40,50,60] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
568 |
pc.labels = ['a','b','c','d','e','f'] |
907 | 569 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
570 |
pc.slices.strokeWidth=0.5 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
571 |
pc.slices[3].popout = 10 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
572 |
pc.slices[3].strokeWidth = 2 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
573 |
pc.slices[3].strokeDashArray = [2,2] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
574 |
pc.slices[3].labelRadius = 1.75 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
575 |
pc.slices[3].fontColor = colors.red |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
576 |
pc.slices[0].fillColor = colors.darkcyan |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
577 |
pc.slices[1].fillColor = colors.blueviolet |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
578 |
pc.slices[2].fillColor = colors.blue |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
579 |
pc.slices[3].fillColor = colors.cyan |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
580 |
pc.slices[4].fillColor = colors.aquamarine |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
581 |
pc.slices[5].fillColor = colors.cadetblue |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
582 |
pc.slices[6].fillColor = colors.lightcoral |
907 | 583 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
584 |
d.add(pc) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
585 |
return d |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
586 |
|
2543 | 587 |
def makePointerLabels(self,angles,plMode): |
588 |
class PL: |
|
589 |
def __init__(self,centerx,centery,xradius,yradius,data,lu=0,ru=0): |
|
590 |
self.centerx = centerx |
|
591 |
self.centery = centery |
|
592 |
self.xradius = xradius |
|
593 |
self.yradius = yradius |
|
594 |
self.data = data |
|
595 |
self.lu = lu |
|
596 |
self.ru = ru |
|
597 |
||
598 |
labelX = self.width-2 |
|
599 |
labelY = self.height |
|
600 |
n = nr = nl = maxW = sumH = 0 |
|
601 |
styleCount = len(self.slices) |
|
602 |
L=[] |
|
603 |
L_add = L.append |
|
604 |
refArcs = _makeSideArcDefs(self.startAngle,self.direction) |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
605 |
for i, A in angles: |
2543 | 606 |
if A[1] is None: continue |
607 |
sn = self.getSeriesName(i,'') |
|
608 |
if not sn: continue |
|
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
609 |
style = self.slices[i%styleCount] |
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
610 |
if not style.label_visible or not style.visible: continue |
2543 | 611 |
n += 1 |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
612 |
l=_addWedgeLabel(self,sn,180,labelX,labelY,style,labelClass=WedgeLabel) |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
613 |
L_add(l) |
2543 | 614 |
b = l.getBounds() |
615 |
w = b[2]-b[0] |
|
616 |
h = b[3]-b[1] |
|
617 |
ri = [(a[0],intervalIntersection(A,(a[1],a[2]))) for a in refArcs] |
|
618 |
li = _findLargestArc(ri,0) |
|
619 |
ri = _findLargestArc(ri,1) |
|
620 |
if li and ri: |
|
621 |
if plMode=='LeftAndRight': |
|
622 |
if li[1]-li[0]<ri[1]-ri[0]: |
|
623 |
li = None |
|
624 |
else: |
|
625 |
ri = None |
|
626 |
else: |
|
627 |
if li[1]-li[0]<0.02*(ri[1]-ri[0]): |
|
628 |
li = None |
|
629 |
elif (li[1]-li[0])*0.02>ri[1]-ri[0]: |
|
630 |
ri = None |
|
631 |
if ri: nr += 1 |
|
632 |
if li: nl += 1 |
|
633 |
l._origdata = dict(bounds=b,width=w,height=h,li=li,ri=ri,index=i,edgePad=style.label_pointer_edgePad,piePad=style.label_pointer_piePad,elbowLength=style.label_pointer_elbowLength) |
|
634 |
maxW = max(w,maxW) |
|
635 |
sumH += h+2 |
|
636 |
||
637 |
if not n: #we have no labels |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
638 |
xradius = self.width*0.5 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
639 |
yradius = self.height*0.5 |
2543 | 640 |
centerx = self.x+xradius |
641 |
centery = self.y+yradius |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
642 |
if self.xradius: xradius = self.xradius |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
643 |
if self.yradius: yradius = self.yradius |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
644 |
if self.sameRadii: xradius=yradius=min(xradius,yradius) |
2543 | 645 |
return PL(centerx,centery,xradius,yradius,[]) |
646 |
||
647 |
aonR = nr==n |
|
648 |
if sumH<self.height and (aonR or nl==n): |
|
649 |
side=int(aonR) |
|
650 |
else: |
|
651 |
side=None |
|
652 |
G,lu,ru,mel = _fixPointerLabels(len(angles),L,self.x,self.y,self.width,self.height,side=side) |
|
653 |
if plMode=='LeftAndRight': |
|
654 |
lu = ru = max(lu,ru) |
|
655 |
x0 = self.x+lu |
|
656 |
x1 = self.x+self.width-ru |
|
657 |
xradius = (x1-x0)*0.5 |
|
658 |
yradius = self.height*0.5-mel |
|
659 |
centerx = x0+xradius |
|
660 |
centery = self.y+yradius+mel |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
661 |
if self.xradius: xradius = self.xradius |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
662 |
if self.yradius: yradius = self.yradius |
2543 | 663 |
if self.sameRadii: xradius=yradius=min(xradius,yradius) |
664 |
return PL(centerx,centery,xradius,yradius,G,lu,ru) |
|
665 |
||
3387 | 666 |
def normalizeData(self,keepData=False): |
3721 | 667 |
data = list(map(abs,self.data)) |
2835 | 668 |
s = self._sum = float(sum(data)) |
4234
0137ff8f82d7
remove scale assumption and allow all zero data (issue raised by Michael Spector & bitbucket)
robin
parents:
3828
diff
changeset
|
669 |
f = 360./s if s!=0 else 1 |
3387 | 670 |
if keepData: |
671 |
return [AngleData(f*x,x) for x in data] |
|
672 |
else: |
|
2835 | 673 |
return [f*x for x in data] |
922 | 674 |
|
2543 | 675 |
def makeAngles(self): |
3387 | 676 |
wr = getattr(self,'wedgeRecord',None) |
3580 | 677 |
if self.sideLabels: |
678 |
startAngle = theta0(self.data, self.direction) |
|
679 |
self.slices.label_visible = 1 |
|
680 |
else: |
|
681 |
startAngle = self.startAngle % 360 |
|
2543 | 682 |
whichWay = self.direction == "clockwise" and -1 or 1 |
3387 | 683 |
D = [a for a in enumerate(self.normalizeData(keepData=wr))] |
3580 | 684 |
if self.orderMode=='alternate' and not self.sideLabels: |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
685 |
W = [a for a in D if abs(a[1])>=1e-5] |
3818 | 686 |
W.sort(key=_arcCF) |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
687 |
T = [[],[]] |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
688 |
i = 0 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
689 |
while W: |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
690 |
if i<2: |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
691 |
a = W.pop(0) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
692 |
else: |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
693 |
a = W.pop(-1) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
694 |
T[i%2].append(a) |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
695 |
i += 1 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
696 |
i %= 4 |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
697 |
T[1].reverse() |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
698 |
D = T[0]+T[1] + [a for a in D if abs(a[1])<1e-5] |
2543 | 699 |
A = [] |
700 |
a = A.append |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
701 |
for i, angle in D: |
2543 | 702 |
endAngle = (startAngle + (angle * whichWay)) |
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
703 |
if abs(angle)>=_ANGLELO: |
2543 | 704 |
if startAngle >= endAngle: |
705 |
aa = endAngle,startAngle |
|
706 |
else: |
|
707 |
aa = startAngle,endAngle |
|
708 |
else: |
|
709 |
aa = startAngle, None |
|
3387 | 710 |
if wr: |
711 |
aa = (AngleData(aa[0],angle._data),aa[1]) |
|
2543 | 712 |
startAngle = endAngle |
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
713 |
a((i,aa)) |
2543 | 714 |
return A |
715 |
||
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
716 |
def makeWedges(self): |
2543 | 717 |
angles = self.makeAngles() |
3580 | 718 |
#Checking to see whether there are too many wedges packed in too small a space |
719 |
halfAngles = [] |
|
720 |
for i,(a1,a2) in angles: |
|
721 |
if a2 is None: |
|
722 |
halfAngle = a1 |
|
723 |
else: |
|
724 |
halfAngle = 0.5*(a2+a1) |
|
725 |
halfAngles.append(halfAngle) |
|
726 |
sideLabels = self.sideLabels |
|
2543 | 727 |
n = len(angles) |
2017 | 728 |
labels = _fixLabels(self.labels,n) |
3387 | 729 |
wr = getattr(self,'wedgeRecord',None) |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
730 |
|
2543 | 731 |
self._seriesCount = n |
732 |
styleCount = len(self.slices) |
|
916
de1bbc3958c3
Made more consistent use of typed collections.
dinu_gherman
parents:
909
diff
changeset
|
733 |
|
2543 | 734 |
plMode = self.pointerLabelMode |
3580 | 735 |
if sideLabels: |
3594
4e090d6bebed
New version of piecharts with new function side labels, documentation and new samples
guillaume
parents:
3590
diff
changeset
|
736 |
plMode = None |
2543 | 737 |
if plMode: |
738 |
checkLabelOverlap = False |
|
739 |
PL=self.makePointerLabels(angles,plMode) |
|
740 |
xradius = PL.xradius |
|
741 |
yradius = PL.yradius |
|
742 |
centerx = PL.centerx |
|
743 |
centery = PL.centery |
|
744 |
PL_data = PL.data |
|
745 |
gSN = lambda i: '' |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
746 |
else: |
2543 | 747 |
xradius = self.width*0.5 |
748 |
yradius = self.height*0.5 |
|
749 |
centerx = self.x + xradius |
|
750 |
centery = self.y + yradius |
|
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
751 |
if self.xradius: xradius = self.xradius |
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
752 |
if self.yradius: yradius = self.yradius |
2543 | 753 |
if self.sameRadii: xradius=yradius=min(xradius,yradius) |
754 |
checkLabelOverlap = self.checkLabelOverlap |
|
755 |
gSN = lambda i: self.getSeriesName(i,'') |
|
921 | 756 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
757 |
g = Group() |
2543 | 758 |
g_add = g.add |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
759 |
L = [] |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
760 |
L_add = L.append |
2543 | 761 |
|
3671 | 762 |
innerRadiusFraction = self.innerRadiusFraction |
763 |
||
2549
5978153b84b0
piecharts: now have orderMode 'alternate' and proper vertical spreading
rgbecker
parents:
2543
diff
changeset
|
764 |
for i,(a1,a2) in angles: |
2543 | 765 |
if a2 is None: continue |
766 |
#if we didn't use %stylecount here we'd end up with the later wedges |
|
767 |
#all having the default style |
|
768 |
wedgeStyle = self.slices[i%styleCount] |
|
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
769 |
if not wedgeStyle.visible: continue |
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
770 |
aa = abs(a2-a1) |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
771 |
|
2543 | 772 |
# is it a popout? |
773 |
cx, cy = centerx, centery |
|
774 |
text = gSN(i) |
|
775 |
popout = wedgeStyle.popout |
|
776 |
if text or popout: |
|
777 |
averageAngle = (a1+a2)/2.0 |
|
778 |
aveAngleRadians = averageAngle/_180_pi |
|
779 |
cosAA = cos(aveAngleRadians) |
|
780 |
sinAA = sin(aveAngleRadians) |
|
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
781 |
if popout and aa<_ANGLEHI: |
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
782 |
# pop out the wedge |
2543 | 783 |
cx = centerx + popout*cosAA |
784 |
cy = centery + popout*sinAA |
|
883
ddfef4e6e647
Removed sector line for single sliced pie charts.
dinu_gherman
parents:
817
diff
changeset
|
785 |
|
3671 | 786 |
if innerRadiusFraction: |
787 |
theWedge = Wedge(cx, cy, xradius, a1, a2, yradius=yradius, |
|
788 |
radius1=xradius*innerRadiusFraction,yradius1=yradius*innerRadiusFraction) |
|
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
789 |
else: |
3671 | 790 |
if aa>=_ANGLEHI: |
791 |
theWedge = Ellipse(cx, cy, xradius, yradius) |
|
792 |
else: |
|
793 |
theWedge = Wedge(cx, cy, xradius, a1, a2, yradius=yradius) |
|
794 |
||
973 | 795 |
|
2543 | 796 |
theWedge.fillColor = wedgeStyle.fillColor |
797 |
theWedge.strokeColor = wedgeStyle.strokeColor |
|
798 |
theWedge.strokeWidth = wedgeStyle.strokeWidth |
|
3227
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
799 |
theWedge.strokeLineJoin = wedgeStyle.strokeLineJoin |
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
800 |
theWedge.strokeLineCap = wedgeStyle.strokeLineCap |
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
801 |
theWedge.strokeMiterLimit = wedgeStyle.strokeMiterLimit |
750fe33ccd5e
piecharts.py: add wedge stroke propertiels and set default LineJoin=1
rgbecker
parents:
3032
diff
changeset
|
802 |
theWedge.strokeWidth = wedgeStyle.strokeWidth |
2543 | 803 |
theWedge.strokeDashArray = wedgeStyle.strokeDashArray |
883
ddfef4e6e647
Removed sector line for single sliced pie charts.
dinu_gherman
parents:
817
diff
changeset
|
804 |
|
2543 | 805 |
g_add(theWedge) |
3387 | 806 |
if wr: |
807 |
wr(theWedge,value=a1._data,label=text) |
|
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
808 |
if wedgeStyle.label_visible: |
3580 | 809 |
if not sideLabels: |
810 |
if text: |
|
811 |
labelRadius = wedgeStyle.labelRadius |
|
812 |
rx = xradius*labelRadius |
|
813 |
ry = yradius*labelRadius |
|
814 |
labelX = cx + rx*cosAA |
|
815 |
labelY = cy + ry*sinAA |
|
816 |
l = _addWedgeLabel(self,text,averageAngle,labelX,labelY,wedgeStyle) |
|
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
817 |
L_add(l) |
3580 | 818 |
if not plMode and l._simple_pointer: |
819 |
l._aax = cx+xradius*cosAA |
|
820 |
l._aay = cy+yradius*sinAA |
|
821 |
if checkLabelOverlap: |
|
822 |
l._origdata = { 'x': labelX, 'y':labelY, 'angle': averageAngle, |
|
823 |
'rx': rx, 'ry':ry, 'cx':cx, 'cy':cy, |
|
824 |
'bounds': l.getBounds(), |
|
825 |
} |
|
826 |
elif plMode and PL_data: |
|
827 |
l = PL_data[i] |
|
828 |
if l: |
|
829 |
data = l._origdata |
|
830 |
sinM = data['smid'] |
|
831 |
cosM = data['cmid'] |
|
832 |
lX = cx + xradius*cosM |
|
833 |
lY = cy + yradius*sinM |
|
834 |
lpel = wedgeStyle.label_pointer_elbowLength |
|
835 |
lXi = lX + lpel*cosM |
|
836 |
lYi = lY + lpel*sinM |
|
837 |
L_add(PolyLine((lX,lY,lXi,lYi,l.x,l.y), |
|
838 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
|
839 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
|
840 |
L_add(l) |
|
841 |
else: |
|
842 |
if text: |
|
843 |
slices_popout = self.slices.popout |
|
844 |
m=0 |
|
845 |
for n, angle in angles: |
|
846 |
if self.slices[n].fillColor: |
|
847 |
m += 1 |
|
848 |
else: |
|
849 |
r = n%m |
|
850 |
self.slices[n].fillColor = self.slices[r].fillColor |
|
851 |
self.slices[n].popout = self.slices[r].popout |
|
852 |
for j in range(0,m-1): |
|
853 |
if self.slices[j].popout > slices_popout: |
|
854 |
slices_popout = self.slices[j].popout |
|
855 |
labelRadius = wedgeStyle.labelRadius |
|
856 |
ry = yradius*labelRadius |
|
857 |
if (abs(averageAngle) < 90 ) or (averageAngle >270 and averageAngle <450) or (-450< |
|
858 |
averageAngle <-270): |
|
3586 | 859 |
labelX = (1+self.sideLabelsOffset)*self.width + self.x + slices_popout |
3580 | 860 |
rx = 0 |
861 |
else: |
|
3586 | 862 |
labelX = self.x - (self.sideLabelsOffset)*self.width - slices_popout |
3580 | 863 |
rx = 0 |
864 |
labelY = cy + ry*sinAA |
|
865 |
l = _addWedgeLabel(self,text,averageAngle,labelX,labelY,wedgeStyle) |
|
866 |
L_add(l) |
|
867 |
if not plMode: |
|
868 |
l._aax = cx+xradius*cosAA |
|
869 |
l._aay = cy+yradius*sinAA |
|
870 |
if checkLabelOverlap: |
|
871 |
l._origdata = { 'x': labelX, 'y':labelY, 'angle': averageAngle, |
|
872 |
'rx': rx, 'ry':ry, 'cx':cx, 'cy':cy, |
|
873 |
'bounds': l.getBounds(), |
|
874 |
} |
|
875 |
x1,y1,x2,y2 = l.getBounds() |
|
876 |
||
2696
add3a2702a41
piecharts.py: allow wedges/wedge labels to be invisible
rgbecker
parents:
2689
diff
changeset
|
877 |
if checkLabelOverlap and L: |
3580 | 878 |
fixLabelOverlaps(L, sideLabels) |
3330 | 879 |
for l in L: g_add(l) |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
880 |
|
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
881 |
if not plMode: |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
882 |
for l in L: |
3580 | 883 |
if l._simple_pointer and not sideLabels: |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
884 |
g_add(Line(l.x,l.y,l._aax,l._aay, |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
885 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
886 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
3580 | 887 |
elif sideLabels: |
888 |
x1,y1,x2,y2 = l.getBounds() |
|
889 |
#add pointers |
|
3586 | 890 |
if l.x == (1+self.sideLabelsOffset)*self.width + self.x: |
3580 | 891 |
g_add(Line(l._aax,l._aay,0.5*(l._aax+l.x),l.y+(0.25*(y2-y1)), |
892 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
|
893 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
|
894 |
g_add(Line(0.5*(l._aax+l.x),l.y+(0.25*(y2-y1)),l.x,l.y+(0.25*(y2-y1)), |
|
895 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
|
896 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
|
897 |
else: |
|
898 |
g_add(Line(l._aax,l._aay,0.5*(l._aax+l.x),l.y+(0.25*(y2-y1)), |
|
899 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
|
900 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
|
901 |
g_add(Line(0.5*(l._aax+l.x),l.y+(0.25*(y2-y1)),l.x,l.y+(0.25*(y2-y1)), |
|
902 |
strokeWidth=wedgeStyle.label_pointer_strokeWidth, |
|
903 |
strokeColor=wedgeStyle.label_pointer_strokeColor)) |
|
2518
355bc0c6c71f
reportlab/graphics/charts: better piechart labels
rgbecker
parents:
2432
diff
changeset
|
904 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
905 |
return g |
737
8f0e58918da9
Initial checkin, replacing previous trailing digit filenames.
dinu_gherman
parents:
diff
changeset
|
906 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
907 |
def draw(self): |
2543 | 908 |
G = self.makeBackground() |
909 |
w = self.makeWedges() |
|
910 |
if G: return Group(G,w) |
|
911 |
return w |
|
922 | 912 |
|
1620 | 913 |
class LegendedPie(Pie): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
914 |
"""Pie with a two part legend (one editable with swatches, one hidden without swatches).""" |
1620 | 915 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
916 |
_attrMap = AttrMap(BASE=Pie, |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
917 |
drawLegend = AttrMapValue(isBoolean, desc="If true then create and draw legend"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
918 |
legend1 = AttrMapValue(None, desc="Handle to legend for pie"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
919 |
legendNumberFormat = AttrMapValue(None, desc="Formatting routine for number on right hand side of legend."), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
920 |
legendNumberOffset = AttrMapValue(isNumber, desc="Horizontal space between legend and numbers on r/hand side"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
921 |
pieAndLegend_colors = AttrMapValue(isListOfColors, desc="Colours used for both swatches and pie"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
922 |
legend_names = AttrMapValue(isNoneOrListOfNoneOrStrings, desc="Names used in legend (or None)"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
923 |
legend_data = AttrMapValue(isNoneOrListOfNoneOrNumbers, desc="Numbers used on r/hand side of legend (or None)"), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
924 |
leftPadding = AttrMapValue(isNumber, desc='Padding on left of drawing'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
925 |
rightPadding = AttrMapValue(isNumber, desc='Padding on right of drawing'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
926 |
topPadding = AttrMapValue(isNumber, desc='Padding at top of drawing'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
927 |
bottomPadding = AttrMapValue(isNumber, desc='Padding at bottom of drawing'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
928 |
) |
1620 | 929 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
930 |
def __init__(self): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
931 |
Pie.__init__(self) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
932 |
self.x = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
933 |
self.y = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
934 |
self.height = 100 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
935 |
self.width = 100 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
936 |
self.data = [38.4, 20.7, 18.9, 15.4, 6.6] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
937 |
self.labels = None |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
938 |
self.direction = 'clockwise' |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
939 |
PCMYKColor, black = colors.PCMYKColor, colors.black |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
940 |
self.pieAndLegend_colors = [PCMYKColor(11,11,72,0,spotName='PANTONE 458 CV'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
941 |
PCMYKColor(100,65,0,30,spotName='PANTONE 288 CV'), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
942 |
PCMYKColor(11,11,72,0,spotName='PANTONE 458 CV',density=75), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
943 |
PCMYKColor(100,65,0,30,spotName='PANTONE 288 CV',density=75), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
944 |
PCMYKColor(11,11,72,0,spotName='PANTONE 458 CV',density=50), |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
945 |
PCMYKColor(100,65,0,30,spotName='PANTONE 288 CV',density=50)] |
1620 | 946 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
947 |
#Allows us up to six 'wedges' to be coloured |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
948 |
self.slices[0].fillColor=self.pieAndLegend_colors[0] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
949 |
self.slices[1].fillColor=self.pieAndLegend_colors[1] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
950 |
self.slices[2].fillColor=self.pieAndLegend_colors[2] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
951 |
self.slices[3].fillColor=self.pieAndLegend_colors[3] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
952 |
self.slices[4].fillColor=self.pieAndLegend_colors[4] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
953 |
self.slices[5].fillColor=self.pieAndLegend_colors[5] |
1620 | 954 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
955 |
self.slices.strokeWidth = 0.75 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
956 |
self.slices.strokeColor = black |
1620 | 957 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
958 |
legendOffset = 17 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
959 |
self.legendNumberOffset = 51 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
960 |
self.legendNumberFormat = '%.1f%%' |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
961 |
self.legend_data = self.data |
1620 | 962 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
963 |
#set up the legends |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
964 |
from reportlab.graphics.charts.legends import Legend |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
965 |
self.legend1 = Legend() |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
966 |
self.legend1.x = self.width+legendOffset |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
967 |
self.legend1.y = self.height |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
968 |
self.legend1.deltax = 5.67 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
969 |
self.legend1.deltay = 14.17 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
970 |
self.legend1.dxTextSpace = 11.39 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
971 |
self.legend1.dx = 5.67 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
972 |
self.legend1.dy = 5.67 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
973 |
self.legend1.columnMaximum = 7 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
974 |
self.legend1.alignment = 'right' |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
975 |
self.legend_names = ['AAA:','AA:','A:','BBB:','NR:'] |
3721 | 976 |
for f in range(len(self.data)): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
977 |
self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f], self.legend_names[f])) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
978 |
self.legend1.fontName = "Helvetica-Bold" |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
979 |
self.legend1.fontSize = 6 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
980 |
self.legend1.strokeColor = black |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
981 |
self.legend1.strokeWidth = 0.5 |
1620 | 982 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
983 |
self._legend2 = Legend() |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
984 |
self._legend2.dxTextSpace = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
985 |
self._legend2.dx = 0 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
986 |
self._legend2.alignment = 'right' |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
987 |
self._legend2.fontName = "Helvetica-Oblique" |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
988 |
self._legend2.fontSize = 6 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
989 |
self._legend2.strokeColor = self.legend1.strokeColor |
1620 | 990 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
991 |
self.leftPadding = 5 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
992 |
self.rightPadding = 5 |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
993 |
self.topPadding = 5 |
1683 | 994 |
self.bottomPadding = 5 |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
995 |
self.drawLegend = 1 |
1620 | 996 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
997 |
def draw(self): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
998 |
if self.drawLegend: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
999 |
self.legend1.colorNamePairs = [] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1000 |
self._legend2.colorNamePairs = [] |
3721 | 1001 |
for f in range(len(self.data)): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1002 |
if self.legend_names == None: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1003 |
self.slices[f].fillColor = self.pieAndLegend_colors[f] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1004 |
self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f], None)) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1005 |
else: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1006 |
try: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1007 |
self.slices[f].fillColor = self.pieAndLegend_colors[f] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1008 |
self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f], self.legend_names[f])) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1009 |
except IndexError: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1010 |
self.slices[f].fillColor = self.pieAndLegend_colors[f%len(self.pieAndLegend_colors)] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1011 |
self.legend1.colorNamePairs.append((self.pieAndLegend_colors[f%len(self.pieAndLegend_colors)], self.legend_names[f])) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1012 |
if self.legend_data != None: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1013 |
ldf = self.legend_data[f] |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1014 |
lNF = self.legendNumberFormat |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1015 |
if ldf is None or lNF is None: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1016 |
pass |
3800 | 1017 |
elif isinstance(lNF,str): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1018 |
ldf = lNF % ldf |
3326 | 1019 |
elif hasattr(lNF,'__call__'): |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1020 |
ldf = lNF(ldf) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1021 |
else: |
3800 | 1022 |
raise ValueError("Unknown formatter type %s, expected string or function" % ascii(self.legendNumberFormat)) |
1023 |
self._legend2.colorNamePairs.append((None,ldf)) |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1024 |
p = Pie.draw(self) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1025 |
if self.drawLegend: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1026 |
p.add(self.legend1) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1027 |
#hide from user - keeps both sides lined up! |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1028 |
self._legend2.x = self.legend1.x+self.legendNumberOffset |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1029 |
self._legend2.y = self.legend1.y |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1030 |
self._legend2.deltax = self.legend1.deltax |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1031 |
self._legend2.deltay = self.legend1.deltay |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1032 |
self._legend2.dy = self.legend1.dy |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1033 |
self._legend2.columnMaximum = self.legend1.columnMaximum |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1034 |
p.add(self._legend2) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1035 |
p.shift(self.leftPadding, self.bottomPadding) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1036 |
return p |
1620 | 1037 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1038 |
def _getDrawingDimensions(self): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1039 |
tx = self.rightPadding |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1040 |
if self.drawLegend: |
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
1041 |
tx += self.legend1.x+self.legendNumberOffset #self._legend2.x |
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
1042 |
tx += self._legend2._calculateMaxWidth(self._legend2.colorNamePairs) |
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1043 |
ty = self.bottomPadding+self.height+self.topPadding |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1044 |
return (tx,ty) |
1620 | 1045 |
|
1677
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1046 |
def demo(self, drawing=None): |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1047 |
if not drawing: |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1048 |
tx,ty = self._getDrawingDimensions() |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1049 |
drawing = Drawing(tx, ty) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1050 |
drawing.add(self.draw()) |
1450177dd19e
Exterminated all tab characters and added a test to make sure
andy_robinson
parents:
1662
diff
changeset
|
1051 |
return drawing |
1620 | 1052 |
|
3580 | 1053 |
from reportlab.graphics.charts.utils3d import _getShaded, _2rad, _360, _pi_2, _2pi, _180_pi |
2017 | 1054 |
class Wedge3dProperties(PropHolder): |
1055 |
"""This holds descriptive information about the wedges in a pie chart. |
|
1056 |
||
1057 |
It is not to be confused with the 'wedge itself'; this just holds |
|
1058 |
a recipe for how to format one, and does not allow you to hack the |
|
1059 |
angles. It can format a genuine Wedge object for you with its |
|
1060 |
format method. |
|
1061 |
""" |
|
1062 |
_attrMap = AttrMap( |
|
3270 | 1063 |
fillColor = AttrMapValue(isColorOrNone,desc=''), |
1064 |
fillColorShaded = AttrMapValue(isColorOrNone,desc=''), |
|
1065 |
fontColor = AttrMapValue(isColorOrNone,desc=''), |
|
1066 |
fontName = AttrMapValue(isString,desc=''), |
|
1067 |
fontSize = AttrMapValue(isNumber,desc=''), |
|
1068 |
label_angle = AttrMapValue(isNumber,desc=''), |
|
2017 | 1069 |
label_bottomPadding = AttrMapValue(isNumber,'padding at bottom of box'), |
3270 | 1070 |
label_boxAnchor = AttrMapValue(isBoxAnchor,desc=''), |
1071 |
label_boxFillColor = AttrMapValue(isColorOrNone,desc=''), |
|
1072 |
label_boxStrokeColor = AttrMapValue(isColorOrNone,desc=''), |
|
1073 |
label_boxStrokeWidth = AttrMapValue(isNumber,desc=''), |
|
1074 |
label_dx = AttrMapValue(isNumber,desc=''), |
|
1075 |
label_dy = AttrMapValue(isNumber,desc=''), |
|
1076 |
label_height = AttrMapValue(isNumberOrNone,desc=''), |
|
1077 |
label_leading = AttrMapValue(isNumberOrNone,desc=''), |
|
2017 | 1078 |
label_leftPadding = AttrMapValue(isNumber,'padding at left of box'), |
3270 | 1079 |
label_maxWidth = AttrMapValue(isNumberOrNone,desc=''), |
2017 | 1080 |
label_rightPadding = AttrMapValue(isNumber,'padding at right of box'), |
3238
77cfc01cb26c
piecharts.py: fix simple pointers attibute in 3d wedges
rgbecker
parents:
3227
diff
changeset
|
1081 |
label_simple_pointer = AttrMapValue(isBoolean,'set to True for simple pointers'), |
3270 | 1082 |
label_strokeColor = AttrMapValue(isColorOrNone,desc=''), |
1083 |
label_strokeWidth = AttrMapValue(isNumber,desc=''), |
|
1084 |
label_text = AttrMapValue(isStringOrNone,desc=''), |
|
1085 |
label_textAnchor = AttrMapValue(isTextAnchor,desc=''), |
|
2017 | 1086 |
label_topPadding = AttrMapValue(isNumber,'padding at top of box'), |
1087 |
label_visible = AttrMapValue(isBoolean,desc="True if the label is to be drawn"), |
|
3270 | 1088 |
label_width = AttrMapValue(isNumberOrNone,desc=''), |
1089 |
labelRadius = AttrMapValue(isNumber,desc=''), |
|
1090 |
popout = AttrMapValue(isNumber,desc=''), |
|
1091 |
shading = AttrMapValue(isNumber,desc=''), |
|
1092 |
strokeColor = AttrMapValue(isColorOrNone,desc=''), |
|
1093 |
strokeColorShaded = AttrMapValue(isColorOrNone,desc=''), |
|
1094 |
strokeDashArray = AttrMapValue(isListOfNumbersOrNone,desc=''), |
|
1095 |
strokeWidth = AttrMapValue(isNumber,desc=''), |
|
2017 | 1096 |
visible = AttrMapValue(isBoolean,'set to false to skip displaying'), |
1097 |
) |
|
1098 |
||
1099 |
def __init__(self): |
|
1100 |
self.strokeWidth = 0 |
|
1101 |
self.shading = 0.3 |
|
1102 |
self.visible = 1 |
|
1103 |
self.strokeColorShaded = self.fillColorShaded = self.fillColor = None |
|
1104 |
self.strokeColor = STATE_DEFAULTS["strokeColor"] |
|
1105 |
self.strokeDashArray = STATE_DEFAULTS["strokeDashArray"] |
|
1106 |
self.popout = 0 |
|
1107 |
self.fontName = STATE_DEFAULTS["fontName"] |
|
1108 |
self.fontSize = STATE_DEFAULTS["fontSize"] |
|
1109 |
self.fontColor = STATE_DEFAULTS["fillColor"] |
|
1110 |
self.labelRadius = 1.2 |
|
1111 |
self.label_dx = self.label_dy = self.label_angle = 0 |
|
1112 |
self.label_text = None |
|
1113 |
self.label_topPadding = self.label_leftPadding = self.label_rightPadding = self.label_bottomPadding = 0 |
|
3016
881516600936
piecharts.py: simple pointers for non-simple labels
rgbecker
parents:
2964
diff
changeset
|
1114 |
self.label_boxAnchor = 'autox' |
2017 | 1115 |
self.label_boxStrokeColor = None #boxStroke |
1116 |
self.label_boxStrokeWidth = 0.5 #boxStrokeWidth |
|
1117 |
self.label_boxFillColor = None |
|
1118 |
self.label_strokeColor = None |
|
1119 |
self.label_strokeWidth = 0.1 |
|
1120 |
self.label_leading = self.label_width = self.label_maxWidth = self.label_height = None |
|
1121 |
self.label_textAnchor = 'start' |
|
1122 |
self.label_visible = 1 |
|
3238
77cfc01cb26c
piecharts.py: fix simple pointers attibute in 3d wedges
rgbecker
parents:
3227
diff
changeset
|
1123 |
self.label_simple_pointer = 0 |
2017 | 1124 |
|
1125 |
class _SL3D: |
|
1126 |
def __init__(self,lo,hi): |
|
1127 |
if lo<0: |
|
1128 |
lo += 360 |
|
1129 |
hi += 360 |
|
1130 |
self.lo = lo |
|
1131 |
self.hi = hi |
|
1132 |
self.mid = (lo+hi)*0.5 |
|
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
1133 |
self.not360 = abs(hi-lo) < _ANGLEHI |
2017 | 1134 |
|
1135 |
def __str__(self): |
|
1136 |
return '_SL3D(%.2f,%.2f)' % (self.lo,self.hi) |
|
1137 |
||
3818 | 1138 |
def _keyS3D(a,b): |
1139 |
return -cmp(a[0],b[0]) |
|
1140 |
_keyS3D = functools.cmp_to_key(_keyS3D) |
|
1141 |
||
2039 | 1142 |
_270r = _2rad(270) |
2019 | 1143 |
class Pie3d(Pie): |
1144 |
_attrMap = AttrMap(BASE=Pie, |
|
1145 |
perspective = AttrMapValue(isNumber, desc='A flattening parameter.'), |
|
1146 |
depth_3d = AttrMapValue(isNumber, desc='depth of the pie.'), |
|
1147 |
angle_3d = AttrMapValue(isNumber, desc='The view angle.'), |
|
1148 |
) |
|
2017 | 1149 |
perspective = 70 |
2019 | 1150 |
depth_3d = 25 |
1151 |
angle_3d = 180 |
|
2017 | 1152 |
|
1153 |
def _popout(self,i): |
|
3474
90bc9414d785
piecharts.py: eliminate wedge line for 360deg slice
rgbecker
parents:
3410
diff
changeset
|
1154 |
return self._sl3d[i].not360 and self.slices[i].popout or 0 |
2017 | 1155 |
|
1156 |
def CX(self, i,d ): |
|
1157 |
return self._cx+(d and self._xdepth_3d or 0)+self._popout(i)*cos(_2rad(self._sl3d[i].mid)) |
|
1158 |
def CY(self,i,d): |
|
1159 |
return self._cy+(d and self._ydepth_3d or 0)+self._popout(i)*sin(_2rad(self._sl3d[i].mid)) |
|
1160 |
def OX(self,i,o,d): |
|
1161 |
return self.CX(i,d)+self._radiusx*cos(_2rad(o)) |
|
1162 |
def OY(self,i,o,d): |
|
1163 |
return self.CY(i,d)+self._radiusy*sin(_2rad(o)) |
|
1164 |
||
1165 |
def rad_dist(self,a): |
|
1166 |
_3dva = self._3dva |
|
1167 |
return min(abs(a-_3dva),abs(a-_3dva+360)) |
|
1168 |
||
1169 |
def __init__(self): |
|
3638
496a6b99c229
piecharts.py: fix Pie3d __init__ to call its superclass as suggested by Stephan Richter <stephan.richter@gmail.com>
rgbecker
parents:
3617
diff
changeset
|
1170 |
Pie.__init__(self) |
496a6b99c229
piecharts.py: fix Pie3d __init__ to call its superclass as suggested by Stephan Richter <stephan.richter@gmail.com>
rgbecker
parents:
3617
diff
changeset
|
1171 |
self.slices[4].fillColor = colors.azure |
496a6b99c229
piecharts.py: fix Pie3d __init__ to call its superclass as suggested by Stephan Richter <stephan.richter@gmail.com>
r |