|
| 1 | +/* |
| 2 | + Helper function that draws a shape using the specified shape mode |
| 3 | + p5 ............... The p5 Instance |
| 4 | + shape ............ The shape to draw. Either 'ellipse', 'arc', or 'rect' |
| 5 | + mode ............. The ellipseMode (for ellipse and arc), or rectMode (for rect) |
| 6 | + Either p5.CORNERS, p5.CORNER, p5.CENTER or p5.RADIUS |
| 7 | + x1, x2, x2, y2 ... Coordinates specifying the shape in CORNERS mode, |
| 8 | + i.e. (x1, y1) and (x2, y2) specify two opposite corners P1 and P2 |
| 9 | +*/ |
| 10 | +function shapeCorners(p5, shape, mode, x1, y1, x2, y2) { |
| 11 | + // Adjust coordinates for testing modes other than CORNERS |
| 12 | + if (mode === p5.CORNER) { |
| 13 | + // Find top left corner |
| 14 | + let x = p5.min(x1, x2); // x |
| 15 | + let y = p5.min(y1, y2); // y |
| 16 | + // Calculate width and height |
| 17 | + // Don't use abs(), so we get negative values as well |
| 18 | + let w = x2 - x1; // w |
| 19 | + let h = y2 - y1; // h |
| 20 | + x1 = x; y1 = y; x2 = w; y2 = h; |
| 21 | + } else if (mode === p5.CENTER) { |
| 22 | + // Find center |
| 23 | + let x = (x2 + x1) / 2; // x |
| 24 | + let y = (y2 + y1) / 2; // y |
| 25 | + // Calculate width and height |
| 26 | + // Don't use abs(), so we get negative values as well |
| 27 | + let w = x2 - x1; |
| 28 | + let h = y2 - y1; |
| 29 | + x1 = x; y1 = y; x2 = w; y2 = h; |
| 30 | + } else if (mode === p5.RADIUS) { |
| 31 | + // Find Center |
| 32 | + let x = (x2 + x1) / 2; // x |
| 33 | + let y = (y2 + y1) / 2; // y |
| 34 | + // Calculate radii |
| 35 | + // Don't use abs(), so we get negative values as well |
| 36 | + let r1 = (x2 - x1) / 2; // r1; |
| 37 | + let r2 = (y2 - y1) / 2; // r2 |
| 38 | + x1 = x; y1 = y; x2 = r1; y2 = r2; |
| 39 | + } |
| 40 | + |
| 41 | + if (shape === 'ellipse') { |
| 42 | + p5.ellipseMode(mode); |
| 43 | + p5.ellipse(x1, y1, x2, y2); |
| 44 | + } else if (shape === 'arc') { |
| 45 | + // Draw four arcs with gaps inbetween |
| 46 | + const GAP = p5.radians(30); |
| 47 | + p5.ellipseMode(mode); |
| 48 | + p5.arc(x1, y1, x2, y2, 0 + GAP, p5.HALF_PI - GAP); |
| 49 | + p5.arc(x1, y1, x2, y2, p5.HALF_PI + GAP, p5.PI - GAP); |
| 50 | + p5.arc(x1, y1, x2, y2, p5.PI + GAP, p5.PI + p5.HALF_PI - GAP); |
| 51 | + p5.arc(x1, y1, x2, y2, p5.PI + p5.HALF_PI + GAP, p5.TWO_PI - GAP); |
| 52 | + } else if (shape === 'rect') { |
| 53 | + p5.rectMode(mode); |
| 54 | + p5.rect(x1, y1, x2, y2); |
| 55 | + } |
| 56 | +} |
| 57 | + |
| 58 | + |
| 59 | +/* |
| 60 | + Comprehensive test for rendering ellipse(), arc(), and rect() |
| 61 | + with the different ellipseMode() / rectMode() values: CORNERS, CORNER, CENTER, RADIUS. |
| 62 | + Each of the 3 shapes is tested with each of the 4 possible modes, resulting in 12 test. |
| 63 | + Each test renders the shape in 16 different coordinate configurations, |
| 64 | + testing combinations of positive and negative coordinate values. |
| 65 | +*/ |
| 66 | +visualSuite('Shape Modes', function(...args) { |
| 67 | + // Shapes to test |
| 68 | + const SHAPES = [ 'ellipse', 'arc', 'rect' ]; |
| 69 | + |
| 70 | + // Modes to test (used with ellipseMode or rectMode, according to shape) |
| 71 | + const MODES = [ 'CORNERS', 'CORNER', 'CENTER', 'RADIUS' ]; |
| 72 | + |
| 73 | + for (let shape of SHAPES) { |
| 74 | + visualSuite(`Shape ${shape}`, function() { |
| 75 | + |
| 76 | + for (let mode of MODES) { |
| 77 | + visualTest(`Mode ${mode}`, function(p5, screenshot) { |
| 78 | + p5.createCanvas(240, 500); |
| 79 | + p5.translate(p5.width/2, p5.height/2); |
| 80 | + |
| 81 | + // Make the following calls to shapeCorners shorter |
| 82 | + // by omitting p5, shape and mode parameters |
| 83 | + function _shapeCorners(x1, y1, x2, y2) { |
| 84 | + shapeCorners(p5, shape, p5[mode], x1, y1, x2, y2); |
| 85 | + } |
| 86 | + |
| 87 | + // Quadrant I (Bottom Right) |
| 88 | + // P1 P2 |
| 89 | + _shapeCorners( 10, 10, 110, 60); // P1 Top Left, P2 Bottom Right |
| 90 | + _shapeCorners( 10, 120, 110, 70); // P1 Bottom Left, P2 Top Right |
| 91 | + _shapeCorners(110, 180, 10, 130); // P1 Bottom Right, P2 Top Left |
| 92 | + _shapeCorners(110, 190, 10, 240); // P1 Top Right, P2 Bottom Left |
| 93 | + |
| 94 | + // Quadrant II (Bottom Left) |
| 95 | + _shapeCorners(-110, 10, -10, 60); |
| 96 | + _shapeCorners(-110, 120, -10, 70); |
| 97 | + _shapeCorners(-10, 180, -110, 130); |
| 98 | + _shapeCorners(-10, 190, -110, 240); |
| 99 | + |
| 100 | + // Quadrant III (Top Left) |
| 101 | + _shapeCorners(-110, -240, -10, -190); |
| 102 | + _shapeCorners(-110, -130, -10, -180); |
| 103 | + _shapeCorners(-10, -70, -110, -120); |
| 104 | + _shapeCorners(-10, -60, -110, -10); |
| 105 | + |
| 106 | + // Quadrant IV (Top Right) |
| 107 | + _shapeCorners( 10, -240, 110, -190); |
| 108 | + _shapeCorners( 10, -130, 110, -180); |
| 109 | + _shapeCorners(110, -70, 10, -120); |
| 110 | + _shapeCorners(110, -60, 10, -10); |
| 111 | + |
| 112 | + screenshot(); |
| 113 | + }); // End of: visualTest |
| 114 | + } // End of: MODES loop |
| 115 | + |
| 116 | + }); // End of: Inner visualSuite |
| 117 | + } // End of: SHAPES loop |
| 118 | +}); // End of: Outer visualSuite |
0 commit comments