Why set(...) doesn't clip

Why does set not clip x,y parameters that are off-screen in this example:

function setup() {
  createCanvas(512, 512);
  background(0);
  for (let i = 0, rs = 0; i < 65536; i++) {
    rs = (rs + 0x105d7152) & 0xffffffff;
    let sb = (rs ^ (rs << 18)) & 0x80000000;
    let bit = sb === 0 ? 0 : 1;
    let x=i & 255;
    let y=i>>8;
    x*=16;
    y*=16;
    if (bit === 1 && x<512 && y<512) {
      set(x, y, color("yellow"));
    }
  }
  updatePixels();
}

I was forced to manually put in clipping to avoid artifacts in the above additive subrandom code.

I have modified your code to make it clear whether the set method is being clipped or not.

In this code only yellow dots should appear. When the code is executed you see a mixture of yellow and red dots proving that the output is not being clipped. I suspect that this is a bug in p5js

function setup() {
    createCanvas(512, 512);
    background(0);
    for (let i = 0, rs = 0; i < 65536; i++) {
        rs = (rs + 0x105d7152) & 0xffffffff;
        let sb = (rs ^ (rs << 18)) & 0x80000000;
        let bit = sb === 0 ? 0 : 1;
        let x = i & 255;
        let y = i >> 8;
        x *= 16;
        y *= 16;
        if (bit === 1)
            if (x >= 0 && y >= 0 && x < 512 && y < 512)
                set(x, y, color("yellow"));
            else
                set(x, y, color("red"));  // should not be visible
    }
    updatePixels();
}
1 Like

Similarly you would not expect to see the red dots in a modern graphics library with this code:

function setup() {
  createCanvas(512, 512);
  background(0);
  for (let i = 0, rs = 0; i < 65536; i++) {
    rs = (rs + 0x105d7152) & 0xffffffff;
    let sb = (rs ^ (rs << 18)) & 0x80000000;
    let bit = sb === 0 ? 0 : 1;
    let x=i & 255;
    let y=i>>8;
    x*=16;
    y*=16;
    if (bit === 1) {
      set(x, y, color("yellow"));
      if(x>=512 | y>=512){
        set(x, y, color("red"));
      }
    }
  }
  updatePixels();
}

I was thinking of doing some blog posts with some embedded processing code.
I slightly worry about doing that now. Having said that I haven’t coded in a year and only know a limited amount of JS. I will try some more with p5.js, I hope it has not gone down hill since I last used it a year ago.

set differs in two respects to other colouring methods e.g. rect, ellipse etc.

  1. it only works in P2D mode
  2. it directly accesses and changes the value in the pixels array

The problem is that the pixel array is single dimension so for a graphic w pixels wide the index position for a pixel [x,y] is calculated using

index = x + y.w

I suspect that when x>w instead of clipping the point it continues and the point effectively wraps to the next line. Obviously a bug. If we use rect instead all is well - try this out

function setup() {
    createCanvas(512, 512);
    background(0);
    for (let i = 0, rs = 0; i < 65536; i++) {
        rs = (rs + 0x105d7152) & 0xffffffff;
        let sb = (rs ^ (rs << 18)) & 0x80000000;
        let bit = sb === 0 ? 0 : 1;
        let x = i & 255;
        let y = i >> 8;
        x *= 16;
        y *= 16;
        if (bit === 1) {
            fill(x >= 0 && y >= 0 && x < 512 && y < 512 ? color("yellow") : color("red"));
            rect(x, y, 2, 2);
        }
    }
}
2 Likes

Thanks, good solution. I remember there was always trouble using direct array access due to different monitor modes, especially if you wrote code on PC and someone tried to use it on a mac. I remember choosing to only use set to avoid that. Now it seems I have to go another level up to avoid trouble.
It could be an issue caused by some kind of chrome update I suppose, rather than a P5 thing.