Christopher Barker wrote:
I'm about to post some new code for that
Enclosed is my new version of PieChart. I'm still going to do a bit of
rearranging, then add it to the floatcanvas package in a new sub-module:
SpecialObjects. I'd love to have whatever testing I could get before that.
One of these days, I'd really like to re-factor and put all the
DrawObject classes in their own module, rather than in the FloatCanvas
module anyway...
I've set it up with a list of default colors -- I'd love a better list
if someone has one -- maybe 10 or so distinct colors.
A couple of the charts will print a message if you click on them.
Please give it try!
-Chris
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
[EMAIL PROTECTED]
import wx
## import a local version of FloatCanvas
import sys
sys.path.append("../../")
from floatcanvas import NavCanvas, FloatCanvas
from floatcanvas.Utilities import BBox
from ArcObject import ArcPoint
import numpy as N
XYObjectMixin = FloatCanvas.XYObjectMixin
LineOnlyMixin = FloatCanvas.LineOnlyMixin
DrawObject = FloatCanvas.DrawObject
class PieChart(XYObjectMixin, LineOnlyMixin, DrawObject):
"""
This is DrawObject for a pie chart
You can pass in a bunch of values, and it will draw a pie chart for
you, and it will make the chart, scaling the size of each "slice" to
match your values.
The parameters are:
XY : The (x,y) coords of the center of the chart
Diameter : The diamter of the chart in worls coords, unless you set
"Scaled" to False, in which case it's in pixel coords.
Values : sequence of values you want to make the chart of.
FillColors=None : sequence of colors you want the slices. If
None, it will choose (no guarantee youll like them!)
FillStyles=None : Fill style you want ("Solid", "Hash", etc)
LineColor = None : Color of lines separating the slices
LineStyle = "Solid" : style of lines separating the slices
LineWidth = 1 : With of lines separating the slices
Scaled = True : Do you want the pie to scale when zooming? or stay the same size in pixels?
InForeground = False: Should it be on the foreground?
"""
##fixme: this should be a longer and better designed set.
DefaultColorList = ["Red", "Green", "Blue", "Purple", "Yellow", "Cyan"]
def __init__(self,
XY,
Diameter,
Values,
FillColors=None,
FillStyles=None,
LineColor = None,
LineStyle = "Solid",
LineWidth = 1,
Scaled = True,
InForeground = False):
DrawObject.__init__(self, InForeground)
self.XY = N.asarray(XY, N.float).reshape( (2,) )
self.Diameter = Diameter
self.Values = N.asarray(Values, dtype=N.float).reshape((-1,1))
if FillColors is None:
FillColors = self.DefaultColorList[:len(Values)]
if FillStyles is None:
FillStyles = ['Solid'] * len(FillColors)
self.FillColors = FillColors
self.FillStyles = FillStyles
self.LineColor = LineColor
self.LineStyle = LineStyle
self.Scaled = Scaled
self.InForeground = InForeground
self.SetPen(LineColor, LineStyle, LineWidth)
self.SetBrushes()
self.CalculatePoints()
def SetFillColors(self, FillColors):
self.FillColors = FillColors
self.SetBrushes()
def SetFillStyles(self, FillStyles):
self.FillStyles = FillStyles
self.SetBrushed()
def SetValues(self, Values):
Values = N.asarray(Values, dtype=N.float).reshape((-1,1))
self.Values = Values
self.CalculatePoints()
def CalculatePoints(self):
# add the zero point to start
Values = N.vstack( ( (0,), self.Values) )
Diameter = self.Diameter
Fractions = Values/Values.sum()
Angles = 2*N.pi * Fractions
Angles = N.cumsum(Angles, axis=0)
Angles[-1,0] = 0 # this should be a full circle, and we want to avoid rounding error.
CirclePoints = N.hstack( (N.cos(Angles)*Diameter, N.sin(Angles)*Diameter) )
if self.Scaled:
CirclePoints += self.XY
else:
CirclePoints = CirclePoints * (1, -1) #(in pixel coords, y is down)
self.Points = CirclePoints
self.CalcBoundingBox()
def SetBrushes(self):
self.Brushes = []
for FillColor, FillStyle in zip(self.FillColors, self.FillStyles):
if FillColor is None or FillStyle is None:
self.Brush = wx.TRANSPARENT_BRUSH
else:
self.Brushes.append(self.BrushList.setdefault( (FillColor, FillStyle),
wx.Brush( FillColor, self.FillStyleList[FillStyle] )
)
)
def CalcBoundingBox(self):
if self.Scaled:
self.BoundingBox = BBox.asBBox( ((self.XY-self.Diameter),(self.XY+self.Diameter)) )
else:
self.BoundingBox = BBox.asBBox((self.XY, self.XY))
if self._Canvas:
self._Canvas.BoundingBoxDirty = True
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
CenterXY = WorldToPixel(self.XY)
if self.Scaled:
CirclePoints = WorldToPixel(self.Points)
else:
CirclePoints = self.Points + CenterXY
dc.SetPen(self.Pen)
for i, brush in enumerate(self.Brushes):
dc.SetBrush( brush )
dc.DrawArcPoint(CirclePoints[i], CirclePoints[i+1], CenterXY)
if HTdc and self.HitAble:
if self.Scaled:
radius = (ScaleWorldToPixel(self.Diameter)/2)[0]# just the x-coord
else:
radius = self.Diameter/2
HTdc.SetPen(self.HitPen)
HTdc.SetBrush(self.HitBrush)
HTdc.DrawCirclePoint(CenterXY, radius)
#!/usr/bin/env python
import wx
## import the installed version
#from wx.lib.floatcanvas import NavCanvas, FloatCanvas
## import a local version
import sys
sys.path.append("../")
from floatcanvas import NavCanvas, FloatCanvas
import numpy as N
class DrawFrame(wx.Frame):
"""
A frame used for the FloatCanvas Demo
"""
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.CreateStatusBar()
# Add the Canvas
Canvas = NavCanvas.NavCanvas(self,-1,
size = (500,500),
Debug = 0,
BackgroundColor = "DARK SLATE BLUE",
).Canvas
self.Canvas = Canvas
from PieChart import PieChart
Values = (10,10,10)
Colors = ('Red', 'Blue', 'Green')
Pie1 = PieChart(N.array((0, 0)), 10, Values, Colors, Scaled=False)
Canvas.AddObject(Pie1)
Values = (10, 5, 5)
Pie2 = PieChart(N.array((40, 0)), 10, Values, Colors)
Canvas.AddObject(Pie2)
# test default colors
Values = (10, 15, 12, 24, 6, 12)
Pie3 = PieChart(N.array((20, 20)), 10, Values, LineColor="Black")
Canvas.AddObject(Pie3)
# missng slice!
Values = (10, 15, 12, 24)
Colors = ('Red', 'Blue', 'Green', None)
Pie4 = PieChart(N.array((0, -15)), 10, Values, Colors, LineColor="Black")
Canvas.AddObject(Pie4)
# Test the styles
Values = (10, 12, 14)
Styles = ("Solid", "CrossDiagHatch","CrossHatch")
Colors = ('Red', 'Blue', 'Green')
Pie4 = PieChart(N.array((20, -20)), 10, Values, Colors, Styles)
Canvas.AddObject(Pie2)
Pie1.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Pie1Hit)
Pie2.Bind(FloatCanvas.EVT_FC_LEFT_DOWN, self.Pie2Hit)
FloatCanvas.EVT_MOTION(self.Canvas, self.OnMove )
self.Show()
Canvas.ZoomToBB()
def Pie1Hit(self, obj):
print "Pie1 hit!"
def Pie2Hit(self, obj):
print "Pie2 hit!"
def OnMove(self, event):
"""
Updates the status bar with the world coordinates
"""
self.SetStatusText("%.2g, %.2g"%tuple(event.Coords))
app = wx.App(False)
F = DrawFrame(None, title="FloatCanvas Demo App", size=(700,700) )
app.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas