@@ -58,6 +58,67 @@ between `line.start` and `line.end`.
5858Points (and mesh vertices and graph nodes) are drawn with a fixed on-screen size
5959in points, so they do not grow or shrink when you zoom.
6060
61+ ## 3D shapes
62+
63+ 3D shapes are drawn as their projection onto the XY plane. A ` Box ` , for example,
64+ is projected face by face, so it reads as a solid wireframe regardless of how its
65+ frame is oriented.
66+
67+ ``` python
68+ from math import radians
69+ from compas.geometry import Box, Frame
70+ from compas_plotters import Plotter
71+
72+ plotter = Plotter(figsize = (8 , 5 ))
73+
74+ # an axis-aligned box projects to a rectangle
75+ plotter.add(Box(3 , 2 , 1 ))
76+
77+ # a rotated box keeps its 3D silhouette
78+ frame = Frame([6 , 0 , 0 ]).rotated(radians(35 ), [1 , 1 , 1 ], point = [6 , 0 , 0 ])
79+ plotter.add(Box(2 , 2 , 2 , frame = frame), facecolor = (0.9 , 0.9 , 1.0 ), alpha = 0.3 )
80+
81+ plotter.zoom_extents()
82+ plotter.show()
83+ ```
84+
85+ Pass ` fill=False ` for a pure wireframe, or tune ` alpha ` and ` facecolor ` to shade
86+ the faces. Because a projection has no depth sorting, faces are not hidden behind
87+ one another — every edge stays visible.
88+
89+ ### Rotating box animation
90+
91+ A good way to confirm the projection is spinning the box and watching the
92+ silhouette update every frame. Rotate the geometry inside a
93+ [ ` Plotter.on ` ] [ compas_plotters.Plotter.on ] callback (see
94+ [ Dynamic plots and animations] ( #dynamic-plots-and-animations ) ) and the plotter
95+ reprojects and redraws it:
96+
97+ ``` python
98+ from math import radians
99+ from compas.geometry import Box, Frame, Rotation
100+ from compas_plotters import Plotter
101+
102+ plotter = Plotter(figsize = (6 , 6 ))
103+
104+ box = Box(2 , 2 , 2 , frame = Frame([0 , 0 , 0 ]).rotated(radians(35 ), [1 , 1 , 1 ]))
105+ plotter.add(box, facecolor = (0.9 , 0.9 , 1.0 ), alpha = 0.3 )
106+
107+ # keep the view fixed so the box is seen to rotate, not the camera
108+ plotter.zoom_extents()
109+
110+ rotation = Rotation.from_axis_and_angle([0 , 1 , 0 ], radians(6 ), point = [0 , 0 , 0 ])
111+
112+ @plotter.on (interval = 0.05 , frames = 60 , record = True , recording = " box.gif" )
113+ def spin (frame ):
114+ box.transform(rotation)
115+
116+ plotter.show()
117+ ```
118+
119+ Each frame applies a small rotation about the Z axis; the six faces are
120+ re-projected onto the XY plane, so the wireframe appears to turn in 3D.
121+
61122## Meshes
62123
63124Meshes reuse the data layer of the COMPAS scene system, so the ` show_vertices ` ,
0 commit comments