File indexing completed on 2026-04-09 07:48:51
0001
0002 """
0003 catmull_rom_spline.py : SEE catmull_rom_spline_2.py FOR A BETTER IMPLEMENTATION
0004 ======================================================================================
0005
0006 ::
0007
0008 epsilon:opticks blyth$ opticks-rl sympy
0009
0010
0011 * https://www.cs.cmu.edu/~fp/courses/graphics/asst5/catmullRom.pdf
0012
0013 * https://qroph.github.io/2018/07/30/smooth-paths-using-catmull-rom-splines.html
0014
0015 * https://www.cs.cmu.edu/~fp/courses/graphics/asst5/catmullRom.pdf
0016
0017 ~/opticks_refs/derivation_catmullRom_spline.pdf
0018
0019
0020 * https://dev.to/ndesmic/splines-from-scratch-catmull-rom-3m66
0021
0022
0023 """
0024
0025 import numpy as np, sympy as sp, matplotlib as mp
0026 from sympy.utilities.lambdify import lambdify
0027 SIZE = np.array([1280, 720])
0028
0029 def pp(q, q_label="?", note=""):
0030 if type(q) is np.ndarray:
0031 q_type = "np"
0032 elif q.__class__.__name__ == 'MutableDenseMatrix':
0033 q_type = "sp.MutableDenseMatrix"
0034 else:
0035 q_type = "?"
0036 pass
0037 print("\n%s : %s : %s : %s \n" % (q_label, q_type, str(q.shape), note) )
0038
0039 if q_type.startswith("sp"):
0040 sp.pprint(q)
0041 elif q_type.startswith("np"):
0042 print(q)
0043 else:
0044 print(q)
0045 pass
0046
0047
0048
0049 if __name__ == '__main__':
0050
0051 """
0052
0053 0,1 1,1
0054 +--------+
0055 | |
0056 | |
0057 | |
0058 +--------+
0059 0,0 1,0
0060
0061 """
0062
0063
0064 points = np.zeros( (16, 3) )
0065 for j in range(len(points)):
0066 angle = 2*np.pi*float(j)/(len(points))
0067
0068
0069 points[j] = [np.cos(angle), np.sin(angle), 0]
0070 pass
0071
0072
0073
0074 A = 0.5
0075
0076 assert len(points) >= 4
0077 numseg = len(points)-3
0078
0079 looped = True
0080 if looped: numseg += 3
0081
0082 segnum = 100
0083 tt = np.linspace(0,1, segnum)
0084
0085 xpp = np.zeros( (numseg*segnum,3) )
0086
0087 u, a = sp.symbols("u a")
0088 M = sp.Matrix([
0089 [ 0 , 1 , 0 , 0 ],
0090 [ -a , 0 , a , 0 ],
0091 [ 2*a , a - 3, 3 - 2*a, -a ],
0092 [ -a , 2 - a, a - 2 , a ]
0093 ])
0094
0095 pp(M,"M")
0096
0097 U = sp.Matrix( [1, u, u*u, u*u*u ] )
0098 V = sp.Matrix( [[1, u, u*u, u*u*u ]] )
0099 pp(U,"U")
0100 pp(V,"V")
0101 pp(U.T,"U.T")
0102 pp(V.T,"V.T")
0103 VM = V*M
0104 pp(VM,"VM")
0105 pp(VM.T,"VM.T")
0106 VMa = VM.subs([(a,A)])
0107
0108 numpoi = len(points)
0109
0110 for iseg in range(numseg):
0111
0112 i0 = (iseg+0) % numpoi
0113 i1 = (iseg+3) % numpoi
0114
0115 p = np.take( points, np.arange(iseg,iseg+4), mode='wrap', axis=0 )
0116
0117
0118
0119
0120 print(" iseg %2d i0 %3d i1 %3d numpoi %3d p %s " % (iseg, i0,i1,numpoi, str(p.shape) ) )
0121
0122
0123
0124
0125
0126
0127
0128 VMa_p = VMa*p
0129
0130 fn = lambdify(u, VMa_p,'numpy')
0131 for i in range(len(tt)):
0132 xpp[iseg*segnum+i] = fn(tt[i])
0133
0134 pass
0135
0136
0137 fig, ax = mp.pyplot.subplots(figsize=SIZE/100.)
0138 fig.suptitle("analytic/catmull_rom_spline.py")
0139 ax.set_aspect('equal')
0140 ax.plot( xpp[:,0], xpp[:,1], label="xpp" )
0141 ax.scatter( points[:,0], points[:,1], label="points" )
0142 ax.legend()
0143 fig.show()
0144