@@ -36,27 +36,23 @@ def calculate(
3636 return np .zeros ((order , 4 ), dtype = float )
3737
3838 phi = (2.0 * np .pi * t ) / total_len
39- coeffs = np .zeros ((order , 4 ), dtype = float )
40- dphi_cos = {}
41- dphi_sin = {}
42-
43- for n in range (1 , order + 1 ):
44- phi_n = phi * n
45- dphi_cos [n ] = np .cos (phi_n [1 :]) - np .cos (phi_n [:- 1 ])
46- dphi_sin [n ] = np .sin (phi_n [1 :]) - np .sin (phi_n [:- 1 ])
39+ ns = np .arange (1 , order + 1 )[:, None ]
40+ phi_n = ns * phi [None , :]
41+ dphi_cos = np .cos (phi_n [:, 1 :]) - np .cos (phi_n [:, :- 1 ])
42+ dphi_sin = np .sin (phi_n [:, 1 :]) - np .sin (phi_n [:, :- 1 ])
4743
4844 dx_over_dt = np .zeros_like (dx , dtype = float )
4945 dy_over_dt = np .zeros_like (dy , dtype = float )
5046 dx_over_dt [valid ] = dx [valid ] / dt [valid ]
5147 dy_over_dt [valid ] = dy [valid ] / dt [valid ]
5248
53- for n in range ( 1 , order + 1 ):
54- const = total_len / ( 2.0 * ( n * np .pi ) ** 2 )
55- an = const * np . sum ( dx_over_dt * dphi_cos [ n ])
56- bn = const * np . sum ( dx_over_dt * dphi_sin [ n ])
57- cn = const * np . sum ( dy_over_dt * dphi_cos [ n ])
58- dn = const * np . sum ( dy_over_dt * dphi_sin [ n ])
59- coeffs [ n - 1 ] = [ an , bn , cn , dn ]
49+ consts = total_len / ( 2.0 * ( ns [:, 0 ] * np . pi ) ** 2 )
50+ coeffs = np .column_stack ([
51+ consts * ( dphi_cos @ dx_over_dt ),
52+ consts * ( dphi_sin @ dx_over_dt ),
53+ consts * ( dphi_cos @ dy_over_dt ),
54+ consts * ( dphi_sin @ dy_over_dt ),
55+ ])
6056
6157 if normalize :
6258 coeffs = EllipticFourier .normalize (coeffs )
@@ -108,11 +104,12 @@ def normalize(coeffs: np.ndarray) -> np.ndarray:
108104 @staticmethod
109105 def reconstruct (coeffs : np .ndarray , num_points : int = 300 ) -> np .ndarray :
110106 t = np .linspace (0.0 , 1.0 , num_points )
111- xt = np .zeros (num_points )
112- yt = np .zeros (num_points )
113- for n , (an , bn , cn , dn ) in enumerate (coeffs , start = 1 ):
114- xt += an * np .cos (2.0 * np .pi * n * t ) + bn * np .sin (2.0 * np .pi * n * t )
115- yt += cn * np .cos (2.0 * np .pi * n * t ) + dn * np .sin (2.0 * np .pi * n * t )
107+ ns = np .arange (1 , len (coeffs ) + 1 )[:, None ]
108+ angles = 2.0 * np .pi * ns * t [None , :]
109+ ab = coeffs [:, :2 ]
110+ cd = coeffs [:, 2 :]
111+ xt = (ab [:, 0 :1 ] * np .cos (angles ) + ab [:, 1 :2 ] * np .sin (angles )).sum (axis = 0 )
112+ yt = (cd [:, 0 :1 ] * np .cos (angles ) + cd [:, 1 :2 ] * np .sin (angles )).sum (axis = 0 )
116113 return np .stack ([xt , yt ], axis = 1 )
117114
118115
0 commit comments