I have three points in 3D and I'd like to a find a smooth curve (e.g., a spline) that goes through all points. With 4 points or more, I can use SciPy's B-splines:
import numpy as np
from scipy.interpolate import splev, splprep
import matplotlib.pyplot as plt
dim = 3
# doesn't work for 3 points
num_points = 4
X = np.random.rand(dim, num_points)
tck, u = splprep(X, s=0)
new_points = splev(np.linspace(0, 1, 100), tck)
# plot
ax = plt.figure().add_subplot(projection="3d")
ax.scatter(*X)
ax.plot(*new_points)
plt.show()
Why doesn't this work for three points? What could I do instead?
You can use cubic spline:
import numpy as np
from scipy.interpolate import CubicSpline
import matplotlib.pyplot as plt
X = np.array([[0, 1, 2], [0, 1, 0], [0, 1, 2]])
t = np.linspace(0, 1, X.shape[1])
sx, sy, sz = CubicSpline(t, X[0]), CubicSpline(t, X[1]), CubicSpline(t, X[2])
nt = np.linspace(0, 1, 100)
nsx, nsy, nsz = sx(nt), sy(nt), sz(nt)
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.scatter(X[0], X[1], X[2], color='r')
ax.plot(nsx, nsy, nsz)
plt.show()
You can also reduce the k to 2 (the degree of spline to a quadratic equation):
import numpy as np
from scipy.interpolate import splev, splprep
import matplotlib.pyplot as plt
dim = 3
num_points = 3
X = np.random.rand(dim, num_points)
tck, u = splprep(X, s=0, k=2)
new_points = splev(np.linspace(0, 1, 100), tck)
fig = plt.figure()
ax = fig.add_subplot(projection="3d")
ax.scatter(*X, color='r')
ax.plot(*new_points)
plt.show()