# Introduction

A zonohedron, roughly speaking, is the projection of a high-dimensional cube to $$\mathbb{R}^3$$. For a precise definition see the Zonotopes vignette, section 1.3. A zonohedron is a special type of convex polyhedron.

The goal of this package is to construct any zonohedron, but especially the ones in these 2 families:
• the classical zonohedra, with high symmetry
• zonohedra that arise naturally from colorimetry, which may contain hundreds of generators, but little symmetry

In the first case, 13 classical zonohedra have been taken from [9] and are built in to the package. In the second case, an object color solid is viewed as a zonohedron; this connection was discovered by Paul Centore and is explained very clearly in [1].

library(zonohedra)
library(rgl)

The package dependencies are:

• rgl [4] - for 3D plotting
• microbenchmark [7] - is suggested for its high-precision timer
• logger [3] - for event logging

Some of the figures below are displayed with WebGL - a JavaScript API for rendering interactive 2D and 3D graphics. Try using the left mouse button to rotate and the scroll wheel to zoom.

# Polar Zonohedra

The generators for a polar zonohedra are particularly simple - they are equally distributed on a circle that is in a plane parallel to the xy-plane and whose center is on the z-axis. Construct polar zonohedra with 5 and 25 generators and plot them.

rgl::mfrow3d( 1, 2 )
pz5 = polarzonohedron( 5 ) ;  plot( pz5, ewd=5 )
rgl::next3d()
plot( polarzonohedron( 25 ), ewd=3 )
rgl::rglwidget( webgl=TRUE )

polar zonohedra with 5 generators (left) and 25 generators (right) â€ƒâ€ƒ [both of these are interactive WebGL widgets]

In these 2 plots, the black dot is the origin, the 5 vertices nearest to the origin are the 5 generators, and the white dot is the point (0,0,$$\pi$$). Each of the generators is assigned a unique color, and every other edge with that color is parallel to the generator. All parallelograms with an edge of that color form the zone or belt for that generator. Each belt is a topological annulus. For more details on these polar zonohedra, see [2].

Print the generators of the first zonohedron pz5; they are the columns of this 3x5 matrix.

getmatrix( pz5 )
##              1         2          3          4          5
## [1,] 0.6283185 0.1941611 -0.5083204 -0.5083204  0.1941611
## [2,] 0.0000000 0.5975664  0.3693164 -0.3693164 -0.5975664
## [3,] 0.6283185 0.6283185  0.6283185  0.6283185  0.6283185

A function similar to polarzonohedron() is regularprism().

# Classic Zonohedra

There are 13 classic zonohedron available in the package, as a list of 3xN matrices, where N is the number of generators. The global data variable is classics.genlist, with S3 class 'genlist'. The 13 matrices in the list are taken from [5].

classics.genlist
##                                   fullname generators vertices edges facets       area     volume pointed
## C                                     cube          3        8    12      6    6.00000    1.00000    TRUE
## RD                    rhombic dodecahedron          4       14    24     12   33.94113   16.00000    TRUE
## BD                   Bilinski dodecahedron          4       14    24     12   38.83282   16.94427    TRUE
## RI                     rhombic icosahedron          5       22    40     20   64.72136   42.36068    TRUE
## RHD          rhombo-hexagonal dodecahedron          5       18    28     12   72.55309   48.00000    TRUE
## RT                 rhombic triacontahedron          6       32    60     30   97.08204   84.72136    TRUE
## TO                    truncated octahedron          6       24    36     14   53.56922   32.00000    TRUE
## TRD         truncated rhombic dodecahedron          7       32    48     18  110.72888   98.76537    TRUE
## TC                 truncated cuboctahedron          9       48    72     26  123.51034  118.22540    TRUE
## RE                rhombic enneacontahedron         10       92   180     90  229.70563  318.88544   FALSE
## RH              rhombic hectotriadiohedron         12      134   264    132  869.36961 2367.25310   FALSE
## TI             truncated icosidodecahedron         15      120   180     62  697.16812 1654.42719    TRUE
## TSR truncated small rhombicosidodecahedron         21      240   360    122 1336.66780 4497.87138   FALSE

Extract the matrix of generators for the truncated cuboctahedron, which is abbreviated by TC.

mat = classics.genlist[['TC']] ; mat
##      [,1]     [,2] [,3] [,4] [,5]     [,6] [,7]     [,8] [,9]
## [1,]    1 1.414214    1    0    1 0.000000    0 0.000000    1
## [2,]   -1 0.000000    0    1    1 1.414214    1 0.000000    0
## [3,]    0 0.000000   -1   -1    0 0.000000    1 1.414214    1
## attr(,"shortname")
## [1] "TC"
## attr(,"fullname")
## [1] "truncated cuboctahedron"

Create the truncated cuboctahedron and plot it, with filled faces.

rgl::par3d( userMatrix = rotationMatrix( -20*pi/180, 0, 1, 1) )
zono = zonohedron( mat )
plot( zono, type='f' )
rgl::rglwidget( webgl=TRUE )

truncated cuboctahedron â€ƒâ€ƒâ€ƒâ€ƒ [This is an interactive WebGL widget]

Before continuing, define function spinit() used for creating animated GIFs.

library(gifski)

#   zono        the zonohedron
#   id          unique ID for this animation, a positive integer
#   fps         frames per second
#   duration    of the animation, in seconds
#   revolutions number of revolutions
#   vpsize      viewport size = (width,height)
spinit <- function( zono, index, fps=5, duration=8, revolutions=1, vpsize=c(480,480) ) {
#  enlarge viewport
wr = par3d( "windowRect" )
par3d( windowRect = c( wr[1:2], wr[1:2] + vpsize ) )
pathtemp = "./figs" ;   if( ! file.exists(pathtemp) ) dir.create(pathtemp)  # make temp folder
#  make a lot of .PNG files in pathtemp
movie3d( spin3d( getcenter(zono), rpm=revolutions*60/duration ), duration=duration, fps=fps, startTime=1/fps,
convert=F, movie='junk', dir=pathtemp, verbose=F, webshot=F )
#  combine all the .PNGs into a single .GIF
pathvec = dir( pathtemp, pattern="png\$", full=T )
gif_file = sprintf( "./figs/animation%g.gif", index )
# if( file.exists(gif_file) )  file.remove( gif_file )
out = gifski::gifski( pathvec, gif_file=gif_file, delay=1/fps, progress=F, width=vpsize[1], height=vpsize[2] )
res = file.remove( pathvec )  # cleanup the .PNG files, leaving just the .GIF

return( out )
}

# Colorimetry Zonohedra

In colorimetry, an object color solid is a zonohedron.

# colorimetry.genlist[[1]] is a 3x81 matrix with the CIE 1931 CMFs at 5nm interval
zono5 = zonohedron( colorimetry.genlist[[1]] )
plot( zono5, type='f' )
gif_file = spinit( zono5, 2, vpsize=c(256,256) )