Philip Nowell (
http://mathproofs.blogspot.com/2005/07/mapping-square-to-circle.html)
devised equations for mapping a square to a circle. I will provide the inverse to the mapping below.
For this blog entry, I use a slightly different notation from his equations; i.e.
u = x'
v = y'
(u,v) are circular coordinates in the domain {(u,v) | u² + v² ≤ 1}
(x,y) are square coordinates in the range [-1,1] x [-1,1]
Here are the inverse mapping equations:
x = ½ √( 2 + 2u√2 + u² - v² ) - ½ √( 2 - 2u√2 + u² - v² )
y = ½ √( 2 + 2v√2 - u² + v² ) - ½ √( 2 - 2v√2 - u² + v² )
or more legibly
The forward equations for the mapping are:
u = x √( 1 - ½ y² )
v = y √( 1 - ½ x² )
Here are some examples of the forward & inverse mappings at work.
For a proof/derivation of the inverse equations, see my paper in
arxiv: "Analytical Methods for Squaring the Disc"
In this blog, I shall refer to this mapping as the
elliptical grid mapping. I chose this name because the mapping has a predilection to map a rectilinear grid into a grid of elliptical arcs in the circle. See Nowell's blog for a discussion and derivation of the elliptical arcs.
Here are more examples of the mapping:
|
Starbucks™ logo converted to a square |
|
Andy Warhol's pop art "Marilyn" as a circle |
[ C++ implementation source code below]
------------------------------------------------------------------------------------------
// sample code accompanying the paper:
// "Analytical Methods for Squaring the Disc"
// http://arxiv.org/abs/1509.06344
#include <stdio.h>
#include <math.h>
// Elliptical Grid mapping
// mapping a circular disc to a square region
// input: (u,v) coordinates in the circle
// output: (x,y) coordinates in the square
void ellipticalDiscToSquare(double u, double v, double& x, double& y)
{
double u2 = u * u;
double v2 = v * v;
double twosqrt2 = 2.0 * sqrt(2.0);
double subtermx = 2.0 + u2 - v2;
double subtermy = 2.0 - u2 + v2;
// Note: These next 4 terms should never be negative
// However, due to numerical imprecision in standard floating point libraries,
// it is possible to get a very small negative value
// when u = sqrt(2)/2 and v = sqrt(2)/2
// To remedy this, we impose an absolute value function
double termx1 = fabs(subtermx + u * twosqrt2);
double termx2 = fabs(subtermx - u * twosqrt2);
double termy1 = fabs(subtermy + v * twosqrt2);
double termy2 = fabs(subtermy - v * twosqrt2);
x = 0.5 * sqrt(termx1) - 0.5 * sqrt(termx2);
y = 0.5 * sqrt(termy1) - 0.5 * sqrt(termy2);
}
// Elliptical Grid mapping
// mapping a square region to a circular disc
// input: (x,y) coordinates in the square
// output: (u,v) coordinates in the circle
void ellipticalSquareToDisc(double x, double y, double& u, double& v)
{
u = x * sqrt(1.0 - y*y/2.0);
v = y * sqrt(1.0 - x*x/2.0);
}
int main()
{
double x,y;
double u,v;
ellipticalSquareToDisc(-0.789,0.654,u,v);
ellipticalDiscToSquare(u,v,x,y);
printf("%f %f\n",u,v);
printf("%f %f\n",x,y);
ellipticalDiscToSquare(0.31415, -0.926535,x,y);
ellipticalSquareToDisc(x,y,u,v);
printf("%f %f\n",x,y);
printf("%f %f\n",u,v);
return 0;
}