4343from mpl_toolkits .mplot3d import Axes3D
4444
4545
46-
4746# TODO
4847# return a redrawer object, that can be used for animation
4948
5049# =========================== 2D shapes =================================== #
5150
51+
5252def plot_text (
5353 pos : ArrayLike2 ,
5454 text : str ,
@@ -101,6 +101,7 @@ def plot_text(
101101 handle = ax .text (pos [0 ], pos [1 ], text , color = color , ** kwargs )
102102 return [handle ]
103103
104+
104105def plot_point (
105106 pos : ArrayLike2 ,
106107 marker : str | None = "bs" ,
@@ -270,6 +271,7 @@ def plot_point(
270271 )
271272 return handles
272273
274+
273275def plot_homline (
274276 lines : ArrayLike3 | NDArray ,
275277 * args ,
@@ -336,6 +338,7 @@ def plot_homline(
336338
337339 return handles
338340
341+
339342def plot_box (
340343 * fmt : str | None ,
341344 lbrt : ArrayLike4 | None = None ,
@@ -509,6 +512,7 @@ def plot_box(
509512
510513 return r
511514
515+
512516def plot_arrow (
513517 start : ArrayLike2 ,
514518 end : ArrayLike2 ,
@@ -609,6 +613,7 @@ def plot_arrow(
609613 label = " " + label
610614 ax .text (* pos , label , ** opt )
611615
616+
612617def plot_polygon (
613618 vertices : NDArray , * fmt , close : bool = False , ** kwargs
614619) -> list [Artist ]:
@@ -643,6 +648,7 @@ def plot_polygon(
643648 vertices = np .hstack ((vertices , vertices [:, [0 ]]))
644649 return _render2D (vertices , fmt = fmt , ** kwargs )
645650
651+
646652def _render2D (
647653 vertices : NDArray ,
648654 pose = None ,
@@ -668,6 +674,7 @@ def _render2D(
668674 r = plt .plot (vertices [0 , :], vertices [1 , :], * fmt , ** kwargs )
669675 return r
670676
677+
671678def circle (
672679 centre : ArrayLike2 = (0 , 0 ),
673680 radius : float = 1 ,
@@ -707,6 +714,7 @@ def circle(
707714 else :
708715 return np .array ((x , y ))
709716
717+
710718def plot_circle (
711719 radius : float ,
712720 centre : ArrayLike2 ,
@@ -763,6 +771,7 @@ def plot_circle(
763771 handles .append (ax .plot (xy [0 , :], xy [1 , :], * fmt , ** kwargs ))
764772 return handles
765773
774+
766775def ellipse (
767776 E : R2x2 ,
768777 centre : ArrayLike2 | None = (0 , 0 ),
@@ -826,6 +835,7 @@ def ellipse(
826835 e = s * sqrtm (E ) @ xy + np .array (centre , ndmin = 2 ).T
827836 return e
828837
838+
829839def plot_ellipse (
830840 E : R2x2 ,
831841 centre : ArrayLike2 ,
@@ -893,8 +903,10 @@ def plot_ellipse(
893903 else :
894904 plt .plot (xy [0 , :], xy [1 , :], * fmt , ** kwargs )
895905
906+
896907# =========================== 3D shapes =================================== #
897908
909+
898910def sphere (
899911 radius : float | None = 1 ,
900912 centre : ArrayLike3 | None = (0 , 0 , 0 ),
@@ -927,6 +939,7 @@ def sphere(
927939
928940 return (x , y , z )
929941
942+
930943def plot_sphere (
931944 radius : float ,
932945 centre : ArrayLike3 | None = (0 , 0 , 0 ),
@@ -995,6 +1008,7 @@ def plot_sphere(
9951008
9961009 return handles
9971010
1011+
9981012def ellipsoid (
9991013 E : R2x2 ,
10001014 centre : ArrayLike3 | None = (0 , 0 , 0 ),
@@ -1042,16 +1056,14 @@ def ellipsoid(
10421056
10431057 x , y , z = sphere () # unit sphere
10441058 centre = smb .getvector (centre , 3 , out = "col" )
1045- e = (
1046- scale * sqrtm (E ) @ np .array ([x .flatten (), y .flatten (), z .flatten ()])
1047- + centre
1048- )
1059+ e = scale * sqrtm (E ) @ np .array ([x .flatten (), y .flatten (), z .flatten ()]) + centre
10491060 return (
10501061 e [0 , :].reshape (x .shape ),
10511062 e [1 , :].reshape (x .shape ),
10521063 e [2 , :].reshape (x .shape ),
10531064 )
10541065
1066+
10551067def plot_ellipsoid (
10561068 E : R3x3 ,
10571069 centre : ArrayLike3 | None = (0 , 0 , 0 ),
@@ -1111,6 +1123,7 @@ def plot_ellipsoid(
11111123 handle = _render3D (ax , X , Y , Z , ** kwargs )
11121124 return [handle ]
11131125
1126+
11141127def cylinder (
11151128 center_x : float ,
11161129 center_y : float ,
@@ -1149,6 +1162,7 @@ def cylinder(
11491162 Y = radius * np .sin (theta_grid ) + center_y
11501163 return X , Y , Z
11511164
1165+
11521166# https://stackoverflow.com/questions/30715083/python-plotting-a-wireframe-3d-cuboid
11531167# https://stackoverflow.com/questions/26874791/disconnected-surfaces-when-plotting-cones
11541168def plot_cylinder (
@@ -1230,6 +1244,7 @@ def plot_cylinder(
12301244
12311245 return handles
12321246
1247+
12331248def plot_cone (
12341249 radius : float ,
12351250 height : float ,
@@ -1298,9 +1313,7 @@ def plot_cone(
12981313
12991314 handles = []
13001315 handles .append (_render3D (ax , X , Y , Z , filled = filled , ** kwargs ))
1301- handles .append (
1302- _render3D (ax , X , (2 * centre [1 ] - Y ), Z , filled = filled , ** kwargs )
1303- )
1316+ handles .append (_render3D (ax , X , (2 * centre [1 ] - Y ), Z , filled = filled , ** kwargs ))
13041317
13051318 if ends and kwargs .get ("filled" , default = False ):
13061319 floor = Circle (centre [:2 ], radius , ** kwargs )
@@ -1313,6 +1326,7 @@ def plot_cone(
13131326
13141327 return handles
13151328
1329+
13161330def plot_cuboid (
13171331 sides : ArrayLike3 = (1 , 1 , 1 ),
13181332 centre : ArrayLike3 | None = (0 , 0 , 0 ),
@@ -1408,6 +1422,7 @@ def plot_cuboid(
14081422 ax .add_collection3d (collection )
14091423 return collection
14101424
1425+
14111426def _render3D (
14121427 ax : Axes ,
14131428 X : NDArray ,
@@ -1445,6 +1460,7 @@ def _render3D(
14451460 kwargs ["colors" ] = color
14461461 return ax .plot_wireframe (X , Y , Z , ** kwargs )
14471462
1463+
14481464def _axes_dimensions (ax : Axes ) -> int :
14491465 """
14501466 Dimensions of axes
@@ -1468,13 +1484,16 @@ def _axes_dimensions(ax: Axes) -> int:
14681484 # print("_axes_dimensions ", ax, ret)
14691485 return ret
14701486
1487+
14711488def axes_get_limits (ax : Axes ) -> NDArray :
14721489 return np .r_ [ax .get_xlim (), ax .get_ylim ()]
14731490
1491+
14741492def axes_get_scale (ax : Axes ) -> float :
14751493 limits = axes_get_limits (ax )
14761494 return max (abs (limits [1 ] - limits [0 ]), abs (limits [3 ] - limits [2 ]))
14771495
1496+
14781497@overload
14791498def axes_logic (
14801499 ax : Axes | None ,
@@ -1483,6 +1502,7 @@ def axes_logic(
14831502 new : bool | None = False ,
14841503) -> Axes : ...
14851504
1505+
14861506@overload
14871507def axes_logic (
14881508 ax : Axes | None ,
@@ -1492,6 +1512,7 @@ def axes_logic(
14921512 new : bool | None = False ,
14931513) -> Axes3D : ...
14941514
1515+
14951516def axes_logic (
14961517 ax : Axes | Axes3D | None ,
14971518 dimensions : int ,
@@ -1566,6 +1587,7 @@ def axes_logic(
15661587
15671588 return ax
15681589
1590+
15691591def plotvol2 (
15701592 dim : ArrayLike | None = None ,
15711593 ax : Axes | None = None ,
@@ -1621,6 +1643,7 @@ def plotvol2(
16211643 ax ._plotvol = True
16221644 return ax
16231645
1646+
16241647def plotvol3 (
16251648 dim : ArrayLike | None = None ,
16261649 ax : Axes | None = None ,
@@ -1682,6 +1705,7 @@ def plotvol3(
16821705 ax ._plotvol = True
16831706 return ax
16841707
1708+
16851709def expand_dims (dim : ArrayLike | None = None , nd : int = 2 ) -> NDArray :
16861710 """
16871711 Expand compact axis dimensions
@@ -1729,6 +1753,7 @@ def expand_dims(dim: ArrayLike | None = None, nd: int = 2) -> NDArray:
17291753 else :
17301754 raise ValueError ("nd is 2 or 3" )
17311755
1756+
17321757def isnotebook () -> bool :
17331758 """
17341759 Determine if code is being run from a Jupyter notebook
@@ -1751,6 +1776,7 @@ def isnotebook() -> bool:
17511776 except NameError :
17521777 return False # Probably standard Python interpreter
17531778
1779+
17541780if __name__ == "__main__" :
17551781 import pathlib
17561782
0 commit comments