Skip to content

Commit

Permalink
Refactored p5 arc to use canvas ellipse
Browse files Browse the repository at this point in the history
  • Loading branch information
ksen0 committed Sep 2, 2024
1 parent cc17b64 commit 94e1969
Showing 1 changed file with 24 additions and 83 deletions.
107 changes: 24 additions & 83 deletions src/core/p5.Renderer2D.js
Original file line number Diff line number Diff line change
Expand Up @@ -532,42 +532,6 @@ class Renderer2D extends p5.Renderer {
// SHAPE | 2D Primitives
//////////////////////////////////////////////

/**
* Generate a cubic Bezier representing an arc on the unit circle of total
* angle `size` radians, beginning `start` radians above the x-axis. Up to
* four of these curves are combined to make a full arc.
*
* See ecridge.com/bezier.pdf for an explanation of the method.
*/
_acuteArcToBezier(
start,
size
) {
// Evaluate constants.
const alpha = size / 2.0,
cos_alpha = Math.cos(alpha),
sin_alpha = Math.sin(alpha),
cot_alpha = 1.0 / Math.tan(alpha),
// This is how far the arc needs to be rotated.
phi = start + alpha,
cos_phi = Math.cos(phi),
sin_phi = Math.sin(phi),
lambda = (4.0 - cos_alpha) / 3.0,
mu = sin_alpha + (cos_alpha - lambda) * cot_alpha;

// Return rotated waypoints.
return {
ax: Math.cos(start).toFixed(7),
ay: Math.sin(start).toFixed(7),
bx: (lambda * cos_phi + mu * sin_phi).toFixed(7),
by: (lambda * sin_phi - mu * cos_phi).toFixed(7),
cx: (lambda * cos_phi - mu * sin_phi).toFixed(7),
cy: (lambda * sin_phi + mu * cos_phi).toFixed(7),
dx: Math.cos(start + size).toFixed(7),
dy: Math.sin(start + size).toFixed(7)
};
}

/*
* This function requires that:
*
Expand All @@ -577,64 +541,41 @@ class Renderer2D extends p5.Renderer {
*/
arc(x, y, w, h, start, stop, mode) {
const ctx = this.drawingContext;
const rx = w / 2.0;
const ry = h / 2.0;
const epsilon = 0.00001; // Smallest visible angle on displays up to 4K.
let arcToDraw = 0;
const curves = [];

x += rx;
y += ry;

// Create curves
while (stop - start >= epsilon) {
arcToDraw = Math.min(stop - start, constants.HALF_PI);
curves.push(this._acuteArcToBezier(start, arcToDraw));
start += arcToDraw;
}

// Fill curves
const centerX = x + w / 2,
centerY = y + h / 2,
radiusX = w / 2,
radiusY = h / 2;

// Determines whether to add a line to the center, which should be done
// when the mode is PIE or default, as well as when the start and end
// angles do not form a full circle.
const createPieSlice = ! (
mode === constants.CHORD ||
mode === constants.OPEN ||
(stop - start) % constants.TWO_PI === 0
);

// Fill
if (this._doFill) {
if (!this._clipping) ctx.beginPath();
curves.forEach((curve, index) => {
if (index === 0) {
ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
}
/* eslint-disable indent */
ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry,
x + curve.cx * rx, y + curve.cy * ry,
x + curve.dx * rx, y + curve.dy * ry);
/* eslint-enable indent */
});
if (mode === constants.PIE || mode == null) {
ctx.lineTo(x, y);
}
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
if (createPieSlice) ctx.lineTo(centerX, centerY);
ctx.closePath();
if (!this._clipping) ctx.fill();
}

// Stroke curves
// Stroke
if (this._doStroke) {
if (!this._clipping) ctx.beginPath();
curves.forEach((curve, index) => {
if (index === 0) {
ctx.moveTo(x + curve.ax * rx, y + curve.ay * ry);
}
/* eslint-disable indent */
ctx.bezierCurveTo(x + curve.bx * rx, y + curve.by * ry,
x + curve.cx * rx, y + curve.cy * ry,
x + curve.dx * rx, y + curve.dy * ry);
/* eslint-enable indent */
});
if (mode === constants.PIE) {
ctx.lineTo(x, y);
ctx.closePath();
} else if (mode === constants.CHORD) {
ctx.closePath();
}
ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, start, stop);
if (createPieSlice) ctx.lineTo(centerX, centerY);
if (mode !== constants.OPEN) ctx.closePath();
if (!this._clipping) ctx.stroke();
}

return this;

}

ellipse(args) {
Expand All @@ -659,7 +600,7 @@ class Renderer2D extends p5.Renderer {
radiusX = w / 2,
radiusY = h / 2;
if (!this._clipping) ctx.beginPath();

ctx.ellipse(centerX, centerY, radiusX, radiusY, 0, 0, 2 * Math.PI);

if (!this._clipping && doFill) {
Expand Down

0 comments on commit 94e1969

Please sign in to comment.