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

Skip to content

Commit 537535d

Browse files
authored
Merge pull request #14390 from timhoffm/doc-bezier
Cleanup docs of bezier
2 parents 152b6ff + b36d05f commit 537535d

1 file changed

Lines changed: 106 additions & 44 deletions

File tree

lib/matplotlib/bezier.py

Lines changed: 106 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"""
2-
A module providing some utility functions regarding bezier path manipulation.
2+
A module providing some utility functions regarding Bezier path manipulation.
33
"""
44

55
import numpy as np
@@ -18,7 +18,7 @@ def get_intersection(cx1, cy1, cos_t1, sin_t1,
1818
cx2, cy2, cos_t2, sin_t2):
1919
"""
2020
Return the intersection between the line through (*cx1*, *cy1*) at angle
21-
*t1* and the line through (*cx2, cy2) at angle *t2*.
21+
*t1* and the line through (*cx2*, *cy2*) at angle *t2*.
2222
"""
2323

2424
# line1 => sin_t1 * (x - cx1) - cos_t1 * (y - cy1) = 0.
@@ -49,7 +49,7 @@ def get_intersection(cx1, cy1, cos_t1, sin_t1,
4949

5050
def get_normal_points(cx, cy, cos_t, sin_t, length):
5151
"""
52-
For a line passing through (*cx*, *cy*) and having a angle *t*, return
52+
For a line passing through (*cx*, *cy*) and having an angle *t*, return
5353
locations of the two points located along its perpendicular line at the
5454
distance of *length*.
5555
"""
@@ -79,7 +79,7 @@ def _de_casteljau1(beta, t):
7979

8080
def split_de_casteljau(beta, t):
8181
"""
82-
Split a bezier segment defined by its control points *beta* into two
82+
Split a Bezier segment defined by its control points *beta* into two
8383
separate segments divided at *t* and return their control points.
8484
"""
8585
beta = np.asarray(beta)
@@ -99,21 +99,41 @@ def split_de_casteljau(beta, t):
9999
def find_bezier_t_intersecting_with_closedpath(
100100
bezier_point_at_t, inside_closedpath, t0=0., t1=1., tolerance=0.01):
101101
"""
102-
Find a parameter t0 and t1 of the given bezier path which
103-
bounds the intersecting points with a provided closed
104-
path(*inside_closedpath*). Search starts from *t0* and *t1* and it
105-
uses a simple bisecting algorithm therefore one of the end point
106-
must be inside the path while the other doesn't. The search stop
107-
when |t0-t1| gets smaller than the given tolerance.
108-
value for
102+
Find the intersection of the Bezier curve with a closed path.
109103
110-
- bezier_point_at_t : a function which returns x, y coordinates at *t*
104+
The intersection point *t* is approximated by two parameters *t0*, *t1*
105+
such that *t0* <= *t* <= *t1*.
111106
112-
- inside_closedpath : return True if the point is inside the path
107+
Search starts from *t0* and *t1* and uses a simple bisecting algorithm
108+
therefore one of the end points must be inside the path while the other
109+
doesn't. The search stops when the distance of the points parametrized by
110+
*t0* and *t1* gets smaller than the given *tolerance*.
113111
114-
"""
115-
# inside_closedpath : function
112+
Parameters
113+
----------
114+
bezier_point_at_t : callable
115+
A function returning x, y coordinates of the Bezier at parameter *t*.
116+
It must have the signature::
117+
118+
bezier_point_at_t(t: float) -> Tuple[float, float]
119+
120+
inside_closedpath : callable
121+
A function returning True if a given point (x, y) is inside the
122+
closed path. It must have the signature::
123+
124+
inside_closedpath(point: Tuple[float, float]) -> bool
116125
126+
t0, t1 : float
127+
Start parameters for the search.
128+
129+
tolerance : float
130+
Maximal allowed distance between the final points.
131+
132+
Returns
133+
-------
134+
t0, t1 : float
135+
The Bezier path parameters.
136+
"""
117137
start = bezier_point_at_t(t0)
118138
end = bezier_point_at_t(t1)
119139

@@ -147,21 +167,22 @@ def find_bezier_t_intersecting_with_closedpath(
147167

148168
class BezierSegment:
149169
"""
150-
A simple class of a 2-dimensional bezier segment
170+
A 2-dimensional Bezier segment.
171+
172+
Parameters
173+
----------
174+
control_points : array-like (N, 2)
175+
A list of the (x, y) positions of control points of the Bezier line.
176+
This must contain N points, where N is the order of the Bezier line.
177+
1 <= N <= 3 is supported.
151178
"""
152-
153-
# Higher order bezier lines can be supported by simplying adding
179+
# Higher order Bezier lines can be supported by simplying adding
154180
# corresponding values.
155181
_binom_coeff = {1: np.array([1., 1.]),
156182
2: np.array([1., 2., 1.]),
157183
3: np.array([1., 3., 3., 1.])}
158184

159185
def __init__(self, control_points):
160-
"""
161-
*control_points* : location of contol points. It needs have a
162-
shape of n * 2, where n is the order of the bezier line. 1<=
163-
n <= 3 is supported.
164-
"""
165186
_o = len(control_points)
166187
self._orders = np.arange(_o)
167188

@@ -171,7 +192,7 @@ def __init__(self, control_points):
171192
self._py = yy * _coeff
172193

173194
def point_at_t(self, t):
174-
"evaluate a point at t"
195+
"""Return the point (x, y) at parameter *t*."""
175196
tt = ((1 - t) ** self._orders)[::-1] * t ** self._orders
176197
_x = np.dot(tt, self._px)
177198
_y = np.dot(tt, self._py)
@@ -182,9 +203,23 @@ def point_at_t(self, t):
182203
def split_bezier_intersecting_with_closedpath(
183204
bezier, inside_closedpath, tolerance=0.01):
184205
"""
185-
bezier : control points of the bezier segment
186-
inside_closedpath : a function which returns true if the point is inside
187-
the path
206+
Split a Bezier curve into two at the intersection with a closed path.
207+
208+
Parameters
209+
----------
210+
bezier : array-like(N, 2)
211+
Control points of the Bezier segment. See `.BezierSegment`.
212+
inside_closedpath : callable
213+
A function returning True if a given point (x, y) is inside the
214+
closed path. See also `.find_bezier_t_intersecting_with_closedpath`.
215+
tolerance : float
216+
The tolerance for the intersection. See also
217+
`.find_bezier_t_intersecting_with_closedpath`.
218+
219+
Returns
220+
-------
221+
left, right
222+
Lists of control points for the two Bezier segments.
188223
"""
189224

190225
bz = BezierSegment(bezier)
@@ -205,12 +240,18 @@ def find_r_to_boundary_of_closedpath(
205240
Find a radius r (centered at *xy*) between *rmin* and *rmax* at
206241
which it intersect with the path.
207242
208-
inside_closedpath : function
209-
cx, cy : center
210-
cos_t, sin_t : cosine and sine for the angle
211-
rmin, rmax :
243+
Parameters
244+
----------
245+
inside_closedpath : callable
246+
A function returning True if a given point (x, y) is inside the
247+
closed path.
248+
xy : float, float
249+
The center of the radius.
250+
cos_t, sin_t : float
251+
Cosine and sine for the angle.
252+
rmin, rmax : float
253+
Starting parameters for the radius search.
212254
"""
213-
214255
cx, cy = xy
215256

216257
def _f(r):
@@ -228,7 +269,6 @@ def split_path_inout(path, inside, tolerance=0.01, reorder_inout=False):
228269
Divide a path into two segments at the point where ``inside(x, y)`` becomes
229270
False.
230271
"""
231-
232272
path_iter = path.iter_segments()
233273

234274
ctl_points, command = next(path_iter)
@@ -287,6 +327,14 @@ def split_path_inout(path, inside, tolerance=0.01, reorder_inout=False):
287327

288328

289329
def inside_circle(cx, cy, r):
330+
"""
331+
Return a function that checks whether a point is in a circle with center
332+
(*cx*, *cy*) and radius *r*.
333+
334+
The returned function has the signature::
335+
336+
f(xy: Tuple[float, float]) -> bool
337+
"""
290338
r2 = r ** 2
291339

292340
def _f(xy):
@@ -295,7 +343,7 @@ def _f(xy):
295343
return _f
296344

297345

298-
# quadratic bezier lines
346+
# quadratic Bezier lines
299347

300348
def get_cos_sin(x0, y0, x1, y1):
301349
dx, dy = x1 - x0, y1 - y0
@@ -309,8 +357,22 @@ def get_cos_sin(x0, y0, x1, y1):
309357
@cbook._rename_parameter("3.1", "tolerence", "tolerance")
310358
def check_if_parallel(dx1, dy1, dx2, dy2, tolerance=1.e-5):
311359
"""
312-
Return 1 if two lines are parallel in same direction, -1 if two lines are
313-
parallel in opposite direction, 0 otherwise.
360+
Check if two lines are parallel.
361+
362+
Parameters
363+
----------
364+
dx1, dy1, dx2, dy2 : float
365+
The gradients *dy*/*dx* of the two lines.
366+
tolerance : float
367+
The angular tolerance in radians up to which the lines are considered
368+
parallel.
369+
370+
Returns
371+
-------
372+
is_parallel
373+
- 1 if two lines are parallel in same direction.
374+
- -1 if two lines are parallel in opposite direction.
375+
- False otherwise.
314376
"""
315377
theta1 = np.arctan2(dx1, dy1)
316378
theta2 = np.arctan2(dx2, dy2)
@@ -325,14 +387,14 @@ def check_if_parallel(dx1, dy1, dx2, dy2, tolerance=1.e-5):
325387

326388
def get_parallels(bezier2, width):
327389
"""
328-
Given the quadratic bezier control points *bezier2*, returns
329-
control points of quadratic bezier lines roughly parallel to given
390+
Given the quadratic Bezier control points *bezier2*, returns
391+
control points of quadratic Bezier lines roughly parallel to given
330392
one separated by *width*.
331393
"""
332394

333-
# The parallel bezier lines are constructed by following ways.
395+
# The parallel Bezier lines are constructed by following ways.
334396
# c1 and c2 are control points representing the begin and end of the
335-
# bezier line.
397+
# Bezier line.
336398
# cm is the middle point
337399

338400
c1x, c1y = bezier2[0]
@@ -355,7 +417,7 @@ def get_parallels(bezier2, width):
355417

356418
# find c1_left, c1_right which are located along the lines
357419
# through c1 and perpendicular to the tangential lines of the
358-
# bezier path at a distance of width. Same thing for c2_left and
420+
# Bezier path at a distance of width. Same thing for c2_left and
359421
# c2_right with respect to c2.
360422
c1x_left, c1y_left, c1x_right, c1y_right = (
361423
get_normal_points(c1x, c1y, cos_t1, sin_t1, width)
@@ -385,7 +447,7 @@ def get_parallels(bezier2, width):
385447
sin_t1, c2x_right, c2y_right,
386448
cos_t2, sin_t2)
387449

388-
# the parallel bezier lines are created with control points of
450+
# the parallel Bezier lines are created with control points of
389451
# [c1_left, cm_left, c2_left] and [c1_right, cm_right, c2_right]
390452
path_left = [(c1x_left, c1y_left),
391453
(cmx_left, cmy_left),
@@ -410,7 +472,7 @@ def find_control_points(c1x, c1y, mmx, mmy, c2x, c2y):
410472
def make_wedged_bezier2(bezier2, width, w1=1., wm=0.5, w2=0.):
411473
"""
412474
Being similar to get_parallels, returns control points of two quadratic
413-
bezier lines having a width roughly parallel to given one separated by
475+
Bezier lines having a width roughly parallel to given one separated by
414476
*width*.
415477
"""
416478

@@ -426,7 +488,7 @@ def make_wedged_bezier2(bezier2, width, w1=1., wm=0.5, w2=0.):
426488

427489
# find c1_left, c1_right which are located along the lines
428490
# through c1 and perpendicular to the tangential lines of the
429-
# bezier path at a distance of width. Same thing for c3_left and
491+
# Bezier path at a distance of width. Same thing for c3_left and
430492
# c3_right with respect to c3.
431493
c1x_left, c1y_left, c1x_right, c1y_right = (
432494
get_normal_points(c1x, c1y, cos_t1, sin_t1, width * w1)

0 commit comments

Comments
 (0)