# Plot Optimal Colors

### Description

Consider a **colorSpec** object `x`

with `type`

equal to `responsivity.material`

and 3 responsivity spectra.
The function `plotOptimals3D`

makes a wireframe plot of the *object-color solid* for `x`

.
The 3D drawing package rgl is required.

The set of all possible material reflectance functions (or transmittance functions)
is convex, closed, and bounded (in any reasonable function space),
and this implies that the set of all possible output responses
from `x`

is also convex, closed, and bounded.
The latter set is called the *object-color solid*,
or *Rösch Farbkörper*, for `x`

.
A color on the boundary of the *object-color solid* is called an *optimal color*.
The special points **W** (the response to the perfect reflecting diffuser)
and **0** are on the boundary of this set.
The interior of the line segment of neutrals joining **0** to **W** is in the interior of the set.
For more see discussion `probeOptimalColors`

.

### Usage

1 2 | ```
## S3 method for class 'colorSpec'
plotOptimals3D( x, size=c(33,33) )
``` |

### Arguments

`x` |
a |

`size` |
an integer 2-vector with the number of meridians and parallels to plot |

### Details

The boundary of the *object-color solid* for `x`

has
a natural parameterization by *ω* and *δ*,
which are analogous to longitude and latitude for the sphere.
See Logvinenko for more details.
These 2 parameters define reflectance spectra with 2 or fewer transitions
between 0 and 1.
By default, the function draws a wireframe with 33 meridians
and 33 parallels.

In addition it draws the box with opposite vertices at the "poles" **0** and **W**
and the diagonal segment of neutral grays that connects **0** and **W**.
It draws a small ball at the midpoint;
the *Rösch Farbkörper* is symmetrical about this midpoint.

### Value

`TRUE`

or `FALSE`

### Note 1

As both **References** point out, the plotted set of 2-transition colors is only optimal
under certain conditions on `x`

,
which are fortunately true for the human responsivity functions `xyz1931.1nm`

.
But they are certainly not true for *all* `x`

,
so the plotted surface seen here might really be sub-optimal.

For general `x`

it may require reflectance
functions with 3,4,5,... transitions to define the optimals.

### Note 2

If all responsivity functions of `x`

are non-negative,
the *object-color solid* of `x`

is inside the box.
If the responsivity functions of `x`

have negative lobes,
the *object-color solid* of `x`

extends outside the box.
Indeed, the box may actually be *inside* the optimals.

The responsivity functions cannot all simultaneously vanish at any wavelength.
In that case the mapping from the *ω* and *δ* sphere
to the output response space is not injective.

### Future Work

For an object `x`

with 2 spectra,
it would not take much work to write a new function
`plotOptimals2D`

that plots the 1-transition colors for `x`

.
These are the short-pass and long-pass colors,
also known as *edge colors* or *Kantenfarben*.
With a lot more work it would be possible to
plot the true optimals for `x`

, with any number of transitions between 0 and 1.

### References

Logvinenko, A. D. An object-color space. Journal of Vision. 9(11):5, 1-23, (2009). http://journalofvision.org/9/11/5/. doi:10.1167/9.11.5.

West, G. and M. H. Brill. Conditions under which Schrödinger object colors are optimal. Journal of the Optical Society of America. 73. pp. 1223-1225. 1983.

### See Also

`type`

,
`probeOptimalColors`

vignette **optimals**

### Examples

1 2 3 4 5 6 | ```
# requires package rgl
library( rgl )
human = product( D50.5nm, 'slot', xyz1931.5nm, wave=400:770 )
plotOptimals3D( human )
scanner = product( D50.5nm, 'slot', BT.709.RGB, wave=400:770 )
plotOptimals3D( scanner )
``` |