Code viewer for World: Doodle like the images...
// Today in the class i was reminded of this video which i have watched years back: 
// https://www.youtube.com/watch?v=Hq8j5vsqCCo - Steve Jobs Video
// https://youtu.be/hqi0114mwtY?si=28TNQZ0BrdReyeDT
// Some useful references
// https://people.csail.mit.edu/sparis/bf_course/slides/02_gaussian_blur.pdf
// https://blog.elixxier.com/en/lighting-design-the-easy-way-secrets-of-inverse-square-law/


/* Note: If you draw slow enough, you are kinda able to mimic the dataset images...*/


const HEIGHT = 28 * 27; // Height of the grid 756
const WIDTH = 28 * 27; // Width of the grid 756

const ROWS = 28; // 28 rows in the grid
const COLS = 28; // 28 columns in the grid

const rectWidth = WIDTH / COLS; // Width of each grid block
const rectHeight = HEIGHT / ROWS; // Height of each grid block
let penWidth = 1.5; // Pen width .. it works good with this number... although you can play around with this..


class Spot {
    constructor(x, y, i, j) {
        this.x = x;
        this.y = y;
        this.i = i; // Column index 
        this.j = j; // Row index 
        this.intensity = 0; 
    }

    // Checks if the mouse is hovering over this spot
    // ref: https://editor.p5js.org/kjhollen/sketches/B_yKRLdj8
    isMouseOver() {
        return (
            mouseX > this.x &&
            mouseX < this.x + rectWidth &&
            mouseY > this.y &&
            mouseY < this.y + rectHeight
        );
    }

    // Draw the spot on the screen
    draw() {
        fill(0 + this.intensity);
        noStroke(); 
        rect(this.x, this.y, rectWidth, rectHeight); // Draw the spot on the screen...
    }

    // make the spot gradually darker based on its distance from the pen
    applyIntensity(distance) {
        
        
        
        // the brush was making the actual doodle also shaded.. 
        // so if the pixel (or spot) if part of doodle ... we just leave it white.. 
        // you can comment it and see what happens..
        if (this.intensity >= 255) {
            return;
        }
        
        let maxDist = penWidth * Math.sqrt(2); // Max distance for intensity falloff 
        let intensity = 255 * (1 - distance / maxDist); // Intensity decreases the further the spot is from the pen


        this.intensity += intensity;
        // keeping it between 0 and 255...
        if (this.intensity < 0) {
            this.intensity = 0; // Set it to 0 if it's less than 0
        } else if (this.intensity > 255) {
            this.intensity = 255; // Set it to 255 if it's greater than 255
        }
    }
}

class Grid {
    constructor(rows, cols) {
        this.rows = rows;
        this.cols = cols;
        this.spots = [];

        // Set up all the spots in the grid.. will be drawn later
        for (let i = 0; i < cols; i++) {
            for (let j = 0; j < rows; j++) {
                let x = i * rectWidth; // X position of this spot
                let y = j * rectHeight; // Y position of this spot
                this.spots.push(new Spot(x, y, i, j)); // Add the new spot to the grid
            }
        }
    }

    // Draw all the spots
    draw() {
        for (let spot of this.spots) {
            spot.draw(); // spot class draw.
        }
    }

    // This is where the "pen" effect happens. It goes through each spot and adjusts its intensity
    applyPen(x, y) {
        for (let spot of this.spots) {
            let distX = spot.i - x; // Get the distance between the pen's X position and the spot
            let distY = spot.j - y; // Get the distance between the pen's Y position and the spot
            let distance = Math.sqrt(distX * distX + distY * distY); // Calculate the total distance using Pythagoras

            // If the spot is within the pen's range..kinda like the brush area
            if (distance <= penWidth * 1.5) {
                spot.applyIntensity(distance); // Adjust the intensity for this spot based on the distance
            }
        }
    }
}

let grid; // This will hold the grid object


function setup() {
    createCanvas(WIDTH, HEIGHT); 
    grid = new Grid(ROWS, COLS); // Initialize the grid
}


function draw() {

    grid.draw(); // Draw the whole grid

    // If the mouse is being clicked... apply the pen effect
    if (mouseIsPressed) {
        let col = Math.floor(mouseX / rectWidth); // Find which column the mouse is over
        let row = Math.floor(mouseY / rectHeight); // Find which row the mouse is over

        // Only do this if the mouse is inside the grid
        if (col >= 0 && col < COLS && row >= 0 && row < ROWS) {
            grid.applyPen(col, row); // Apply the pen effect to the grid based on the mouse position
        }
    }
}