For just starting to explore with VPython window, getting one's feet wet, I'm looking at such as stickworks.py as a simple place to begin (excerpts below). The stickworks namespace wants us to think of Vector objects as radiating from (0,0,0), i.e. they're always tail anchored to the origin. class Vector (object): """ A wrapper for visual.vector that expresses a cylinder via draw(), always pegged to the origin """ radius = 0.03 def __init__(self, xyz, color=(0,0,1)): self.v = vector(*xyz) self.xyz = xyz self.color = color self.cyl = None def draw(self): """define and render the cylinder""" self.cyl = cylinder(pos = (0,0,0), axis = self.v, radius = self.radius, color = self.color) def erase(self): """toss the cylinder""" if self.cyl: self.cyl.visible = 0 self.cyl = None def __repr__(self): return 'Vector @ (%s,%s,%s)' % self.xyz # some vector ops, including scalar multiplication def cross(self, other): temp = cross(self.v, other.v) return Vector((temp.x, temp.y, temp.z)) etc. Edges, on the other hand, otherwise known as line segments, may connect any two points in space, and as such are defined by the arrow *tips* of two Vectors of the type defined above. class Edge (object): """ Edges are defined by two Vectors (above) and express as cylinder via draw(). """ radius = 0.03 def __init__(self, v0, v1, color=(1,0,0)): self.v0 = v0 self.v1 = v1 self.color = color self.cyl = None def draw(self): """define and render the cylinder""" temp = (self.v1 - self.v0).xyz self.cyl = cylinder(pos = self.v0.xyz, axis = vector(*temp), radius = self.radius, color = self.color) def erase(self): """toss the cylinder""" if self.cyl: self.cyl.visible = 0 self.cyl = None def __repr__(self): return 'Edge from %s to %s' % (self.v0, self.v1) You'll find this dichotomy in some published linear algebra books e.g. this one by Wayne Bishop and Stewart Venit ISBN: 087150300X (Wayne being a Cal State prof and one of my sparring partners on math-teach). I'm not using VPython's cylinder and vector objects directly because I'm wanting an even simpler namespace. Vectors are my primary constituent, followed by edges as pairs of vectors, and faces as tuples of vectors defining three or more edges. Of course in the Fuller School we quickly move to a small subset of polyhedra organized in a particular way (or core mandala, source of many dharmas). We harp on Euler's V + F = E + 2. We talk in an alien manner about our 4D Simplex with energy added (4D++). But that doesn't mean every gnu math teachers needs to follow our lead and/or sequence. The curriculum is a network, and the many trailheads go to many places (partially overlapping) in different orders. Plus Arthur of Pygeo has a whole other toolset you could explore. Save the Bucky stuff for later, if ever. Tell 'em I said it was OK. The sequence I'm developing here is: intro to namespaces --> import stickworks as a namespace --> explore in VPython Given stickworks is provided, student creativity will be more in what they can *do* with it. I'll be thinking of some projects. Dissecting and tweaking source code will also be a focus, as fluency gradually develops, plus writing new modules that assume the above as all given. Kirby
On 9/13/06, kirby urner <kirby.urner@gmail.com> wrote:
Given stickworks is provided, student creativity will be more in what they can *do* with it. I'll be thinking of some projects.
Probably a most obvious application for an Edge connecting pairs of vectors, is to do simple plotting, either in xy or in xyz. Now that we have generators, it's easy to think of a functions domain as a kind of indefinite loop:
def dgen(start, step): while True: yield start start += step
domain = dgen(-10, 0.1)
Similar to xrange, but spelled out. Could be fancier, including a stop point. Then, if we wanted to graph something like cosine, would could pass both the domain and the function as arguments to a plot generator:
import math def f(x): return math.cos(x)
Like, if you wanted 200 points, you could just go:
mkgraph = xyplotter(domain, f) # initialize a generator
for i in xrange(200): mkgraph.next()
This'd give you the sinusoidal wave in VPython, complete with zoom in/out and rotate mouse action. Picture: http://www.4dsolutions.net/ocn/graphics/cosines.png Of course you might also want some axes to make the graph more readable. So... adding xyplotter and axes to stickworks.py: ==== def xyplotter(domain, f): x0 = domain.next() y0 = f(x0) while True: x1 = domain.next() y1 = f(x1) e = Edge( Vector((x0, y0, 0)), Vector((x1, y1, 0)) ) e.draw() yield None # could yield something more explicit x0, y0 = x1, y1 # keep last point, get next def axes(x,y,z): v0 = Vector((x,0,0)) v0.draw() v0 = Vector((-x,0,0)) v0.draw() v0 = Vector((0,y,0)) v0.draw() v0 = Vector((0,-y,0)) v0.draw() v0 = Vector((0,0,z)) v0.draw() v0 = Vector((0,0,-z)) v0.draw() ==== see: http://www.python.org/ocn/python/stickworks.py There's a lot more basic algebra to explore. Parametric equations, various curves... All that stuff we do with TI calculators today, and loosely call "precalculus". I don't think the 'generator' concept, using yield instead of return, is that difficult to understand, and so tend to introduce it early on. By this time, generators are intrinsic to core Python, not esoteric "advanced features" (although itertools may be considered esoteric). Kirby Note: One possible student enchancement might be to stick little balls at the ends of the vector and edge cylinders, to make 'em more rounded, less likely to show gaps.
On 9/13/06, kirby urner <kirby.urner@gmail.com> wrote:
Dang, sorry: http://www.4dsolutions.net/ocn/python/stickworks.py Kirby
participants (1)
-
kirby urner