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>// 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
I did test with 100 values of x and y in range [-1,1]. I run from square to disc and disc to square for getting a set of y values back. I also run every y value in x values from square to disc. I found only some y values with some x values can be retrieved from disc to square. The total of pairs running in this test is 100 x 100. The total of distance error is so small, 2.708423763042589e-14, but will cost me in some how. So, can I conclude that because a simple stretching method is not equiareal as mentioned in your paper, there will be a negligible value of distortion hidding. Pls. comment of what I conclude
ReplyDeleteThe simple stretching map is not equareal! Use the Shirley-Chiu concentric map instead
Deletesee:
http://psgraphics.blogspot.com/2011/01/improved-code-for-concentric-map.html
Confused about data test. My y values in the range of x values, say [min, max] of y value is [0.009, 0.126] and of x value is [-1,1]. It is OK to run square to disc and disc to square. If yes, my x value can also be in range [-0.6,0.6] for [0.009, 0.126]. Pls. correct.
ReplyDeleteAll values inside the square have to be between [-1,1]. None of the mappings will work otherwise
Deletefrom
ReplyDelete1. (fabs(x) < epsilon) || (fabs(y) < epsilon)) is when shape of squre is slightly changed to disc at all
2. (fabs(u) < epsilon) || (fabs(v) < epsilon)) is when shape of disc is slightly changed to squre at all
My question why you set epsilon value to 0.0000001? Pls. guide me.
The epsilon value was set arbitrarily to avoid numerical imprecision. You can change the value of epsilon as long as it is a reasonably small number.
DeleteFrom AnonymousSeptember 23, 2018:
ReplyDeleteIt is like a majic faster than my technique. Using (fabs(x) < epsilon) || (fabs(y) < epsilon)) and (fabs(u) < epsilon) || (fabs(v) < epsilon)) are so work in both simple stretching mapping and FG-Squircular Mapping. Thx a lot for a guide.
That's going great!
ReplyDeleteI derive it and I got the same function!
It uses trigonometry. When mapping a circle to a square, it uses the radius of the point as the x or y value of an output point on the square, determined by where the input point is. And then, it calculates the missing x or y value to complete the coordinate.
It is the same idea but inverses the change when mapping square to circle. It uses the x or y value of the input point on the square as the radius of the output point on the circle. Using trigonometry, we can find the output x and y values.
I know this comment might sound silly but I teach myself trigonometry and I'm happy that I also derive this on my own.
(Sorry I'm not focusing on your code, but more on the math.)