Given the 4x4 transform matrix of a sphere and a point in space, I want to find the closest point on the sphere's surface.
Normally I would trace a line between the point and the sphere's center, and use the sphere's radius to get my solution, but here i am dealing with a non-uniformly scaled sphere. Here's a quick example in Python:
import numpy as np
from numpy.core.umath_tests import inner1d
# 4x4 transform matrix of a sphere with the following components:
# Scale XYZ = 1,5,1 (Scaled only in Y axis to keep this example simple)
# Rotation XYZ = 0,0,45 (Simple tilt for this example)
# Position XYZ = -1,3,0 (Position along XY plane, again for simplicity)
M = np.array([[ 0.70710678, 0.70710678, 0. , 0. ],
[-3.53553391, 3.53553391, 0. , 0. ],
[ 0. , 0. , 1. , 0. ],
[-1. , 3. , 0. , 1. ]])
# Query point p0
p0 = np.array([-2,6,0])
# Transform the point into a unit sphere
I = np.linalg.inv(M)
p1 = np.array(p)-M[3,:3]
p1 = np.dot(p1,I)
# Normalize the point so it is on the surface of the unit sphere
mag = np.sqrt(inner1d(p1,p1)) # magnitude
p1 /= mag
# Transform back into 3D space
p1 = np.dot(p1,M[:3,:3]) + M[3,:3] #result [-1.65653216, 4.96959649, 0.]
This solution is fast and works well when the query point is already close to the sphere, but not so much when it is distant. See in the image above: point p2 which would be the desired result.