SWSpade Reference
Composite Shape (Inverted Heart + SWSpire) — SketchWaveJS
♠ Composite Class Design
SWSpade is a composite class. It draws the traditional playing-card spade ♠ using two parts:
- Body — the classic inverted heart, rendered as a closed polygon from a 4-harmonic parametric curve sampled at 200 points. The y-axis is negated to flip the standard heart upward into the spade orientation.
- Stem —
SWSpirewithhalfShape = trueandrotationDeg = 180, producing a downward-pointing cusp arch whose base attaches at the lowest point of the body.
The attachment point of the stem is computed each frame by _getBodyMinLy(), which samples the body curve to find the minimum local y (the lowest point of the two lobes). This keeps the stem correctly positioned even as the scale parameter changes during pulse animation.
Draw order: stem is drawn first (behind), then the body on top. The body fill naturally covers the arch base, hiding the seam.
Mathematical Foundation
Body: Inverted Parametric Heart
The body uses the classic 4-harmonic heart parametric equations, with the y component negated to produce the spade orientation (sharp tip pointing up, lobes curving down):
y(t) = −scale · (b·cos(t) + c·cos(2t) + d·cos(3t) + e·cos(4t))
Defaults: a=16, b=13, c=−5, d=−2, e=−1, scale=0.5
t ∈ [0, 2π), 200 sample points
At t = π/2, x = scale · a and y = 0, placing the widest point of the right lobe at the horizontal midline. The sharp upward cusp occurs at t = π/2 (or equivalently t = −π/2 for the top tip) due to the sin³ term collapsing to zero while the y harmonic sum reaches its minimum (most negative).
Coefficient Interpretation
| Param | Role | Default | Effect of increasing |
|---|---|---|---|
a | Width amplitude | 16 | Wider left/right lobes |
b | Primary y harmonic (cos 1) | 13 | Taller overall shape; deeper lower lobes |
c | Second y harmonic (cos 2) | −5 | Sharpens / blunts the tip; more negative = sharper tip |
d | Third y harmonic (cos 3) | −2 | Adds subtle secondary inflection near the top |
e | Fourth y harmonic (cos 4) | −1 | Fine-tunes lobe curvature near base |
scale | Uniform scale factor | 0.5 | Scales entire body in grid units |
Stem: Half SWSpire Arch
The stem is a half-arch traced from t = 0 to t = π:
y(t) = radiusY · |sin(t)|2/power · sign(sin(t))
t ∈ [0, π], closed with CLOSE
With rotationDeg = 180 + total rotation, the arch base lies horizontally at y = 0 in local space and curves down to a cusp at (0, −radiusY). endShape(CLOSE) closes the arch with a flat base.
Stem Placement (Attachment Math)
Let minLy = _getBodyMinLy() (the minimum local-y of the body, a negative number ≈ −5.3 at defaults). After applying total rotation θ:
stemY = center.y + minLy · cos(θ)
Because minLy is negative, −minLy is positive, so the formula places the stem below the body at the correct local-y position. The rotation matrix keeps the stem attached during spin.
Constructor
new SWSpade(center, a, b, c, d, e, fillColor, strokeColor, thickness, scale, stemLength, stemWidth, stemPower, rotationDeg, stemOffset)
| Parameter | Type | Default | Description |
|---|---|---|---|
center | SWPoint | required | Center of the body in user (grid) coordinates |
a | number | 16 | Width amplitude of the heart parametric curve |
b | number | 13 | Primary y harmonic (cos 1t coefficient) |
c | number | −5 | Second y harmonic (cos 2t coefficient) |
d | number | −2 | Third y harmonic (cos 3t coefficient) |
e | number | −1 | Fourth y harmonic (cos 4t coefficient) |
fillColor | SWColor | undefined | Fill color for body and stem; undefined = no fill |
strokeColor | SWColor | undefined | Stroke color; undefined = no stroke |
thickness | number | 2 | Stroke weight in pixels |
scale | number | 0.5 | Uniform scale factor (grid units); controls overall body size (min 0.01) |
stemLength | number | 2.0 | SWSpire radiusY: depth of the downward cusp arch (grid units, min 0.1) |
stemWidth | number | 0.6 | SWSpire radiusX: half-width of the arch base (grid units, min 0.05) |
stemPower | number | 5 | SWSpire power exponent: 1 = smooth arch; 9 = sharp spike |
stemOffset | number | 0 | Additional vertical shift of the stem center along the body-bottom axis (grid units); positive moves the stem toward the body |
rotationDeg | number | 0 | Static base rotation in CCW degrees; persists across reset() |
Properties
| Property | Type | Description |
|---|---|---|
center | SWPoint | Body center in user coordinates. Move by setting center.x, center.y. |
a | number | Width amplitude. |
b | number | Primary y harmonic coefficient. |
c | number | Second y harmonic coefficient. |
d | number | Third y harmonic coefficient. |
e | number | Fourth y harmonic coefficient. |
scale | number | Current uniform scale factor. |
stemLength | number | Current stem depth (SWSpire radiusY). |
stemWidth | number | Current stem half-width (SWSpire radiusX). |
stemPower | number | Current cusp sharpness exponent. |
stemOffset | number | Current vertical stem offset (grid units). Positive = toward body. |
fillColor | SWColor | Shared fill color for body and stem. |
strokeColor | SWColor | Shared stroke color. |
thickness | number | Stroke weight in pixels. |
rotationDeg | number | Static base rotation (CCW degrees). Persists across reset(). |
rotation | number | Accumulated spin from rotate(). Cleared by reset(). |
SAMPLE_COUNT | static number | 200 — number of parametric sample points for the body polygon. |
_stem | SWSpire | Internal. Do not access directly. |
Methods
Drawing
| Method | Description |
|---|---|
drawOnGrid(grid) | Syncs stem then draws stem + body through SWGrid coordinate mapping. Preferred method. |
draw() | Syncs stem then draws in raw screen (pixel) coordinates. Use only when no grid is present. |
Animation
| Method | Description |
|---|---|
rotate(deltaAngle) | Adds deltaAngle degrees (CCW+, CW−) to rotation. Call once per frame: spade.rotate(speed * deltaT). |
Setters
| Method | Parameter | Description |
|---|---|---|
setA(v) | number | Sets the width amplitude a. |
setB(v) | number | Sets primary y harmonic b. |
setC(v) | number | Sets second y harmonic c. |
setD(v) | number | Sets third y harmonic d. |
setE(v) | number | Sets fourth y harmonic e. |
setScale(s) | number ≥ 0.01 | Sets the uniform scale factor. Stem attachment recalculates automatically on next draw. |
setStemLength(l) | number ≥ 0.1 | Sets the stem cusp depth. |
setStemWidth(w) | number ≥ 0.05 | Sets the stem base half-width. |
setStemPower(p) | number ≥ 1 | Sets the cusp sharpness exponent. |
setRotation(deg) | number | Sets the static base rotation (CCW degrees). |
setFillColor(fc) | SWColor|undefined | Sets the fill color (deep copies the SWColor). |
setStrokeColor(sc) | SWColor|undefined | Sets the stroke color. |
setStrokeWeight(w) | number | Sets stroke thickness in pixels. |
setFillAlpha(alpha) | 0–100 | Sets fill opacity and rebuilds the p5 color object. |
setStrokeAlpha(alpha) | 0–100 | Sets stroke opacity and rebuilds the p5 color object. |
Reset & Utility
| Method | Description |
|---|---|
reset() | Restores all parameters to constructor values. Clears rotation. Does not move center. |
static copy(other) | Returns a deep copy of the SWSpade, preserving all current and original state. |
toString() | Returns a summary string of current parameter values. |
Code Examples
Basic Setup
let spade; let grid; function setup() { createCanvas(400, 400); colorMode(HSB, 360, 100, 100, 100); initializeSWColors(); grid = new SWGrid({ UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10) }); const center = new SWPoint(0, 0); const fillCol = SWColor.fromHex('#22225a', 100, 'fill'); const strokeCol = SWColor.fromHex('#1a1a40', 100, 'stroke'); spade = new SWSpade(center, 16, 13, -5, -2, -1, fillCol, strokeCol, 2, 0.5, 2.0, 0.6, 5, 0); } function draw() { background(240, 10, 95); grid.draw(); spade.drawOnGrid(grid); }
Spin Animation
let prevT = 0; function draw() { const t = millis() / 1000; const deltaT = (prevT > 0) ? (t - prevT) : 0; prevT = t; background(240, 10, 95); grid.draw(); spade.rotate(45 * deltaT); // 45 °/sec CCW spade.drawOnGrid(grid); }
Pulse Animation
let pulseBase = 0.5; // base scale function draw() { const t = millis() / 1000; background(240, 10, 95); grid.draw(); // Oscillate scale ±0.08 at 0.5 Hz — stem follows automatically const s = pulseBase + 0.08 * Math.sin(2 * Math.PI * 0.5 * t); spade.setScale(Math.max(0.05, s)); spade.drawOnGrid(grid); }
Copy & Reset
// Deep copy const spade2 = SWSpade.copy(spade); spade2.center.x += 5; // moved independently // Restore factory values spade.reset(); // Inspect console.log(spade.toString()); // SWSpade(scale=0.50, a=16, b=13, c=-5, d=-2, e=-1, stemLength=2.0, ...)
Source Code
📄 Toggle Source: swSpade.js
Loading source...