This answer contains the cube2sphere
and sphere2cube
without the restriction of a = 1
. So the cube has side 2a
from -a
to a
and the radius of the sphere is a
.
I know it's been 10 years since this question was asked. Nevertheless, I am giving the answer in case someone needs it. The implementation is in Python,
I am using (x, y, z)
for the cube coordinates, (p, q, r)
for the sphere coordinates and the relevant underscore variables (x_, y_, z_)
meaning they have been produced by using the inverse function.
import math
from random import randint # for testing
def sign_aux(x):
return lambda y: math.copysign(x, y)
sign = sign_aux(1) # no built-in sign function in python, I know...
def cube2sphere(x, y, z):
if (all([x == 0, y == 0, z == 0])):
return 0, 0, 0
def aux(x, y_2, z_2, a, a_2):
return x * math.sqrt(a_2 - y_2/2 - z_2/2 + y_2*z_2/(3*a_2))/a
x_2 = x*x
y_2 = y*y
z_2 = z*z
a = max(abs(x), abs(y), abs(z))
a_2 = a*a
return aux(x, y_2, z_2, a, a_2), aux(y, x_2, z_2, a, a_2), aux(z, x_2, y_2, a, a_2)
def sphere2cube(p, q, r):
if (all([p == 0, q == 0, r == 0])):
return 0, 0, 0
def aux(s, t, radius):
A = 3*radius*radius
R = 2*(s*s - t*t)
S = math.sqrt( max(0, (A+R)*(A+R) - 8*A*s*s) ) # use max 0 for accuraccy error
iot = math.sqrt(2)/2
s_ = sign(s) * iot * math.sqrt(max(0, A + R - S)) # use max 0 for accuraccy error
t_ = sign(t) * iot * math.sqrt(max(0, A - R - S)) # use max 0 for accuraccy error
return s_, t_
norm_p, norm_q, norm_r = abs(p), abs(q), abs(r)
norm_max = max(norm_p, norm_q, norm_r)
radius = math.sqrt(p*p + q*q + r*r)
if (norm_max == norm_p):
y, z = aux(q, r, radius)
x = sign(p) * radius
return x, y, z
if (norm_max == norm_q):
z, x = aux(r, p, radius)
y = sign(q) * radius
return x, y, z
x, y = aux(p, q, radius)
z = sign(r) * radius
return x, y, z
# measuring accuracy
max_mse = 0
for i in range(100000):
x = randint(-20, 20)
y = randint(-20, 20)
z = randint(-20, 20)
p, q, r = cube2sphere(x, y, z)
x_, y_, z_ = sphere2cube(p, q, r)
max_mse = max(max_mse, math.sqrt(((x-x_)**2 + (y-y_)**2 + (z-z_)**2))/3)
print(max_mse)
# 1.1239159602905078e-07
max_mse = 0
for i in range(100000):
p = randint(-20, 20)
q = randint(-20, 20)
r = randint(-20, 20)
x, y, z = sphere2cube(p, q, r)
p_, q_, r_ = cube2sphere(x, y, z)
max_mse = max(max_mse, math.sqrt(((p-p_)**2 + (q-q_)**2 + (r-r_)**2))/3)
print(max_mse)
# 9.832883321715792e-08
Also, I mapped some points to check the function visually and these are the results.

