В основном я имею дело с 2D-массивами, которые составляют пиксели на сетке. 2D-массив состоит из чисел от 0 до 10, которые представляют цвет каждого пикселя. Число 0 означает, что пиксель не заполнен цветом, в то время как все числа от 1 до 10 означают, что пиксель заполнен цветом. Я пытаюсь выяснить, когда эти значения в массиве образуют прямоугольник, а затем получают координату левого верхнего угла [x1, y1] и координату нижнего правого угла [x2, y2] каждого отдельного прямоугольника.
Представление 2D-массива со значениями от 0 до 4 и окрашенными цветами каждого прямоугольника.
Вот желаемый результат координат, который я хотел бы получить:
Зеленый 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]
Код, который я использую:
Обратите внимание, что это получает только координаты прямоугольников со значением один. Как я могу заставить это работать и для других ценностей?
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.info(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;
}
}
}Получил код от: Найдите координаты всех прямоугольников смежных единиц в 2D-массиве в Javascript
Если бы кто-нибудь мог мне помочь с этим или предоставить какой-нибудь код, это было бы просто потрясающе !!!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я узнал, как это сделать, я использовал часть кода 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.info(greenRects);
console.info(redRects);
console.info(blueRects);
console.info(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();