""" A Visual Python animation showing a "triangular page" going back and forth between triangular book covers laid flat against the XY plane. The page tip traces a semi-circle (not displayed but certainly computed). As a result of two triangular "flaps" (cover and page) at some dihedral angle, a tetrahedron is defined, actually two, one with each cover as base, tip as opposite vertex. Their volumes will always be the same. The video pauses in two places (time.sleep()). The Tetrahedron class (imported) is designed to natively return volume in "tetravolumes" but you can flip that switch easily to use xyz_volume instead.
Dependencies: Python 3.x (python.org) Visual Python (vpython.org) stickworks.py (3.x version) https://mail.python.org/pipermail/edu-sig/2013-September/010896.html tetravolumes.py https://mail.python.org/pipermail/edu-sig/2013-August/010872.html (watch for / repair word-wrapping in this code -- too wide for mailman defaults) Videos and more explanation: http://controlroom.blogspot.com/2013/09/polyhedrons-at-play.html """ from tetravolumes import Tetrahedron from stickworks import Vector, Edge import math import time from visual import * # This module runs as "__main__" so the visual stuff kicks it off scene2 = display(title = "Book Covers", width=500, height=500, background=(0,0,0), center=(0,0,0)) scene2.forward = (0,1,-.3) scene2.autocenter = False scene2.range = (2,2,4) scene2.select() # In this namespace, a rod with its tail at the origin is a Vector while some line # segment floating in space with neither end at the origin is an Edge. # So rods like C0--S1 and even the spine and axis themselves are modeled # as Edges, not Vectors. Edges are *defined* using two Vectors however, # one pointing to each end. # S0 --- S1 is the spine, two XYZ Vectors (defined in a different module named # stickworks. I use the Y axis, with Z considered vertical. S0 = Vector((0,0.5,0)) S1 = -S0 spine = Edge(S0, S1) # spine of a book (equilateral triangular book covers) # C0 -- C1 would be the book cover axis from cover to cover, nailed down and # fixed. Again, these are modeled as Vectors. X axis is used. C0 = Vector((math.sqrt(3)/2,0,0)) C1 = -C0 axis = Edge(C0, C1) # another fixed Edge # spine to C0 S0C0 = Edge(S0,C0) S1C0 = Edge(S1,C0) # spine to C1 S0C1 = Edge(S0,C1) S1C1 = Edge(S1,C1) class Page: """ triangular page modeled by its tip oscillating between pages. """ def __init__(self, angle=0): self.angle = angle # degrees self.tip = self._getVector() def delta_angle(self, degrees): self.angle += degrees self.tip = self._getVector() def _getVector(self): #The page tip's job is to make an arc using sine and cosine of the dihedral # angle the page is making with the flap, starting with tip at C0. z = math.sin(math.radians(self.angle)) * axis.length/2 x = math.cos(math.radians(self.angle)) * axis.length/2 y = 0 return Vector((x,y,z)) def complementary(page): a = Edge(page.tip, S0).length b = Edge(page.tip, C0).length c = Edge(page.tip, S1).length d = S0C0.length e = S1C0.length f = spine.length t0 = Tetrahedron(a,b,c,d,e,f) a = Edge(page.tip, S0).length b = Edge(page.tip, C1).length c = Edge(page.tip, S1).length d = S0C1.length e = S1C1.length f = spine.length t1 = Tetrahedron(a,b,c,d,e,f) return t0, t1 def inadvertent(page): # stub function marking a 3rd tetrahedron of opposite # edges green and blue, other edges red, as a fall-out, # like another consequence of the setting for t. Per # Koski's studies. t2 = Tetrahedron( ) return t2 spine.draw() S0C0.draw() S1C0.draw() S0C1.draw() S1C1.draw() lamp = local_light(pos=(0,-3,0), color=color.yellow) page = Page() def drawit(page): s=Edge(page.tip, S0, color=(1,0,0)) t=Edge(page.tip, C1, color=(0,0,1)) u=Edge(page.tip, S1, color=(1,0,0)) v=Edge(page.tip, C0, color=(0,1,0)) s.draw() t.draw() u.draw() v.draw() rate(30) return s,t,u,v def eraseit(*seq): for obj in seq: obj.erase() # a loop drives the page back and forth by upping and lowering # the degrees, of the dihedral angle. So you'll spot where, when I'm # close to "regular tetrahedron" (71 degree) I swap in a dihedral angle # computed with trig -- you could say it's a still snap shot of the ideal, # whereas the animation skips such "irrational" dihedrals. for i in range(4): for t in range(180): page.delta_angle(1) a,b,c,d = drawit(page) if i == 2 and t == 71: page = Page(math.degrees(math.asin( 1/sqrt(3))) * 2) T1, T2 = complementary(page) # choose T1.ivm_volume OR T1.xyz_volume tx =text(text="Vol = {:>6.3f}".format(T1.ivm_volume()), pos=(-1, 0, -1), height=0.4, depth=-0.1, up=(0,0,1), color = color.orange) time.sleep(10) tx.visible = False eraseit(a,b,c,d) # The two stops to display volumes are programmed in. It's not like # I can stop it arbitrarily and have the volume displayed, although the # 2nd video may give that illusion. for t in range(180): page.delta_angle(-1) a,b,c,d = drawit(page) if i == 0 and t == 90: T1, T2 = complementary(page) # choose T1.ivm_volume OR T1.xyz_volume tx =text(text="Vol = {:>6.3f}".format(T1.ivm_volume()), pos=(-1, 0, -1), height=0.4, depth=-0.1, up=(0,0,1), color = color.orange) time.sleep(10) tx.visible = False eraseit(a,b,c,d)
_______________________________________________ Edu-sig mailing list Edu-sig@python.org https://mail.python.org/mailman/listinfo/edu-sig