UNPKG

p5

Version:

[![npm version](https://badge.fury.io/js/p5.svg)](https://www.npmjs.com/package/p5)

1,454 lines (1,402 loc) 39.2 kB
import { e as CORNER, f as TWO_PI, g as HALF_PI, h as PI } from '../constants-BRcElHU3.js'; import canvas from '../core/helpers.js'; /** * @module Shape * @submodule 2D Primitives * @for p5 * @requires core * @requires constants */ function primitives(p5, fn){ /** * This function does 3 things: * * 1. Bounds the desired start/stop angles for an arc (in radians) so that: * * 0 <= start < TWO_PI ; start <= stop < start + TWO_PI * * This means that the arc rendering functions don't have to be concerned * with what happens if stop is smaller than start, or if the arc 'goes * round more than once', etc.: they can just start at start and increase * until stop and the correct arc will be drawn. * * 2. Optionally adjusts the angles within each quadrant to counter the naive * scaling of the underlying ellipse up from the unit circle. Without * this, the angles become arbitrary when width != height: 45 degrees * might be drawn at 5 degrees on a 'wide' ellipse, or at 85 degrees on * a 'tall' ellipse. * * 3. Flags up when start and stop correspond to the same place on the * underlying ellipse. This is useful if you want to do something special * there (like rendering a whole ellipse instead). */ fn._normalizeArcAngles = ( start, stop, width, height, correctForScaling ) => { const epsilon = 0.00001; // Smallest visible angle on displays up to 4K. let separation; // The order of the steps is important here: each one builds upon the // adjustments made in the steps that precede it. // Constrain both start and stop to [0,TWO_PI). start = start - TWO_PI * Math.floor(start / TWO_PI); stop = stop - TWO_PI * Math.floor(stop / TWO_PI); // Get the angular separation between the requested start and stop points. // // Technically this separation only matches what gets drawn if // correctForScaling is enabled. We could add a more complicated calculation // for when the scaling is uncorrected (in which case the drawn points could // end up pushed together or pulled apart quite dramatically relative to what // was requested), but it would make things more opaque for little practical // benefit. // // (If you do disable correctForScaling and find that correspondToSamePoint // is set too aggressively, the easiest thing to do is probably to just make // epsilon smaller...) separation = Math.min( Math.abs(start - stop), TWO_PI - Math.abs(start - stop) ); // Optionally adjust the angles to counter linear scaling. if (correctForScaling) { if (start <= HALF_PI) { start = Math.atan(width / height * Math.tan(start)); } else if (start > HALF_PI && start <= 3 * HALF_PI) { start = Math.atan(width / height * Math.tan(start)) + PI; } else { start = Math.atan(width / height * Math.tan(start)) + TWO_PI; } if (stop <= HALF_PI) { stop = Math.atan(width / height * Math.tan(stop)); } else if (stop > HALF_PI && stop <= 3 * HALF_PI) { stop = Math.atan(width / height * Math.tan(stop)) + PI; } else { stop = Math.atan(width / height * Math.tan(stop)) + TWO_PI; } } // Ensure that start <= stop < start + TWO_PI. if (start > stop) { stop += TWO_PI; } return { start, stop, correspondToSamePoint: separation < epsilon }; }; /** * Draws an arc. * * An arc is a section of an ellipse defined by the `x`, `y`, `w`, and * `h` parameters. `x` and `y` set the location of the arc's center. `w` and * `h` set the arc's width and height. See * <a href="#/p5/ellipse">ellipse()</a> and * <a href="#/p5/ellipseMode">ellipseMode()</a> for more details. * * The fifth and sixth parameters, `start` and `stop`, set the angles * between which to draw the arc. Arcs are always drawn clockwise from * `start` to `stop`. Angles are always given in radians. * * The seventh parameter, `mode`, is optional. It determines the arc's fill * style. The fill modes are a semi-circle (`OPEN`), a closed semi-circle * (`CHORD`), or a closed pie segment (`PIE`). * * The eighth parameter, `detail`, is also optional. It determines how many * vertices are used to draw the arc in WebGL mode. The default value is 25. * * @method arc * @param {Number} x x-coordinate of the arc's ellipse. * @param {Number} y y-coordinate of the arc's ellipse. * @param {Number} w width of the arc's ellipse by default. * @param {Number} h height of the arc's ellipse by default. * @param {Number} start angle to start the arc, specified in radians. * @param {Number} stop angle to stop the arc, specified in radians. * @param {(CHORD|PIE|OPEN)} [mode] optional parameter to determine the way of drawing * the arc. either CHORD, PIE, or OPEN. * @param {Integer} [detail] optional parameter for WebGL mode only. This is to * specify the number of vertices that makes up the * perimeter of the arc. Default value is 25. Won't * draw a stroke for a detail of more than 50. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * arc(50, 50, 80, 80, 0, PI + HALF_PI); * * describe('A white circle on a gray canvas. The top-right quarter of the circle is missing.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * arc(50, 50, 80, 40, 0, PI + HALF_PI); * * describe('A white ellipse on a gray canvas. The top-right quarter of the ellipse is missing.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Bottom-right. * arc(50, 55, 50, 50, 0, HALF_PI); * * noFill(); * * // Bottom-left. * arc(50, 55, 60, 60, HALF_PI, PI); * * // Top-left. * arc(50, 55, 70, 70, PI, PI + QUARTER_PI); * * // Top-right. * arc(50, 55, 80, 80, PI + QUARTER_PI, TWO_PI); * * describe( * 'A shattered outline of an circle with a quarter of a white circle at the bottom-right.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Default fill mode. * arc(50, 50, 80, 80, 0, PI + QUARTER_PI); * * describe('A white circle with the top-right third missing. The bottom is outlined in black.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // OPEN fill mode. * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, OPEN); * * describe( * 'A white circle missing a section from the top-right. The bottom is outlined in black.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // CHORD fill mode. * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, CHORD); * * describe('A white circle with a black outline missing a section from the top-right.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // PIE fill mode. * arc(50, 50, 80, 80, 0, PI + QUARTER_PI, PIE); * * describe('A white circle with a black outline. The top-right third is missing.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * // PIE fill mode. * arc(0, 0, 80, 80, 0, PI + QUARTER_PI, PIE); * * describe('A white circle with a black outline. The top-right third is missing.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * // PIE fill mode with 5 vertices. * arc(0, 0, 80, 80, 0, PI + QUARTER_PI, PIE, 5); * * describe('A white circle with a black outline. The top-right third is missing.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * describe('A yellow circle on a black background. The circle opens and closes its mouth.'); * } * * function draw() { * background(0); * * // Style the arc. * noStroke(); * fill(255, 255, 0); * * // Update start and stop angles. * let biteSize = PI / 16; * let startAngle = biteSize * sin(frameCount * 0.1) + biteSize; * let endAngle = TWO_PI - startAngle; * * // Draw the arc. * arc(50, 50, 80, 80, startAngle, endAngle, PIE); * } * </code> * </div> */ fn.arc = function(x, y, w, h, start, stop, mode, detail) { // this.validate("p5.arc", arguments); // p5._validateParameters('arc', arguments); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately if (!this._renderer.states.strokeColor && !this._renderer.states.fillColor) { return this; } if (start === stop) { return this; } start = this._toRadians(start); stop = this._toRadians(stop); const vals = canvas.modeAdjust(x, y, w, h, this._renderer.states.ellipseMode); const angles = this._normalizeArcAngles(start, stop, vals.w, vals.h, true); if (angles.correspondToSamePoint) { // If the arc starts and ends at (near enough) the same place, we choose to // draw an ellipse instead. This is preferable to faking an ellipse (by // making stop ever-so-slightly less than start + TWO_PI) because the ends // join up to each other rather than at a vertex at the centre (leaving // an unwanted spike in the stroke/fill). this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detail]); } else { this._renderer.arc( vals.x, vals.y, vals.w, vals.h, angles.start, // [0, TWO_PI) angles.stop, // [start, start + TWO_PI) mode, detail ); //accessible Outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('arc', [ vals.x, vals.y, vals.w, vals.h, angles.start, angles.stop, mode ]); } } return this; }; /** * Draws an ellipse (oval). * * An ellipse is a round shape defined by the `x`, `y`, `w`, and * `h` parameters. `x` and `y` set the location of its center. `w` and * `h` set its width and height. See * <a href="#/p5/ellipseMode">ellipseMode()</a> for other ways to set * its position. * * If no height is set, the value of width is used for both the width and * height. If a negative height or width is specified, the absolute value is * taken. * * The fifth parameter, `detail`, is also optional. It determines how many * vertices are used to draw the ellipse in WebGL mode. The default value is * 25. * * @method ellipse * @param {Number} x x-coordinate of the center of the ellipse. * @param {Number} y y-coordinate of the center of the ellipse. * @param {Number} w width of the ellipse. * @param {Number} [h] height of the ellipse. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * ellipse(50, 50, 80, 80); * * describe('A white circle on a gray canvas.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * ellipse(50, 50, 80); * * describe('A white circle on a gray canvas.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * ellipse(50, 50, 80, 40); * * describe('A white ellipse on a gray canvas.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * ellipse(0, 0, 80, 40); * * describe('A white ellipse on a gray canvas.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * // Use 6 vertices. * ellipse(0, 0, 80, 40, 6); * * describe('A white hexagon on a gray canvas.'); * } * </code> * </div> */ /** * @method ellipse * @param {Number} x * @param {Number} y * @param {Number} w * @param {Number} h * @param {Integer} [detail] optional parameter for WebGL mode only. This is to * specify the number of vertices that makes up the * perimeter of the ellipse. Default value is 25. Won't * draw a stroke for a detail of more than 50. */ fn.ellipse = function(x, y, w, h, detailX) { // p5._validateParameters('ellipse', arguments); return this._renderEllipse(...arguments); }; /** * Draws a circle. * * A circle is a round shape defined by the `x`, `y`, and `d` parameters. * `x` and `y` set the location of its center. `d` sets its width and height (diameter). * Every point on the circle's edge is the same distance, `0.5 * d`, from its center. * `0.5 * d` (half the diameter) is the circle's radius. * See <a href="#/p5/ellipseMode">ellipseMode()</a> for other ways to set its position. * * @method circle * @param {Number} x x-coordinate of the center of the circle. * @param {Number} y y-coordinate of the center of the circle. * @param {Number} d diameter of the circle. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * circle(50, 50, 25); * * describe('A white circle with black outline in the middle of a gray canvas.'); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * circle(0, 0, 25); * * describe('A white circle with black outline in the middle of a gray canvas.'); * } * </code> * </div> */ fn.circle = function(...args) { // p5._validateParameters('circle', args); const argss = args.slice( 0, 2); argss.push(args[2], args[2]); return this._renderEllipse(...argss); }; // internal method for drawing ellipses (without parameter validation) fn._renderEllipse = function(x, y, w, h, detailX) { // if the current stroke and fill settings wouldn't result in something // visible, exit immediately if (!this._renderer.states.strokeColor && !this._renderer.states.fillColor) { return this; } // Duplicate 3rd argument if only 3 given. if (typeof h === 'undefined') { h = w; } const vals = canvas.modeAdjust(x, y, w, h, this._renderer.states.ellipseMode); this._renderer.ellipse([vals.x, vals.y, vals.w, vals.h, detailX]); //accessible Outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('ellipse', [vals.x, vals.y, vals.w, vals.h]); } return this; }; /** * Draws a straight line between two points. * * A line's default width is one pixel. The version of `line()` with four * parameters draws the line in 2D. To color a line, use the * <a href="#/p5/stroke">stroke()</a> function. To change its width, use the * <a href="#/p5/strokeWeight">strokeWeight()</a> function. A line * can't be filled, so the <a href="#/p5/fill">fill()</a> function won't * affect the line's color. * * The version of `line()` with six parameters allows the line to be drawn in * 3D space. Doing so requires adding the `WEBGL` argument to * <a href="#/p5/createCanvas">createCanvas()</a>. * * @method line * @param {Number} x1 the x-coordinate of the first point. * @param {Number} y1 the y-coordinate of the first point. * @param {Number} x2 the x-coordinate of the second point. * @param {Number} y2 the y-coordinate of the second point. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * line(30, 20, 85, 75); * * describe( * 'A black line on a gray canvas running from top-center to bottom-right.' * ); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Style the line. * stroke('magenta'); * strokeWeight(5); * * line(30, 20, 85, 75); * * describe( * 'A thick, magenta line on a gray canvas running from top-center to bottom-right.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Top. * line(30, 20, 85, 20); * * // Right. * stroke(126); * line(85, 20, 85, 75); * * // Bottom. * stroke(255); * line(85, 75, 30, 75); * * describe( * 'Three lines drawn in grayscale on a gray canvas. They form the top, right, and bottom sides of a square.' * ); * } * </code> * </div> * * @example * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * line(-20, -30, 35, 25); * * describe( * 'A black line on a gray canvas running from top-center to bottom-right.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('A black line connecting two spheres. The scene spins slowly.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Draw a line. * line(0, 0, 0, 30, 20, -10); * * // Draw the center sphere. * sphere(10); * * // Translate to the second point. * translate(30, 20, -10); * * // Draw the bottom-right sphere. * sphere(10); * } * </code> * </div> * */ /** * @method line * @param {Number} x1 * @param {Number} y1 * @param {Number} z1 the z-coordinate of the first point. * @param {Number} x2 * @param {Number} y2 * @param {Number} z2 the z-coordinate of the second point. * @chainable */ fn.line = function(...args) { // p5._validateParameters('line', args); if (this._renderer.states.strokeColor) { this._renderer.line(...args); } //accessible Outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('line', args); } return this; }; /** * Draws a single point in space. * * A point's default width is one pixel. To color a point, use the * <a href="#/p5/stroke">stroke()</a> function. To change its width, use the * <a href="#/p5/strokeWeight">strokeWeight()</a> function. A point * can't be filled, so the <a href="#/p5/fill">fill()</a> function won't * affect the point's color. * * The version of `point()` with two parameters allows the point's location to * be set with its x- and y-coordinates, as in `point(10, 20)`. * * The version of `point()` with three parameters allows the point to be drawn * in 3D space with x-, y-, and z-coordinates, as in `point(10, 20, 30)`. * Doing so requires adding the `WEBGL` argument to * <a href="#/p5/createCanvas">createCanvas()</a>. * * The version of `point()` with one parameter allows the point's location to * be set with a <a href="#/p5/p5.Vector">p5.Vector</a> object. * * @method point * @param {Number} x the x-coordinate. * @param {Number} y the y-coordinate. * @param {Number} [z] the z-coordinate (for WebGL mode). * @chainable * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Top-left. * point(30, 20); * * // Top-right. * point(85, 20); * * // Bottom-right. * point(85, 75); * * // Bottom-left. * point(30, 75); * * describe( * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Top-left. * point(30, 20); * * // Top-right. * point(70, 20); * * // Style the next points. * stroke('purple'); * strokeWeight(10); * * // Bottom-right. * point(70, 80); * * // Bottom-left. * point(30, 80); * * describe( * 'Four points drawn on a gray canvas. Two are black and two are purple. The points form the corners of a square.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Top-left. * let a = createVector(30, 20); * point(a); * * // Top-right. * let b = createVector(70, 20); * point(b); * * // Bottom-right. * let c = createVector(70, 80); * point(c); * * // Bottom-left. * let d = createVector(30, 80); * point(d); * * describe( * 'Four small, black points drawn on a gray canvas. The points form the corners of a square.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('Two purple points drawn on a gray canvas.'); * } * * function draw() { * background(200); * * // Style the points. * stroke('purple'); * strokeWeight(10); * * // Top-left. * point(-20, -30); * * // Bottom-right. * point(20, 30); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('Two purple points drawn on a gray canvas. The scene spins slowly.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Style the points. * stroke('purple'); * strokeWeight(10); * * // Top-left. * point(-20, -30, 0); * * // Bottom-right. * point(20, 30, -50); * } * </code> * </div> */ /** * @method point * @param {p5.Vector} coordinateVector the coordinate vector. * @chainable */ fn.point = function(...args) { // p5._validateParameters('point', args); if (this._renderer.states.strokeColor) { if (args.length === 1 && args[0] instanceof p5.Vector) { this._renderer.point.call( this._renderer, args[0].x, args[0].y, args[0].z ); } else { this._renderer.point(...args); //accessible Outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('point', args); } } } return this; }; /** * Draws a quadrilateral (four-sided shape). * * Quadrilaterals include rectangles, squares, rhombuses, and trapezoids. The * first pair of parameters `(x1, y1)` sets the quad's first point. The next * three pairs of parameters set the coordinates for its next three points * `(x2, y2)`, `(x3, y3)`, and `(x4, y4)`. Points should be added in either * clockwise or counter-clockwise order. * * The version of `quad()` with twelve parameters allows the quad to be drawn * in 3D space. Doing so requires adding the `WEBGL` argument to * <a href="#/p5/createCanvas">createCanvas()</a>. * * The thirteenth and fourteenth parameters are optional. In WebGL mode, they * set the number of segments used to draw the quadrilateral in the x- and * y-directions. They're both 2 by default. * * @method quad * @param {Number} x1 the x-coordinate of the first point. * @param {Number} y1 the y-coordinate of the first point. * @param {Number} x2 the x-coordinate of the second point. * @param {Number} y2 the y-coordinate of the second point. * @param {Number} x3 the x-coordinate of the third point. * @param {Number} y3 the y-coordinate of the third point. * @param {Number} x4 the x-coordinate of the fourth point. * @param {Number} y4 the y-coordinate of the fourth point. * @param {Integer} [detailX] number of segments in the x-direction. * @param {Integer} [detailY] number of segments in the y-direction. * @chainable * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * quad(20, 20, 80, 20, 80, 80, 20, 80); * * describe('A white square with a black outline drawn on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * quad(20, 30, 80, 30, 80, 70, 20, 70); * * describe('A white rectangle with a black outline drawn on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * quad(50, 62, 86, 50, 50, 38, 14, 50); * * describe('A white rhombus with a black outline drawn on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * quad(20, 50, 80, 30, 80, 70, 20, 70); * * describe('A white trapezoid with a black outline drawn on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * quad(-30, -30, 30, -30, 30, 30, -30, 30); * * describe('A white square with a black outline drawn on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('A wavy white surface spins around on gray canvas.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Draw the quad. * quad(-30, -30, 0, 30, -30, 0, 30, 30, 20, -30, 30, -20); * } * </code> * </div> */ /** * @method quad * @param {Number} x1 * @param {Number} y1 * @param {Number} z1 the z-coordinate of the first point. * @param {Number} x2 * @param {Number} y2 * @param {Number} z2 the z-coordinate of the second point. * @param {Number} x3 * @param {Number} y3 * @param {Number} z3 the z-coordinate of the third point. * @param {Number} x4 * @param {Number} y4 * @param {Number} z4 the z-coordinate of the fourth point. * @param {Integer} [detailX] * @param {Integer} [detailY] * @chainable */ fn.quad = function(...args) { // p5._validateParameters('quad', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { if (this._renderer.isP3D && args.length < 12) { // if 3D and we weren't passed 12 args, assume Z is 0 this._renderer.quad.call( this._renderer, args[0], args[1], 0, args[2], args[3], 0, args[4], args[5], 0, args[6], args[7], 0, args[8], args[9]); } else { this._renderer.quad(...args); //accessibile outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('quadrilateral', args); } } } return this; }; /** * Draws a rectangle. * * A rectangle is a four-sided shape defined by the `x`, `y`, `w`, and `h` * parameters. `x` and `y` set the location of its top-left corner. `w` sets * its width and `h` sets its height. Every angle in the rectangle measures * 90˚. See <a href="#/p5/rectMode">rectMode()</a> for other ways to define * rectangles. * * The version of `rect()` with five parameters creates a rounded rectangle. The * fifth parameter sets the radius for all four corners. * * The version of `rect()` with eight parameters also creates a rounded * rectangle. Each of the last four parameters set the radius of a corner. The * radii start with the top-left corner and move clockwise around the * rectangle. If any of these parameters are omitted, they are set to the * value of the last radius that was set. * * @method rect * @param {Number} x x-coordinate of the rectangle. * @param {Number} y y-coordinate of the rectangle. * @param {Number} w width of the rectangle. * @param {Number} [h] height of the rectangle. * @param {Number} [tl] optional radius of top-left corner. * @param {Number} [tr] optional radius of top-right corner. * @param {Number} [br] optional radius of bottom-right corner. * @param {Number} [bl] optional radius of bottom-left corner. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * rect(30, 20, 55, 55); * * describe('A white square with a black outline on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * rect(30, 20, 55, 40); * * describe('A white rectangle with a black outline on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Give all corners a radius of 20. * rect(30, 20, 55, 50, 20); * * describe('A white rectangle with a black outline and round edges on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Give each corner a unique radius. * rect(30, 20, 55, 50, 20, 15, 10, 5); * * describe('A white rectangle with a black outline and round edges of different radii.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * rect(-20, -30, 55, 55); * * describe('A white square with a black outline on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('A white square spins around on gray canvas.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Draw the rectangle. * rect(-20, -30, 55, 55); * } * </code> * </div> */ /** * @method rect * @param {Number} x * @param {Number} y * @param {Number} w * @param {Number} h * @param {Integer} [detailX] number of segments in the x-direction (for WebGL mode). * @param {Integer} [detailY] number of segments in the y-direction (for WebGL mode). * @chainable */ fn.rect = function(...args) { // p5._validateParameters('rect', args); return this._renderRect(...args); }; /** * Draws a square. * * A square is a four-sided shape defined by the `x`, `y`, and `s` * parameters. `x` and `y` set the location of its top-left corner. `s` sets * its width and height. Every angle in the square measures 90˚ and all its * sides are the same length. See <a href="#/p5/rectMode">rectMode()</a> for * other ways to define squares. * * The version of `square()` with four parameters creates a rounded square. * The fourth parameter sets the radius for all four corners. * * The version of `square()` with seven parameters also creates a rounded * square. Each of the last four parameters set the radius of a corner. The * radii start with the top-left corner and move clockwise around the * square. If any of these parameters are omitted, they are set to the * value of the last radius that was set. * * @method square * @param {Number} x x-coordinate of the square. * @param {Number} y y-coordinate of the square. * @param {Number} s side size of the square. * @param {Number} [tl] optional radius of top-left corner. * @param {Number} [tr] optional radius of top-right corner. * @param {Number} [br] optional radius of bottom-right corner. * @param {Number} [bl] optional radius of bottom-left corner. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * square(30, 20, 55); * * describe('A white square with a black outline in on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Give all corners a radius of 20. * square(30, 20, 55, 20); * * describe( * 'A white square with a black outline and round edges on a gray canvas.' * ); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * // Give each corner a unique radius. * square(30, 20, 55, 20, 15, 10, 5); * * describe('A white square with a black outline and round edges of different radii.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * square(-20, -30, 55); * * describe('A white square with a black outline in on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('A white square spins around on gray canvas.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Draw the square. * square(-20, -30, 55); * } * </code> * </div> */ fn.square = function(x, y, s, tl, tr, br, bl) { // p5._validateParameters('square', arguments); // duplicate width for height in case of square return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl); }; // internal method to have renderer draw a rectangle fn._renderRect = function() { if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { // duplicate width for height in case only 3 arguments is provided if (arguments.length === 3) { arguments[3] = arguments[2]; } const vals = canvas.modeAdjust( arguments[0], arguments[1], arguments[2], arguments[3], this._renderer.states.rectMode ); // For the default rectMode (CORNER), restore a possible negative width/height // removed by modeAdjust(). This results in flipped/mirrored rendering, // which is especially noticable when using WEGBL rendering and texture(). // Note that this behavior only applies to rect(), NOT to ellipse() and arc(). if (this._renderer.states.rectMode === CORNER) { vals.w = arguments[2]; vals.h = arguments[3]; } const args = [vals.x, vals.y, vals.w, vals.h]; // append the additional arguments (either cornder radii, or // segment details) to the argument list for (let i = 4; i < arguments.length; i++) { args[i] = arguments[i]; } this._renderer.rect(args); //accessible outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('rectangle', [vals.x, vals.y, vals.w, vals.h]); } } return this; }; /** * Draws a triangle. * * A triangle is a three-sided shape defined by three points. The * first two parameters specify the triangle's first point `(x1, y1)`. The * middle two parameters specify its second point `(x2, y2)`. And the last two * parameters specify its third point `(x3, y3)`. * * @method triangle * @param {Number} x1 x-coordinate of the first point. * @param {Number} y1 y-coordinate of the first point. * @param {Number} x2 x-coordinate of the second point. * @param {Number} y2 y-coordinate of the second point. * @param {Number} x3 x-coordinate of the third point. * @param {Number} y3 y-coordinate of the third point. * @chainable * * @example * <div> * <code> * function setup() { * createCanvas(100, 100); * * background(200); * * triangle(30, 75, 58, 20, 86, 75); * * describe('A white triangle with a black outline on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * background(200); * * triangle(-20, 25, 8, -30, 36, 25); * * describe('A white triangle with a black outline on a gray canvas.'); * } * </code> * </div> * * <div> * <code> * function setup() { * createCanvas(100, 100, WEBGL); * * describe('A white triangle spins around on a gray canvas.'); * } * * function draw() { * background(200); * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * * // Draw the triangle. * triangle(-20, 25, 8, -30, 36, 25); * } * </code> * </div> */ fn.triangle = function(...args) { // p5._validateParameters('triangle', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { this._renderer.triangle(args); } //accessible outputs if (this._accessibleOutputs.grid || this._accessibleOutputs.text) { this._accsOutput('triangle', args); } return this; }; } if(typeof p5 !== 'undefined'){ primitives(p5, p5.prototype); } export { primitives as default };