Skip to content

Commit e721e86

Browse files
authored
Merge pull request #40 from martinRenou/arc_methods
Arc methods
2 parents 16f283a + 591eef7 commit e721e86

File tree

5 files changed

+143
-14
lines changed

5 files changed

+143
-14
lines changed

docs/source/drawing_shapes.rst

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,34 @@ You can also clear a certain canvas rectangle area:
6666
6767
.. image:: images/rects.png
6868

69+
Drawing circles
70+
---------------
71+
72+
There are four methods that draw circles on the canvas:
73+
74+
- ``fill_arc(x, y, radius, start_angle, end_angle, anticlockwise=False)``: Draw a filled arc centered at ``(x, y)`` with a radius of ``radius``.
75+
- ``stroke_arc(x, y, radius, start_angle, end_angle, anticlockwise=False)``: Draw an arc outline centered at ``(x, y)`` with a radius of ``radius``.
76+
- ``fill_arcs(x, y, radius, start_angle, end_angle, anticlockwise=False)``: 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.
77+
- ``stroke_arcs(x, y, radius, start_angle, end_angle, anticlockwise=False)``: 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.
78+
79+
.. code:: Python
80+
81+
from math import pi
82+
83+
from ipycanvas import Canvas
84+
85+
canvas = Canvas(size=(200, 200))
86+
87+
canvas.fill_style = 'red'
88+
canvas.stroke_style = 'blue'
89+
90+
canvas.fill_arc(60, 60, 50, 0, pi)
91+
canvas.stroke_arc(60, 60, 40, 0, 2 * pi)
92+
93+
canvas
94+
95+
.. image:: images/arc.png
96+
6997
Drawing paths
7098
-------------
7199

docs/source/images/arc.png

4.19 KB
Loading

examples/plotting.ipynb

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -131,20 +131,14 @@
131131
" canvas.stroke_style = stroke_color\n",
132132
"\n",
133133
" for idx in range(n_marks):\n",
134-
" canvas.begin_path()\n",
135-
"\n",
136134
" canvas.fill_style = colormap(color[idx])\n",
135+
" \n",
136+
" mark_x = scale_x(x[idx])\n",
137+
" mark_y = scale_y(y[idx])\n",
138+
" mark_size = size[idx]\n",
137139
"\n",
138-
" canvas.arc(\n",
139-
" scale_x(x[idx]), scale_y(y[idx]),\n",
140-
" size[idx],\n",
141-
" 0, 2 * pi\n",
142-
" )\n",
143-
"\n",
144-
" canvas.fill()\n",
145-
" canvas.stroke()\n",
146-
"\n",
147-
" canvas.close_path()\n",
140+
" canvas.fill_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n",
141+
" canvas.stroke_arc(mark_x, mark_y, mark_size, 0, 2 * pi)\n",
148142
"\n",
149143
" canvas.restore()\n",
150144
"\n",
@@ -246,7 +240,7 @@
246240
"metadata": {},
247241
"outputs": [],
248242
"source": [
249-
"n_points = 500"
243+
"n_points = 1_000"
250244
]
251245
},
252246
{

ipycanvas/canvas.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,49 @@ def clear_rect(self, x, y, width, height=None):
164164

165165
self._send_canvas_command('clearRect', (x, y, width, height))
166166

167+
# Arc methods
168+
def fill_arc(self, x, y, radius, start_angle, end_angle, anticlockwise=False):
169+
"""Draw a filled arc centered at ``(x, y)`` with a radius of ``radius``."""
170+
self._send_canvas_command('fillArc', (x, y, radius, start_angle, end_angle, anticlockwise))
171+
172+
def stroke_arc(self, x, y, radius, start_angle, end_angle, anticlockwise=False):
173+
"""Draw an arc outline centered at ``(x, y)`` with a radius of ``radius``."""
174+
self._send_canvas_command('strokeArc', (x, y, radius, start_angle, end_angle, anticlockwise))
175+
176+
def fill_arcs(self, x, y, radius, start_angle, end_angle, anticlockwise=False):
177+
"""Draw filled arcs centered at ``(x, y)`` with a radius of ``radius``.
178+
179+
Where ``x``, ``y``, ``radius`` and other arguments are NumPy arrays, lists or scalar values.
180+
"""
181+
args = []
182+
buffers = []
183+
184+
populate_args(x, args, buffers)
185+
populate_args(y, args, buffers)
186+
populate_args(radius, args, buffers)
187+
populate_args(start_angle, args, buffers)
188+
populate_args(end_angle, args, buffers)
189+
args.append(anticlockwise)
190+
191+
self._send_canvas_command('fillArcs', args, buffers)
192+
193+
def stroke_arcs(self, x, y, radius, start_angle, end_angle, anticlockwise=False):
194+
"""Draw an arc outlines centered at ``(x, y)`` with a radius of ``radius``.
195+
196+
Where ``x``, ``y``, ``radius`` and other arguments are NumPy arrays, lists or scalar values.
197+
"""
198+
args = []
199+
buffers = []
200+
201+
populate_args(x, args, buffers)
202+
populate_args(y, args, buffers)
203+
populate_args(radius, args, buffers)
204+
populate_args(start_angle, args, buffers)
205+
populate_args(end_angle, args, buffers)
206+
args.append(anticlockwise)
207+
208+
self._send_canvas_command('strokeArcs', args, buffers)
209+
167210
# Paths methods
168211
def begin_path(self):
169212
"""Call this method when you want to create a new path."""

src/widget.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,18 @@ class CanvasModel extends DOMWidgetModel {
8686
case 'strokeRects':
8787
this.drawRects(command.args, buffers, 'strokeRect');
8888
break;
89+
case 'fillArc':
90+
this.fillArc(command.args, buffers);
91+
break;
92+
case 'strokeArc':
93+
this.strokeArc(command.args, buffers);
94+
break;
95+
case 'fillArcs':
96+
this.drawArcs(command.args, buffers, 'fill');
97+
break;
98+
case 'strokeArcs':
99+
this.drawArcs(command.args, buffers, 'stroke');
100+
break;
89101
case 'set':
90102
this.setAttr(command.attr, command.value);
91103
break;
@@ -116,6 +128,58 @@ class CanvasModel extends DOMWidgetModel {
116128
this.ctx.drawImage(offscreenCanvas, dx, dy);
117129
}
118130

131+
private fillArc(args: any[], buffers: any) {
132+
this.ctx.save();
133+
134+
this.ctx.beginPath();
135+
this.executeCommand('arc', args);
136+
this.ctx.closePath();
137+
138+
this.ctx.fill();
139+
this.ctx.restore();
140+
}
141+
142+
private strokeArc(args: any[], buffers: any) {
143+
this.ctx.save();
144+
145+
this.ctx.beginPath();
146+
this.executeCommand('arc', args);
147+
this.ctx.closePath();
148+
149+
this.ctx.stroke();
150+
this.ctx.restore();
151+
}
152+
153+
private drawArcs(args: any[], buffers: any, commandName: string) {
154+
const x = getArg(args[0], buffers);
155+
const y = getArg(args[1], buffers);
156+
const radius = getArg(args[2], buffers);
157+
const startAngle = getArg(args[3], buffers);
158+
const endAngle = getArg(args[4], buffers);
159+
const anticlockwise = getArg(args[5], buffers);
160+
161+
const numberArcs = Math.min(
162+
x.length, y.length, radius.length,
163+
startAngle.length, endAngle.length
164+
);
165+
166+
this.ctx.save();
167+
168+
for (let idx = 0; idx < numberArcs; ++idx) {
169+
this.ctx.beginPath();
170+
this.ctx.arc(
171+
x.getItem(idx), y.getItem(idx), radius.getItem(idx),
172+
startAngle.getItem(idx), endAngle.getItem(idx),
173+
anticlockwise.getItem(idx)
174+
);
175+
this.ctx.closePath();
176+
177+
this.executeCommand(commandName);
178+
}
179+
180+
this.ctx.restore();
181+
}
182+
119183
private drawRects(args: any[], buffers: any, commandName: string) {
120184
const x = getArg(args[0], buffers);
121185
const y = getArg(args[1], buffers);
@@ -140,7 +204,7 @@ class CanvasModel extends DOMWidgetModel {
140204
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
141205
}
142206

143-
private executeCommand(name: string, args: any[]) {
207+
private executeCommand(name: string, args: any[] = []) {
144208
(this.ctx as any)[name](...args);
145209
}
146210

0 commit comments

Comments
 (0)