This weekend I continued my experiments with Python and Avalon. Before I was hosting Python in an existing app, but now I've started from almost scratch. I have to clean up the code and wait for the outside world to get new Avalon bits, but I can describe a bit of Pythalon.
Basically it is a Python console below and a Avalon viewing area above. I injected a variable called RootElement into the Python Processor so I can write little programs against the Avalon OM rooted in RootElement (hence the name). It turns out to be way fun. My first example is a little Koch snowflake generator. I divided the code into two modules: a platform independent pure math routine, and an Avalon dependent module that creates a Path. Here's the first section:
from math import * def vecadd(v1,v2): return [x+y for x,y in zip(v1,v2)] def vecsub(v1, v2): return [x-y for x,y in zip(v1,v2)] def scalarprod(s, v1): return [x * s for x in v1] def dotprod(v1, v2): t = [x*y for x,y in zip(v1,v2)] s = 0.0 for x in t: s += x return s def length(vector): return sqrt(dotprod(vector,vector)) def vector(point1, point2): return [y - x for x,y in zip(point1, point2)] def dist(point1, point2): return length(vector(point1, point2)) def normalize(vector): l = length(vector) return scalarprod(1.0/l, vector) def KochFunc(point1, point2): if (len(point1) != 2): return [] v = vector(point1,point2) n3 = scalarprod(1.0/3.0, v) c = cos(-pi/3) s = sin(-pi/3) n3rotated = [n3[0] * c - n3[1] * s, n3[0]* s + n3[1] * c] p1 = point1 p2 = vecadd(point1, n3) p3 = vecadd(p2, n3rotated) p4 = vecadd(p2,n3) p5 = point2 return [p1, p2, p3, p4, p5] def KochFuncOnSequence(s): retval = [] for i in range(len(s)-1): retval += KochFunc(s[i], s[i+1])[:4] retval += KochFunc(s[len(s)-1], s[0]) return retval
from math import *
def vecadd(v1,v2): return [x+y for x,y in zip(v1,v2)]
def vecsub(v1, v2): return [x-y for x,y in zip(v1,v2)]
def scalarprod(s, v1): return [x * s for x in v1]
def dotprod(v1, v2): t = [x*y for x,y in zip(v1,v2)] s = 0.0 for x in t: s += x return s def length(vector): return sqrt(dotprod(vector,vector))
def vector(point1, point2): return [y - x for x,y in zip(point1, point2)] def dist(point1, point2): return length(vector(point1, point2))
def normalize(vector): l = length(vector) return scalarprod(1.0/l, vector)
def KochFunc(point1, point2): if (len(point1) != 2): return [] v = vector(point1,point2) n3 = scalarprod(1.0/3.0, v) c = cos(-pi/3) s = sin(-pi/3) n3rotated = [n3[0] * c - n3[1] * s, n3[0]* s + n3[1] * c] p1 = point1 p2 = vecadd(point1, n3) p3 = vecadd(p2, n3rotated) p4 = vecadd(p2,n3) p5 = point2 return [p1, p2, p3, p4, p5] def KochFuncOnSequence(s): retval = [] for i in range(len(s)-1): retval += KochFunc(s[i], s[i+1])[:4] retval += KochFunc(s[len(s)-1], s[0]) return retval
and here's the second:
import syssys.LoadAssemblyByName("PresentationCore")sys.LoadAssemblyByName("PresentationFramework")sys.LoadAssemblyByName("WindowsBase") from math import *from System.Windows import *from System.Windows.Media import *from System.Windows.Controls import *from System.Windows.Shapes import *from Koch import * def makePoints(sequence): retval = [] for x in sequence: retval.append(Point(x[0],x[1])) return retval def makeFigure(sequence): points = makePoints(sequence) figure = PathFigure() figure.StartAt(points[0]) for x in points[1:-1]: figure.LineTo(x) return figure def makeGeometry(sequence): g = PathGeometry() g.AddFigure(makeFigure(sequence)) return g def makeSnowFlake(sequence): g = makeGeometry(sequence) p = Path() p.Data = g return p Scale = 800.0StartTriangle = [[0,100], [Scale,100], [Scale/2, Scale*sin(pi/3)+100]]FirstDegreeFlake = KochFuncOnSequence(StartTriangle)SecondDegreeFlake = KochFuncOnSequence(FirstDegreeFlake) def drawFlake(target, degree = 2, brush=Brushes.Cyan): s = StartTriangle for i in range(degree): s = KochFuncOnSequence(s) p = makeSnowFlake(s) p.Fill = brush p.SetValue(Canvas.TopProperty, 50.0) target.Children.Add(p) return p def sampleFlake(target): stop1 = GradientStop(Colors.Yellow, 0.0) stop2 = GradientStop(Colors.Orange, 1.0) stops = GradientStopCollection() stops.Add(stop1) stops.Add(stop2) p = drawFlake(target, 6, LinearGradientBrush(stops)) p.SetValue(Canvas.TopProperty, 120.0) p.Stroke = Brushes.Violet return p
import syssys.LoadAssemblyByName("PresentationCore")sys.LoadAssemblyByName("PresentationFramework")sys.LoadAssemblyByName("WindowsBase")
from math import *from System.Windows import *from System.Windows.Media import *from System.Windows.Controls import *from System.Windows.Shapes import *from Koch import *
def makePoints(sequence): retval = [] for x in sequence: retval.append(Point(x[0],x[1])) return retval def makeFigure(sequence): points = makePoints(sequence) figure = PathFigure() figure.StartAt(points[0]) for x in points[1:-1]: figure.LineTo(x) return figure def makeGeometry(sequence): g = PathGeometry() g.AddFigure(makeFigure(sequence)) return g def makeSnowFlake(sequence): g = makeGeometry(sequence) p = Path() p.Data = g return p
Scale = 800.0StartTriangle = [[0,100], [Scale,100], [Scale/2, Scale*sin(pi/3)+100]]FirstDegreeFlake = KochFuncOnSequence(StartTriangle)SecondDegreeFlake = KochFuncOnSequence(FirstDegreeFlake)
def drawFlake(target, degree = 2, brush=Brushes.Cyan): s = StartTriangle for i in range(degree): s = KochFuncOnSequence(s) p = makeSnowFlake(s) p.Fill = brush p.SetValue(Canvas.TopProperty, 50.0) target.Children.Add(p) return p
def sampleFlake(target): stop1 = GradientStop(Colors.Yellow, 0.0) stop2 = GradientStop(Colors.Orange, 1.0) stops = GradientStopCollection() stops.Add(stop1) stops.Add(stop2) p = drawFlake(target, 6, LinearGradientBrush(stops)) p.SetValue(Canvas.TopProperty, 120.0) p.Stroke = Brushes.Violet return p