diff --git a/src/shape/curves.js b/src/shape/curves.js index ef0d0bc448..0f8ab0ad8d 100644 --- a/src/shape/curves.js +++ b/src/shape/curves.js @@ -12,7 +12,7 @@ function curves(p5, fn){ * Bézier curves can form shapes and curves that slope gently. They're defined * by two anchor points and two control points. Bézier curves provide more * control than the spline curves created with the - * curve() function. + * spline() function. * * The first two parameters, `x1` and `y1`, set the first anchor point. The * first anchor point is where the curve starts. @@ -462,38 +462,53 @@ function curves(p5, fn){ /** * Draws a curve using a Catmull-Rom spline. - * + * * Spline curves can form shapes and curves that slope gently. They’re like - * cables that are attached to a set of points. Splines are defined by two - * anchor points and two control points. - * - * The first two parameters, `x1` and `y1`, set the first control point. This - * point isn’t drawn and can be thought of as the curve’s starting point. - * - * The next four parameters, `x2`, `y2`, `x3`, and `y3`, set the two anchor - * points. The anchor points are the start and end points of the curve’s - * visible segment. - * - * The seventh and eighth parameters, `x4` and `y4`, set the last control - * point. This point isn’t drawn and can be thought of as the curve’s ending - * point. + * cables that are attached to a set of points. By default (`ends: INCLUDE`), + * the curve passes through all four points you provide, in order + * `p0(x1,y1)` -> `p1(x2,y2)` -> `p2(x3,y3)` -> `p3(x4,y4)`. Think of them as + * points on a curve. If you switch to `ends: EXCLUDE`, p0 and p3 act + * like control points and only the middle span `p1->p2` is drawn. * * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of * `spline()` has twelve arguments because each point has x-, y-, and * z-coordinates. * * @method spline - * @param {Number} x1 x-coordinate of the first control point. - * @param {Number} y1 y-coordinate of the first control point. - * @param {Number} x2 x-coordinate of the first anchor point. - * @param {Number} y2 y-coordinate of the first anchor point. - * @param {Number} x3 x-coordinate of the second anchor point. - * @param {Number} y3 y-coordinate of the second anchor point. - * @param {Number} x4 x-coordinate of the second control point. - * @param {Number} y4 y-coordinate of the second control point. + * @param {Number} x1 x-coordinate of point p0. + * @param {Number} y1 y-coordinate of point p0. + * @param {Number} x2 x-coordinate of point p1. + * @param {Number} y2 y-coordinate of point p1. + * @param {Number} x3 x-coordinate of point p2. + * @param {Number} y3 y-coordinate of point p2. + * @param {Number} x4 x-coordinate of point p3. + * @param {Number} y4 y-coordinate of point p3. * @chainable * * @example + * + *
+ * + * function setup() { + * createCanvas(200, 200); + * background(240); + * noFill(); + * + * stroke(0); + * strokeWeight(2); + * spline(40, 60, 100, 40, 120, 120, 60, 140); + * + * strokeWeight(5); + * point(40, 60); + * point(100, 40); + * point(120, 120); + * point(60, 140); + * + * describe('A black spline passes smoothly through four points'); + * } + * + *
+ * *
* * function setup() { @@ -501,24 +516,27 @@ function curves(p5, fn){ * * background(200); * + * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn. + * splineProperty('ends', EXCLUDE); + * * // Draw a black spline curve. * noFill(); * strokeWeight(1); * stroke(0); * spline(5, 26, 73, 24, 73, 61, 15, 65); * - * // Draw red spline curves from the anchor points to the control points. + * // Draw red spline curves from the points. * stroke(255, 0, 0); * spline(5, 26, 5, 26, 73, 24, 73, 61); * spline(73, 24, 73, 61, 15, 65, 15, 65); * - * // Draw the anchor points in black. + * // Draw the points in black. * strokeWeight(5); * stroke(0); * point(73, 24); * point(73, 61); * - * // Draw the control points in red. + * // Draw the points in red. * stroke(255, 0, 0); * point(5, 26); * point(15, 65); @@ -546,14 +564,17 @@ function curves(p5, fn){ * * function draw() { * background(200); - * + * + * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn. + * splineProperty('ends', EXCLUDE); + * * // Draw a black spline curve. * noFill(); * strokeWeight(1); * stroke(0); * spline(x1, y1, 73, 24, 73, 61, 15, 65); * - * // Draw red spline curves from the anchor points to the control points. + * // Draw red spline curves from the points. * stroke(255, 0, 0); * spline(x1, y1, x1, y1, 73, 24, 73, 61); * spline(73, 24, 73, 61, 15, 65, 15, 65); @@ -564,25 +585,25 @@ function curves(p5, fn){ * point(73, 24); * point(73, 61); * - * // Draw the control points in red. + * // Draw the points in red. * stroke(255, 0, 0); * point(x1, y1); * point(15, 65); * } * - * // Start changing the first control point if the user clicks near it. + * // Start changing the first point if the user clicks near it. * function mousePressed() { * if (dist(mouseX, mouseY, x1, y1) < 20) { * isChanging = true; * } * } * - * // Stop changing the first control point when the user releases the mouse. + * // Stop changing the first point when the user releases the mouse. * function mouseReleased() { * isChanging = false; * } * - * // Update the first control point while the user drags the mouse. + * // Update the first point while the user drags the mouse. * function mouseDragged() { * if (isChanging === true) { * x1 = mouseX; @@ -598,7 +619,10 @@ function curves(p5, fn){ * createCanvas(100, 100); * * background('skyblue'); - * + * + * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn. + * splineProperty('ends', EXCLUDE); + * * // Draw the red balloon. * fill('red'); * spline(-150, 275, 50, 60, 50, 60, 250, 275); @@ -621,7 +645,10 @@ function curves(p5, fn){ * * function draw() { * background('skyblue'); - * + * + * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn. + * splineProperty('ends', EXCLUDE); + * * // Rotate around the y-axis. * rotateY(frameCount * 0.01); * @@ -640,16 +667,16 @@ function curves(p5, fn){ * @method spline * @param {Number} x1 * @param {Number} y1 - * @param {Number} z1 z-coordinate of the first control point. + * @param {Number} z1 z-coordinate of point p0. * @param {Number} x2 * @param {Number} y2 - * @param {Number} z2 z-coordinate of the first anchor point. + * @param {Number} z2 z-coordinate of point p1. * @param {Number} x3 * @param {Number} y3 - * @param {Number} z3 z-coordinate of the second anchor point. + * @param {Number} z3 z-coordinate of point p2. * @param {Number} x4 * @param {Number} y4 - * @param {Number} z4 z-coordinate of the second control point. + * @param {Number} z4 z-coordinate of point p3. * @chainable */ fn.spline = function(...args) { @@ -664,30 +691,30 @@ function curves(p5, fn){ /** * Calculates coordinates along a spline curve using interpolation. * - * `splinePoint()` calculates coordinates along a spline curve using the - * anchor and control points. It expects points in the same order as the + * `splinePoint()` calculates coordinates along a spline curve using four + * points p0, p1, p2, p3. It expects points in the same order as the * spline() function. `splinePoint()` works one axis - * at a time. Passing the anchor and control points' x-coordinates will - * calculate the x-coordinate of a point on the curve. Passing the anchor and - * control points' y-coordinates will calculate the y-coordinate of a point on + * at a time. Passing the points' x-coordinates will + * calculate the x-coordinate of a point on the curve. Passing the + * points' y-coordinates will calculate the y-coordinate of a point on * the curve. * - * The first parameter, `a`, is the coordinate of the first control point. + * The first parameter, `a`, is the coordinate of point p0. * - * The second and third parameters, `b` and `c`, are the coordinates of the - * anchor points. + * The second and third parameters, `b` and `c`, are the coordinates of + * points p1 and p2. * - * The fourth parameter, `d`, is the coordinate of the last control point. + * The fourth parameter, `d`, is the coordinate of point p3. * - * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 - * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * The fifth parameter, `t`, is the amount to interpolate along the span + * from p1 to p2. `t = 0` is p1, `t = 1` is p2, and `t = 0.5` is halfway * between them. * * @method splinePoint - * @param {Number} a coordinate of first control point. - * @param {Number} b coordinate of first anchor point. - * @param {Number} c coordinate of second anchor point. - * @param {Number} d coordinate of second control point. + * @param {Number} a coordinate of point p0. + * @param {Number} b coordinate of point p1. + * @param {Number} c coordinate of point p2. + * @param {Number} d coordinate of point p3. * @param {Number} t amount to interpolate between 0 and 1. * @return {Number} coordinate of a point on the curve. * @@ -699,7 +726,8 @@ function curves(p5, fn){ * * background(200); * - * // Set the coordinates for the curve's anchor and control points. + * + * // Set the coordinates for the curve's four points (p0, p1, p2, p3). * let x1 = 5; * let y1 = 26; * let x2 = 73; @@ -747,7 +775,7 @@ function curves(p5, fn){ * function draw() { * background(200); * - * // Set the coordinates for the curve's anchor and control points. + * // Set the coordinates for the curve's four points (p0, p1, p2, p3). * let x1 = 5; * let y1 = 26; * let x2 = 73; @@ -773,6 +801,7 @@ function curves(p5, fn){ * *
*/ + fn.splinePoint = function(a, b, c, d, t) { const s = this._renderer.states.splineProperties.tightness, t3 = t * t * t, @@ -790,30 +819,27 @@ function curves(p5, fn){ * Tangent lines skim the surface of a curve. A tangent line's slope equals * the curve's slope at the point where it intersects. * - * `splineTangent()` calculates coordinates along a tangent line using the - * spline curve's anchor and control points. It expects points in the same - * order as the spline() function. `splineTangent()` - * works one axis at a time. Passing the anchor and control points' - * x-coordinates will calculate the x-coordinate of a point on the tangent - * line. Passing the anchor and control points' y-coordinates will calculate - * the y-coordinate of a point on the tangent line. - * - * The first parameter, `a`, is the coordinate of the first control point. + * `splineTangent()` calculates coordinates along a tangent line using four + * points p0, p1, p2, p3. It expects points in the same order as the + * spline() function. `splineTangent()` works one + * axis at a time. Passing the points' x-coordinates returns the x-component of + * the tangent vector; passing the points' y-coordinates returns the y-component. + * The first parameter, `a`, is the coordinate of point p0. * - * The second and third parameters, `b` and `c`, are the coordinates of the - * anchor points. + * The second and third parameters, `b` and `c`, are the coordinates of + * points p1 and p2. * - * The fourth parameter, `d`, is the coordinate of the last control point. + * The fourth parameter, `d`, is the coordinate of point p3. * - * The fifth parameter, `t`, is the amount to interpolate along the curve. 0 - * is the first anchor point, 1 is the second anchor point, and 0.5 is halfway + * The fifth parameter, `t`, is the amount to interpolate along the span + * from p1 to p2. `t = 0` is p1, `t = 1` is p2, and `t = 0.5` is halfway * between them. * * @method splineTangent - * @param {Number} a coordinate of first control point. - * @param {Number} b coordinate of first anchor point. - * @param {Number} c coordinate of second anchor point. - * @param {Number} d coordinate of second control point. + * @param {Number} a coordinate of point p0. + * @param {Number} b coordinate of point p1. + * @param {Number} c coordinate of point p2. + * @param {Number} d coordinate of point p3. * @param {Number} t amount to interpolate between 0 and 1. * @return {Number} coordinate of a point on the tangent line. * @@ -821,11 +847,54 @@ function curves(p5, fn){ *
* * function setup() { + * createCanvas(120, 120); + * describe('A black spline on a gray canvas. A red dot moves along the curve on its own. A short line shows the tangent direction at the dot.'); + * } + * + * function draw() { + * background(240); + * + * const x1 = 15, y1 = 40; + * const x2 = 90, y2 = 25; + * const x3 = 95, y3 = 95; + * const x4 = 30, y4 = 110; + * + * noFill(); + * stroke(0); + * strokeWeight(2); + * spline(x1, y1, x2, y2, x3, y3, x4, y4); + * + * const t = 0.5 + 0.5 * sin(frameCount * 0.03); + * + * const px = splinePoint(x1, x2, x3, x4, t); + * const py = splinePoint(y1, y2, y3, y4, t); + * + * let tx = splineTangent(x1, x2, x3, x4, t); + * let ty = splineTangent(y1, y2, y3, y4, t); + * + * const m = Math.hypot(tx, ty) || 1; + * tx = (tx / m) * 16; + * ty = (ty / m) * 16; + * + * stroke(0); + * strokeWeight(2); + * line(px, py, px + tx, py + ty); + * + * noStroke(); + * fill('red'); + * circle(px, py, 7); + * } + * + *
+ * + *
+ * + * function setup() { * createCanvas(100, 100); * * background(200); * - * // Set the coordinates for the curve's anchor and control points. + * // Set the coordinates for the curve's four points (p0, p1, p2, p3). * let x1 = 5; * let y1 = 26; * let x2 = 73; diff --git a/src/shape/custom_shapes.js b/src/shape/custom_shapes.js index 9e22f0b75c..68805260f3 100644 --- a/src/shape/custom_shapes.js +++ b/src/shape/custom_shapes.js @@ -1647,67 +1647,73 @@ function customShapes(p5, fn) { }; + /** - * Adds a spline curve segment to a custom shape. + * Connects points with a smooth curve (a spline). * - * `splineVertex()` adds a curved segment to custom shapes. The spline curves - * it creates are defined like those made by the - * curve() function. `splineVertex()` must be called - * between the beginShape() and + * `splineVertex()` adds a curved segment to custom shapes. + * The curve it creates follows the same rules as the ones + * made with the spline() function. + * `splineVertex()` must be called between the + * beginShape() and * endShape() functions. * * Spline curves can form shapes and curves that slope gently. They’re like - * cables that are attached to a set of points. Splines are defined by two - * anchor points and two control points. `splineVertex()` must be called at - * least four times between + * cables that are attached to a set of points. `splineVertex()` draws a smooth + * curve through the points you give it. * beginShape() and * endShape() in order to draw a curve: * + * + * If you provide three points, the spline will pass through them. + * It works the same way with any number of points. + * + * + * * ```js * beginShape(); * - * // Add the first control point. - * splineVertex(84, 91); + * // Add the first point. + * splineVertex(25, 80); * - * // Add the anchor points to draw between. - * splineVertex(68, 19); - * splineVertex(21, 17); + * // Add the second point. + * splineVertex(20, 30); * - * // Add the second control point. - * splineVertex(32, 91); + * // Add the last point. + * splineVertex(85, 60); * * endShape(); * ``` - * - * The code snippet above would only draw the curve between the anchor points, - * similar to the curve() function. The segments - * between the control and anchor points can be drawn by calling - * `splineVertex()` with the coordinates of the control points: - * + * + * + * + * + * Passing in `CLOSE` to `endShape()` closes the spline smoothly. * ```js * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Add the anchor points to draw between. - * splineVertex(68, 19); - * splineVertex(21, 17); - * - * // Add the second control point. - * splineVertex(32, 91); - * - * // Uncomment the next line to draw the segment to the second control point. - * // splineVertex(32, 91); - * - * endShape(); + * + * // Add the first point. + * splineVertex(25, 80); + * + * // Add the second point. + * splineVertex(20, 30); + * + * // Add the second point. + * splineVertex(85, 60); + * + * endShape(CLOSE); * ``` - * - * The first two parameters, `x` and `y`, set the vertex’s location. For - * example, calling `splineVertex(10, 10)` adds a point to the curve at - * `(10, 10)`. - * + * + * + * + * + * By default (`ends: INCLUDE`), the curve passes through + * all the points you add with `splineVertex()`, similar to + * the spline() function. To draw only + * the middle span p1->p2 (skipping p0->p1 and p2->p3), set + * `splineProperty('ends', EXCLUDE)`. You don’t need to duplicate + * vertices to draw those spans. + * * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of * `splineVertex()` has three arguments because each point has x-, y-, and * z-coordinates. By default, the vertex’s z-coordinate is set to 0. @@ -1725,46 +1731,29 @@ function customShapes(p5, fn) { * * function setup() { * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. + * + * background(220); * noFill(); * strokeWeight(1); - * - * // Start drawing the shape. + * * beginShape(); - * - * // Add the first control point. - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * - * // Stop drawing the shape. + * splineVertex(25, 80); + * splineVertex(20, 30); + * splineVertex(85, 60); * endShape(); - * - * // Style the anchor and control points. + * * strokeWeight(5); - * - * // Draw the anchor points in black. * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); - * + * + * point(25, 80); + * point(20, 30); + * point(85, 60); + * * describe( - * 'A black curve drawn on a gray background. The curve has black dots at its ends. Two red dots appear near the bottom of the canvas.' + * 'On a gray background, a black spline passes through three marked points.' * ); * } + * * *
* @@ -1772,204 +1761,63 @@ function customShapes(p5, fn) { * * function setup() { * createCanvas(100, 100); + * background(220); * - * background(200); - * - * // Style the shape. - * noFill(); - * strokeWeight(1); - * - * // Start drawing the shape. * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); + * splineVertex(25, 80); + * splineVertex(20, 30); + * splineVertex(85, 60); + * endShape(CLOSE); * * describe( - * 'A black curve drawn on a gray background. The curve passes through one red dot and two black dots. Another red dot appears near the bottom of the canvas.' + * 'On a gray background, a closed black spline with a white interior forms a triangular shape with smooth corners.' * ); * } + * * * * *
* - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Style the shape. - * noFill(); - * strokeWeight(1); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); + * let ringInnerRadius, ringWidth; + * let radius, dRadius; + * let theta, dTheta; + * let time, dTime; + * let vertexCount, unit, offset; * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(32, 91); - * point(84, 91); - * - * describe( - * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' - * ); - * } - * - *
+ * function setup() { + * createCanvas(400, 400); * - *
- * - * // Click the mouse near the red dot in the bottom-left corner - * // and drag to change the curve's shape. + * vertexCount = 15; + * unit = createVector(1, 0); + * dTheta = TAU / vertexCount; + * dTime = 0.004; * - * let x1 = 32; - * let y1 = 91; - * let isChanging = false; + * ringInnerRadius = 25; + * ringWidth = 5 * ringInnerRadius; * - * function setup() { - * createCanvas(100, 100); + * offset = width; * * describe( - * 'A black U curve drawn upside down on a gray background. The curve passes from one red dot through two black dots and ends at another red dot.' + * 'A white blob with a black outline changes its shape over time.' * ); * } * * function draw() { - * background(200); + * background(220); + * strokeWeight(2); + * translate(width / 2, height / 2); * - * // Style the shape. - * noFill(); - * stroke(0); - * strokeWeight(1); + * time = dTime * frameCount; * - * // Start drawing the shape. * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(x1, y1); - * splineVertex(x1, y1); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point and draw a segment to it. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * // Style the anchor and control points. - * strokeWeight(5); - * - * // Draw the anchor points in black. - * stroke(0); - * point(21, 17); - * point(68, 19); - * - * // Draw the control points in red. - * stroke(255, 0, 0); - * point(x1, y1); - * point(84, 91); - * } - * - * // Start changing the first control point if the user clicks near it. - * function mousePressed() { - * if (dist(mouseX, mouseY, x1, y1) < 20) { - * isChanging = true; - * } - * } - * - * // Stop changing the first control point when the user releases the mouse. - * function mouseReleased() { - * isChanging = false; - * } - * - * // Update the first control point while the user drags the mouse. - * function mouseDragged() { - * if (isChanging === true) { - * x1 = mouseX; - * y1 = mouseY; + * for (let i = 0; i < vertexCount; i++) { + * unit.rotate(dTheta); + * dRadius = noise(offset + unit.x, offset + unit.y, time) * ringWidth; + * radius = ringInnerRadius + dRadius; + * splineVertex(radius * unit.x, radius * unit.y); * } - * } - * - *
- * - *
- * - * function setup() { - * createCanvas(100, 100); - * - * background(200); - * - * // Start drawing the shape. - * beginShape(); - * - * // Add the first control point and draw a segment to it. - * splineVertex(32, 91); - * splineVertex(32, 91); - * - * // Add the anchor points. - * splineVertex(21, 17); - * splineVertex(68, 19); - * - * // Add the second control point. - * splineVertex(84, 91); - * splineVertex(84, 91); - * - * // Stop drawing the shape. - * endShape(); - * - * describe('A ghost shape drawn in white on a gray background.'); + * endShape(CLOSE); * } * *
@@ -2058,25 +1906,83 @@ function customShapes(p5, fn) { }; /** - * Sets the property of a curve. - * - * For example, set tightness, - * use `splineProperty('tightness', t)`, with `t` between 0 and 1, - * at 0 as default. - * - * Spline curves are like cables that are attached to a set of points. - * Adjusting tightness adjusts how tightly the cable is - * attached to the points. The parameter, tightness, determines - * how the curve fits to the vertex points. By default, - * tightness is set to 0. Setting tightness to 1, as in - * `splineProperty('tightness', 1)`, connects the curve's points - * using straight lines. Values in the range from –5 to 5 - * deform curves while leaving them recognizable. - * - * This function can also be used to set 'ends' property - * (see also: the curveDetail() example), - * such as: `splineProperty('ends', EXCLUDE)` to exclude - * vertices, or `splineProperty('ends', INCLUDE)` to include them. + * Gets or sets a given spline property. + * + * Use `splineProperty()` to adjust the behavior of splines + * created with `splineVertex()` or `spline()`. You can control + * two key aspects of a spline: its end behavior (`ends`) and + * its curvature (`tightness`). + * + * By default, the ends property is set to `INCLUDE`, which means + * the spline passes through every point, including the endpoints. + * You can also set it to `EXCLUDE` i.e. `splineProperty('ends', EXCLUDE)`, + * which makes the spline pass through all points except the endpoints. + * + * `INCLUDE` case will have the spline passing through + * all points, like this: + * + * ```js + * splineProperty('ends', INCLUDE); // no need to set this, as it is the default + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * + * point(25, 46); + * point(93, 44); + * point(93, 81); + * point(35, 85); + * ``` + * + * + * + * + * EXCLUDE case will have the spline passing through + * the middle points, like this: + * + * + * ```js + * splineProperty('ends', INCLUDE); + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * + * point(25, 46); + * point(93, 44); + * point(93, 81); + * point(35, 85); + * ``` + * + * + * + * By default, the tightness property is set to `0`, + * producing a smooth curve that passes evenly through + * the vertices. Negative values make the curve looser, + * while positive values make it tighter. Common values + * range between -1 and 1, though values outside this + * range can also be used for different effects. + * + * For example, To set tightness, use `splineProperty('tightness', t)`, + * (default: t = 0). + * + * Here's the example showing negetive value of tightness, + * which creates a rounder bulge: + * + * ```js + * splineProperty('tightness', -5) + * stroke(0); + * strokeWeight(2); + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * ``` + * + * Here's the example showing positive value of tightness, + * which makes the curve tighter and more angular: + * + * ```js + * splineProperty('tightness', 5) + * stroke(0); + * strokeWeight(2); + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * ``` + * + * In all cases, the splines in p5.js are cardinal splines. + * When tightness is 0, these splines are often known as + * Catmull-Rom splines * * @method splineProperty * @param {String} property @@ -2086,33 +1992,111 @@ function customShapes(p5, fn) { *
* * // Move the mouse left and right to see the curve change. - * + * + * let t; + * * function setup() { * createCanvas(100, 100); - * describe('A black curve forms a sideways U shape. The curve deforms as the user moves the mouse from left to right'); + * * } - * + * * function draw() { - * background(200); - * - * // Set the curve's tightness using the mouse. - * let t = map(mouseX, 0, 100, -5, 5, true); + * background(240); + * + * t = map(mouseX, 0, width, -5, 5, true); * splineProperty('tightness', t); - * - * // Draw the curve. + * * noFill(); + * stroke(0); + * strokeWeight(2); + * * beginShape(); * splineVertex(10, 26); - * splineVertex(10, 26); * splineVertex(83, 24); + * * splineVertex(83, 61); * splineVertex(25, 65); - * splineVertex(25, 65); * endShape(); + * + * push(); + * strokeWeight(5); + * point(10, 26); + * point(83, 24); + * point(83, 61); + * point(25, 65); + * pop(); + * + * fill(0); + * noStroke(); + * textSize(10); + * text(`tightness: ${round(t, 1)}`, 15, 90); + * describe('A black spline forms a sideways U shape through four points. The spline passes through the points more loosely as the mouse moves left of center (negative tightness), and more tightly as it moves right of center (positive tightness). The tightness is displayed at the bottom.'); + * } + * + *
+ * + * @example + *
+ * + * function setup() { + * createCanvas(360, 140); + * background(240); + * noFill(); + * + * // Right panel: ends = INCLUDE (all spans). + * push(); + * translate(10, 10); + * stroke(220); + * rect(0, 0, 160, 120); + * fill(30); + * textSize(11); + * text('ends: INCLUDE (all spans)', 8, 16); + * noFill(); + * + * splineProperty('ends', INCLUDE); + * stroke(0); + * strokeWeight(2); + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * + * // vertices + * strokeWeight(5); + * stroke(0); + * point(25, 46); + * point(93, 44); + * point(93, 81); + * point(35, 85); + * pop(); + * + * // Right panel: ends = EXCLUDE (middle only). + * push(); + * translate(190, 10); + * stroke(220); + * rect(0, 0, 160, 120); + * noStroke(); + * fill(30); + * text('ends: EXCLUDE ', 18, 16); + * noFill(); + * + * splineProperty('ends', EXCLUDE); + * stroke(0); + * strokeWeight(2); + * spline(25, 46, 93, 44, 93, 81, 35, 85); + * + * // vertices + * strokeWeight(5); + * stroke(0); + * point(25, 46); + * point(93, 44); + * point(93, 81); + * point(35, 85); + * pop(); + * + * describe('Left panel shows spline with ends INCLUDE (three spans). Right panel shows EXCLUDE (only the middle span). Four black points mark the vertices.'); * } * *
*/ + /** * @method splineProperty * @param {String} property