Skip to content

Commit ea23937

Browse files
Add docs for styled batch drawings (#232)
* updated docs for styled batch drawings * Update docs/source/drawing_shapes.rst Co-authored-by: martinRenou <[email protected]> * extended docs Co-authored-by: martinRenou <[email protected]>
1 parent 4901de1 commit ea23937

10 files changed

+329
-42
lines changed

docs/source/drawing_shapes.rst

Lines changed: 280 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ left corner of the blue square becomes x pixels from the left and y pixels from
2020
Drawing rectangles
2121
------------------
2222

23-
There are four methods that draw rectangles on the canvas:
23+
There are six methods that draw rectangles on the canvas:
2424

2525
- ``fill_rect(x, y, width, height=None)``:
2626
Draws a filled rectangle. If ``height`` is None, it is set to the same value as ``width``.
@@ -32,6 +32,10 @@ There are four methods that draw rectangles on the canvas:
3232
- ``stroke_rects(x, y, width, height=None)``:
3333
Draws rectangular outlines. Where ``x``, ``y``, ``width`` and ``height`` are either integers, lists of integers or NumPy arrays.
3434
If ``height`` is None, it is set to the same value as ``width``.
35+
- ``fill_styled_rect(x, y, width, height, color, alpha)``:
36+
Same as ``fill_rects`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
37+
- ``stroke_styled_rects(x, y, width, height, color, alpha)``:
38+
Same as ``stroke_rects`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
3539

3640
You can also clear a certain canvas rectangle area:
3741

@@ -83,8 +87,19 @@ It's the fastest way to draw a polygon with ipycanvas.
8387

8488
- ``fill_polygon(points)``:
8589
Fill a polygon from a list of points ``[(x1, y1), (x2, y2), ..., (xn, yn)]``.
86-
- ``stroke_polygon(points)``:
87-
Draw polygon outline from a list of points ``[(x1, y1), (x2, y2), ..., (xn, yn)]``.
90+
- ``stroke_polygon(points)``: Draw polygon outline from a list of points ``[(x1, y1), (x2, y2), ..., (xn, yn)]``.
91+
92+
- ``fill_polygons(points, points_per_polygon=None)``:
93+
Fill multiple polygons at once.
94+
- ``stroke_polygons(points, points_per_polygon=None)``:
95+
Stroke multiple polygons at once. See :ref:`styled_polygons` for details.
96+
- ``fill_styled_polygons(points, color, alpha, points_per_polygon=None)``:
97+
Fill multiple polygons at once where each polygon can have its own color.
98+
See :ref:`styled_polygons` for details.
99+
- ``stroke_styled_polygons(points, color, alpha, points_per_polygon=None)``:
100+
Stroke multiple polygons at once where each polygon can have its own color.
101+
See :ref:`styled_polygons` for details.
102+
88103

89104
.. code:: Python
90105
@@ -146,6 +161,10 @@ There are methods that draw arcs/circles on the canvas:
146161
Draw filled arcs centered at ``(x, y)`` with a radius of ``radius``. Where ``x``, ``y``, ``radius`` and other arguments are NumPy arrays, lists or scalar values.
147162
- ``stroke_arcs(x, y, radius, start_angle, end_angle, anticlockwise=False)``:
148163
Draw an arc outlines centered at ``(x, y)`` with a radius of ``radius``. Where ``x``, ``y``, ``radius`` and other arguments are NumPy arrays, lists or scalar values.
164+
- ``fill_styled_arcs( x, y, radius, start_angle, end_angle, color, alpha, anticlockwise=False)``:
165+
Same as ``fill_arcs`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
166+
- ``stroke_styled_arcs( x, y, radius, start_angle, end_angle, color, alpha, anticlockwise=False)``:
167+
Same as ``stroke_arcs`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
149168

150169
- ``fill_circle(x, y, radius)``:
151170
Draw a filled circle centered at ``(x, y)`` with a radius of ``radius``.
@@ -155,7 +174,10 @@ There are methods that draw arcs/circles on the canvas:
155174
Draw filled circles centered at ``(x, y)`` with a radius of ``radius``. Where ``x``, ``y``, ``radius`` are NumPy arrays, lists or scalar values.
156175
- ``stroke_circles(x, y, radius)``:
157176
Draw a circle outlines centered at ``(x, y)`` with a radius of ``radius``. Where ``x``, ``y``, ``radius`` are NumPy arrays, lists or scalar values.
158-
177+
- ``fill_styled_circles( x, y, radius color, alpha)`` :
178+
Same as ``fill_circles`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
179+
- ``stroke_styled_circles( x, y, radius, color, alpha)`` :
180+
Same as ``stroke_circles`` but with additional ``(n x 3)`` ``color`` ndarray and ``(n)`` ``alpha`` ndarray.
159181

160182
.. code:: Python
161183
@@ -184,6 +206,10 @@ There are two commands for drawing a straight line from one point to another:
184206
Draw a line from ``(x1, y1)`` to ``(x2, y2)``.
185207
- ``stroke_lines(points)``:
186208
Draw a path of consecutive lines from a list of points ``[(x1, y1), (x2, y2), ..., (xn, yn)]``.
209+
- ``stroke_styled_line_segments(points, points_per_line_segment=None)``:
210+
Draw multiple disconnected line-segments at once. See :ref:`styled_polygons` for details.
211+
- ``stroke_styled_line_segments(points, color, alpha, points_per_line_segment=None)``:
212+
Draw multiple disconnected line-segments at once. See :ref:`styled_polygons` for details.
187213

188214
.. code:: Python
189215
@@ -228,7 +254,7 @@ There are two commands for drawing a straight line from one point to another:
228254
Vectorized methods
229255
------------------
230256

231-
Some methods like ``fill_rect`` and ``fill_circle`` have a vectorized counterpart: ``fill_rects`` and ``fill_circles``. It is essential
257+
Most methods like ``fill_rect``/``stroke_rect`` and ``fill_circle``/``stroke_circle`` have vectorized counterparts: ``fill_rects``/``stroke_rects`` and ``fill_circles``/``stroke_circles``. It is essential
232258
to use those methods when you want to draw the same shape multiple times with the same style.
233259

234260
For example, it is way faster to run:
@@ -265,3 +291,252 @@ instead of running:
265291
canvas.fill_rect(position, position, size)
266292
267293
canvas
294+
295+
296+
.. _styled_vectorized_methods:
297+
298+
Styled vectorized methods
299+
------------------------------------
300+
301+
Ipycanvas provides methods to draw the same shape multiple times but with different colors:
302+
303+
- ``fill_styled_rects`` / ``stroke_styled_rects``
304+
- ``fill_styled_circles`` / ``stroke_styled_circles``
305+
- ``fill_styled_arcs`` / ``stroke_styled_arcs``
306+
- ``fill_styled_polygons`` / ``stroke_styled_polygons``
307+
- ``fill_styled_line_segments`` / ``stroke_styled_line_segments``
308+
309+
310+
Rects
311+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
312+
313+
.. code:: Python
314+
315+
import numpy as np
316+
from ipycanvas import Canvas, hold_canvas
317+
318+
canvas = Canvas(width=400, height=300)
319+
n_rects = 300
320+
x = np.random.randint(0, canvas.width, size=(n_rects))
321+
y = np.random.randint(0, canvas.width, size=(n_rects))
322+
width = np.random.randint(10, 40, size=(n_rects))
323+
height = np.random.randint(10, 40, size=(n_rects))
324+
colors_fill = np.random.randint(0, 255, size=(n_rects, 3))
325+
colors_outline = np.random.randint(0, 255, size=(n_rects, 3))
326+
alphas = np.random.random(n_rects)
327+
with hold_canvas(canvas):
328+
canvas.fill_styled_rects(x, y, width, height,
329+
color=colors_fill,
330+
alpha=alphas)
331+
canvas.line_width = 2
332+
canvas.stroke_styled_rects(x, y, width, height,
333+
color=colors_outline,
334+
alpha=alphas)
335+
canvas
336+
337+
338+
.. image:: images/draw_styled_rects.png
339+
:scale: 50 %
340+
341+
Circles
342+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
343+
344+
.. code:: Python
345+
346+
import numpy as np
347+
from ipycanvas import Canvas, hold_canvas
348+
349+
canvas = Canvas(width=300, height=300)
350+
n_circles = 100
351+
x = np.random.randint(0, canvas.width, size=(n_circles))
352+
y = np.random.randint(0, canvas.width, size=(n_circles))
353+
r = np.random.randint(10, 20, size=(n_circles))
354+
colors_fill = np.random.randint(0, 255, size=(n_circles, 3))
355+
colors_outline = np.random.randint(0, 255, size=(n_circles, 3))
356+
alphas = np.random.random(n_circles)
357+
with hold_canvas(canvas):
358+
canvas.fill_styled_circles(x, y, r, color=colors_fill, alpha=alphas)
359+
canvas.line_width = 2
360+
canvas.stroke_styled_circles(x, y, r, color=colors_outline, alpha=1)
361+
canvas
362+
363+
364+
.. image:: images/draw_styled_circles.png
365+
:scale: 50 %
366+
367+
Arcs
368+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
369+
370+
.. code:: Python
371+
372+
import numpy as np
373+
from ipycanvas import Canvas, hold_canvas
374+
import math
375+
376+
canvas = Canvas(width=300, height=300)
377+
n_circles = 100
378+
x = np.random.randint(0, canvas.width, size=(n_circles))
379+
y = np.random.randint(0, canvas.width, size=(n_circles))
380+
r = np.random.randint(10, 20, size=(n_circles))
381+
start_angle = np.random.randint(0, 360, size=(n_circles))
382+
end_angle = np.random.randint(0, 360, size=(n_circles))
383+
start_angle = 0
384+
end_angle = math.pi
385+
start_angle = np.random.random(n_circles) * math.pi
386+
end_angle = np.random.random(n_circles) * math.pi
387+
alphas = np.random.random(n_circles)
388+
with hold_canvas(canvas):
389+
canvas.fill_style = "cyan"
390+
canvas.fill_arcs(x, y, r, start_angle, end_angle)
391+
canvas.line_width = 1
392+
canvas.stroke_style = "black"
393+
canvas.stroke_arcs(x, y, r, start_angle, end_angle)
394+
canvas
395+
396+
.. image:: images/draw_styled_arcs.png
397+
:scale: 50 %
398+
399+
400+
.. _styled_polygons:
401+
402+
Polygons / line-segments
403+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
404+
405+
Case 1: All polygons / line-segments have the same number of points
406+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
407+
408+
.. code:: Python
409+
410+
import numpy as np
411+
from ipycanvas import Canvas, hold_canvas
412+
413+
canvas = Canvas(width=300, height=300)
414+
n_polygons = 50
415+
416+
# each polygon has 4 points
417+
n_points_per_polygon = 4
418+
419+
polygons = np.zeros([n_polygons, n_points_per_polygon, 2])
420+
421+
polygons[:, 0, 0] = 0.0
422+
polygons[:, 0, 1] = 0.0
423+
424+
polygons[:, 1, 0] = 1.0
425+
polygons[:, 1, 1] = 0.0
426+
427+
polygons[:, 2, 0] = 1.0
428+
polygons[:, 2, 1] = 1.0
429+
430+
polygons[:, 3, 0] = 0.0
431+
polygons[:, 3, 1] = 1.0
432+
433+
colors_fill = np.random.randint(0, 255, size=(n_polygons, 3))
434+
colors_outline = np.random.randint(0, 255, size=(n_polygons, 3))
435+
436+
# scale each polygon
437+
polygons *= np.linspace(1.0, 200.0, num=n_polygons)[:, None, None]
438+
439+
# translate each polygon
440+
polygons += np.linspace(1.0, 100.0, num=n_polygons)[:, None, None]
441+
442+
points_per_polygon = np.ones([n_polygons]) * n_points_per_polygon
443+
with hold_canvas(canvas):
444+
canvas.stroke_styled_polygons(polygons, color=colors_fill, alpha=1)
445+
canvas
446+
447+
448+
.. image:: images/draw_styled_polygons.png
449+
:scale: 50 %
450+
451+
452+
.. code:: Python
453+
454+
import numpy as np
455+
from ipycanvas import Canvas, hold_canvas
456+
457+
canvas = Canvas(width=300, height=300)
458+
459+
n_line_segments = 20
460+
461+
n_points_per_line_segment = 500
462+
463+
line_segments = np.zeros([n_line_segments, n_points_per_line_segment, 2])
464+
465+
x = np.linspace(0, canvas.width, num=n_points_per_line_segment)[None, :]
466+
line_segments[:, :, 0] = np.linspace(0, canvas.width,
467+
num=n_points_per_line_segment)[None, :]
468+
line_segments[:, :, 1] = (30.0 * np.sin(x * 0.1))[None, :]
469+
470+
colors_outline = np.random.randint(0, 255, size=(n_polygons, 3))
471+
472+
# translate line segments in y direction
473+
line_segments[:, :, 1] += np.linspace(1.0, canvas.height,
474+
num=n_line_segments)[:, None]
475+
476+
with hold_canvas(canvas):
477+
canvas.stroke_styled_line_segments(line_segments, color=colors_fill, alpha=1)
478+
canvas
479+
480+
481+
.. image:: images/draw_styled_line_segments.png
482+
:scale: 50 %
483+
484+
485+
Case 2: Polygons / line-segments can have different number of Points.
486+
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
487+
488+
Polygons can be given as a list of ndarrays:
489+
490+
.. code:: Python
491+
492+
import numpy as np
493+
from ipycanvas import Canvas, hold_canvas
494+
495+
canvas = Canvas(width=400, height=400)
496+
497+
triangle = [(0, 0), (0, 40), (30, 40)] # triangle
498+
rectangle = [(100, 100), (300, 100), (300, 200), (100, 200)] # rectangle
499+
irregular = np.random.randint(0, 400, size=(5, 2)) # irregular with 5 sides
500+
polygons = [triangle, rectangle, irregular]
501+
colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]
502+
503+
with hold_canvas(canvas):
504+
canvas.fill_styled_polygons(polygons, color=colors, alpha=1)
505+
canvas
506+
507+
.. image:: images/draw_styled_polygons_from_list.png
508+
:scale: 50 %
509+
510+
511+
Polygons can be given as a flat ndarray:
512+
513+
.. code:: Python
514+
515+
import numpy as np
516+
from ipycanvas import Canvas, hold_canvas
517+
518+
canvas = Canvas(width=400, height=400)
519+
n_polygons = 20
520+
points_per_polygon = np.random.randint(3, 6, size=n_polygons)
521+
total_points = np.sum(points_per_polygon)
522+
polygons = np.random.randint(0, 400, size=[total_points, 2])
523+
alpha = np.random.random(n_polygons)
524+
colors_fill = np.random.randint(0, 255, size=(n_polygons, 3))
525+
colors_outline = np.random.randint(0, 255, size=(n_polygons, 3))
526+
527+
with hold_canvas(canvas):
528+
# the filling
529+
canvas.fill_styled_polygons(
530+
polygons, points_per_polygon=points_per_polygon,
531+
color=colors_fill, alpha=alpha
532+
)
533+
534+
# draw outlines ontop where each line has the same style
535+
canvas.stroke_style = "black"
536+
canvas.line_width = 2
537+
canvas.stroke_polygons(polygons, points_per_polygon=points_per_polygon)
538+
canvas
539+
540+
541+
.. image:: images/draw_styled_polygons_flat_array.png
542+
:scale: 50 %
60.5 KB
Loading
155 KB
Loading
217 KB
Loading
65.4 KB
Loading
267 KB
Loading
17.3 KB
Loading
72.1 KB
Loading

examples/batch_drawing.ipynb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@
337337
"colors = [(255, 0, 0), (0, 255, 0), (0, 0, 255)]\n",
338338
"\n",
339339
"with hold_canvas(canvas):\n",
340-
" canvas.fill_styled_polygons(polygons, color=colors_fill, alpha=1)\n",
340+
" canvas.fill_styled_polygons(polygons, color=colors, alpha=1)\n",
341341
"canvas"
342342
]
343343
},

0 commit comments

Comments
 (0)