【问题标题】:Find the coordinates of all rectangles in a 2D array查找二维数组中所有矩形的坐标
【发布时间】:2021-06-26 00:20:25
【问题描述】:

基本上我要处理的是一个二维数组,它构成了网格上的像素。二维数组由数字 0 到 10 组成,代表每个像素的颜色。数字 0 表示一个像素未填充颜色,而所有数字 1 到 10 表示一个像素已填充颜色。我想弄清楚的是,当数组中的这些值形成一个矩形,然后获取每个单独矩形的左上角坐标 [x1, y1] 和右下角坐标 [x2, y2] 时。

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].

这是我想要得到的坐标输出:

绿色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]

红色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]

蓝色 [3]:

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

紫色 [4]:

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

我使用的代码:

请注意,这只获取值为 1 的矩形的坐标。我怎样才能使它也适用于其他值?

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;
        }
    }
}

代码来自:Find the coordinates of all rectangles of contiguous 1s in a 2D array in Javascript

如果有人能帮我做这件事或提供一些代码,那真是太棒了!!!

【问题讨论】:

    标签: javascript arrays matrix multidimensional-array


    【解决方案1】:

    我发现了如何做到这一点,我在已经使用的代码之上使用了一些 StackSlave 的代码,并且必须为每个不同颜色的矩形创建一个函数。

    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();

    【讨论】:

      猜你喜欢
      • 2019-07-12
      • 1970-01-01
      • 1970-01-01
      • 2010-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多