Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2eeaa51

Browse files
Refactor bezier poly coefficient calcs for speedup
1 parent 42e142d commit 2eeaa51

1 file changed

Lines changed: 21 additions & 17 deletions

File tree

lib/matplotlib/bezier.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,31 @@
33
"""
44

55
from functools import lru_cache
6-
import math
6+
from math import comb, factorial
77
import warnings
88

99
import numpy as np
1010

1111
from matplotlib import _api
1212

1313

14-
# same algorithm as 3.8's math.comb
15-
@np.vectorize
16-
@lru_cache(maxsize=128)
17-
def _comb(n, k):
18-
if k > n:
19-
return 0
20-
k = min(k, n - k)
21-
i = np.arange(1, k + 1)
22-
return np.prod((n + 1 - i)/i).astype(int)
14+
@lru_cache(maxsize=16)
15+
def _get_coeff_matrix(n):
16+
"""
17+
Compute the matrix for converting Bezier control points to polynomial
18+
coefficients for a curve of degree n.
19+
20+
The matrix M is such that M @ control_points gives polynomial coefficients.
21+
Entry M[j, i] = C(n, j) * (-1)^(i+j) * C(j, i) where C is the binomial
22+
coefficient.
23+
"""
24+
def _comb(n, k):
25+
return np.vectorize(comb)(n, k)
26+
27+
j = np.arange(n + 1)[:, None]
28+
i = np.arange(n + 1)[None, :] # _comb is non-zero for i <= j
29+
prefactor = (-1) ** (i + j) * _comb(j, i) # j on axis 0, i on axis 1
30+
return (_comb(n, j) * prefactor).astype(float)
2331

2432

2533
class NonIntersectingPathException(ValueError):
@@ -203,8 +211,8 @@ def __init__(self, control_points):
203211
self._cpoints = np.asarray(control_points)
204212
self._N, self._d = self._cpoints.shape
205213
self._orders = np.arange(self._N)
206-
coeff = [math.factorial(self._N - 1)
207-
// (math.factorial(i) * math.factorial(self._N - 1 - i))
214+
coeff = [factorial(self._N - 1)
215+
// (factorial(i) * factorial(self._N - 1 - i))
208216
for i in range(self._N)]
209217
self._px = (self._cpoints.T * coeff).T
210218

@@ -279,11 +287,7 @@ def polynomial_coefficients(self):
279287
if n > 10:
280288
warnings.warn("Polynomial coefficients formula unstable for high "
281289
"order Bezier curves!", RuntimeWarning)
282-
P = self.control_points
283-
j = np.arange(n+1)[:, None]
284-
i = np.arange(n+1)[None, :] # _comb is non-zero for i <= j
285-
prefactor = (-1)**(i + j) * _comb(j, i) # j on axis 0, i on axis 1
286-
return _comb(n, j) * prefactor @ P # j on axis 0, self.dimension on 1
290+
return _get_coeff_matrix(n) @ self.control_points
287291

288292
def axis_aligned_extrema(self):
289293
"""

0 commit comments

Comments
 (0)