---
author: Stéphane Laurent
date: '2022-02-05'
highlighter: 'pandoc-solarized'
output:
html_document:
highlight: kate
keep_md: no
md_document:
preserve_yaml: True
variant: markdown
rbloggers: yes
tags: 'R, maths, geometry, graphics, rgl'
title: 'Gyrotriangle (aka hyperbolic triangle) with moving colors'
---
My package [gyro](https://github.com/stla/gyro) has been freshly
released on CRAN. I implemented the ideas given in [this blog
post](https://laustep.github.io/stlahblog/posts/hyperbolicPolyhedra.html)
in this package. It has a short
[vignette](https://cran.r-project.org/web/packages/gyro/vignettes/getstarted.html).
The `gyrodemos` function provides some examples. But none of them
explains how I did the moving colors on this polyhedra that you can see
on the Github repo:
![](https://raw.githubusercontent.com/stla/gyro/main/inst/images/icosahedron_dynamic_colors.gif)
So I will explain here. In fact, this is similar to the method I
presented
[here](https://laustep.github.io/stlahblog/posts/PyVistaDynamicCmap.html)
for **PyVista** and
[here](https://laustep.github.io/stlahblog/posts/HopfTorusDynamicColors.html)
for **rgl**.
The `gyrotriangle` function of the **gyro** package has a `palette`
argument, in which the user provides a vector of colors. Here is an
example:
``` {.r}
library(gyro)
library(rgl)
s <- 0.6 # hyperbolic curvature
A <- c(1, 0, 0); B <- c(0, 1, 0); C <- c(0, 0, 1)
ABC <- gyrotriangle(
A, B, C, s = s,
palette = hcl.colors(n = 256, palette = "Berlin")
)
open3d(windowRect = c(50, 50, 562, 562))
material3d(lit = FALSE)
view3d(10, 40, zoom = 0.8)
shade3d(ABC)
```
![](figures/gyrotriangle.png)
Under the hood, the `gyrotriangle` function uses the
[colorRamp](https://www.rdocumentation.org/packages/grDevices/versions/3.6.2/topics/colorRamp)
with the vector of colors passed to the `palette` argument. This creates
a function, let's call it `fpalette`, that assigns a color to each
number in the interval $[0, 1]$. Then, `gyrotriangle` calculates all the
distances from the points in the mesh forming the triangle to the
gyrocentroid of the triangle. Finally, it linearly normalizes these
distances to the interval $[0, 1]$, and it applies the `fpalette`
function to the normalized distances.
Now, the `gyrotriangle` function has a `g` argument. This is the key to
make the moving colors. This argument `g` must be a function from
$[0, 1]$ to $[0, 1]$, by default it is the `identity` function, and
`fpalette` is actually applied to the normalized distances transformed
by `g`.
So, here is how we can do to get some moving colors:
``` {.r}
shift_ <- seq(0, 1, length.out = 61)[-1]
for(i in seq_along(shift_)){
ABC <- gyrotriangle(
A, B, C, s,
palette = hcl.colors(n = 256, palette = "Berlin"),
g = function(u) (sin(2*pi*(u - shift_[i])) + 1) / 2
)
open3d(windowRect = c(50, 50, 562, 562))
material3d(lit = FALSE)
view3d(10, 40, zoom = 0.8)
shade3d(ABC)
rgl.snapshot(sprintf("snapshot%03d", i))
close3d()
}
library(gifski)
pngs <- list.files(pattern = "^snapshot")
gifski(
pngs,
gif_file = "gyrotriangle.gif",
width = 512,
height = 512,
delay = 1/8
)
file.remove(pngs)
```
![](figures/gyrotriangle.gif)