---
title: "Implicitization"
author: "Glenn Davis"
date: "`r Sys.Date()`"
output:
rmarkdown::html_vignette:
toc: true
toc_depth: 2
number_sections: false
header-includes:
- \newcommand{\abs}[1]{\lvert #1 \rvert}
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{Implicitization}
%\VignetteEngine{knitr::rmarkdown}
---
```{css, echo=FALSE}
body {
max-width: 725px; /* make wider, default is 700px */
}
```
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
old_opt = options( width=144 )
```
# Introduction
```{r, echo=FALSE, message=FALSE}
library(polarzonoid)
```
In the [User Guide](../doc/polarzonoid-guide.html) vignette
it is shown that there is are homeomorphisms
\begin{equation}
A_n ~~ \longleftrightarrow ~~ \partial Z_n ~~ \longleftrightarrow ~~ \mathbb{S}^{2n}
\end{equation}
where $A_n$ is the space of $n$ or fewer pairwise disjoint arcs in the circle,
and $Z_n$ is the polar zonoid in $\mathbb{R}^{2n+1}$.
The forward direction $\partial Z_n ~~ \to ~~ \mathbb{S}^{2n}$ is the trivial projection
onto the unit sphere centered at $(0,...0,\pi)$.
But the reverse direction requires intersecting a ray with $\partial Z_n$, which is non-trivial.
The function in the package that performs this intersection is `boundaryfromsphere()`.
It expresses $\partial Z_n$ as the level set of a real-valued function,
and uses `uniroot()` to solve for the intersection point.
In this vignette, we outline how $\partial Z_n$ is defined parametrically
and how the real-valued function is derived. This process is called _implicitization_, see @cox2008.
In the current version of the package, the implicitization has only been computed for $n$=1,2, and 3.
Throughout this vignette we think of $\partial Z_n \subseteq \mathbb{R}^{2n+1}$
and identify the latter with points $(z_1,...,z_n,L)$ where $z_i$ are complex
numbers and $L$ is real.
Assume first that $n{=}1$ so there is a single arc in the circle, i.e. a point in $A_1$.
We parameterize the arc by its first and last endpoints $u_1$ and $v_1$,
both on the unit circle in the complex plane, and proceeding counterclockwise from $u_1$ to $v_1$.
Let the length of the arc be $l_1$, so that $v_1 = u_1 e^{i l_1}$.
It is not hard to show that the map $A_1 \to \partial Z_1$ is given by
\begin{equation}
(u_1,v_1) \mapsto ( ~(v_1{-}u_1)/i, ~ l_1 ~) ~=~ (z_1,L)
\end{equation}
where $z_1 := (v_1{-}u_1)/i$.
Similarly, when $n{=}2$, it is easy to show that the map $A_2 \to \partial Z_2$ is given by:
\begin{equation}
(u_1,v_1,u_2,v_2) \mapsto ( ~ \left( v_1{-}u_1 + v_2{-}u_2 \right)/i, ~ \left( v_1^2{-}u_1^2 + v_2^2{-}u_2^2 \right)/(2i), ~ l_1{+}l_2 ~) ~=~ (z_1,z_2,L)
\end{equation}
and so on for $n \ge 3$.
Since $u_i$ and $v_i$ are unit vectors, $u_i \overline{u_i} = 1$ and $v_i \overline{v_i} = 1$
where the overline denotes complex conjugate.
It follows easily that:
\begin{align}
\overline{z_1} &= \big( u_2 v_2 (v_1 - u_1) + u_1 v_1(v_2 - u_2) \big) \left( -i / (u_1 u_2 v_1 v_2) \right) \\
\overline{z_2} &= \big( u_2^2 v_2^2 (v_1^2 - u_1^2) + u_1^2 v_1^2(v_2^2 - u_2^2) \big) \left( -i / (2 u_1^2 u_2^2 v_1^2 v_2^2) \right)
\end{align}
And using Euler's formula, one can show:
\begin{align}
\sin(L/2) &= \frac{v_1 v_2 - u_1 u_2}{2i} ~~ \frac{e ^{-iL/2}}{u_1 u_2} \\
\cos(L/2) &= \frac{v_1 v_2 + u_1 u_2}{2} ~~ \frac{e ^{-iL/2}}{u_1 u_2}
\end{align}
The expressions for $n{=}1$ and $n{=}3$ are similar.
These right-hand-sides are "rational enough" that algebraic geometry can be used for implicitization.
We use the Rational Implicitization algorithm in Chapter 3, Section 3 of @cox2008.
The fact that second term in each RHS is a unit complex number plays a simplifying role.
The results are in the next section.
# The Equations for $n$ = 1,2, and 3 arcs
Throughout this section we assume that $L \in [0,2\pi]$.
With lots of help from Macaulay2 @M2, followed by manual rearrangement,
one can show that for $n$ = 1,2, and 3 that
\begin{equation}
(z_1,...,z_n,L) \in \partial Z_n ~~~ \text{ iff } ~~~ | \gamma_n(z_1,...,z_n,L) | = \rho_n(z_1,...,z_n,L)
\end{equation}
and
\begin{equation}
(z_1,...,z_n,L) \in Z_n ~~~ \text{ iff } ~~~ | \gamma_n(z_1,...,z_n,L) | \le \rho_n(z_1,...,z_n,L)
\end{equation}
where $\gamma_n()$ is a complex-valued function, and $\rho_n()$ is a real-valued function.
The details of this are complicated, especially for $n{=}3$, and are omitted.
For $n{=}4$, Macaulay2 runs out of memory and
cannot finish; but I conjecture that these two functions exist for all $n$.
For small $n$, they are given in this table:
```{r, echo=FALSE, message=TRUE}
library( flextable )
requireNamespace('equatags',quietly=TRUE)
rhs <- c(
"\\gamma_n(z_1,...,z_n,L)",
"z_1",
"\\cos(L/2)z_1^2 ~-~ 2 \\sin(L/2)z_2",
"12 ( 4\\sin^2(L/2) ~-~ |z_1|^2 ) z_3 \\newline { ~+~ (8\\cos^2(L/2) - |z_1|^2 + 4) z_1^3 } \\newline ~-~ 48 \\sin(L/2)\\cos(L/2) z_1 z_2 ~+~ 12 \\overline{z_1} z_2^2"
)
lhs = c(
"\\rho_n(z_1,...,z_n,L)",
"2\\sin(L/2)",
"4\\sin^2(L/2) ~-~ |z_1|^2",
"{ 6\\sin(L/2) (|z_1|^4 - 8|z_1|^2 - 4|z_2|^2 ) } \\newline { ~+~ 12\\cos(L/2)(\\overline{z_1}^2z_2 + z_1^2\\overline{z_2}) } \\newline ~+~ 96\\sin^3(L/2)" )
df <- data.frame( n=c('n',1:3), gamma=rhs, rho=lhs ) # ; df
ft <- flextable(df)
ft <- compose( x=ft, j="n", value = as_paragraph(as_equation(n, width=0.5)))
ft <- compose( x=ft, j="gamma", value = as_paragraph(as_equation(gamma, width=4.2)))
ft <- compose( x=ft, j="rho", value = as_paragraph(as_equation(rho, width=4.2)))
ft <- align( ft, align = "center", part = "all")
ft <- width( ft, j=c(2,3), width=4.2 )
ft <- delete_part( ft, part="header" )
# add borders
thick_border = fp_border_default(color="black", width = 2)
thin_border = fp_border_default(color="gray", width = 1)
ft <- border_inner_h( ft, part="all", border = thin_border )
ft <- border_inner_v( ft, part="all", border = thin_border )
ft <- border_outer( ft, part="all", border = thick_border )
ft <- hline( ft, i=1, border=thick_border )
ft <- vline( ft, i=1, j=c(1,2), border=thick_border )
ft
```
The functions $\rho_1()$ and $\rho_2()$ are obviously real,
and $\rho_3()$ is real because $\overline{z_1}^2z_2 + z_1^2\overline{z_2}$ is real.
The case $n{=}1$ is in $\mathbb{R}^3$ and easy to visualize:
\begin{equation}
(z_1,L) \in \partial Z_1 ~~~ \text{ iff } ~~~ |z_1| = 2\sin(L/2)
\end{equation}
This is a surface of revolution - a sine wave around the L axis.
It is like a football with poles at (0,0) and (0,$2\pi$).
Note that these 2 poles are exactly the points where the right side of the equality vanishes.
If we define $f(z_1,...,z_n,L) := | \gamma_n(z_1,...,z_n,L) | - \rho_n(z_1,...,z_n,L)$
then $f()$ vanishes on $\partial Z_n$, is negative in the interior of $Z_n$,
and is positive outside $Z_n$.
This _level-set function_ $f()$ is used in `boundaryfromsphere()` to compute the intersection of a ray
based at $(0,\pi)$ and $\partial Z_n$.
The gradient of $f()$ is used in `arcsfromboundary()`; see the next section.
# Supporting Hyperplanes of $\partial Z_n$
For $x = (z_1,...,z_n,L) \in \partial Z_n$ evaluating the function $\partial Z_n \to A_n$ requires
the outward normal of a supporting hyperplane to $\partial Z_n$ at $x$.
The coordinates of this normal become the coefficients of a trigonometric polynomial,
whose roots are the endpoints of arcs.
If $\partial Z_n$ is smooth at $x$ the supporting hyperplane is unique,
and is in fact the gradient of the level-set function $f()$ at $x$.
Also in this case the trigonometric polynomial has the full set of $2n$ roots, defining $n$ arcs.
But unfortunately, $\partial Z_n$ is _NOT_ smooth at all $x$.
We saw this already with $n{=}1$, where the surface is not smooth at the 2 poles.
At the poles, there are infinitely many supporting planes,
the trigonometric polynomial has 0 roots,
the "south pole" maps to the empty arc, and the "north pole" to the full circle.
The function $\partial Z_n \to A_n$ is implemented in `arcsfromboundary()`.
This **R** function has to deal with the non-smooth case.
It turns out that $\partial Z_n$ is smooth at $x$ iff $\rho_n(x) > 0$.
We saw this already with $n{=}1$.
So starting at $k{=}1$ and incrementing up to $n$, it tests $\rho_k(z_1,...,z_k,L)$.
If $\rho_k(z_1,...,z_k,L) < \epsilon$, it returns a collection of $k{-}1$ arcs in $A_n$.
Otherwise the surface is smooth at $x$ and it returns $n$ arcs.
Recall that $A_n$ is the space of $n$ _or fewer_ arcs.
`arcsfromboundary()` first calculates the outward pointing normal at p.
The the gradient of the level-set function $f()$ is used to compute this normal;
the expressions for the gradient are more complicated than the ones in the above table,
and are omitted here.
This coordinates of this normal are the coefficients of
a trigonometric polynomial whose roots are calculated with `trigpolyroot()`.
These roots are the endpoints of the arcs.
**NOTE:**
The differences $X_i := \partial Z_i - \partial Z_{i-1}$ almost surely form
a _Thom-Mather stratification_ of $\partial Z_n \subset \mathbb{R}^{2n+1}$,
but I have not checked this.
The conditions for such a stratification are complex, and are in @ThomMather.
Each $X_i$ is the image of _exactly_ $i$ arcs.
I think that the above functions $\rho_i()$, after restriction to $X_i$,
can serve as the _distance functions_ in the stratification.
# Summary
The forward functions:
\begin{equation}
A_n ~~ \longrightarrow ~~ \partial Z_n ~~ \longrightarrow ~~ \mathbb{S}^{2n}
\end{equation}
are straightforward.
In the package, they are implemented as `boundaryfromarcs()` and `spherefromboundary()` respectively.
But the inverse functions:
\begin{equation}
A_n ~~ \longleftarrow ~~ \partial Z_n ~~ \longleftarrow ~~ \mathbb{S}^{2n}
\end{equation}
use convergent numerical iteration.
The first one, `boundaryfromsphere()`, uses the implicit function defined above,
and this version of the package requires that $n$ = 1, 2, or 3.
The second one, `arcsfromsphere()`, solves for the roots of a trigonometric polynomial
and uses `base::polyroot()`.
# References
```{r, echo=FALSE, results='asis'} options(old_opt) sessionInfo() ```