--- title: "zonohedra User Guide" author: "Glenn Davis" date: "`r Sys.Date()`" output: rmarkdown::html_vignette: toc: true toc_depth: 2 number_sections: false bibliography: bibliography.bib # csl: iso690-numeric-brackets-cs.csl csl: personal.csl # csl: institute-of-mathematical-statistics.csl # csl: transactions-on-mathematical-software.csl vignette: > %\VignetteIndexEntry{zonohedra User Guide} %\VignetteEngine{knitr::rmarkdown} --- ```{css, echo=FALSE} body { max-width: 750px; /* make a little wider, default is 700px */ } /* div.figure { border: 1px; border-style: groove; } */ ``` ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) old_opt = options( width=120 ) # if( !file.exists("figs") ) dir.create("figs") require("rgl",quietly=TRUE) rgl::setupKnitr(autoprint = TRUE) ``` # Introduction A _zonohedron_, roughly speaking, is the projection of a high-dimensional cube to $\mathbb{R}^3$. For a precise definition see the [Zonotopes](zonotopes.html) 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 @wikiZonohedron 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 @Centore2013. ```{r, echo=TRUE, message=FALSE} 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.

# 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. ```{r, echo=TRUE, message=TRUE, warning=TRUE, fig.width=8, fig.height=4, fig.cap='polar zonohedra with 5 generators (left) and 25 generators (right)    [both of these are interactive WebGL widgets]', fig.keep='none', fig.show='hide', out.width="100%", cache=FALSE } rgl::mfrow3d( 1, 2 ) pz5 = polarzonohedron( 5 ) ; plot( pz5, ewd=5 ) rgl::next3d() plot( polarzonohedron( 25 ), ewd=3 ) rgl::rglwidget( webgl=TRUE ) ``` 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 @Chilton1963. Print the generators of the first zonohedron `pz5`; they are the columns of this 3x5 matrix. ```{r, echo=TRUE, message=FALSE} getmatrix( pz5 ) ``` 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 @Eppstein. ```{r, echo=TRUE, message=FALSE} classics.genlist ``` Extract the matrix of generators for the `truncated cuboctahedron`, which is abbreviated by `TC`. ```{r, echo=TRUE, message=TRUE} mat = classics.genlist[['TC']] ; mat ``` Create the truncated cuboctahedron and plot it, with filled faces. ```{r, rgl=TRUE, echo=TRUE, message=TRUE, warning=TRUE, fig.width=8, fig.height=5, out.width="100%", fig.align="center", fig.cap='truncated cuboctahedron      [This is an interactive WebGL widget]', fig.keep='last', fig.show='hide', cache=FALSE } rgl::par3d( userMatrix = rotationMatrix( -20*pi/180, 0, 1, 1) ) zono = zonohedron( mat ) plot( zono, type='f' ) rgl::rglwidget( webgl=TRUE ) ```
Before continuing, define function `spinit()` used for creating animated GIFs. ```{r, echo=TRUE, message=FALSE, warning=FALSE} 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. ```{r, echo=TRUE, message=TRUE, warning=TRUE, fig.cap='object color solid', fig.keep='last', fig.show='hide', cache=FALSE } # 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) ) ``` ![object color solid at 5nm interval](`r gif_file`){width=60%} 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.

# Future Work 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.

# References


\Appendix

## Appendix A - Methods The constructor `zonohedron()` uses the optimizations in Paul Heckbert's memo @Heckbert1985. 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 @uniqueAtomMat.

## Appendix B - Logging Logging is performed using the package **logger**, see @logger. 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( , 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.

# Session Information This document was prepared `r format(Sys.Date(), "%a %b %d, %Y")` with the following configuration:
```{r, echo=FALSE, results='asis'}
options( old_opt )
sessionInfo()
```