Quick Reference
SWDisk is a SketchWave class for representing circles and disks in 2D space with full styling control, including fill color, stroke color, and geometric properties like area and circumference.
- Extends: Nothing (standalone class)
- Dependencies: SWPoint, SWColor, p5.js
- Key Features: Custom fill/stroke colors, area/circumference calculations, breathing animation, center point display, hit detection
- Common Uses: Color wheels, circular UI elements, animated disks, interactive buttons, visualization of circular data
Overview
The SWDisk class represents circular shapes (disks) in 2D coordinate space. It provides complete control over appearance, position, and behavior, making it ideal for creating color wheels, interactive circular elements, and animated visual effects.
Key Capabilities
- Flexible Positioning: Center defined by an SWPoint instance
- Full Styling Control: Independent fill and stroke colors using SWColor
- Geometric Properties: Automatic area and circumference calculations
- Animation Support: Built-in "breathing" effect using SWSinusoid
- Interactive Features: Hit detection with containsPoint() method
- Dual Coordinate Systems: Draw in screen pixels or grid coordinates
- Center Point Display: Optional visualization of disk center with automatic color selection
Typical Workflow
- Create an SWDisk with center point, radius, and colors
- Optionally configure center point visibility and styling
- Draw the disk in your animation loop using draw() or drawOnGrid()
- Interact with the disk using hit detection or modify properties dynamically
- Apply animations like breathing or color cycling as needed
Constructor
new SWDisk(center, radius, thickness, fillColor, strokeColor)Creates a new SWDisk instance with specified geometric and styling properties.
| Parameter | Type | Default | Description |
|---|---|---|---|
center |
SWPoint | required | Center point of the disk |
radius |
number | required | Radius in user units |
thickness |
number | 2 | Border (stroke) thickness in pixels |
fillColor |
SWColor | undefined | Interior fill color (no fill if undefined) |
strokeColor |
SWColor | undefined | Border color (no stroke if undefined) |
// Minimal: center and radius only
let disk1 = new SWDisk(new SWPoint(0, 0), 5);
// With fill color
let disk2 = new SWDisk(new SWPoint(0, 0), 5, 2, swBlue);
// With fill and stroke
let disk3 = new SWDisk(new SWPoint(0, 0), 5, 3, swYellow, swBlack);
// Fully configured disk
let centerPt = new SWPoint(10, 10);
let fillCol = new SWColor(120, 80, 90, 100, "greenFill");
let strokeCol = new SWColor(0, 0, 0, 100, "blackStroke");
let disk4 = new SWDisk(centerPt, 8, 4, fillCol, strokeCol);
Properties
SWDisk instances have the following properties:
center SWPointThe center point of the disk as an SWPoint instance. Changing this moves the disk.
disk.center.x = 5; disk.center.y = 10; // Move disk to (5, 10)
radius numberThe radius of the disk in user units. Directly modifying this updates area and circumference automatically.
disk.radius = 10; // Set radius to 10 units
thickness numberThe stroke (border) thickness in pixels.
disk.thickness = 5; // Thicker border
fillColor SWColorThe interior fill color as an SWColor instance. Set to undefined for no fill.
disk.fillColor = new SWColor(240, 100, 100, 100, "blue");
strokeColor SWColorThe border color as an SWColor instance. Set to undefined for no stroke.
disk.strokeColor = swBlack;
originalFillColor SWColorA copy of the fill color provided at construction. Used by resetFillColor() to restore the original color.
// Read-only reference to original color
originalRadius numberThe radius value at construction. Used by reset() to restore the original size after animations.
// Used internally for reset()
area number read-onlyThe computed area of the disk (πr²). Automatically updated when radius changes.
console.log(`Area: ${disk.area.toFixed(2)}`);
circumference number read-onlyThe computed circumference of the disk (2πr). Automatically updated when radius changes.
console.log(`Circumference: ${disk.circumference.toFixed(2)}`);
shouldShowCenter booleanWhether to display the center point when drawing. Default is true.
disk.shouldShowCenter = false; // Hide center point
centerColor SWColorThe color of the center point, automatically determined from stroke or fill color.
// Automatically managed by updateCenterColor()
Methods
Core Drawing Methods
draw()Draws the disk in screen (pixel) coordinates using p5.js.
void
function draw() {
background(220);
disk.draw(); // Draws at screen coordinates
}
drawOnGrid(grid)Draws the disk in user (grid) coordinates, converting to screen space using the provided SWGrid.
grid(SWGrid) - Grid for coordinate transformation
void
function draw() {
background(220);
grid.draw();
disk.drawOnGrid(grid); // Draws in grid coordinates
}
Color and Styling Methods
setFillColor(swColor)Sets the fill color of the disk. A copy is made to avoid mutating shared color objects.
swColor(SWColor) - New fill color
disk.setFillColor(swRed); // Change fill to red
resetFillColor()Restores the fill color to its original value from construction.
disk.resetFillColor(); // Restore original color
setStrokeColor(swColor)Sets the border (stroke) color of the disk.
swColor(SWColor) - New stroke color
disk.setStrokeColor(swBlack); // Black border
setStrokeWeight(w)Sets the border thickness in pixels.
w(number) - Thickness in pixels
disk.setStrokeWeight(5); // Thicker border
setFillAlpha(alpha)Sets the alpha (transparency) of the fill color. The alpha value is clamped between 0 and 100 and the underlying p5.js color object is updated immediately.
alpha(number) - Alpha value 0–100 (0 = fully transparent, 100 = fully opaque)
disk.setFillAlpha(50); // 50% transparent fill
setStrokeAlpha(alpha)Sets the alpha (transparency) of the stroke (border) color. The alpha value is clamped between 0 and 100, the p5.js color object is updated, and updateCenterColor() is called automatically.
alpha(number) - Alpha value 0–100 (0 = fully transparent, 100 = fully opaque)
disk.setStrokeAlpha(75); // Semi-transparent border
updateCenterColor()Updates the center point color according to these rules: uses strokeColor if present, otherwise uses a 20% darker version of fillColor, otherwise uses black.
// Called automatically when colors change
disk.updateCenterColor();
Geometry Methods
setRadius(r)Sets the radius and automatically updates area and circumference properties.
r(number) - New radius in user units
disk.setRadius(10);
console.log(disk.area); // Updated automatically
setShowCenter(show)Controls whether the center point is visible when drawing.
show(boolean) - true to show center, false to hide (default: true)
disk.setShowCenter(false); // Hide center point
Animation Methods
breathe(sinusoid, t)Modulates the radius using a SWSinusoid, creating a "breathing" animation effect. The radius is set to the sinusoid's value at time t.
sinusoid(SWSinusoid) - Sinusoid controlling radius modulationt(number) - Time or parameter value
let breathSin = new SWSinusoid(5, 2, 0.5, 0); // Center at 5, amplitude 2
disk.breathe(breathSin, frameCount * 0.01);
reset()Resets the radius to its original value and recalculates area and circumference.
disk.reset(); // Restore original radius
Interaction Methods
containsPoint(x, y, grid)Tests if a screen (pixel) coordinate is inside the disk. Useful for mouse/touch interaction.
x(number) - X coordinate in screen pixelsy(number) - Y coordinate in screen pixelsgrid(SWGrid) - Grid for coordinate mapping
boolean - true if point is inside disk, false otherwise
function mousePressed() {
if (disk.containsPoint(mouseX, mouseY, grid)) {
console.log("Disk clicked!");
}
}
Utility Methods
toString()Returns a string representation of the disk with all its properties.
string - Formatted description of the disk
console.log(disk.toString());
// Output: "SWDisk(center: SWPoint(x: 0, y: 0), radius: 5, thickness: 2, ...)"
Usage Examples
Example 1: Basic Disk with Grid
let grid;
let disk;
function setup() {
createCanvas(400, 400);
// Create grid
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create a simple disk at origin
let center = new SWPoint(0, 0);
let fillColor = new SWColor(240, 80, 90, 100, "blue");
let strokeColor = new SWColor(0, 0, 0, 100, "black");
disk = new SWDisk(center, 5, 3, fillColor, strokeColor);
}
function draw() {
background(220);
grid.draw();
disk.drawOnGrid(grid);
}
Example 2: Color Wheel with Multiple Disks
let grid;
let disks = [];
function setup() {
createCanvas(600, 600);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create 12 disks in a circle (color wheel)
const numDisks = 12;
const wheelRadius = 6;
const diskRadius = 1.5;
for (let i = 0; i < numDisks; i++) {
const angle = (i / numDisks) * TWO_PI;
const x = wheelRadius * cos(angle);
const y = wheelRadius * sin(angle);
const hue = (i / numDisks) * 360;
const fillColor = new SWColor(hue, 100, 90, 100, `hue${i}`);
const strokeColor = new SWColor(0, 0, 0, 100, "black");
const center = new SWPoint(x, y);
const disk = new SWDisk(center, diskRadius, 2, fillColor, strokeColor);
disks.push(disk);
}
}
function draw() {
background(220);
grid.draw();
disks.forEach(disk => disk.drawOnGrid(grid));
}
Example 3: Breathing Animation
let grid;
let disk;
let breathSinusoid;
function setup() {
createCanvas(400, 400);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create disk
let center = new SWPoint(0, 0);
disk = new SWDisk(center, 5, 3, swBlue, swBlack);
// Create sinusoid for breathing: center=5, amplitude=2
// Radius will oscillate between 3 and 7
breathSinusoid = new SWSinusoid(5, 2, 0.5, 0);
}
function draw() {
background(220);
grid.draw();
// Apply breathing animation
disk.breathe(breathSinusoid, frameCount * 0.02);
disk.drawOnGrid(grid);
// Display current radius
fill(0);
text(`Radius: ${disk.radius.toFixed(2)}`, 10, 20);
text(`Area: ${disk.area.toFixed(2)}`, 10, 40);
}
Example 4: Interactive Disk Selection
let grid;
let disks = [];
let selectedDisk = null;
function setup() {
createCanvas(600, 600);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create several disks at random positions
for (let i = 0; i < 8; i++) {
const x = random(-8, 8);
const y = random(-8, 8);
const hue = random(360);
const center = new SWPoint(x, y);
const fillColor = new SWColor(hue, 80, 90, 100, `disk${i}`);
const disk = new SWDisk(center, 1.5, 2, fillColor, swBlack);
disks.push(disk);
}
}
function draw() {
background(220);
grid.draw();
// Draw all disks
disks.forEach(disk => {
// Highlight selected disk
if (disk === selectedDisk) {
disk.setStrokeWeight(5);
} else {
disk.setStrokeWeight(2);
}
disk.drawOnGrid(grid);
});
// Display selection info
if (selectedDisk) {
fill(0);
text(`Selected: ${selectedDisk.fillColor.name}`, 10, 20);
text(`Center: (${selectedDisk.center.x.toFixed(1)}, ${selectedDisk.center.y.toFixed(1)})`, 10, 40);
}
}
function mousePressed() {
// Check which disk was clicked
selectedDisk = null;
for (let disk of disks) {
if (disk.containsPoint(mouseX, mouseY, grid)) {
selectedDisk = disk;
console.log(`Selected: ${disk.fillColor.name}`);
break;
}
}
}
Example 5: Dynamic Color Modification
let grid;
let disk;
let saturation = 100;
let brightness = 100;
function setup() {
createCanvas(600, 400);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create disk with modifiable color
let center = new SWPoint(0, 0);
let fillColor = new SWColor(180, saturation, brightness, 100, "cyan");
disk = new SWDisk(center, 5, 3, fillColor, swBlack);
// Create sliders
createP('Saturation');
let satSlider = createSlider(0, 100, 100);
satSlider.input(() => {
saturation = satSlider.value();
updateDiskColor();
});
createP('Brightness');
let brightSlider = createSlider(0, 100, 100);
brightSlider.input(() => {
brightness = brightSlider.value();
updateDiskColor();
});
}
function updateDiskColor() {
let newColor = new SWColor(180, saturation, brightness, 100, "cyan");
disk.setFillColor(newColor);
}
function draw() {
background(220);
grid.draw();
disk.drawOnGrid(grid);
// Display values
fill(0);
text(`S: ${saturation}, B: ${brightness}`, 10, 20);
}
function keyPressed() {
if (key === 'r') {
disk.resetFillColor();
saturation = 100;
brightness = 100;
}
}
Example 6: Multi-Disk Synchronized Breathing
let grid;
let disks = [];
let breathSinusoid;
function setup() {
createCanvas(600, 600);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create 6 disks in a hexagon pattern
const numDisks = 6;
const hexRadius = 5;
for (let i = 0; i < numDisks; i++) {
const angle = (i / numDisks) * TWO_PI;
const x = hexRadius * cos(angle);
const y = hexRadius * sin(angle);
const hue = (i / numDisks) * 360;
const fillColor = new SWColor(hue, 80, 90, 100, `disk${i}`);
const center = new SWPoint(x, y);
const disk = new SWDisk(center, 2, 2, fillColor, swWhite);
disks.push(disk);
}
// Breathing sinusoid: center=2, amplitude=1 (range: 1 to 3)
breathSinusoid = new SWSinusoid(2, 1, 0.3, 0);
frameRate(30);
}
function draw() {
background(220);
grid.draw();
// All disks breathe in sync
const t = frameCount * 0.02;
disks.forEach(disk => {
disk.breathe(breathSinusoid, t);
disk.drawOnGrid(grid);
});
}
Example 7: Disk Without Center Point
let grid;
let disk;
function setup() {
createCanvas(400, 400);
grid = new SWGrid({UL: new SWPoint(-10, 10), LR: new SWPoint(10, -10)});
// Create disk
let center = new SWPoint(0, 0);
disk = new SWDisk(center, 5, 3, swOrange, swBlack);
// Hide center point for clean circular appearance
disk.setShowCenter(false);
}
function draw() {
background(220);
grid.draw();
disk.drawOnGrid(grid);
}
function mousePressed() {
// Toggle center point visibility
disk.setShowCenter(!disk.shouldShowCenter);
}
Best Practices
1. Color Management
- Use SWColor instances: Always pass SWColor objects for colors rather than raw p5.js color values
- Store original colors: The class automatically stores originalFillColor for easy reset
- Copy colors when sharing: SWDisk automatically copies colors to avoid mutation issues
// Good: Using SWColor
let fillColor = new SWColor(240, 80, 90, 100, "blue");
let disk = new SWDisk(center, 5, 2, fillColor);
// Later, reset is safe
disk.resetFillColor();
2. Coordinate Systems
- Use drawOnGrid() for logical coordinates: When working with mathematical or world coordinates
- Use draw() for screen coordinates: When positioning relative to canvas pixels
- Be consistent: Don't mix coordinate systems within the same sketch
3. Animation and Performance
- Use breathe() for radius animation: Built-in support for smooth sinusoidal scaling
- Call reset() before changing animations: Restore original state before new effects
- Limit disk count: Drawing many disks can impact performance; consider culling off-screen disks
4. Interaction
- Use containsPoint() for hit detection: Accurate circular hit testing
- Provide visual feedback: Change strokeWeight or color on hover/click
- Consider touch targets: Make interactive disks large enough for easy clicking
function mousePressed() {
if (disk.containsPoint(mouseX, mouseY, grid)) {
disk.setStrokeWeight(5); // Visual feedback
// Handle click...
}
}
5. Center Point Display
- Hide centers for clean UI: Use setShowCenter(false) for interface elements
- Show centers for debugging: Helpful for visualizing disk positions during development
- Automatic color selection: Center color is automatically chosen for good contrast
6. Geometric Properties
- Use setRadius() for updates: Automatically maintains area/circumference consistency
- Access computed properties: Use disk.area and disk.circumference for calculations
- Don't modify radius directly during animation: Use breathe() instead for smooth effects
Integration with Other SketchWave Classes
Script Loading Order
Load dependencies before SWDisk:
<!-- p5.js library -->
<script src="https://cdn.jsdelivr.net/npm/p5@1.6.0/lib/p5.js"></script>
<!-- SketchWave classes in dependency order -->
<script src="scripts/swColor.js"></script>
<script src="scripts/swPoint.js"></script>
<script src="scripts/swGrid.js"></script>
<script src="scripts/swSinusoid.js"></script>
<script src="scripts/swDisk.js"></script>
<!-- Your sketch -->
<script src="scripts/yourSketch.js"></script>
Working with SWPoint
SWDisk uses SWPoint for its center:
- The center is a full SWPoint instance with all point capabilities
- Center point is automatically drawn (unless disabled) with appropriate color
- You can modify the center point directly to move the disk
// Access center point properties
console.log(disk.center.x, disk.center.y);
// Move disk by changing center
disk.center.x = 5;
disk.center.y = 10;
Working with SWColor
SWDisk uses SWColor for all color management:
- Fill and stroke colors are SWColor instances
- Colors are automatically copied to prevent shared mutation
- Use SWColor methods to modify brightness, saturation, etc.
// Modify disk color using SWColor methods
disk.fillColor.brightenBy(0.2); // 20% brighter
disk.fillColor.setAlphaTo(50); // 50% transparent
Working with SWGrid
SWDisk integrates with SWGrid for coordinate mapping:
- Use drawOnGrid() to draw in user coordinates
- Grid scales radius appropriately from user units to screen pixels
- containsPoint() uses grid for accurate hit detection
Working with SWSinusoid
SWDisk's breathe() method uses SWSinusoid for animation:
- Create a sinusoid with desired center value, amplitude, and frequency
- Pass it to breathe() along with a time parameter
- Radius will follow the sinusoid's waveform
// Create breathing effect centered at radius 5
let breathe = new SWSinusoid(5, 2, 0.5, 0);
disk.breathe(breathe, frameCount * 0.01);
Common Patterns
Pattern 1: Color Wheel Display
Create a circular arrangement of disks showing hue variation:
const numHues = 12;
const wheelRadius = 6;
for (let i = 0; i < numHues; i++) {
const angle = (i / numHues) * TWO_PI;
const x = wheelRadius * cos(angle);
const y = wheelRadius * sin(angle);
const hue = (i / numHues) * 360;
const fillColor = new SWColor(hue, 100, 90, 100);
const center = new SWPoint(x, y);
const disk = new SWDisk(center, 1.5, 2, fillColor, swBlack);
disks.push(disk);
}
Pattern 2: Interactive Selection with Visual Feedback
Highlight selected disk with thicker border:
function draw() {
disks.forEach(disk => {
disk.setStrokeWeight(disk === selectedDisk ? 6 : 2);
disk.drawOnGrid(grid);
});
}
function mousePressed() {
for (let disk of disks) {
if (disk.containsPoint(mouseX, mouseY, grid)) {
selectedDisk = disk;
break;
}
}
}
Pattern 3: Pulsing/Breathing Animation
Create smooth size oscillation:
// Setup
let breathSin = new SWSinusoid(baseRadius, amplitude, frequency, 0);
// Draw loop
disk.breathe(breathSin, frameCount * timeScale);
disk.drawOnGrid(grid);
Pattern 4: Dynamic Color Adjustment
Modify disk color properties in real-time:
function updateDiskColor(h, s, b, a) {
let newColor = new SWColor(h, s, b, a, disk.fillColor.name);
disk.setFillColor(newColor);
}
// Connect to sliders or keyboard input
function keyPressed() {
if (key === 'b') disk.fillColor.brightenBy(0.1);
if (key === 'd') disk.fillColor.darkenBy(0.1);
}
Source Code
The complete SWDisk class implementation:
Show/Hide Source Code
/*
File: swDisk.js
Date: 2026-02-17
Author: klp
Workspace: SWaveJS2026-01-30-StgC
Purpose: SWDisk class for SketchWaveJS
Comment(s):
Has an update: if a 'null' color is passed for the center point, it will use
the disk's stroke color (if available) or a darker version of the fill color
(if available) or swBlack as a last resort. This allows the center point to
automatically adapt its color based on the disk's styling, while still
allowing explicit control if desired.
Another update: setFillAlpha and setStrokeAlpha methods have been added to
allow changing the transparency of the fill and stroke colors after the disk
has been created. These methods ensure that the alpha value is clamped
between 0 and 100 and update the corresponding p5.js color object accordingly.
*/
console.log("[swDisk.js] SWDisk class loaded.");
class SWDisk {
/**
* @param {SWPoint} center - Center point (SWPoint instance)
* @param {number} radius - Radius (user units)
* @param {number} [thickness=2] - Border (stroke) thickness
* @param {SWColor} [fillColor] - Fill color (SWColor instance)
* @param {SWColor} [strokeColor] - Border color (SWColor instance)
*/
constructor(center, radius, thickness = 2, fillColor = undefined, strokeColor = undefined) {
this.center = center; // SWPoint instance
this.radius = radius;
this.thickness = thickness;
// Store a copy of the original fill color for reset
this.originalFillColor = fillColor ? SWColor.copy(fillColor) : undefined;
// fillColor is always a copy, so cycleParameter only affects the current color
this.fillColor = fillColor ? SWColor.copy(fillColor) : undefined;
this.strokeColor = strokeColor ? SWColor.copy(strokeColor) : undefined;
// Store original radius for breathing
this.originalRadius = radius;
// Area and circumference
this.area = Math.PI * radius * radius;
this.circumference = 2 * Math.PI * radius;
// Show center point (default: true for this version)
this.shouldShowCenter = true;
// Set center point color according to rules
this.updateCenterColor();
}//end constructor
/**
* Updates the center point color according to the rules:
* - If strokeColor, use that
* - Else if fillColor, use 20% darker version
* - Else use swBlack
* Note: This DOES NOT modify the center point itself, just stores
* the color to use when drawing the center as part of this disk.
*/
updateCenterColor() {
let centerColor;
if (this.strokeColor && this.strokeColor.col) {
centerColor = this.strokeColor;
} else if (this.fillColor && this.fillColor.col) {
// Make a color 20% darker (reduce brightness by 20%)
if (typeof SWColor === 'function') {
let h = this.fillColor.h !== undefined ? this.fillColor.h : 0;
let s = this.fillColor.s !== undefined ? this.fillColor.s : 0;
let b = this.fillColor.b !== undefined ? this.fillColor.b : 100;
let a = this.fillColor.a !== undefined ? this.fillColor.a : 100;
let darkerB = Math.max(0, b - 20);
centerColor = new SWColor(h, s, darkerB, a, 'centerDarker');
} else {
centerColor = swBlack;
}
} else {
centerColor = swBlack;
}
// Store the color for use when drawing, but DON'T modify the center point
this.centerColor = centerColor;
}//end updateCenterColor
/**
* Draws the disk in screen coordinates (p5.js)
*/
draw() {
if (this.fillColor && this.fillColor.col) {
fill(this.fillColor.col);
} else {
noFill();
}
if (this.strokeColor && this.strokeColor.col) {
stroke(this.strokeColor.col);
} else {
noStroke();
}
strokeWeight(this.thickness);
ellipse(this.center.x, this.center.y, 2 * this.radius, 2 * this.radius);
// Optionally draw center point (pass disk's stroke color as default)
if (this.shouldShowCenter && this.center && this.center.draw) {
this.center.draw(this.strokeColor);
}
noStroke();
noFill();
strokeWeight(1);
}//end draw
/**
* Draws the disk in user (grid) coordinates using the given SWGrid
* @param {SWGrid} grid
*/
drawOnGrid(grid) {
const { x: cx, y: cy } = grid.userToScreen(this.center.x, this.center.y);
// Convert radius from user units to screen units (average scale)
const rx = grid.xScale * this.radius;
const ry = grid.yScale * this.radius;
const rScreen = (rx + ry) / 2;
if (this.fillColor && this.fillColor.col) {
fill(this.fillColor.col);
} else {
noFill();
}
if (this.strokeColor && this.strokeColor.col) {
stroke(this.strokeColor.col);
} else {
noStroke();
}
strokeWeight(this.thickness);
ellipse(cx, cy, 2 * rScreen, 2 * rScreen);
// Optionally draw center point (pass disk's stroke color as default)
if (this.shouldShowCenter && this.center && this.center.drawOnGrid) {
this.center.drawOnGrid(grid, this.strokeColor);
}
noStroke();
noFill();
strokeWeight(1);
}//end drawOnGrid
setShowCenter(show = true) {
this.shouldShowCenter = show;
}
breathe(sinusoid, t) {
this.radius = sinusoid.getValue(t);
this.area = Math.PI * this.radius * this.radius;
this.circumference = 2 * Math.PI * this.radius;
}
reset() {
this.radius = this.originalRadius;
this.area = Math.PI * this.radius * this.radius;
this.circumference = 2 * Math.PI * this.radius;
}//end reset
toString() {
return `SWDisk(center: ${this.center.toString()}, radius: ${this.radius}, thickness: ${this.thickness}, fillColor: ${this.fillColor ? this.fillColor.toString() : 'none'}, strokeColor: ${this.strokeColor ? this.strokeColor.toString() : 'none'}, area: ${this.area.toFixed(2)}, circumference: ${this.circumference.toFixed(2)})`;
}//end toString
setFillColor(swColor) {
// Always make a copy to avoid mutating shared color objects
this.fillColor = swColor ? SWColor.copy(swColor) : undefined;
this.updateCenterColor();
}//end setFillColor
resetFillColor() {
if (this.originalFillColor) {
this.fillColor = SWColor.copy(this.originalFillColor);
this.updateCenterColor();
}
}//end resetFillColor
setStrokeColor(swColor) {
this.strokeColor = swColor;
this.updateCenterColor();
}//end setStrokeColor
setStrokeWeight(w) {
this.thickness = w;
}//end setStrokeWeight
setRadius(r) {
//dwr! changing r, changes other dependent properties
this.radius = r;
this.area = Math.PI * r * r;
this.circumference = 2 * Math.PI * r;
}//end setRadius
setFillAlpha(alpha) {
if (this.fillColor) {
this.fillColor.a = Math.max(0, Math.min(100, alpha));
this.fillColor.col = color(this.fillColor.h, this.fillColor.s, this.fillColor.b, this.fillColor.a);
}
}//end setFillAlpha
setStrokeAlpha(alpha) {
if (this.strokeColor) {
this.strokeColor.a = Math.max(0, Math.min(100, alpha));
this.strokeColor.col = color(this.strokeColor.h, this.strokeColor.s, this.strokeColor.b, this.strokeColor.a);
this.updateCenterColor();
}
}//end setStrokeAlpha
containsPoint(x, y, grid) {
// Get disk center in screen coordinates
const { x: cx, y: cy } = grid.userToScreen(this.center.x, this.center.y);
// Convert radius from user units to screen units (average scale)
const rx = grid.xScale * this.radius;
const ry = grid.yScale * this.radius;
const rScreen = (rx + ry) / 2;
// Compute distance from (x, y) to center
const distSq = (x - cx) * (x - cx) + (y - cy) * (y - cy);
return distSq <= rScreen * rScreen;
}//end containsPoint
}//end class SWDisk