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 object color solid is viewed as a zonohedron; this connection was discovered by Paul Centore and is explained very clearly in [1].
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.
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.
## 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].
## 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
.
## [,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 )
}
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) )
In this figure, the black dot is the black point [0,0,0]. The white dot is the white point, i.e. the column sums of the generating matrix.
Here are a few possible improvements and additions.
export
There should be a way to export a zonohedron as a quadrilateral mesh in
some standard format(s).
vignettes
There should be more vignettes. One idea is to show ways to examine
individual hyperplanes and facets of a zonohedron. Another idea is to
display some interesting Minkowski sums of a few classic zonohedra.
The constructor zonohedron()
uses the optimizations in
Paul Heckbert’s memo [6]. The key step is
sorting points that lie on a great circle on the sphere. This efficient
method is \(O(N^2\log(N))\); whereas
the naive method is \(O(N 2^N)\).
The central symmetry is used whenever possible, and when used this can speed things up by a factor of 2. To further speed things up, many of the methods use C/C++.
The function grpDuplicated()
was written by Long Qu,
with a small modification of the return value by myself. It is written
in C/C++ and is implemented with std::unordered_map
. The
code was taken from the discontinued package
uniqueAtomMat, see [8].
Logging is performed using the package logger, see
[3]. This is a powerful package that
allows a separate configuration for logging from within
zonohedra, and that is what I have done. During package
loading, the logging threshold is changed from INFO
to
WARN
. To change it back again, one can execute:
log_threshold( INFO, namespace="zonohedra" )
The layout callback functions is customized; it adds the name of the
calling function to the message. To install your own layout function,
you can execute:
log_layout( <your function>, namespace="zonohedra" )
The appender callback functions is also customized; it comes to an
immediate stop if the message level is ERROR
or
FATAL
. To return to the default behavior, you can
execute:
log_appender( appender_console, namespace="zonohedra" )
The formatter callback function is forced to be
formatter_sprintf()
; this should not be changed.
R version 4.4.2 (2024-10-31 ucrt) Platform: x86_64-w64-mingw32/x64 Running under: Windows 11 x64 (build 26100) Matrix products: default locale: [1] LC_COLLATE=C [2] LC_CTYPE=English_United States.utf8 [3] LC_MONETARY=English_United States.utf8 [4] LC_NUMERIC=C [5] LC_TIME=English_United States.utf8 time zone: America/Los_Angeles tzcode source: internal attached base packages: [1] stats graphics grDevices utils datasets methods base other attached packages: [1] gifski_1.32.0-1 orientlib_0.10.5 rgl_1.3.12 zonohedra_0.4-0 loaded via a namespace (and not attached): [1] digest_0.6.37 R6_2.5.1 base64enc_0.1-3 [4] microbenchmark_1.5.0 fastmap_1.2.0 xfun_0.49 [7] magrittr_2.0.3 glue_1.8.0 cachem_1.1.0 [10] knitr_1.49 htmltools_0.5.8.1 logger_0.4.0 [13] rmarkdown_2.29 lifecycle_1.0.4 cli_3.6.3 [16] sass_0.4.9 jquerylib_0.1.4 compiler_4.4.2 [19] tools_4.4.2 evaluate_1.0.1 bslib_0.8.0 [22] yaml_2.3.10 htmlwidgets_1.6.4 rlang_1.1.4 [25] jsonlite_1.8.9