Saturday, September 19, 2015

Square O'Clock


input file: Roman numeral clock

Schwarz-Christoffel mapping

elliptical grid mapping


FG-squircular mapping


Shirley-Chiu concentric map





Monday, September 14, 2015

Andy Warhol's Campbell soup


circularized pop art. Mmm mmm good.


input: Andy Warhol's soup cans

Schwarz-Christoffel mapping

FG-squircular mapping

elliptical grid mapping



Shirley-Chiu concentric map







Friday, September 11, 2015

Circular Monopoly


Monopoly is a board game traditionally played on a square board. What happens if we convert the board to a circle?

input: Monopoly board game


Schwarz-Christoffel mapping


FG-squircular mapping
elliptical grid mapping



Shirley-Chiu concentric map





Thursday, September 10, 2015

2015 NBA champions

Here is a circular logo of the Golden State Warriors converted into a square.

input file: Golden State Warriors


Schwarz-Christoffel mapping



FG-squircular mapping

elliptical grid mapping




Shirley-Chiu concentric map





Circular Brady Bunch


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!



Wednesday, September 9, 2015

Schwarz-Christoffel mapping


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:

where z and w are points in the complex plane defined as

z = x + y i
w = u + v i

and

F is the incomplete 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).

Saturday, September 5, 2015

FG-Squircular Mapping


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:
u = x √(x² + y² - x²y²) / √(x² + y²)
v = y √(x² + y² - x²y²) / √(x² + y²)

circle to square:
x = √½  sgn(uv)/v √(u² + v² - √(u² + v²) √(u² + v² - 4u²v²) )
y = √½  sgn(uv)/u √(u² + v² - √(u² + v²) √(u² + v² - 4u²v²) )


where sgn(z) is the signum function;
(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]

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.

See http://squircular.blogspot.com/2015/09/fernandez-guastis-squircle.html for more details on the Fernandez-Guasti squircle.

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)
{
    x = u;
    y = v;
 
    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)));

     if  (fabs(u) > epsilon)   {
        y = sgnuv/u * sqrto;
    }
   
    if  (fabs(v) > epsilon) {
       x = sgnuv/v * 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)
{
    u = x;
    v = y;
   
    double x2 = x * x;
    double y2 = y * y;
    double r2 = x2 + y2;
    double rad = sqrt( r2 - x2 * y2);

    // avoid division by zero if (x,y) is closed to origin
    if (r2 < epsilon)   {
        return;
    }

    // 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;
}

Thursday, September 3, 2015

Fernandez-Guasti's squircle


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

The curve has two parameters: radius r and squareness s


















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 are mainly interested with the curve located in the region
-r ≤ x ≤ r and -r ≤ y ≤ r

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


See http://148.206.32.135/mfg/arti/90-94/agrec-ijmest92.pdf
for Fernandez-Guasti's original paper.

See also my paper https://arxiv.org/ftp/arxiv/papers/1604/1604.02174.pdf
for more details.

Squared Corporate Logos


The following logos are circular ones mapped to a square.





















Thanks to Seb Przd for inspiring this post

Mapping a Circle to a Square

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;
}


Simple Stretching: Mapping a circular disc to a square

We can map the circular disc to a square by just linearly stretching each point radially so that the rim of the circle matches the rim of the square.




The equations for the mapping are provided below

where sgn(x) is the signum function.

(u,v) are circular coordinates in the unit disc.
(x,y) are coordinates in the square [-1,1] x [-1,1]

[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> #define epsilon 0.0000001 inline float sgn(float input) { float output = 1.0f; if (input < 0.0) { output = -1.0f; } return output; } // Simple Stretching map // mapping a circular disc to a square region // input: (u,v) coordinates in the circle // output: (x,y) coordinates in the square void stretchDiscToSquare(float u, float v, float& x, float& y) { if ( (fabs(u) < epsilon) || (fabs(v) < epsilon)) { x = u; y = v; return; } float u2 = u * u; float v2 = v * v; float r = sqrt(u2 + v2); // a trick based on Dave Cline's idea // link Peter Shirley's blog if (u2 >= v2) { float sgnu = sgn(u); x = sgnu * r; y = sgnu * r * v / u; } else { float sgnv = sgn(v); x = sgnv * r * u / v; y = sgnv * r; } } // Simple Stretching map // mapping a square region to a circular disc // input: (x,y) coordinates in the square // output: (u,v) coordinates in the circle void stretchSquareToDisc(float x, float y, float& u, float& v) { if ( (fabs(x) < epsilon) || (fabs(y) < epsilon)) { u = x; v = y; return; } float x2 = x*x; float y2 = y*y; float hypothenusSquared = x2 + y2; // code can use fast reciprocal sqrt floating point trick // https://en.wikipedia.org/wiki/Fast_inverse_square_root
    float reciprocalHypothenus =  1.0f/sqrt(hypothenusSquared);
    
    float multiplier = 1.0f;
    // a trick based on Dave Cline's idea
    if (x2 > y2) {
        multiplier = sgn(x) * x * reciprocalHypothenus;
    } else {
        multiplier = sgn(y) * y * reciprocalHypothenus;
    }

    u = x * multiplier;
    v = y * multiplier;
}


int main()
{
    float x,y;
    float u,v;

    stretchSquareToDisc(0.0f,0.6f,u,v);
    stretchDiscToSquare(u,v,x,y);
    
    printf("%f %f\n",u,v);
    printf("%f %f\n",x,y);

    stretchDiscToSquare(0.857f, 0.514496f,x,y);
    stretchSquareToDisc(x,y,u,v);
    
    printf("%f %f\n",x,y);
    printf("%f %f\n",u,v);

    return 0;
}


Canonical space in disc-to-square mapping

In this blog, I will discuss several ways to map the circular disc to a square and vice versa.  This is the canonical mapping space:














circular domain: {(u,v) | u² + v² ≤ 1}
square range: [-1,1] x [-1,1]

The points (u,v) are in circular disc coordinates
The points (x,y) are in square coordinates


===============================================
Some other relevant links:
1) Stackoverflow.com also discussed the mapping and asked for the inverse.
http://stackoverflow.com/questions/13211595/how-can-i-convert-coordinates-on-a-circle-to-coordinates-on-a-square
http://stackoverflow.com/questions/1621831/how-can-i-convert-coordinates-on-a-square-to-coordinates-on-a-circle

2) Greg Cope has a nice image of a square maze converted to a circular disc.
http://www.algosome.com/articles/maze-generation-depth-first.html

3) Peter Shirley mentioned Dave Cline's trick to simplify his concentric map code
http://psgraphics.blogspot.com/2011/01/improved-code-for-concentric-map.html

4) Stack exchange also has a discussion on this:
http://math.stackexchange.com/questions/440611/geometric-deformations/1662347#1662347