8000 Cleanup docs of bezier · matplotlib/matplotlib@b36d05f · GitHub
[go: up one dir, main page]

Skip to content

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit b36d05f

Browse files
committed
Cleanup docs of bezier
1 parent f67d556 commit b36d05f

File tree

1 file changed

+106
-44
lines changed

1 file changed

+106
-44
lines changed

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
BC5F 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)
0