I put together a little python program to play around with the calculation of Hermite curves to make sure I understood them before attempting to use it in other applications.
import wx
import time
import threading
class point():
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
def curve(p1, p2, t1, t2, time):
t = time
b0 = 2*t*t*t - 3*t*t + 1
b1 = -2*t*t*t + 3*t*t
b2 = t*t*t - 2*t*t + t
b3 = t*t*t - t*t
x = b0*p1.x + b1*p2.x + b2*t1.x + b3*t2.x
y = b0*p1.y + b1*p2.y + b2*t1.y + b3*t2.y
z = b0*p1.z + b1*p2.z + b2*t1.z + b3*t2.z
return point(x,y,z)
class CurveFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title='HermiteCurve.py', style=wx.DEFAULT_FRAME_STYLE & ~wx.RESIZE_BORDER)
# Initilize curve data.
self.p1 = point()
self.p2 = point()
self.t1 = point()
self.t2 = point()
self.data = list()
# Create wx panel to draw the curve on.
self.CurvePanel = CurvePanel(self)
# Control Panel
self.ControlPanel = wx.Panel(self)
# Controls for curve data.
self.p1x = wx.Slider(self.ControlPanel, -1, 0, -200, 200, size=(200,-1), style=wx.SL_LABELS)
self.p2x = wx.Slider(self.ControlPanel, -1, 0, -200, 200, size=(200,-1), style=wx.SL_LABELS)
self.t1x = wx.Slider(self.ControlPanel, -1, 0, -5000, 5000, size=(200,-1), style=wx.SL_LABELS)
self.t2x = wx.Slider(self.ControlPanel, -1, 0, -5000, 5000, size=(200,-1), style=wx.SL_LABELS)
# Size it up!
controlsizer = wx.GridBagSizer(0,0)
controlsizer.Add(wx.StaticText(self.ControlPanel, label='Point 1 Value:'), (1,0), flag=wx.ALL, border=5)
controlsizer.Add(self.p1x, (2,0), flag=wx.ALL, border=5)
controlsizer.Add(wx.StaticText(self.ControlPanel, label='Point 2 Value:'), (3,0), flag=wx.ALL, border=5)
controlsizer.Add(self.p2x, (4,0), flag=wx.ALL, border=5)
controlsizer.Add(wx.StaticText(self.ControlPanel, label='Tangent 1 Magnitude:'), (5,0), flag=wx.ALL, border=5)
controlsizer.Add(self.t1x, (6,0), flag=wx.ALL, border=5)
controlsizer.Add(wx.StaticText(self.ControlPanel, label='Tangent 2 Magnitude:'), (7,0), flag=wx.ALL, border=5)
controlsizer.Add(self.t2x, (8,0), flag=wx.ALL, border=5)
self.ControlPanel.SetSizerAndFit(controlsizer)
sizer = wx.GridBagSizer(0,0)
sizer.Add(self.CurvePanel, (0,0), flag=wx.ALL, border=5)
sizer.Add(self.ControlPanel, (0,1), flag=wx.ALL, border=5)
self.SetSizerAndFit(sizer)
# Show the frame.
self.Show(True)
# Thread to update.
self.thread = threading.Thread(target=self.Update)
self.thread.start()
def Update(self):
while(True):
self.p1.x = self.p1x.GetValue()
self.p2.x = self.p2x.GetValue()
self.t1.x = self.t1x.GetValue()
self.t2.x = self.t2x.GetValue()
self.CalcCurve()
self.Draw()
time.sleep(.1)
def CalcCurve(self):
time = 0
self.data = list()
while time < 1.01:
p = curve(self.p1, self.p2, self.t1, self.t2, time)
self.data.append(time)
self.data.append(p.x)
self.data.append(p.y)
self.data.append(p.z)
time = time + .01
def Draw(self):
# Redraw the curve panel.
self.CurvePanel.Refresh()
class CurvePanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent, id=wx.ID_ANY, size=(600,500), style=wx.SIMPLE_BORDER)
self.parent = parent
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
def OnEraseBackground(self, event):
pass
def OnPaint(self, event):
dc = wx.BufferedPaintDC(self)
self.Draw(dc)
def Draw(self, dc):
dc.SetBrush(wx.WHITE_BRUSH)
dc.DrawRectangle(-1, -1, self.Size.width, self.Size.height)
data = self.parent.data
d = self.parent.data
width = self.GetSize()[0]
height = self.GetSize()[1]
padding = 20
# Scale the data to the graph size panel's size.
for x in range(len(data)/4):
d[4*x+0] = (width-2*padding) * data[4*x+0] + padding
d[4*x+1] = -1 * data[4*x+1] + (height/2)
# Draw the graph axis.
dc.DrawLine(padding, height/2, width-padding, height/2)
dc.DrawLine(padding, padding, padding, height-padding)
# Draw the data.
dc.SetPen(wx.Pen(wx.BLUE, 2))
for x in range(len(data)/4):
try:
x1 = d[4*x]
y1 = d[4*x+1]
x2 = d[4*(x+1)]
y2 = d[4*(x+1)+1]
dc.DrawLine(x1,y1,x2,y2)
except:
pass
if __name__ =='__main__':
app = wx.App(0)
frame = CurveFrame(None)
app.MainLoop()
Download HermiteCurve.py code here.
No comments:
Post a Comment