#!/usr/bin/env python # coding: utf-8 # # Central Angles of the E-Module # # #### By David Koski (trig) & Kirby Urner (python) # # ![E mod](http://www.rwgrayprojects.com/synergetics/s09/figs/f86411b.gif) # # The above [Fig. 986.411B](http://www.rwgrayprojects.com/synergetics/s09/figs/f86411b.html) shows the "plane net" or template for an E or T module. # # If you cut it out with scissors and fold it up, reversing the lid (have to slice it off), you'll get a tetrahedron. You can fold it up in two ways, creasing towards you or away from you. # # A & B modules, used to assemble other shapes, also come with plane nets and fold the same two ways, into "left" and "right". You can call them "congruent" but don't forget they're mirror images or inside-out versions of one another. # # The T & E modules have the same angles. 120 Ts (60 left, 60 right) build a Rhombic Triacontahedron of tetravolume 5, whereas 120 Es build a Rhombic Triacontahedron of radius 1. # # The Tmod RT has a slightly shorter radius of ~0.9994 versus 1.0. Its volume is therefore a bit less as well. # # Here's [Fig. 986.419] from Buckminster Fuller's *Synergetics*: # # ![T mod](http://www.rwgrayprojects.com/synergetics/s09/figs/f86419.gif) # # [Fig. 986.419]: http://www.rwgrayprojects.com/synergetics/s09/figs/f86419.html # # Per David Koski's research, we an use the arctangent function to express angles using expressions involving the golden ratio or Phi (Greek letter: Ø). # # The central angles are at the center of the Rhombic Triacontahedron, where three vectors radiate towards the surface, forming three angles with one another. In this Notebook, we see how smaller angles may be used to define bigger ones. # #
# The three central angles of the E module are:
# a = 31.717474411º
# b = 37.377368140º
# c = 20.905157447º
# these three sum to 90º
# 
# # With the help of two smaller angles, d and e, we can build a and b. # #
# d = 13.282525588º
# e = 10.812316963º
# a = c + e
# b = 2d + e
# 
# # And with still smaller angles, we can build d and e, also c: # #
# Now we introduce three even smaller angles, f and g:
# f = 7.622631859º
# g = 5.659893729º
# h = 5.152423234º
# 
# c = 2f + g
# d = f + g
# e = g + h
# 
# # In sum, f and g will build all the angles so far: # #
# a = 2f + 2g + h
# b = 2f + 3g + h
# c = 2f + g
# 
# # Here are all of the eight angles in terms of the arctangent of a "phi expression": # #
# a = 31.717474º  = arctan(Ø^-1)       = arctan(0.618034)
# b = 37.377368º  = arctan(2Ø^-2)      = arctan(0.763932)
# c = 20.905157º  = arctan(Ø^-2)       = arctan(0.381966)
# d = 13.282525º  = arctan(Ø^-3)       = arctan(0.236068)
# e = 10.812316º  = arctan(Ø^-2/2)     = arctan(0.190983)
# f = 7.622631º   = arctan((2√5-3)/11) = arctan(0.133830)
# g = 5.659893º   = arctan((5√5-9)/22) = arctan(0.099106)
# h = 5.152423º   = arctan(Ø^-5)       = arctan(0.090169)
# 
# # As a prelude to getting some work done, lets import some tools familiar to most Pythonistas. These are likewise "namepaces" e.g inside of numpy we find a collection of names. These names have "powers" in the sense of capabilities, as well as "attributes" (as in properties). # In[1]: import numpy as np import pandas as pd from math import atan, tan, degrees, radians, sqrt # We say "square" root (in quotes) because in *Synergetics* we may want to use a triangular area to show the same idea. Two edges A, B at 60 degrees multiply to give an area A times B. Just add the 3rd vector (A-B) to "close the lid". The same technique applies to multiplying A times B times C: three vectors from an origin, at 60 degrees to one another, define a tetrahedron. "Close the lid" to get the corresponding volume. # # Here's another figure, [Fig. 990.01] from *Synergetics* to help make sense of this idea. # # ![Fig. 990.01](http://www.rwgrayprojects.com/synergetics/s09/figs/f9001.gif) # # [Fig. 990.01]: http://www.rwgrayprojects.com/synergetics/s09/figs/f9001.html # # It's important to introduce these alternative models of 2nd and 3rd powering because our idea of "tetravolumes" derives from there. # # As of 2018, very few mathematicians have dared to comment on this 1900s literary innovation within New England Transcendentalism. # # Hugh Kenner, a James Joyce scholar, is one of the few to have contributed any secondary literature regarding Fuller's forays into mathematics and logic. Given how alien this thinking remains, we sometimes refer to it as "Martian Math". # In[2]: rt5 = sqrt(5) # 2nd root of 5 or "square" root Ø = (1 + rt5)/2 # golden ratio f = atan((2*rt5 - 3)/11) g = atan((5*rt5 - 9)/22) h = atan(Ø ** -5) # Per David's comments above: f, g, h serve as basis angles such that linear combinations thereof net additional angles a-e. # #
# a = 2f + 2g + h
# b = 2f + 3g + h
# c = 2f + g
# d = f + g
# e = g + h
# 
# # When it comes to linear combinations, we tend to use "matrix operations" and in this case simple integer coefficients do the work. Create ```[f, g, h]``` as a vertical column vector, and multiply it on the left with a matrix. For example, in the top row of this matrix we have # ```[2,2,1]``` meaning we'll get ```2 * f + 2 * g + h``` as the top cell of our 5 by 1 result matrix, or angle a. # In[3]: m = np.array([f, g, h]).reshape(3,1) m # In[4]: coeffs = np.array([[2,2,1],[2,3,1],[2,1,0],[1,1,0],[0,1,1]]) coeffs # In[5]: coeffs.dot(m) # In order to use "parallel assignment" we may stretch this column vector into a numpy array of shape (5, ), making it akin to an ordinary Python list. # In[6]: angles = coeffs.dot(m).ravel() angles.shape # In[7]: a,b,c,d,e = angles # get the five values # Now let's build a 1-d vector this time adding f,g,h on the end. We will use this numpy ndarray to transition to a pandas Series, very like a column vector yet able to support labels i.e. string indexes. # In[8]: vector = np.array([a,b,c,d,e,f,g,h]) vector # In[9]: col1 = pd.Series(vector, index=['a','b','c','d','e','f','g','h']) # note letter indexes # In[10]: col1 # a pandas Series # We get our arctangent results in radians. To confirm we getting the right numbers in terms of degrees, lets set up a parallel column. Numpy operations apply to entire columns or vectors, no need to write a Python loop. # In[11]: col2 = np.degrees(col1) # convert radians to degrees col2 # Now we'll use the pandas ```concat``` function to create a pandas Dataframe. Since we're expanding along the column axis, not the row axis, we say axis = 1. Otherwise ```concat``` will try to put the columns on top of one another. # In[12]: df = pd.concat([col1, col2], axis=1) # build a 2-column dataframe # In[13]: df.rename(columns={0: 'Radians', 1: 'Degrees'}, inplace=True) # renaming columns # In[14]: df # Using the Dataframe ```loc``` attribute, and square brackets (for indexing), we may give both row and column lists. Below we're checking that a, b, c sum to 90 degrees as expected. If we sum the radians column, we would expect pi/2. # In[15]: np.sum(df.loc[['a','b','c'], 'Degrees']) # In[16]: np.sum(df.loc[['a','b','c'], 'Radians']) # The arctangent function is the inverse of the tangent function. Going from the radians column back to some initial argument to arctangent, should give us a final cross-check of our initial phi expressions, derived by David Koski. # # Here we go then: # In[17]: col0 = np.tan(col1) # work back from radians # In[18]: col0 #
# The arctangents of the 8 angles described above:
# a = 31.717474º  = arctan(Ø^-1)       = arctan(0.618034)
# b = 37.377368º  = arctan(2Ø^-2)      = arctan(0.763932)
# c = 20.905157º  = arctan(Ø^-2)       = arctan(0.381966)
# d = 13.282525º  = arctan(Ø^-3)       = arctan(0.236068)
# e = 10.812316º  = arctan(Ø^-2/2)     = arctan(0.190983)
# f = 7.622631º   = arctan((2√5-3)/11) = arctan(0.133830)
# g = 5.659893º   = arctan((5√5-9)/22) = arctan(0.099106)
# h = 5.152423º   = arctan(Ø^-5)       = arctan(0.090169)
# 
# In[19]: phi_expr = pd.Series([Ø**-1, 2*Ø**-2, Ø**-2, Ø**-3, (Ø**-2)/2,(2*rt5-3)/11, (5*rt5-9)/22, Ø**-5], index=['a','b','c','d','e','f','g','h']) phi_expr # In[20]: df = pd.concat([phi_expr, col0, col1, col2], axis=1) # In[21]: df.rename(columns={0: "Phi Expr", 1: "Arctan of...", 2: 'Radians', 3: 'Degrees'}, inplace=True) # In[22]: df