1

Basically what I'm dealing with is a 2D arrays that make up the pixels on grid. The 2D array consists of the numbers 0 through 10 which represents what color each pixel is. The number 0 represents that a pixel is not filled with a color, while all the numbers 1 though 10 represent that a pixel is filled with a color. What I'm trying to figure out is when these values within the array makes a rectangle and then getting the upper left hand coordinate [x1, y1] and lower right hand coordinate[x2, y2] of each separate rectangle.

A representation of the 2D array with it's values ranging from 0 to 4, and each rectangle color coated.

A representation of the points on each rectangle that I would like to get the coordinates of. With brown representing [x1, y1] and pink representing [x2, y2].

Here is the desired output of coordinates that I would like to get:

Green 1:

1: [x1: 0] [y1: 0] [x2: 4] [y2: 2]

2: [x1: 0] [y1: 3] [x2: 2] [y2: 5]

3: [x1: 3] [y1: 5] [x2: 7] [y2: 5]

4: [x1: 10] [y1: 7] [x2: 12] [y2: 10]

5:[x1: 6] [y1: 13] [x2: 8] [y1: 15]

Red 2:

1: [x1: 5] [y1: 0] [x2: 7] [y2: 2]

2: [x1: 10] [y1: 4] [x2: 15] [y2: 6]

3: [x1: 13 ] [y1: 7] [x2: 15] [y2: 10]

4: [x1: 1] [y1: 10] [x2: 5] [y2: 15]

Blue [3]:

1: [x1: 3] [y1: 3] [x2: 7] [y2: 4]

Purple [4]:

1: [x1: 14] [y1: 0] [x2: 15] [y2: 1]

Code that I use:

Note that this only gets the coordinates of rectangles with a value of one. How can I make this work for the other values as well?

const array = [
    [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //0
    [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //1
    [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0], //2
    [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], //3
    [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 2, 2, 2, 2, 2, 2], //4
    [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2], //5
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2], //6
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //7
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //8
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //9
    [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //10
    [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //11
    [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //12
    [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //13
    [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //14
    [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]  //15
];

const W = array[0].length;
const H = array.length;

// get the area covered by rectangles
let totalRectArea = 0;
for (let i = 0; i < W; ++i) {
    for (let j = 0; j < H; ++j) {
        totalRectArea += array[j][i] > 0 ? 1 : 0;
    }
}

const rects = [];
let rectArea = 0;

// find all rectangle until their area matches the total
while (rectArea < totalRectArea) {
    const rect = findNextRect();
    rects.push(rect);
    markRect(rect);
    rectArea += (rect.x2 - rect.x1 + 1) * (rect.y2 - rect.y1 + 1);
}

console.log(rects);

function findNextRect() {
    // find top left corner
    let foundCorner = false;
    const rect = { x1: 0, x2: W - 1, y1: 0, y2: H - 1 };
    for (let i = 0; i < W; ++i) {
        for (let j = 0; j < H; ++j) {
            if (array[j][i] === 1) {
                rect.x1 = i;
                rect.y1 = j;
                foundCorner = true;
                break;
            }
        }
        if (foundCorner) break;
    }
    // find bottom right corner
    for (let i = rect.x1; i <= rect.x2; ++i) {
        if (array[rect.y1][i] !== 1) {
            rect.x2 = i - 1;
            return rect;
        }
        for (let j = rect.y1; j <= rect.y2; ++j) {
            if (array[j][i] !== 1) {
                rect.y2 = j - 1;
                break;
            }
        }
    }
    return rect;
}

// mark rectangle so won't be counted again
function markRect({ x1, y1, x2, y2 }) {
    for (let i = x1; i <= x2; ++i) {
        for (let j = y1; j <= y2; ++j) {
            array[j][i] = 2;
        }
    }
}

Got the code from: Find the coordinates of all rectangles of contiguous 1s in a 2D array in Javascript

If anyone can help me with doing this or supply some code, that would be absolutely amazing!!!

1 Answers1

0

I found out how to do it, I used some of StackSlave's code on top of the code I was already using and had to create a function for every differently colored rectangle.

function test(){
    array = [
        [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //0
        [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //1
        [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0], //2
        [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], //3
        [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 2, 2, 2, 2, 2, 2], //4
        [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2], //5
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2], //6
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //7
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //8
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //9
        [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //10
        [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //11
        [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //12
        [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //13
        [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //14
        [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0]  //15
];

     W = array[0].length;
     H = array.length;
     green = []
     red = []
     blue = []
     purple = []

    // get the area covered by rectangles
     greenTotalRectArea = 0;
     redTotalRectArea = 0;
    blueTotalRectArea = 0;
    purpleTotalRectArea = 0;

    for (let i = 0, a, l = array.length; i < l; i++) {
        a = array[i];
        for (let n = 0, q = a.length; n < q; n++) {
            switch (a[n]) {
                case 1:
                    green.push(n);
                    greenTotalRectArea = green.length;
                    break;
                case 2:
                    red.push(n);
                    redTotalRectArea = red.length;
                    break;
                case 3:
                    blue.push(n);
                    blueTotalRectArea = blue.length;
                    break;
                case 4:
                    purple.push(n);
                    purpleTotalRectArea = purple.length;
                    break;
                }       
            }
       }
    greenRects = [];
    greenRectArea = 0;
    while (greenRectArea < greenTotalRectArea) {
        const greenRect = findGreenRect();
        greenRects.push(greenRect);
        markRect(greenRect);
        greenRectArea += (greenRect.x2 - greenRect.x1 + 1) * (greenRect.y2 - greenRect.y1 + 1);
}
    redRects = [];
    redRectArea = 0;
    while (redRectArea < redTotalRectArea) {
        const redRect = findRedRect();
        redRects.push(redRect);
        markRect(redRect);
        redRectArea += (redRect.x2 - redRect.x1 + 1) * (redRect.y2 - redRect.y1 + 1);
    }
    blueRects = [];
    blueRectArea = 0;
    while (blueRectArea < blueTotalRectArea) {
        const blueRect = findBlueRect();
        blueRects.push(blueRect);
        markRect(blueRect);
        blueRectArea += (blueRect.x2 - blueRect.x1 + 1) * (blueRect.y2 - blueRect.y1 + 1);
    }
    purpleRects = [];
    purpleRectArea = 0;
    while (purpleRectArea < purpleTotalRectArea) {
        const purpleRect = findPurpleRect();
        purpleRects.push(purpleRect);
        markRect(purpleRect);
        purpleRectArea += (purpleRect.x2 - purpleRect.x1 + 1) * (purpleRect.y2 - purpleRect.y1 + 1);
    }
    console.log(greenRects);
    console.log(redRects);
    console.log(blueRects);
    console.log(purpleRects);
}
    function findGreenRect() {
        // find top left corner
        let foundGreenCorner = false;
        const greenRect = { x1: 0, x2: W - 1, y1: 0, y2: H - 1 };
        for (let i = 0; i < W; ++i) {
            for (let j = 0; j < H; ++j) {
                if (array[j][i] === 1) {
                    greenRect.x1 = i;
                    greenRect.y1 = j;
                    foundGreenCorner = true;
                    break;
                }           
            }
            if (foundGreenCorner) break;
        }
        // find bottom right corner
        for (let i = greenRect.x1; i <= greenRect.x2; ++i) {
            if (array[greenRect.y1][i] !== 1) {
                greenRect.x2 = i - 1;
                return greenRect;
            }           
            for (let j = greenRect.y1; j <= greenRect.y2; ++j) {
                if (array[j][i] !== 1) {
                    greenRect.y2 = j - 1;
                    break;
                }               
            }
        }
        return greenRect;
    }
function findRedRect() {
    // find top left corner
    let foundRedCorner = false;
    const redRect = { x1: 0, x2: W - 1, y1: 0, y2: H - 1 };
    for (let i = 0; i < W; ++i) {
        for (let j = 0; j < H; ++j) {
            if (array[j][i] === 2) {
                redRect.x1 = i;
                redRect.y1 = j;
                foundRedCorner = true;
                break;
            }
        }
        if (foundRedCorner) break;
    }
    // find bottom right corner
    for (let i = redRect.x1; i <= redRect.x2; ++i) {
        if (array[redRect.y1][i] !== 2) {
            redRect.x2 = i - 1;
            return redRect;
        }
        for (let j = redRect.y1; j <= redRect.y2; ++j) {
            if (array[j][i] !== 2) {
                redRect.y2 = j - 1;
                break;
            }
        }
    }
    return redRect;
}
function findBlueRect() {
    // find top left corner
    let foundBlueCorner = false;
    const blueRect = { x1: 0, x2: W - 1, y1: 0, y2: H - 1 };
    for (let i = 0; i < W; ++i) {
        for (let j = 0; j < H; ++j) {
            if (array[j][i] === 3) {
                blueRect.x1 = i;
                blueRect.y1 = j;
                foundBlueCorner = true;
                break;
            }
        }
        if (foundBlueCorner) break;
    }
    // find bottom right corner
    for (let i = blueRect.x1; i <= blueRect.x2; ++i) {
        if (array[blueRect.y1][i] !== 3) {
            blueRect.x2 = i - 1;
            return blueRect;
        }
        for (let j = blueRect.y1; j <= blueRect.y2; ++j) {
            if (array[j][i] !== 3) {
                blueRect.y2 = j - 1;
                break;
            }
        }
    }
    return blueRect;
}
function findPurpleRect() {
    // find top left corner
    let foundPurpleCorner = false;
    const purpleRect = { x1: 0, x2: W - 1, y1: 0, y2: H - 1 };
    for (let i = 0; i < W; ++i) {
        for (let j = 0; j < H; ++j) {
            if (array[j][i] === 4) {
                purpleRect.x1 = i;
                purpleRect.y1 = j;
                foundPurpleCorner = true;
                break;
            }
        }
        if (foundPurpleCorner) break;
    }
    // find bottom right corner
    for (let i = purpleRect.x1; i <= purpleRect.x2; ++i) {
        if (array[purpleRect.y1][i] !== 4) {
            purpleRect.x2 = i - 1;
            return purpleRect;
        }
        for (let j = purpleRect.y1; j <= purpleRect.y2; ++j) {
            if (array[j][i] !== 4) {
                purpleRect.y2 = j - 1;
                break;
            }
        }
    }
    return purpleRect;
}
    // mark rectangle so won't be counted again
    function markRect({ x1, y1, x2, y2 }) {
        for (let i = x1; i <= x2; ++i) {
            for (let j = y1; j <= y2; ++j) {
                array[j][i] = 99;
            }
        }
    }
test();