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:In the first case, 13 classical zonohedra have been taken from [9] and are built in to the package. In the second case, an optimal 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:
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.
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.
::mfrow3d( 1, 2 )
rgl= polarzonohedron( 5 ) ; plot( pz5, ewd=5 )
pz5 ::next3d()
rglplot( polarzonohedron( 25 ), ewd=3 )
::rglwidget( webgl=TRUE ) rgl
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()
.
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
.
= classics.genlist[['TC']] ; mat 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.
::par3d( userMatrix = rotationMatrix( -20*pi/180, 0, 1, 1) )
rgl= zonohedron( mat )
zono plot( zono, type='f' )
::rglwidget( webgl=TRUE ) rgl
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)
<- function( zono, index, fps=5, duration=8, revolutions=1, vpsize=c(480,480) ) {
spinit # enlarge viewport
= par3d( "windowRect" )
wr par3d( windowRect = c( wr[1:2], wr[1:2] + vpsize ) )
= "./figs" ; if( ! file.exists(pathtemp) ) dir.create(pathtemp) # make temp folder
pathtemp # 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
= dir( pathtemp, pattern="png$", full=T )
pathvec = sprintf( "./figs/animation%g.gif", index )
gif_file # if( file.exists(gif_file) ) file.remove( gif_file )
= gifski::gifski( pathvec, gif_file=gif_file, delay=1/fps, progress=F, width=vpsize[1], height=vpsize[2] )
out = file.remove( pathvec ) # cleanup the .PNG files, leaving just the .GIF
res
return( out )
}
In colorimetry, an optimal color solid is a zonohedron.
# colorimetry.genlist[[1]] is a 3x81 matrix with the CIE 1931 CMFs at 5nm interval
= zonohedron( colorimetry.genlist[[1]] )
zono5 plot( zono5, type='f' )
= spinit( zono5, 2, vpsize=c(256,256) ) gif_file