On Tue, 2007-09-11 at 10:40 -0700, Christopher Barker wrote:
> One note: you code mixes tabs and spaces -- that is a serious no-no
> in
> python (it really should be dis-allowed, but legacies will persist)
>
> FloatCanvas (and wxPython, and ...) uses the now almost-standard of
> four
> spaces per indent.
>
Sorry about that, I knew about the convention, but I didn't realise I
hadn't set 'expandtab' in my editor's config. I also now find 'python
-tt' as a useful safety net!
Attached is a new version with the proper code indentation (no tabs),
and some modifications to make the lines end with perpendicular edges.
This raises a general problem with this method, which is that the lines
that are filled between always maintain the same vertical distance, i.e.
the 'gap' is created by a simple y co-ordinate offset for each point. To
make the lines properly parallel would require significantly more
overhead, unless there's some nice numpy function to shift a set of
co-ordinates around in the cartesian plane.
Jamie
--
www.postlude.co.uk
#!/usr/bin/env python
"""
An attempt at an AlphaLine class using NavCanvas and GraphicsContext
"""
import numpy as N
import sys,wx
sys.path.append("../")
from floatcanvas import FloatCanvas, NavCanvas
from math import sin,cos,atan,pi
class AlphaLine(FloatCanvas.Line):
"""
The AlphaLine class takes a list of 2 - 2-tuples, or a 2X2 NumPy Float array
of point coordinates.
It will draw a line.
"""
def __init__(self,Points,
LineColor = "Black",
LineStyle = "Solid",
LineWidth = 1,
InForeground = True,
StartAlpha = 0,
EndAlpha = 255,
BorderColour = "White"):
FloatCanvas.DrawObject.__init__(self, InForeground)
self.Points = N.array(Points,N.float)
self.CalcBoundingBox()
self.LineColor = LineColor
self.LineStyle = LineStyle
self.LineWidth = LineWidth
self.StartAlpha = StartAlpha
self.EndAlpha = EndAlpha
self.BorderColour = BorderColour
def Perpendicular(self, line, length):
"""Return a point that is perpendicular to 'line'
Given a line defined as two points [(x1, y1), (x2, y2)] return a point
that will create a new line that is perpendicular. 'length' gives the
vertical distance from (x2, y2)
"""
x1,y1 = line[0]
x2,y2 = line[1]
angle = pi
theta = atan((x2 - x1) / (y2 - y1))
alpha = 2 * pi - (angle + theta)
l = length * cos(alpha)
dx = l * sin(alpha)
dy = l * cos(alpha)
if dx != abs(dx):
dx *= -1
if dy != abs(dy):
dy *= -1
x3 = x2 - dx
y3 = y2 - dy
return x3,y3
def _Draw(self, dc , WorldToPixel, ScaleWorldToPixel, HTdc=None):
bcolour = self.BorderColour
Points = self.Points
GC = wx.GraphicsContext.Create(dc)
c = wx.Color()
c.SetFromName(self.LineColor)
r,g,b = c.Get()
c1 = wx.Color(r, g, b, self.StartAlpha)
c2 = wx.Color(r, g, b, self.EndAlpha)
Path = GC.CreatePath()
bottomline = Points[1:].copy()
lastline = Points[-2:]
firstline = Points[:2]
firstline = firstline[::-1]
perplast = self.Perpendicular(lastline, self.LineWidth)
perpfirst = self.Perpendicular(firstline, self.LineWidth)
data = Points[:]
data[:,1] -= self.LineWidth
while perplast[0] > data[-1,0]:
data = data[:-1]
data = N.resize(data, (len(data) + 1,2))
data[-1] = perplast
data = data[::-1]
while perpfirst[0] > data[-1,0]:
data = data[:-1]
data = N.resize(data, (len(data) + 1,2))
data[-1] = perpfirst
topline = data
Path.MoveToPoint(perpfirst)
if bottomline[-1, 0] >= perplast[0]:
bottomline[-1] = perplast
for point in bottomline:
Path.AddLineToPoint(point)
for point in topline:
Path.AddLineToPoint(point)
GC.SetPen(wx.Pen(bcolour))
GC.DrawPath(Path)
m = Points[:,0].size - 1
Brush = \
GC.CreateLinearGradientBrush(Points[0,0], \
Points[0,1], Points[m,0], Points[m,1], c1, c2)
GC.SetBrush(Brush)
GC.FillPath(Path)
# Don't know what this does (HTdc?)
if HTdc and self.HitAble:
HTdc.SetPen(self.HitPen)
HTdc.DrawLines(Points)
class MyFrame(wx.Frame):
def __init__(self, *args, **kwargs):
kwargs['size'] = (700, 300)
kwargs['pos'] = (50,50)
wx.Frame.__init__(self, *args, **kwargs)
NC = NavCanvas.NavCanvas(self ,wx.ID_ANY ,(500,500),
ProjectionFun = None,
BackgroundColor = "WHITE"
)
self.Canvas = NC.Canvas
self.DrawLine()
self.DrawCurve()
return None
def DrawLine(self):
data = ([400,100], [100,50])
self.Canvas.AddObject(AlphaLine(data,
LineColor = "Red",
LineStyle = "Solid",
LineWidth = 4,
InForeground = 1,
StartAlpha = 255,
EndAlpha = 0,
BorderColour = "Black"))
self.Canvas.Draw()
def DrawCurve(self):
time = 2.0*N.pi*N.arange(100)/100.0
data = 1.0*N.ones((100,2))
data[:,0] = time * 100 + 20
data[:,1] = N.sin(time) * 100 + 150
self.Canvas.AddObject(AlphaLine(data,
LineColor = "Blue",
LineStyle = "Solid",
LineWidth = 6,
InForeground = 1,
StartAlpha = 0,
EndAlpha = 255,
BorderColour = "White"))
self.Canvas.Draw()
A = wx.App(0)
F = MyFrame(None)
F.Show()
A.MainLoop()
_______________________________________________
FloatCanvas mailing list
[email protected]
http://mail.mithis.com/cgi-bin/mailman/listinfo/floatcanvas