Как я могу получить окончательный размер бина с помощью алгоритма упаковки бина растущего javascript?
Используя этот 2-й алгоритм упаковки бинов (EDIT: Fixed demo), который является вариацией этого, как я могу получить окончательную ширину бина и высоту каждого бина?
Мой демонстрационный код выглядит следующим образом:
var blocks = [
{w: 1000, h: 800},
{w: 500, h: 700},
{w: 500, h: 700},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 500, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350},
{w: 250, h: 350}
];
var sheets = [];
while(blocks.length) {
var packer = new GrowingPacker(1000,800);
packer.fit(blocks);
sheet = [];
for (var i=blocks.length-1; i>=0; i--) {
if (blocks[i].fit !== undefined && blocks[i].fit !== null) {
//console.log(blocks[i].fit);
sheet.unshift(blocks[i]);
blocks.splice(i,1);
}
}
//console.log(sheet[sheet.length-1].fit.y + sheet[sheet.length-1].h);
//console.log(sheet);
sheets.push(sheet);
}
for(var i=0; i<sheets.length; i++) {
var sheet = sheets[i];
var sheetWidth = sheet[sheet.length-1].w + sheet[sheet.length-1].fit.x;
var sheetHeight = sheet[sheet.length-1].h + sheet[sheet.length-1].fit.y;
for(var j=0; j<sheet.length; j++) {
console.log("SHEET #" + i + " - W: " + sheetWidth + " H: " + sheetHeight + " BLOCK #" + j + " - W: " + sheet[j].w + " H: " + sheet[j].h + " X: " + sheet[j].fit.x + " Y: " + sheet[j].fit.y);
}
}
Оригинальный алгоритм имеет дело только с одним постоянно расширяющимся мусорным баком, поэтому я изменил его, чтобы получить максимальную ширину и высоту. Затем я пробегаю массив блоков, вызываю упаковщик, помещаю блоки подгонки в новый массив и сбрасываю их из "блоков", пока "блоки" не станут пустыми. Был ли это лучший подход - это вопрос другого вопроса.
Во всяком случае, я попытался изменить growNode так:
growNode: function(w, h) {
var canGrowRight = (w <= this.root.w && this.root.w + w <= maxW);
var canGrowDown = (h <= this.root.h && this.root.h + h <= maxH);
if (canGrowRight) {
this.sheetW = this.root.w + w; //<--------------added
return this.growRight(w, h);
}
else if (canGrowDown) {
this.sheetH = this.root.h + h; //<--------------added
return this.growDown(w, h);
}
else
return null; // need to ensure sensible root starting size to avoid this happening
},
который работает для каждого листа, но первый. Я попытался добавить эти строки в несколько других методов, но безуспешно. Я также попытался получить размер листа из последнего блока по ширине листа + x, но это работает, только если лист заполнен.
Мой вопрос снова: как я могу получить окончательный размер листа для каждого листа?
2 ответа
В конце концов я понял это. Я добавил две строки для findNode()
findNode: function(root, w, h) {
if (root.used) {
return this.findNode(root.right, w, h) || this.findNode(root.down, w, h);
}
else if ((w <= root.w && w <= this.maxW) && (h <= root.h && w <= this.maxW)) {
this.binWidth = this.root.w <= this.maxW ? this.root.w : this.maxW;
this.binHeight = this.root.h <= this.maxH ? this.root.h : this.maxH;
return root;
}
else {
return null;
}
},
Вот jsfiddle, если вы хотите поиграть с ним. Я рекомендую попробовать что-то вроде этого для ввода:
100x80
50x70
50x35x2
25x35x4
Вы можете использовать растущий алгоритм и увеличить корзину слева или справа: http://codeincomplete.com/posts/2011/5/7/bin_packing.