@@ -12,7 +12,7 @@ function curves(p5, fn){
1212 * Bézier curves can form shapes and curves that slope gently. They're defined
1313 * by two anchor points and two control points. Bézier curves provide more
1414 * control than the spline curves created with the
15- * <a href="#/p5/curve">curve ()</a> function.
15+ * <a href="#/p5/spline">spline ()</a> function.
1616 *
1717 * The first two parameters, `x1` and `y1`, set the first anchor point. The
1818 * first anchor point is where the curve starts.
@@ -462,63 +462,81 @@ function curves(p5, fn){
462462
463463 /**
464464 * Draws a curve using a Catmull-Rom spline.
465- *
465+ *
466466 * Spline curves can form shapes and curves that slope gently. They’re like
467- * cables that are attached to a set of points. Splines are defined by two
468- * anchor points and two control points.
469- *
470- * The first two parameters, `x1` and `y1`, set the first control point. This
471- * point isn’t drawn and can be thought of as the curve’s starting point.
472- *
473- * The next four parameters, `x2`, `y2`, `x3`, and `y3`, set the two anchor
474- * points. The anchor points are the start and end points of the curve’s
475- * visible segment.
476- *
477- * The seventh and eighth parameters, `x4` and `y4`, set the last control
478- * point. This point isn’t drawn and can be thought of as the curve’s ending
479- * point.
467+ * cables that are attached to a set of points. By default (`ends: INCLUDE`),
468+ * the curve passes through all four points you provide, in order
469+ * `p0(x1,y1)` -> `p1(x2,y2)` -> `p2(x3,y3)` -> `p3(x4,y4)`. Think of them as
470+ * points on a curve. If you switch to `ends: EXCLUDE`, p0 and p3 act
471+ * like control points and only the middle span `p1->p2` is drawn.
480472 *
481473 * Spline curves can also be drawn in 3D using WebGL mode. The 3D version of
482474 * `spline()` has twelve arguments because each point has x-, y-, and
483475 * z-coordinates.
484476 *
485477 * @method spline
486- * @param {Number } x1 x-coordinate of the first control point.
487- * @param {Number } y1 y-coordinate of the first control point.
488- * @param {Number } x2 x-coordinate of the first anchor point.
489- * @param {Number } y2 y-coordinate of the first anchor point.
490- * @param {Number } x3 x-coordinate of the second anchor point.
491- * @param {Number } y3 y-coordinate of the second anchor point.
492- * @param {Number } x4 x-coordinate of the second control point.
493- * @param {Number } y4 y-coordinate of the second control point.
478+ * @param {Number } x1 x-coordinate of point p0 .
479+ * @param {Number } y1 y-coordinate of point p0 .
480+ * @param {Number } x2 x-coordinate of point p1 .
481+ * @param {Number } y2 y-coordinate of point p1 .
482+ * @param {Number } x3 x-coordinate of point p2 .
483+ * @param {Number } y3 y-coordinate of point p2 .
484+ * @param {Number } x4 x-coordinate of point p3 .
485+ * @param {Number } y4 y-coordinate of point p3 .
494486 * @chainable
495487 *
496488 * @example
489+ *
490+ * <div>
491+ * <code>
492+ * function setup() {
493+ * createCanvas(200, 200);
494+ * background(240);
495+ * noFill();
496+ *
497+ * stroke(0);
498+ * strokeWeight(2);
499+ * spline(40, 60, 100, 40, 120, 120, 60, 140);
500+ *
501+ * strokeWeight(5);
502+ * point(40, 60);
503+ * point(100, 40);
504+ * point(120, 120);
505+ * point(60, 140);
506+ *
507+ * describe('A black spline passes smoothly through four points');
508+ * }
509+ * </code>
510+ * </div>
511+ *
497512 * <div>
498513 * <code>
499514 * function setup() {
500515 * createCanvas(100, 100);
501516 *
502517 * background(200);
503518 *
519+ * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn.
520+ * splineProperty('ends', EXCLUDE);
521+ *
504522 * // Draw a black spline curve.
505523 * noFill();
506524 * strokeWeight(1);
507525 * stroke(0);
508526 * spline(5, 26, 73, 24, 73, 61, 15, 65);
509527 *
510- * // Draw red spline curves from the anchor points to the control points.
528+ * // Draw red spline curves from the points.
511529 * stroke(255, 0, 0);
512530 * spline(5, 26, 5, 26, 73, 24, 73, 61);
513531 * spline(73, 24, 73, 61, 15, 65, 15, 65);
514532 *
515- * // Draw the anchor points in black.
533+ * // Draw the points in black.
516534 * strokeWeight(5);
517535 * stroke(0);
518536 * point(73, 24);
519537 * point(73, 61);
520538 *
521- * // Draw the control points in red.
539+ * // Draw the points in red.
522540 * stroke(255, 0, 0);
523541 * point(5, 26);
524542 * point(15, 65);
@@ -546,14 +564,17 @@ function curves(p5, fn){
546564 *
547565 * function draw() {
548566 * background(200);
549- *
567+ *
568+ * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn.
569+ * splineProperty('ends', EXCLUDE);
570+ *
550571 * // Draw a black spline curve.
551572 * noFill();
552573 * strokeWeight(1);
553574 * stroke(0);
554575 * spline(x1, y1, 73, 24, 73, 61, 15, 65);
555576 *
556- * // Draw red spline curves from the anchor points to the control points.
577+ * // Draw red spline curves from the points.
557578 * stroke(255, 0, 0);
558579 * spline(x1, y1, x1, y1, 73, 24, 73, 61);
559580 * spline(73, 24, 73, 61, 15, 65, 15, 65);
@@ -564,25 +585,25 @@ function curves(p5, fn){
564585 * point(73, 24);
565586 * point(73, 61);
566587 *
567- * // Draw the control points in red.
588+ * // Draw the points in red.
568589 * stroke(255, 0, 0);
569590 * point(x1, y1);
570591 * point(15, 65);
571592 * }
572593 *
573- * // Start changing the first control point if the user clicks near it.
594+ * // Start changing the first point if the user clicks near it.
574595 * function mousePressed() {
575596 * if (dist(mouseX, mouseY, x1, y1) < 20) {
576597 * isChanging = true;
577598 * }
578599 * }
579600 *
580- * // Stop changing the first control point when the user releases the mouse.
601+ * // Stop changing the first point when the user releases the mouse.
581602 * function mouseReleased() {
582603 * isChanging = false;
583604 * }
584605 *
585- * // Update the first control point while the user drags the mouse.
606+ * // Update the first point while the user drags the mouse.
586607 * function mouseDragged() {
587608 * if (isChanging === true) {
588609 * x1 = mouseX;
@@ -598,7 +619,10 @@ function curves(p5, fn){
598619 * createCanvas(100, 100);
599620 *
600621 * background('skyblue');
601- *
622+ *
623+ * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn.
624+ * splineProperty('ends', EXCLUDE);
625+ *
602626 * // Draw the red balloon.
603627 * fill('red');
604628 * spline(-150, 275, 50, 60, 50, 60, 250, 275);
@@ -621,7 +645,10 @@ function curves(p5, fn){
621645 *
622646 * function draw() {
623647 * background('skyblue');
624- *
648+ *
649+ * // Exclude the ends—skip the outer spans (p0→p1 and p2→p3) so only the middle span (p1→p2) is drawn.
650+ * splineProperty('ends', EXCLUDE);
651+ *
625652 * // Rotate around the y-axis.
626653 * rotateY(frameCount * 0.01);
627654 *
@@ -640,16 +667,16 @@ function curves(p5, fn){
640667 * @method spline
641668 * @param {Number } x1
642669 * @param {Number } y1
643- * @param {Number } z1 z-coordinate of the first control point.
670+ * @param {Number } z1 z-coordinate of point p0 .
644671 * @param {Number } x2
645672 * @param {Number } y2
646- * @param {Number } z2 z-coordinate of the first anchor point.
673+ * @param {Number } z2 z-coordinate of point p1 .
647674 * @param {Number } x3
648675 * @param {Number } y3
649- * @param {Number } z3 z-coordinate of the second anchor point.
676+ * @param {Number } z3 z-coordinate of point p2 .
650677 * @param {Number } x4
651678 * @param {Number } y4
652- * @param {Number } z4 z-coordinate of the second control point.
679+ * @param {Number } z4 z-coordinate of point p3 .
653680 * @chainable
654681 */
655682 fn . spline = function ( ...args ) {
@@ -664,30 +691,30 @@ function curves(p5, fn){
664691 /**
665692 * Calculates coordinates along a spline curve using interpolation.
666693 *
667- * `splinePoint()` calculates coordinates along a spline curve using the
668- * anchor and control points . It expects points in the same order as the
694+ * `splinePoint()` calculates coordinates along a spline curve using four
695+ * points p0, p1, p2, p3 . It expects points in the same order as the
669696 * <a href="#/p5/spline">spline()</a> function. `splinePoint()` works one axis
670- * at a time. Passing the anchor and control points' x-coordinates will
671- * calculate the x-coordinate of a point on the curve. Passing the anchor and
672- * control points' y-coordinates will calculate the y-coordinate of a point on
697+ * at a time. Passing the points' x-coordinates will
698+ * calculate the x-coordinate of a point on the curve. Passing the
699+ * points' y-coordinates will calculate the y-coordinate of a point on
673700 * the curve.
674701 *
675- * The first parameter, `a`, is the coordinate of the first control point.
702+ * The first parameter, `a`, is the coordinate of point p0 .
676703 *
677- * The second and third parameters, `b` and `c`, are the coordinates of the
678- * anchor points.
704+ * The second and third parameters, `b` and `c`, are the coordinates of
705+ * points p1 and p2 .
679706 *
680- * The fourth parameter, `d`, is the coordinate of the last control point.
707+ * The fourth parameter, `d`, is the coordinate of point p3 .
681708 *
682- * The fifth parameter, `t`, is the amount to interpolate along the curve. 0
683- * is the first anchor point, 1 is the second anchor point , and 0.5 is halfway
709+ * The fifth parameter, `t`, is the amount to interpolate along the span
710+ * from p1 to p2. `t = 0` is p1, `t = 1` is p2 , and `t = 0.5` is halfway
684711 * between them.
685712 *
686713 * @method splinePoint
687- * @param {Number } a coordinate of first control point.
688- * @param {Number } b coordinate of first anchor point.
689- * @param {Number } c coordinate of second anchor point.
690- * @param {Number } d coordinate of second control point.
714+ * @param {Number } a coordinate of point p0 .
715+ * @param {Number } b coordinate of point p1 .
716+ * @param {Number } c coordinate of point p2 .
717+ * @param {Number } d coordinate of point p3 .
691718 * @param {Number } t amount to interpolate between 0 and 1.
692719 * @return {Number } coordinate of a point on the curve.
693720 *
@@ -699,7 +726,8 @@ function curves(p5, fn){
699726 *
700727 * background(200);
701728 *
702- * // Set the coordinates for the curve's anchor and control points.
729+ *
730+ * // Set the coordinates for the curve's four points (p0, p1, p2, p3).
703731 * let x1 = 5;
704732 * let y1 = 26;
705733 * let x2 = 73;
@@ -747,7 +775,7 @@ function curves(p5, fn){
747775 * function draw() {
748776 * background(200);
749777 *
750- * // Set the coordinates for the curve's anchor and control points .
778+ * // Set the coordinates for the curve's four points (p0, p1, p2, p3) .
751779 * let x1 = 5;
752780 * let y1 = 26;
753781 * let x2 = 73;
@@ -773,6 +801,7 @@ function curves(p5, fn){
773801 * </code>
774802 * </div>
775803 */
804+
776805 fn . splinePoint = function ( a , b , c , d , t ) {
777806 const s = this . _renderer . states . splineProperties . tightness ,
778807 t3 = t * t * t ,
@@ -790,42 +819,82 @@ function curves(p5, fn){
790819 * Tangent lines skim the surface of a curve. A tangent line's slope equals
791820 * the curve's slope at the point where it intersects.
792821 *
793- * `splineTangent()` calculates coordinates along a tangent line using the
794- * spline curve's anchor and control points. It expects points in the same
795- * order as the <a href="#/p5/spline">spline()</a> function. `splineTangent()`
796- * works one axis at a time. Passing the anchor and control points'
797- * x-coordinates will calculate the x-coordinate of a point on the tangent
798- * line. Passing the anchor and control points' y-coordinates will calculate
799- * the y-coordinate of a point on the tangent line.
800- *
801- * The first parameter, `a`, is the coordinate of the first control point.
822+ * `splineTangent()` calculates coordinates along a tangent line using four
823+ * points p0, p1, p2, p3. It expects points in the same order as the
824+ * <a href="#/p5/spline">spline()</a> function. `splineTangent()` works one
825+ * axis at a time. Passing the points' x-coordinates returns the x-component of
826+ * the tangent vector; passing the points' y-coordinates returns the y-component.
827+ * The first parameter, `a`, is the coordinate of point p0.
802828 *
803- * The second and third parameters, `b` and `c`, are the coordinates of the
804- * anchor points.
829+ * The second and third parameters, `b` and `c`, are the coordinates of
830+ * points p1 and p2 .
805831 *
806- * The fourth parameter, `d`, is the coordinate of the last control point.
832+ * The fourth parameter, `d`, is the coordinate of point p3 .
807833 *
808- * The fifth parameter, `t`, is the amount to interpolate along the curve. 0
809- * is the first anchor point, 1 is the second anchor point , and 0.5 is halfway
834+ * The fifth parameter, `t`, is the amount to interpolate along the span
835+ * from p1 to p2. `t = 0` is p1, `t = 1` is p2 , and `t = 0.5` is halfway
810836 * between them.
811837 *
812838 * @method splineTangent
813- * @param {Number } a coordinate of first control point.
814- * @param {Number } b coordinate of first anchor point.
815- * @param {Number } c coordinate of second anchor point.
816- * @param {Number } d coordinate of second control point.
839+ * @param {Number } a coordinate of point p0 .
840+ * @param {Number } b coordinate of point p1 .
841+ * @param {Number } c coordinate of point p2 .
842+ * @param {Number } d coordinate of point p3 .
817843 * @param {Number } t amount to interpolate between 0 and 1.
818844 * @return {Number } coordinate of a point on the tangent line.
819845 *
820846 * @example
821847 * <div>
822848 * <code>
823849 * function setup() {
850+ * createCanvas(120, 120);
851+ * 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.');
852+ * }
853+ *
854+ * function draw() {
855+ * background(240);
856+ *
857+ * const x1 = 15, y1 = 40;
858+ * const x2 = 90, y2 = 25;
859+ * const x3 = 95, y3 = 95;
860+ * const x4 = 30, y4 = 110;
861+ *
862+ * noFill();
863+ * stroke(0);
864+ * strokeWeight(2);
865+ * spline(x1, y1, x2, y2, x3, y3, x4, y4);
866+ *
867+ * const t = 0.5 + 0.5 * sin(frameCount * 0.03);
868+ *
869+ * const px = splinePoint(x1, x2, x3, x4, t);
870+ * const py = splinePoint(y1, y2, y3, y4, t);
871+ *
872+ * let tx = splineTangent(x1, x2, x3, x4, t);
873+ * let ty = splineTangent(y1, y2, y3, y4, t);
874+ *
875+ * const m = Math.hypot(tx, ty) || 1;
876+ * tx = (tx / m) * 16;
877+ * ty = (ty / m) * 16;
878+ *
879+ * stroke(0);
880+ * strokeWeight(2);
881+ * line(px, py, px + tx, py + ty);
882+ *
883+ * noStroke();
884+ * fill('red');
885+ * circle(px, py, 7);
886+ * }
887+ * </code>
888+ * </div>
889+ *
890+ * <div>
891+ * <code>
892+ * function setup() {
824893 * createCanvas(100, 100);
825894 *
826895 * background(200);
827896 *
828- * // Set the coordinates for the curve's anchor and control points .
897+ * // Set the coordinates for the curve's four points (p0, p1, p2, p3) .
829898 * let x1 = 5;
830899 * let y1 = 26;
831900 * let x2 = 73;
0 commit comments