M.C. Escher created the square limit woodcut in 1964.

input: Escher's "Square Limit" woodcut |

Schwarz-Christoffel mapping |

elliptical grid mapping |

FG-squircular mapping |

Shirley-Chiu concentric map |

H.S.M. Coxeter published a checkered {6,4} hyperbolic tiling of the Poincare disk in his 1957 paper: "Crystal Symmetry and Its Generalizations".

Here, we convert the conformal hyperbolic disk to hyperbolic squares.

Here, we convert the conformal hyperbolic disk to hyperbolic squares.

input: Coxeter {6,4} tiling of Poincare disk |

Schwarz-Christoffel mapping |

elliptical grid mapping |

FG-squircular mapping |

Shirley-Chiu concentric map |

Here are results of different square-to-circle mapping algorithms on a bunch of television icons of the 70's. Marcia. Marcia. Marcia!

input file: Brady Bunch |

Schwarz-Christoffel conformal mapping |

elliptical grid mapping |

FG-squircular mapping |

Shirley-Chiu concentric map |

Not to be confused with this "The Brady Bunch Movie" refrigerator magnet I found on ebay!

This conformal mapping developed in the 1860s by Hermann Schwarz and Elwin Christoffel can be used to map a circle to a square and vice versa.

The equations for mapping the circular disc to a square region (and vice versa) are:

and

F is the Legendre elliptic integral of the 1st kind.

cn is a Jacobi elliptic function.

Ke is the complete elliptic integral of the 1st kind with parameter m = ½

(x,y) are coordinates on the square

(u,v) are coordinates on the circular disc

See Section 7 of my paper (page 19) for an explanation of the formulas

http://arxiv.org/ftp/arxiv/papers/1509/1509.06344.pdf

========================================================

Here is an example image of using the Schwarz-Christoffel mapping on a square chessboard

Schwarz-Christoffel chessboard |

and another on MC Escher's "Circle Limit IV"; i.e. angels and devils inside the Poincare disk.

Schwarz-Christoffel for squared Circle Limit IV |

Note that the Jacobi cn() function is an even function, so cn(x,k) = cn(-x,k).

The elliptical grid mapping is by no means the only way to map the square to a circle and vice versa.

In this entry, I shall introduce a disc to square mapping based on the Fernandez-Guasti squircle.

Here are the equations for the mapping.

square to circle:

circle to square:

where sgn(z) is the signum function;

Note: We need to handle zero inputs as a special case.

When input u or v is zero, just set x = u and y = v.

When input x or y is zero, just set u = x and v = y.

The main idea behind this mapping is to map concentric circles inside the circular disc to Fernandez-Guasti squircles inside the square.

C++ sample implementation below

--------------------------------------------------------------------------------------------------

// sample code accompanying the paper:

// "Analytical Methods for Squaring the Disc"

// http://arxiv.org/abs/1509.06344

#include <stdio.h>

#include <math.h>

#define epsilon 0.0000001

inline double sgn(double input)

{

double output = 1.0;

if (input < 0.0) {

output = -1.0;

}

return output;

}

// FG-Squircular mapping

// mapping a circular disc to a square region

// input: (u,v) coordinates in the circle

// output: (x,y) coordinates in the square

void fgsDiscToSquare(double u, double v, double& x, double& y)

{

if ( (fabs(u) < epsilon) || (fabs(v) < epsilon)) {

x = u;

y = v;

return;

}

double u2 = u * u;

double v2 = v * v;

double r2 = u2 + v2;

double uv = u * v;

double fouru2v2 = 4.0 * uv * uv;

double rad = r2 * (r2 - fouru2v2);

double sgnuv = sgn(uv);

double sqrto = sqrt(0.5 * (r2 - sqrt(rad)));

x = sgnuv/v * sqrto;

y = sgnuv/u * sqrto;

}

// FG-Squircular mapping

// mapping a square region to a circular disc

// input: (x,y) coordinates in the square

// output: (u,v) coordinates in the circle

void fgsSquareToDisc(double x, double y, double& u, double& v)

{

if ( (fabs(x) < epsilon) || (fabs(y) < epsilon)) {

u = x;

v = y;

return;

}

double x2 = x * x;

double y2 = y * y;

double r2 = x2 + y2;

double rad = sqrt( r2 - x2 * y2);

// This code is amenable to the fast reciprocal sqrt floating point trick

// https://en.wikipedia.org/wiki/Fast_inverse_square_root

double reciprocalSqrt = 1.0/sqrt(r2);

u = x * rad * reciprocalSqrt;

v = y * rad * reciprocalSqrt;

}

int main()

{

double x,y;

double u,v;

fgsSquareToDisc(0.0,-0.789,u,v);

fgsDiscToSquare(u,v,x,y);

printf("%f %f\n",u,v);

printf("%f %f\n",x,y);

fgsDiscToSquare(-0.31415, -0.926535,x,y);

fgsSquareToDisc(x,y,u,v);

printf("%f %f\n",x,y);

printf("%f %f\n",u,v);

return 0;

}

In 1992, Manuel Fernandez-Guasti introduced a smooth algebraic curve that lies between the circle and the square.

The curve has two parameters:

This is a quartic curve (i.e. degree 4) because of the x²y² term.

When s = 0, the FG-squircle is a circle with radius r.

When s = 1, the FG-squircle is a square with side length 2r.

In between, it is a shape that resembles both the circle and the square

Note: For this discussion, we shall limit the scope of the curve to

-r ≤ x ≤ r and -r ≤ y ≤ r

This quartic polynomial equation can have values for (x,y) outside this scope, but we will ignore those regions.

See http://148.206.32.135/mfg/arti/90-94/agrec-ijmest92.pdf

for Fernandez-Guasti's original paper.

The following logos are circular ones mapped to a square.

Thanks to Seb Przd for inspiring this post

Philip Nowell (http://mathproofs.blogspot.com/2005/07/mapping-square-to-circle.html)

has an equation for mapping a square to a circle.

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]

Many people have asked for the inverse of the mapping. I provide it below:

**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:

[ C++ implementation source code below]

------------------------------------------------------------------------------------------

has an equation for mapping a square to a circle.

For this blog entry, I use a slightly different notation from his equations; i.e.

u = x'

v = y'

Many people have asked for the inverse of the mapping. I provide it below:

or more legibly

The forward equations for the mapping are:

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

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;
double termx1 = subtermx + u * twosqrt2;
double termx2 = subtermx - u * twosqrt2;
double termy1 = subtermy + v * twosqrt2;
double termy2 = 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;
}

Subscribe to:
Posts (Atom)