[Edu-sig] bookdemo.py (a Visual Python animation -- reprogrammable)

kirby urner kirby.urner at gmail.com
Sun Sep 29 19:54:52 CEST 2013


"""
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)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/edu-sig/attachments/20130929/30c80806/attachment-0001.html>


More information about the Edu-sig mailing list