Initially, my plan was to determine values along four segments of two axes, says, j = — i and — j = — i.
Then for each quadrant, I thought I would use one segment as a “base” and computed an “offset” from the base. It would look like this:


It turned out to be a mess as doing it this way produced edge cases along the axes.
To compromise that, I use only one line (two segments) as the base:

Still, another line is need to draw the boundary, so quadrant calculation is unavoidable.
The code to determine the quadrant of a given point looks like this:
// Axes are i = j and i = - j.
int get_quadrant(int i, int j) {
bool x_positive = (j - i) > 0;
bool y_positive = (i + j) > 0;
if ( !x_positive && !y_positive) return 3;
else if ( !x_positive && y_positive) return 2;
else if ( x_positive && y_positive) return 1;
else return 0;
}And code to determine actual values:
int unspiral(int i, int j) {
int q = get_quadrant(i, j);
// x along line j = - i.
int x = max(abs(i), abs(j));
if (q >= 2) x = - x;
int base = (2 * x) * (2 * x) - (2 * x);
int offset;
if (q == 0) offset = x - j;
else if (q == 1) offset = i - x;
else if (q == 2) offset = j - x;
else offset = x + i;
return base - offset;
}Frankly, I don’t like it that much. I hope there is a cleaner constructive way to create a spiral but I can’t come up with one yet, so I decide to post this one first.
Is it run in constant time? Yes. Is it easy to understand? I would say that this is easier to understand than the original one (at least to me). It might not be that easy to modify though.
Note that I have given some thoughts about using polar coordinate system. Even that, I’m convinced that distance calculation between points and the center is not negligible. Since it is the case, I encourage any programmer to point out this calculation in a separate line.
Since Thai posted an additional picture, which he used during his thought, let me take the space here to say that your choices of segments were elegant because two normal lines pointing out from your base segment wouldn’t be intersected.
P.S. I prefer (2 * x) * (2 * x) to 4 * x * x since it gives me a sense of scaling to a single number rather than a random multiplying factor.
P.S.2, I do not write this in JS and I feel guilty about it, but it shouldn’t make no different in terms of code understanding.
