Javascript matrix check neighbor state to find edges

144 Views Asked by At

i am making a virtual Hama beads tool online. (its a kids toy where you put plastic beads on a matrix and iron them to make them stick together and form a solid shape)like this one below (real hama)

So far i managed to make this work (you can try it out there : https://static.club1.fr/alixturcq/hama%20dev/ ) but i would like to make it more elaborate and have the beads on the edges more realistic with round corners where there are no neighbors (virtual hama)

This would mean having a special image for each of theses neighbor cases like this (neighbor_cases)

So each bead is an object, and i have added a "neighbor" parameter to display the correct image.

Every object is automatically placed on the matrix at start but "isOn" is false, so nothing is displayed. When I click on the matrix, I change the 'isOn' boolean to true and the hama bead displays.

The objects are stored in a 1D array called hamas[], but are being displayed as a 2D array, so i can manipulate it as 2D.

class hama {
    constructor(isOn, posx, posy, color, neighbor) {
        this.posx = posx;
        this.posy = posy;
        this.color = color;
        this.isOn = isOn;
        this.neighbor = neighbor;
        this.variation = int(random(0,6));
        map
        
    }
    display() {

        if (this.isOn == true) {
            if (ironed == true) {
                image(hamas_img[this.color][this.neighbor], this.posx, this.posy, CELL_SIZE, CELL_SIZE);
            }
            else {
                image(ironed_hamas_img[this.color][this.neighbor], this.posx, this.posy, CELL_SIZE, CELL_SIZE);
            }
        }
    }
}

Every time I place a bead i need the program to check every objects if they are On, and also what is the 'isOn' state of each of the neighbors in the matrix.

So far I've done this in pseudo-code but I hope there are smarter ways.

// creating an array of neighbor indexes (clockwise around the object)

checkAround[(+1); (width+1); (width); (width-1); (-1); (-width-1); (-width); (-width+1)]

// creating an empty string that is going to be the neighbor code

neighborCode= "";

// check around object to get neighborstate
for (int i=0; i<checkAround.count; i++){
  
    if (hammas[hammaIndex+checkAround[i]].isOn==true){
        neighborCode += "O"
    }
    else {
       neighborCode += "X"

   }

}

Then I get neighbourCode strings looking like "XOOXOXOO" and map all these code to appropriate neighbour state number and display the correct image.

So this is rather twisted, I was hoping someone could help me find a smarter solution !

And also I have to find a way to avoid checking non existing indexes on the edges of the matrix, but this should not be to hard to find.

Thanks in advance

Al

1

There are 1 best solutions below

0
On

What you are looking for is edge detection on a pixel array and has been solved many times before. You can solve it yourself and it's fun to figure out yourself.

When a problem exists in 2D space, it often helps to think in 2D. But your data is structured in 1D (which is fine, and the convention)

Each pixel/bead has a position in the 1D array -let's call that i- and a position in 2D space, defined by x and y.

The relationship between those is like this: i = x + y * w ( Where w is the width of the image)

With this information you can traverse the 1D array through x and y quite easily and decide for each pixel what its neighbours are doing.

example:

for(var x = 0; x < width; x++){
    for(var y = 0; y < height; y++){
       var i = x + y * width; // id of the current pixel being checked.
       // Calculate neighbour ids:
       var iNorth = x + (y - 1) * width;
       var iSouth = x + (y + 1) * width;
       var iEast = x + 1 + y * width;
       var iWest = x - 1 + y * width;
       var iNorthWest = (x - 1) + (y - 1) * width; // haha Kanye
       // etc.. you get the point
       
       // Now encode all those vars in one single byte
       // Use that byte to choose the right image for the bead at position I
       // Don't forget to deal with your edge cases

    }
}

You can optimize later. (eg. You don't have to update the whole image each time you change one pixel, only its neighbors are affected.)

Your "OXOOXOOO" string is a perfectly acceptable way of storing the different states of a bead. A more nerdy approach would be to just store bits in a 8 bit byte.(because each pixel has only 8 neighbours..) Those bytes can be stored in a buffer with the same exact structure as your actual pixel data.

I think this should get you started without spoiling too much of the fun?