drawlib 0.2.3.dev2__py3-none-any.whl → 0.2.3.dev4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of drawlib might be problematic. Click here for more details.

@@ -10,17 +10,24 @@
10
10
 
11
11
  """Canvas's original arrow feature implementation module."""
12
12
 
13
- from typing import Literal, Optional, Tuple, Union
13
+ import math
14
+ from typing import List, Literal, Optional, Tuple, Union
15
+
16
+ from matplotlib.patches import PathPatch
17
+ from matplotlib.path import Path
14
18
 
15
19
  import drawlib.v0_2.private.validators.args as validator
16
20
  from drawlib.v0_2.private.core.model import ShapeStyle, ShapeTextStyle
17
21
  from drawlib.v0_2.private.core.theme import dtheme
18
22
  from drawlib.v0_2.private.core.util import ShapeUtil
19
23
  from drawlib.v0_2.private.core_canvas.base import CanvasBase
24
+ from drawlib.v0_2.private.core_canvas.line import LineArcHelper
20
25
  from drawlib.v0_2.private.util import (
21
26
  error_handler,
22
27
  get_angle,
23
28
  get_distance,
29
+ get_rotated_path_points,
30
+ get_rotated_points,
24
31
  )
25
32
 
26
33
 
@@ -137,3 +144,472 @@ class CanvasOriginalArrowFeature(CanvasBase):
137
144
  textsize=textsize,
138
145
  textstyle=textstyle,
139
146
  )
147
+
148
+ @error_handler
149
+ def arrow_polyline(
150
+ self,
151
+ xys: List[Tuple[float, float]],
152
+ tail_width: float,
153
+ head_width: float,
154
+ head_length: float,
155
+ head: Literal[
156
+ "->",
157
+ "<-",
158
+ "<->",
159
+ ] = "->",
160
+ r: float = 0,
161
+ style: Union[ShapeStyle, str, None] = None,
162
+ ) -> None:
163
+ """Draw single and double-headed arrow.
164
+
165
+ Args:
166
+ xys: List[Tuple[float, float]]: Arrow points.
167
+ tail_width: float: Width of the arrow tail.
168
+ head_width: float: Width of the arrow head.
169
+ head_length: float: Length of the arrow head.
170
+ head: Literal["->", "<-", "<->"]: Arrow head style ("->", "<-", "<->").
171
+ r (float, optional): Radius for rounded connections (default is 0.0).
172
+ style: Union[ShapeStyle, str, None]: Optional style of the arrow.
173
+
174
+ Returns:
175
+ None
176
+ """
177
+ # matplotlib FancyArrow, FancyArrowPatch seems not good
178
+ # for implement this function.
179
+ # Calculate arrow points pass it to shape().
180
+
181
+ style, _ = ShapeUtil.format_styles(
182
+ style,
183
+ None,
184
+ dtheme.arrowstyles.get,
185
+ dtheme.arrowtextstyles.get,
186
+ )
187
+ validator.validate_shape_args(locals())
188
+
189
+ def point_on_line(a: Tuple[float, float], b: Tuple[float, float], n: float) -> Tuple[float, float]:
190
+ ab = (b[0] - a[0], b[1] - a[1])
191
+ ab_length = math.sqrt(ab[0] ** 2 + ab[1] ** 2)
192
+ ab_unit = (ab[0] / ab_length, ab[1] / ab_length)
193
+ scaled_vector = (ab_unit[0] * n, ab_unit[1] * n)
194
+ new_point = (a[0] + scaled_vector[0], a[1] + scaled_vector[1])
195
+ return new_point
196
+
197
+ def point_parallel_to_line(
198
+ a: Tuple[float, float], b: Tuple[float, float], distance: float
199
+ ) -> Tuple[float, float]:
200
+ ab = (b[0] - a[0], b[1] - a[1])
201
+ ab_length = math.sqrt(ab[0] ** 2 + ab[1] ** 2)
202
+ ab_unit = (ab[0] / ab_length, ab[1] / ab_length)
203
+ ab_perpendicular = (-ab_unit[1], ab_unit[0])
204
+ scaled_vector = (ab_perpendicular[0] * distance, ab_perpendicular[1] * distance)
205
+ new_point = (a[0] + scaled_vector[0], a[1] + scaled_vector[1])
206
+ return new_point
207
+
208
+ if head in {"<-", "<->"}:
209
+ xys_start = point_on_line(xys[0], xys[1], head_length)
210
+ else:
211
+ xys_start = xys[0]
212
+
213
+ if head in {"->", "<->"}:
214
+ xys_end = point_on_line(xys[-1], xys[-2], head_length)
215
+ else:
216
+ xys_end = xys[-1]
217
+
218
+ new_xys = xys[1:-1]
219
+ new_xys.insert(0, xys_start)
220
+ new_xys.append(xys_end)
221
+ aph = ArrowPolylineHelper(new_xys, r, 100)
222
+ parallel_xys1 = aph.get_parallel_curve_points(tail_width / 2)
223
+ parallel_xys2 = aph.get_parallel_curve_points(tail_width / -2)
224
+ parallel_xys2.reverse()
225
+
226
+ if head in {"<-", "<->"}:
227
+ ahp1 = point_parallel_to_line(xys_start, xys[1], head_width / 2)
228
+ ahp2 = point_parallel_to_line(xys_start, xys[1], head_width / -2)
229
+ parallel_xys1.insert(0, xys[0])
230
+ parallel_xys1.insert(1, ahp1)
231
+ parallel_xys2.append(ahp2)
232
+
233
+ if head in {"->", "<->"}:
234
+ ahp3 = point_parallel_to_line(xys_end, xys[-2], head_width / -2)
235
+ ahp4 = point_parallel_to_line(xys_end, xys[-2], head_width / 2)
236
+ parallel_xys1.append(ahp3)
237
+ parallel_xys1.append(xys[-1])
238
+ parallel_xys1.append(ahp4)
239
+
240
+ parallel_xys1.extend(parallel_xys2)
241
+ self.polygon(xys=parallel_xys1, style=style, text="", textstyle=None)
242
+
243
+ @error_handler
244
+ def arrow_arc(
245
+ self,
246
+ xy: Tuple[float, float],
247
+ width: float,
248
+ height: float,
249
+ tail_width: float,
250
+ head_width: float,
251
+ head_angle: float = 10,
252
+ head: Literal["->", "<-", "<->"] = "->",
253
+ angle_start: float = 0,
254
+ angle_end: float = 180,
255
+ angle: float = 0,
256
+ style: Union[ShapeStyle, str, None] = None,
257
+ ) -> None:
258
+ """Draw arc arrow.
259
+
260
+ Args:
261
+ xy: Tuple[float, float]: The center point of the circle from which the arc arrow is drawn.
262
+ width: float: The width of the ellipse.
263
+ height: float: The height of the ellipse
264
+ tail_width: float: The width of the tail of the arrow.
265
+ head_width: float: The width of the head of the arrow.
266
+ head_angle: float: The angle of the arrowhead in degrees (default is 10).
267
+ head: Literal["->", "<-", "<->"]: The arrowhead style ("->", "<-", "<->").
268
+ angle_start: float: The starting angle of the arc in degrees (default is 0).
269
+ angle_end: float: The ending angle of the arc in degrees (default is 180).
270
+ angle (float): The angle of ellipse.
271
+ style: Union[ShapeStyle, str, None]: Optional shape style.
272
+
273
+ Returns:
274
+ None
275
+ """
276
+ style, _ = ShapeUtil.format_styles(
277
+ style,
278
+ None,
279
+ dtheme.arrowstyles.get,
280
+ dtheme.arrowtextstyles.get,
281
+ )
282
+ validator.validate_shape_args(locals())
283
+
284
+ width_int = width - tail_width
285
+ width_ext = width + tail_width
286
+ height_int = height - tail_width
287
+ height_ext = height + tail_width
288
+
289
+ if head in {"<-", "<->"}:
290
+ angle_start2 = angle_start + head_angle
291
+ angle_start2 %= 360
292
+ else:
293
+ angle_start2 = angle_start
294
+
295
+ if head in {"->", "<->"}:
296
+ angle_end2 = angle_end - head_angle
297
+ angle_end2 %= 360
298
+ else:
299
+ angle_end2 = angle_end
300
+
301
+ if angle_start2 > angle_end2:
302
+ pp1_fa = -1 * (360 - angle_start2)
303
+ pp1_ta = angle_end2
304
+ pp2_fa = angle_end2
305
+ pp2_ta = pp1_fa
306
+ else:
307
+ pp1_fa = angle_start2
308
+ pp1_ta = angle_end2
309
+ pp2_fa = angle_end2
310
+ pp2_ta = angle_start2
311
+
312
+ path_points1 = LineArcHelper.get_ellipse_path_points(
313
+ xy,
314
+ width_int,
315
+ height_int,
316
+ pp1_fa,
317
+ pp1_ta,
318
+ )
319
+ path_points2 = LineArcHelper.get_ellipse_path_points(
320
+ xy,
321
+ width_ext,
322
+ height_ext,
323
+ pp2_fa,
324
+ pp2_ta,
325
+ )
326
+
327
+ if angle_start > angle_end:
328
+ angle_start = -1 * (360 - angle_start)
329
+
330
+ if head in {"<-", "<->"}:
331
+ path_points1.insert(
332
+ 0,
333
+ LineArcHelper.get_point_on_ellipse(
334
+ xy,
335
+ width,
336
+ height,
337
+ angle_start,
338
+ ),
339
+ )
340
+ path_points1.insert(
341
+ 1,
342
+ LineArcHelper.get_point_on_ellipse(
343
+ xy,
344
+ width - head_width,
345
+ height - head_width,
346
+ angle_start2,
347
+ ),
348
+ )
349
+ path_points2.append(
350
+ LineArcHelper.get_point_on_ellipse(
351
+ xy,
352
+ width + head_width,
353
+ height + head_width,
354
+ angle_start2,
355
+ )
356
+ )
357
+
358
+ if head in {"->", "<->"}:
359
+ path_points1.append(
360
+ LineArcHelper.get_point_on_ellipse(
361
+ xy,
362
+ width - head_width,
363
+ height - head_width,
364
+ angle_end2,
365
+ )
366
+ )
367
+ path_points1.append(
368
+ LineArcHelper.get_point_on_ellipse(
369
+ xy,
370
+ width,
371
+ height,
372
+ angle_end,
373
+ )
374
+ )
375
+ path_points2.insert(
376
+ 0,
377
+ LineArcHelper.get_point_on_ellipse(
378
+ xy,
379
+ width + head_width,
380
+ height + head_width,
381
+ angle_end2,
382
+ ),
383
+ )
384
+
385
+ path_points1.extend(path_points2)
386
+
387
+ if angle != 0:
388
+ path_points1 = get_rotated_path_points(path_points1, xy, angle) # type: ignore
389
+
390
+ # create Path
391
+ vertices = [path_points1[0]]
392
+ codes = [Path.MOVETO]
393
+ for p in path_points1[1:]:
394
+ length = len(p)
395
+ if length not in {2, 3}:
396
+ raise ValueError()
397
+
398
+ if not isinstance(p[0], tuple):
399
+ vertices.append(p)
400
+ codes.append(Path.LINETO)
401
+
402
+ elif length == 2:
403
+ vertices.extend([p[0], p[1]]) # type: ignore
404
+ codes.extend([Path.CURVE3] * 2)
405
+
406
+ else:
407
+ vertices.extend([p[0], p[1], p[2]]) # type: ignore
408
+ codes.extend([Path.CURVE4] * 3)
409
+
410
+ vertices.append(path_points1[0])
411
+ codes.append(Path.CLOSEPOLY)
412
+ path = Path(vertices=vertices, codes=codes)
413
+
414
+ # create PathPatch
415
+
416
+ options = ShapeUtil.get_shape_options(style)
417
+ self._artists.append(PathPatch(path=path, **options))
418
+
419
+ @error_handler
420
+ def arrow_l(
421
+ self,
422
+ xy: Tuple[float, float],
423
+ width: float,
424
+ height: float,
425
+ tail_width: float,
426
+ head_width: float,
427
+ head_length: float,
428
+ head: Literal["->", "<-", "<->"] = "->",
429
+ r: float = 0,
430
+ angle: float = 0,
431
+ style: Union[ShapeStyle, str, None] = None,
432
+ ) -> None:
433
+ """Draw "L" shape arrow.
434
+
435
+ Args:
436
+ xy: Tuple[float, float]: The center point of L arrow.
437
+ width: float: The width L arrow.
438
+ height: float: The height of L arrow.
439
+ tail_width: float: The width of the tail of the arrow.
440
+ head_width: float: The width of the head of the arrow.
441
+ head_length: float: Length of the arrow head.
442
+ head: Literal["->", "<-", "<->"]: Arrow head style ("->", "<-", "<->").
443
+ r (float, optional): Radius for rounded connections (default is 0.0).
444
+ angle: float: rotate angle.
445
+ style: Union[ShapeStyle, str, None]: Optional shape style.
446
+
447
+ Returns:
448
+ None
449
+ """
450
+ style, _ = ShapeUtil.format_styles(
451
+ style,
452
+ None,
453
+ dtheme.arrowstyles.get,
454
+ dtheme.arrowtextstyles.get,
455
+ )
456
+ validator.validate_shape_args(locals())
457
+
458
+ p1 = (xy[0] - width / 2, xy[1] + height / 2)
459
+ p2 = (xy[0] - width / 2, xy[1] - height / 2)
460
+ p3 = (xy[0] + width / 2, xy[1] - height / 2)
461
+
462
+ xys = [p1, p2, p3]
463
+ if angle != 0:
464
+ xys = get_rotated_points(xys=xys, center=xy, angle=angle)
465
+
466
+ self.arrow_polyline(
467
+ xys=xys,
468
+ tail_width=tail_width,
469
+ head_width=head_width,
470
+ head_length=head_length,
471
+ head=head,
472
+ r=r,
473
+ style=style,
474
+ )
475
+
476
+ @error_handler
477
+ def arrow_u(
478
+ self,
479
+ xy: Tuple[float, float],
480
+ width: float,
481
+ height: float,
482
+ tail_width: float,
483
+ head_width: float,
484
+ head_length: float,
485
+ head: Literal["->", "<-", "<->"] = "->",
486
+ r: float = 0,
487
+ angle: float = 0,
488
+ style: Union[ShapeStyle, str, None] = None,
489
+ ) -> None:
490
+ """Draw "U" shape arrow.
491
+
492
+ Args:
493
+ xy: Tuple[float, float]: The center point U arrow.
494
+ width: float: The width of the U arrow.
495
+ height: float: The height of the U arrow.
496
+ tail_width: float: The width of the tail of the arrow.
497
+ head_width: float: The width of the head of the arrow.
498
+ head_length: float: Length of the arrow head.
499
+ head: Literal["->", "<-", "<->"]: Arrow head style ("->", "<-", "<->").
500
+ r (float, optional): Radius for rounded connections (default is 0.0).
501
+ angle: float: rotate angle.
502
+ style: Union[ShapeStyle, str, None]: Optional shape style.
503
+
504
+ Returns:
505
+ None
506
+ """
507
+ style, _ = ShapeUtil.format_styles(
508
+ style,
509
+ None,
510
+ dtheme.arrowstyles.get,
511
+ dtheme.arrowtextstyles.get,
512
+ )
513
+ validator.validate_shape_args(locals())
514
+
515
+ p1 = (xy[0] - width / 2, xy[1] + height / 2)
516
+ p2 = (xy[0] - width / 2, xy[1] - height / 2)
517
+ p3 = (xy[0] + width / 2, xy[1] - height / 2)
518
+ p4 = (xy[0] + width / 2, xy[1] + height / 2)
519
+
520
+ xys = [p1, p2, p3, p4]
521
+ if angle != 0:
522
+ xys = get_rotated_points(xys=xys, center=xy, angle=angle)
523
+
524
+ self.arrow_polyline(
525
+ xys=xys,
526
+ tail_width=tail_width,
527
+ head_width=head_width,
528
+ head_length=head_length,
529
+ head=head,
530
+ r=r,
531
+ style=style,
532
+ )
533
+
534
+
535
+ class ArrowPolylineHelper:
536
+ """Internal class"""
537
+
538
+ def __init__(
539
+ self,
540
+ xys: List[Tuple[float, float]],
541
+ r: float,
542
+ num_points: int = 100,
543
+ ) -> None:
544
+ """Internal function"""
545
+
546
+ def get_mid_points(
547
+ a: Tuple[float, float],
548
+ b: Tuple[float, float],
549
+ ) -> Tuple[Tuple[float, float], Tuple[float, float]]:
550
+ ab = [b[0] - a[0], b[1] - a[1]]
551
+ ab_distance = math.sqrt(ab[0] ** 2 + ab[1] ** 2)
552
+ ab_unit = [ab[0] / ab_distance, ab[1] / ab_distance]
553
+ c = (a[0] + r * ab_unit[0], a[1] + r * ab_unit[1])
554
+ d = (b[0] - r * ab_unit[0], b[1] - r * ab_unit[1])
555
+ return c, d
556
+
557
+ def bernstein_poly(i: int, n: int, t: float) -> float:
558
+ return math.comb(n, i) * (t**i) * ((1 - t) ** (n - i))
559
+
560
+ def get_points(
561
+ bezier_points: List[Tuple[float, float]],
562
+ ) -> List[Tuple[float, float]]:
563
+ n = len(bezier_points) - 1
564
+ curve = []
565
+ for t in [i / (num_points - 1) for i in range(num_points)]:
566
+ x = sum(bernstein_poly(i, n, t) * bezier_points[i][0] for i in range(n + 1))
567
+ y = sum(bernstein_poly(i, n, t) * bezier_points[i][1] for i in range(n + 1))
568
+ curve.append((x, y))
569
+ return curve
570
+
571
+ points = []
572
+ bezier_start: Tuple[float, float] = (0, 0)
573
+ last_i = len(xys) - 2
574
+ # last_xy = (0, 0)
575
+ for i in range(len(xys)):
576
+ # first straight line
577
+ if i == 0:
578
+ _, bezier_start = get_mid_points(xys[0], xys[1])
579
+ points.append(xys[0])
580
+ continue
581
+
582
+ # last straight line
583
+ if i == last_i:
584
+ p1, _ = get_mid_points(xys[i], xys[i + 1])
585
+ bezier_points = [bezier_start, xys[i], p1]
586
+ points.extend(get_points(bezier_points))
587
+ points.append(xys[i + 1])
588
+ break
589
+
590
+ p1, p2 = get_mid_points(xys[i], xys[i + 1])
591
+ bezier_points = [bezier_start, xys[i], p1]
592
+ points.extend(get_points(bezier_points))
593
+ bezier_start = p2
594
+
595
+ self._original_curve_points = points
596
+
597
+ def get_parallel_curve_points(self, distance: float) -> List[Tuple[float, float]]:
598
+ """Internal function"""
599
+
600
+ def get_distance(p1: Tuple[float, float], p2: Tuple[float, float]) -> float:
601
+ return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
602
+
603
+ parallel_curve_points = []
604
+ for i in range(1, len(self._original_curve_points)):
605
+ p0, p1 = self._original_curve_points[i - 1], self._original_curve_points[i]
606
+ dx, dy = p1[0] - p0[0], p1[1] - p0[1]
607
+ length = get_distance(p0, p1)
608
+ nx, ny = -dy / length, dx / length
609
+ px0, py0 = p0[0] + distance * nx, p0[1] + distance * ny
610
+ px1, py1 = p1[0] + distance * nx, p1[1] + distance * ny
611
+ parallel_curve_points.append((px0, py0))
612
+ if i == len(self._original_curve_points) - 1:
613
+ parallel_curve_points.append((px1, py1))
614
+
615
+ return parallel_curve_points
@@ -16,7 +16,6 @@ from matplotlib.patches import (
16
16
  Arc,
17
17
  Circle,
18
18
  Ellipse,
19
- Polygon,
20
19
  RegularPolygon,
21
20
  Wedge,
22
21
  )
@@ -26,7 +25,7 @@ from drawlib.v0_2.private.core.model import ShapeStyle, ShapeTextStyle
26
25
  from drawlib.v0_2.private.core.theme import dtheme
27
26
  from drawlib.v0_2.private.core.util import ShapeUtil
28
27
  from drawlib.v0_2.private.core_canvas.base import CanvasBase
29
- from drawlib.v0_2.private.util import error_handler, get_center_and_size
28
+ from drawlib.v0_2.private.util import error_handler
30
29
 
31
30
 
32
31
  class CanvasPatchesFeature(CanvasBase):
@@ -46,8 +45,8 @@ class CanvasPatchesFeature(CanvasBase):
46
45
  xy: Tuple[float, float],
47
46
  width: float,
48
47
  height: float,
49
- from_angle: Union[int, float] = 0.0,
50
- to_angle: Union[int, float] = 360.0,
48
+ angle_start: Union[int, float] = 0.0,
49
+ angle_end: Union[int, float] = 360.0,
51
50
  angle: Union[int, float] = 0.0,
52
51
  style: Union[ShapeStyle, str, None] = None,
53
52
  text: str = "",
@@ -60,8 +59,8 @@ class CanvasPatchesFeature(CanvasBase):
60
59
  xy: Center of the arc.
61
60
  width: Width of the arc.
62
61
  height: Height of the arc.
63
- from_angle (optional): Starting angle of the arc (default is 0.0).
64
- to_angle (optional): Ending angle of the arc (default is 360.0).
62
+ angle_start (optional): Starting angle of the arc (default is 0.0).
63
+ angle_end (optional): Ending angle of the arc (default is 360.0).
65
64
  angle (optional): Rotation angle of the arc.
66
65
  style (optional): Style of the arc.
67
66
  text (optional): Text shown at the center of the arc.
@@ -90,8 +89,8 @@ class CanvasPatchesFeature(CanvasBase):
90
89
  width=width,
91
90
  height=height,
92
91
  angle=angle,
93
- theta1=from_angle,
94
- theta2=to_angle,
92
+ theta1=angle_start,
93
+ theta2=angle_end,
95
94
  **options,
96
95
  )
97
96
  )
@@ -227,55 +226,6 @@ class CanvasPatchesFeature(CanvasBase):
227
226
  ),
228
227
  )
229
228
 
230
- @error_handler
231
- def polygon(
232
- self,
233
- xys: List[Tuple[float, float]],
234
- style: Union[ShapeStyle, str, None] = None,
235
- text: str = "",
236
- textsize: Optional[float] = None,
237
- textstyle: Union[ShapeTextStyle, str, None] = None,
238
- ) -> None:
239
- """Draw a polygon on the canvas.
240
-
241
- Args:
242
- xys: List of vertices [(x1, y1), ...(x_n, y_n)].
243
- style (optional): Style of the polygon.
244
- text (optional): Text shown at the center of the polygon.
245
- textsize (optional): Font size of the text.
246
- textstyle (optional): Style of the text.
247
-
248
- Returns:
249
- None
250
- """
251
- style, textstyle = ShapeUtil.format_styles(
252
- style,
253
- textstyle,
254
- dtheme.polygonstyles.get,
255
- dtheme.polygontextstyles.get,
256
- )
257
- validator.validate_shape_args(locals())
258
-
259
- if textsize is not None:
260
- textstyle.size = textsize
261
-
262
- style.halign = None
263
- style.valign = None
264
- options = ShapeUtil.get_shape_options(style)
265
- self._artists.append(Polygon(xy=xys, closed=True, **options))
266
-
267
- if not text:
268
- return
269
- center, (_, _) = get_center_and_size(xys)
270
- self._artists.append(
271
- ShapeUtil.get_shape_text(
272
- center,
273
- text=text,
274
- angle=0,
275
- style=textstyle,
276
- ),
277
- )
278
-
279
229
  @error_handler
280
230
  def regularpolygon(
281
231
  self,
@@ -345,8 +295,8 @@ class CanvasPatchesFeature(CanvasBase):
345
295
  xy: Tuple[float, float],
346
296
  radius: float,
347
297
  width: Optional[float] = None,
348
- from_angle: float = 0,
349
- to_angle: float = 360,
298
+ angle_start: float = 0,
299
+ angle_end: float = 360,
350
300
  angle: Union[int, float] = 0.0,
351
301
  style: Union[ShapeStyle, str, None] = None,
352
302
  text: str = "",
@@ -360,8 +310,8 @@ class CanvasPatchesFeature(CanvasBase):
360
310
  radius: Radius of the wedge.
361
311
  width (optional): Length from outer to inner circumference.
362
312
  Default is same as radius.
363
- from_angle (optional): Starting angle of the wedge (default is 0).
364
- to_angle (optional): Ending angle of the wedge (default is 360).
313
+ angle_start (optional): Starting angle of the wedge (default is 0).
314
+ angle_end (optional): Ending angle of the wedge (default is 360).
365
315
  angle (optional): Rotation angle of the wedge.
366
316
  style (optional): Style of the wedge.
367
317
  text (optional): Text shown at the center of the wedge.
@@ -391,8 +341,8 @@ class CanvasPatchesFeature(CanvasBase):
391
341
  center=xy,
392
342
  r=radius,
393
343
  width=width, # None makes no hole
394
- theta1=from_angle + angle,
395
- theta2=to_angle + angle,
344
+ theta1=angle_start + angle,
345
+ theta2=angle_end + angle,
396
346
  **options,
397
347
  )
398
348
  )
@@ -459,8 +409,8 @@ class CanvasPatchesFeature(CanvasBase):
459
409
  self,
460
410
  xy: Tuple[float, float],
461
411
  radius: float,
462
- from_angle: float = 0,
463
- to_angle: float = 180,
412
+ angle_start: float = 0,
413
+ angle_end: float = 180,
464
414
  angle: Union[int, float] = 0.0,
465
415
  style: Union[ShapeStyle, str, None] = None,
466
416
  text: str = "",
@@ -472,8 +422,8 @@ class CanvasPatchesFeature(CanvasBase):
472
422
  Args:
473
423
  xy: Center of the fan.
474
424
  radius: Radius of the fan.
475
- from_angle (optional): Starting angle of the fan (default is 0).
476
- to_angle (optional): Ending angle of the fan (default is 180).
425
+ angle_start (optional): Starting angle of the fan (default is 0).
426
+ angle_end (optional): Ending angle of the fan (default is 180).
477
427
  angle (optional): Rotation angle of the fan.
478
428
  style (optional): Style of the fan.
479
429
  text (optional): Text shown at the center of the fan.
@@ -495,8 +445,8 @@ class CanvasPatchesFeature(CanvasBase):
495
445
  xy=xy,
496
446
  radius=radius,
497
447
  width=None,
498
- from_angle=from_angle,
499
- to_angle=to_angle,
448
+ angle_start=angle_start,
449
+ angle_end=angle_end,
500
450
  angle=angle,
501
451
  style=style,
502
452
  text=text,