├── README.md ├── index.html └── pack1.js /README.md: -------------------------------------------------------------------------------- 1 | # 3dbinpackingjs 2 | javascript conversion of https://github.com/wknechtel/3d-bin-pack/ 3 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Packaging Script from C 6 | 7 | 8 |
9 |
10 |

Boxes

11 |
12 |
13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 |
21 |
22 | 23 | 24 | 25 | 26 |
27 |
28 |
29 |
Report
30 | 31 |
32 | 33 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /pack1.js: -------------------------------------------------------------------------------- 1 | /* Original File 2 | https://raw.githubusercontent.com/wknechtel/3d-bin-pack/master/src/binpack.c 3 | 4 | */ 5 | 6 | var initialize = function(){}, 7 | inputboxlist = function(){}, 8 | execiterations = function(){}, 9 | listcanditlayers = function(){}, 10 | complayerlist = function(i, j){}, 11 | packlayer = function(){}, 12 | findlayer = function(thickness){}, 13 | findbox = function(hmx, hy, hmy, hz, hmz){}, 14 | analyzebox = function(hmx, hy, hmy, hz, hmz, dim1, dim2, dim3){}, 15 | findsmallestz = function(){}, 16 | checkfound = function(){}, 17 | volumecheck = function(){}, 18 | graphunpackedout = function(){}, 19 | outputboxlist = function(){}, 20 | report = function(){}, 21 | 22 | //******************************************************** 23 | // VARIABLE, CONSTANT AND STRUCTURE DECLARATIONS 24 | //******************************************************** 25 | 26 | strpx = '', 27 | strpy = '', 28 | strpz = '', 29 | strcox = '', 30 | strcoy = '', 31 | strcoz = '', 32 | strpackx = '', 33 | strpacky = '', 34 | strpackz = '', 35 | filename = '', 36 | strtemp = '', 37 | packing = '', 38 | layerdone = '', 39 | evened = '', 40 | variant = '', 41 | bestvariant = '', 42 | packingbest = '', 43 | hundredpercent = '', 44 | graphout = "visudat", 45 | unpacked = '', 46 | quit = '', 47 | 48 | boxx, boxy, boxz, boxi, 49 | bboxx, bboxy, bboxz, bboxi, 50 | cboxx, cboxy, cboxz, cboxi, 51 | bfx, bfy, bfz, 52 | bbfx, bbfy, bbfz, 53 | xx, yy, zz, 54 | px, py, pz, 55 | tbn, 56 | x, 57 | n, 58 | layerlistlen, 59 | layerinlayer, 60 | prelayer, 61 | lilz, 62 | itenum, 63 | hour, 64 | min, 65 | sec, 66 | layersindex, 67 | remainpx, remainpy, remainpz, 68 | packedy, 69 | prepackedy, 70 | layerthickness, 71 | itelayer, 72 | preremainpy, 73 | bestite, 74 | packednumbox, 75 | bestpackednum, 76 | 77 | packedvolume, 78 | bestvolume, 79 | totalvolume, 80 | totalboxvol, 81 | temp, 82 | percentageused, 83 | percentagepackedbox, 84 | elapsedtime; 85 | 86 | function boxinfo(){ 87 | this.packst = null; 88 | this.dim1 = null; 89 | this.dim2 = null; 90 | this.dim3 = null; 91 | this.n = null; 92 | this.cox = null; 93 | this.coy = null; 94 | this.coz = null; 95 | this.packx = null; 96 | this.packy = null; 97 | this.packz = null; 98 | this.vol = null; 99 | }; 100 | 101 | var boxlist = new Array(); 102 | boxlist[0] = new boxinfo(); 103 | 104 | function layerlist(){ 105 | this.layereval = ""; 106 | this.layerdim = ""; 107 | }; 108 | var layers = new Array(); 109 | 110 | function scrappad(){ 111 | this.pre = ""; 112 | this.pos = ""; 113 | this.cumx = ""; 114 | this.cumz = ""; 115 | }; 116 | 117 | var scrapfirst, scrapmemb, smallestz, trash; 118 | 119 | var start, finish; 120 | 121 | var ifp, gfp; 122 | 123 | 124 | /* 125 | Compability functions for converting from C to Javascript by Can Bayraktar 126 | */ 127 | // Console replacement (also console.log can be used) 128 | var sc = document.getElementById('screen'); 129 | var printf = function(){ 130 | for(i = 0; i < arguments.length; i+=1){ 131 | sc.innerHTML += arguments[i] + ' '; 132 | } 133 | sc.innerHTML += '\n'; 134 | } 135 | 136 | // Ascii to integer 137 | var atoi = function(a){ return (+a); }; 138 | 139 | // Quick Sort 140 | var swap = function(items, firstIndex, secondIndex){ 141 | var temp = items[firstIndex]; 142 | items[firstIndex] = items[secondIndex]; 143 | items[secondIndex] = temp; 144 | } 145 | var partition = function(items, left, right) { 146 | var pivot = items[Math.floor((right + left) / 2)].layereval, 147 | i = left, 148 | j = right; 149 | while (i <= j) { 150 | while (items[i].layereval < pivot) { i++; } 151 | while (items[j].layereval > pivot) { j--; } 152 | if (i <= j) { 153 | swap(items, i, j); 154 | i++; 155 | j--; 156 | } 157 | } 158 | return i; 159 | } 160 | var qsort = function(items, left, right) { 161 | var index; 162 | if (items.length > 1) { 163 | left = typeof left != "number" ? 0 : left; 164 | right = typeof right != "number" ? items.length - 1 : right; 165 | index = partition(items, left, right); 166 | if (left < index - 1) { 167 | qsort(items, left, index - 1); 168 | } 169 | if (index < right) { 170 | qsort(items, index, right); 171 | } 172 | } 173 | return items; 174 | } 175 | 176 | 177 | //******************************************************** 178 | // MAIN PROGRAM 179 | //******************************************************** 180 | 181 | function main(){ 182 | initialize(); console.log("initialized."); 183 | execiterations(); console.log("execiterations done."); 184 | report(); console.log("report printed."); 185 | return 0; 186 | } 187 | 188 | //******************************************************** 189 | // PERFORMS INITIALIZATIONS 190 | //******************************************************** 191 | 192 | var initialize = function(){ 193 | inputboxlist(); 194 | 195 | temp = 1.0; 196 | totalvolume = temp * xx * yy * zz; 197 | 198 | totalboxvol = 0.0; 199 | for (x=1; x <= tbn; x++) { 200 | totalboxvol = totalboxvol + boxlist[x].vol; 201 | } 202 | 203 | scrapfirst = new scrappad(); 204 | 205 | scrapfirst.pre = null; 206 | scrapfirst.pos = null; 207 | bestvolume = 0.0; 208 | packingbest = 0; 209 | hundredpercent = 0; 210 | itenum = 0; 211 | quit = 0; 212 | } 213 | 214 | 215 | //********************************************************************** 216 | // READS THE PALLET AND BOX SET DATA ENTERED BY THE USER FROM 217 | // THE INPUT FILE 218 | //********************************************************************** 219 | 220 | var inputboxlist = function(){ 221 | var n, 222 | lbl = "", 223 | dim1 = "", 224 | dim2 = "", 225 | dim3 = "", 226 | boxn = "", 227 | strxx = "", 228 | stryy = "", 229 | strzz = ""; 230 | 231 | tbn = 1; 232 | 233 | strxx = document.getElementById("strxx").value; 234 | stryy = document.getElementById("stryy").value; 235 | strzz = document.getElementById("strzz").value; 236 | 237 | xx = atoi(strxx); 238 | yy = atoi(stryy); 239 | zz = atoi(strzz); 240 | 241 | var bi = document.getElementsByClassName('box-inputs'); 242 | 243 | for(i = 0; i < bi.length; i+=1){ 244 | boxlist[tbn] = new boxinfo(); 245 | boxlist[tbn].dim1 = atoi(bi[i].children.dim1.value); 246 | boxlist[tbn].dim2 = atoi(bi[i].children.dim2.value); 247 | boxlist[tbn].dim3 = atoi(bi[i].children.dim3.value); 248 | 249 | boxlist[tbn].vol = boxlist[tbn].dim1 * boxlist[tbn].dim2 * boxlist[tbn].dim3; 250 | n = atoi(bi[i].children.boxn.value); 251 | boxlist[tbn].n = n; 252 | 253 | for(j = 1; j < n; j+=1){ 254 | boxlist[tbn+j] = Object.create(boxlist[tbn]); 255 | } 256 | tbn += n; 257 | } 258 | boxlist[tbn] = new boxinfo(); 259 | --tbn; 260 | return; 261 | } 262 | 263 | //********************************************************************** 264 | // ITERATIONS ARE DONE AND PARAMETERS OF THE BEST SOLUTION ARE 265 | // FOUND 266 | //********************************************************************** 267 | 268 | var execiterations = function(){ 269 | 270 | for (variant = 1; (variant <= 6) && !quit; variant++) { 271 | 272 | switch(variant){ 273 | case 1: 274 | px=xx; py=yy; pz=zz; 275 | break; 276 | case 2: 277 | px=zz; py=yy; pz=xx; 278 | break; 279 | case 3: 280 | px=zz; py=xx; pz=yy; 281 | break; 282 | case 4: 283 | px=yy; py=xx; pz=zz; 284 | break; 285 | case 5: 286 | px=xx; py=zz; pz=yy; 287 | break; 288 | case 6: 289 | px=yy; py=zz; pz=xx; 290 | break; 291 | } 292 | 293 | listcanditlayers(); 294 | layers[0] = new layerlist(); 295 | layers[0].layereval = -1; 296 | qsort(layers); 297 | 298 | for (layersindex = 1; (layersindex <= layerlistlen) && !quit; layersindex++) { 299 | ++itenum; 300 | 301 | 302 | printf("VARIANT: "+variant+"; ITERATION (TOTAL): "+itenum+"; BEST SO FAR: "+percentageused+" %%;"); 303 | packedvolume = 0.0; 304 | packedy = 0; 305 | packing = 1; 306 | layerthickness = layers[layersindex].layerdim; 307 | itelayer = layersindex; 308 | remainpy = py; 309 | remainpz = pz; 310 | packednumbox = 0; 311 | 312 | for (x = 1; x <= tbn; x++) 313 | { 314 | boxlist[x].packst=0; 315 | } 316 | 317 | //BEGIN DO-WHILE 318 | do { 319 | layerinlayer = 0; 320 | layerdone = 0; 321 | 322 | if (packlayer()) { exit(1); } 323 | 324 | packedy = packedy + layerthickness; 325 | remainpy = py - packedy; 326 | 327 | if (layerinlayer && !quit) { 328 | 329 | prepackedy = packedy; 330 | preremainpy = remainpy; 331 | remainpy = layerthickness - prelayer; 332 | packedy = packedy - layerthickness + prelayer; 333 | remainpz = lilz; 334 | layerthickness = layerinlayer; 335 | layerdone = 0; 336 | 337 | if (packlayer()) { exit( 1); } 338 | 339 | packedy = prepackedy; 340 | remainpy = preremainpy; 341 | remainpz = pz; 342 | } 343 | findlayer(remainpy); 344 | 345 | } while (packing && !quit); 346 | // END DO-WHILE 347 | 348 | if ((packedvolume > bestvolume) && !quit) { 349 | bestvolume = packedvolume; 350 | bestvariant = variant; 351 | bestite = itelayer; 352 | bestpackednum = packednumbox; 353 | } 354 | 355 | if (hundredpercent) break; 356 | 357 | percentageused = bestvolume * 100 / totalvolume; 358 | } 359 | if (hundredpercent) break; 360 | if ((xx == yy) && (yy == zz)) variant = 6; 361 | } 362 | } 363 | 364 | //********************************************************************** 365 | // LISTS ALL POSSIBLE LAYER HEIGHTS BY GIVING A WEIGHT VALUE TO 366 | // EACH OF THEM. 367 | //********************************************************************** 368 | var listcanditlayers = function(){ 369 | var same, 370 | exdim, dimdif, dimen2, dimen3, y, z, k, 371 | layereval; 372 | 373 | layerlistlen = 0; 374 | 375 | for (x = 1; x <= tbn; x++){ 376 | for(y = 1; y <= 3; y++){ 377 | switch(y){ 378 | case 1: 379 | exdim = boxlist[x].dim1; 380 | dimen2 = boxlist[x].dim2; 381 | dimen3 = boxlist[x].dim3; 382 | break; 383 | case 2: 384 | exdim = boxlist[x].dim2; 385 | dimen2 = boxlist[x].dim1; 386 | dimen3 = boxlist[x].dim3; 387 | break; 388 | case 3: 389 | exdim = boxlist[x].dim3; 390 | dimen2 = boxlist[x].dim1; 391 | dimen3 = boxlist[x].dim2; 392 | break; 393 | } 394 | if ((exdim > py) || (((dimen2 > px) || (dimen3 > pz)) && ((dimen3 > px) || (dimen2 > pz)))) continue; 395 | same = 0; 396 | 397 | for (k = 1; k <= layerlistlen; k++){ 398 | if (exdim == layers[k].layerdim){ 399 | same = 1; 400 | continue; 401 | } 402 | } 403 | if (same) continue; 404 | layereval = 0; 405 | 406 | for (z = 1; z <= tbn; z++){ 407 | if(!(x == z)){ 408 | dimdif = Math.abs(exdim - boxlist[z].dim1); 409 | 410 | if ( Math.abs(exdim - boxlist[z].dim2) < dimdif ){ 411 | dimdif = Math.abs(exdim - boxlist[z].dim2); 412 | } 413 | if ( Math.abs(exdim - boxlist[z].dim3) < dimdif ){ 414 | dimdif = Math.abs(exdim - boxlist[z].dim3); 415 | } 416 | layereval = layereval + dimdif; 417 | } 418 | } 419 | layers[++layerlistlen] = new layerlist(); 420 | layers[layerlistlen].layereval = layereval; 421 | layers[layerlistlen].layerdim = exdim; 422 | } 423 | } 424 | return; 425 | } 426 | 427 | //********************************************************************** 428 | // PACKS THE BOXES FOUND AND ARRANGES ALL VARIABLES AND 429 | // RECORDS PROPERLY 430 | //********************************************************************** 431 | 432 | var packlayer = function(){ 433 | var lenx, lenz, lpz; 434 | 435 | if (!layerthickness){ 436 | packing = 0; 437 | return 0; 438 | } 439 | 440 | scrapfirst.cumx = px; 441 | scrapfirst.cumz = 0; 442 | 443 | for(;!quit;){ 444 | 445 | findsmallestz(); 446 | 447 | if (!(smallestz.pre) && !(smallestz.pos) ){ 448 | //*** SITUATION-1: NO BOXES ON THE RIGHT AND LEFT SIDES *** 449 | 450 | lenx = smallestz.cumx; 451 | lpz = remainpz - smallestz.cumz; 452 | findbox(lenx, layerthickness, remainpy, lpz, lpz); 453 | checkfound(); 454 | 455 | if (layerdone) break; 456 | if (evened) continue; 457 | 458 | boxlist[cboxi].cox = 0; 459 | boxlist[cboxi].coy = packedy; 460 | boxlist[cboxi].coz = smallestz.cumz; 461 | if (cboxx == smallestz.cumx){ 462 | smallestz.cumz = smallestz.cumz + cboxz; 463 | } else { 464 | smallestz.pos = new scrappad(); 465 | 466 | smallestz.pos.pos = null; 467 | smallestz.pos.pre = smallestz; 468 | smallestz.pos.cumx = smallestz.cumx; 469 | smallestz.pos.cumz = smallestz.cumz; 470 | smallestz.cumx = cboxx; 471 | smallestz.cumz = smallestz.cumz + cboxz; 472 | } 473 | volumecheck(); 474 | } else if (!(smallestz.pre) ) { 475 | //*** SITUATION-2: NO BOXES ON THE LEFT SIDE *** 476 | 477 | lenx = smallestz.cumx; 478 | lenz = smallestz.pos.cumz - smallestz.cumz; 479 | lpz = remainpz - smallestz.cumz; 480 | findbox(lenx, layerthickness, remainpy, lenz, lpz); 481 | checkfound(); 482 | 483 | if (layerdone) break; 484 | if (evened) continue; 485 | 486 | boxlist[cboxi].coy = packedy; 487 | boxlist[cboxi].coz = smallestz.cumz; 488 | if (cboxx == smallestz.cumx){ 489 | 490 | boxlist[cboxi].cox = 0; 491 | if ( smallestz.cumz + cboxz == smallestz.pos.cumz ) { 492 | smallestz.cumz = smallestz.pos.cumz; 493 | smallestz.cumx = smallestz.pos.cumx; 494 | trash = smallestz.pos; 495 | smallestz.pos = smallestz.pos.pos; 496 | 497 | if (smallestz.pos) { 498 | smallestz.pos.pre = smallestz; 499 | } 500 | } else { 501 | smallestz.cumz = smallestz.cumz + cboxz; 502 | } 503 | } else { 504 | boxlist[cboxi].cox = smallestz.cumx - cboxx; 505 | if ( smallestz.cumz + cboxz == smallestz.pos.cumz ) { 506 | smallestz.cumx = smallestz.cumx - cboxx; 507 | } else { 508 | smallestz.pos.pre = new scrappad(); 509 | 510 | smallestz.pos.pre.pos = smallestz.pos; 511 | smallestz.pos.pre.pre = smallestz; 512 | smallestz.pos = smallestz.pos.pre; 513 | smallestz.pos.cumx = smallestz.cumx; 514 | smallestz.cumx = smallestz.cumx - cboxx; 515 | smallestz.pos.cumz = smallestz.cumz + cboxz; 516 | } 517 | } 518 | volumecheck(); 519 | } else if (!smallestz.pos) { 520 | //*** SITUATION-3: NO BOXES ON THE RIGHT SIDE *** 521 | 522 | lenx = smallestz.cumx - smallestz.pre.cumx; 523 | lenz = smallestz.pre.cumz - smallestz.cumz; 524 | lpz = remainpz - smallestz.cumz; 525 | findbox(lenx, layerthickness, remainpy, lenz, lpz); 526 | checkfound(); 527 | 528 | if (layerdone) break; 529 | if (evened) continue; 530 | 531 | boxlist[cboxi].coy = packedy; 532 | boxlist[cboxi].coz = smallestz.cumz; 533 | boxlist[cboxi].cox = smallestz.pre.cumx; 534 | 535 | if (cboxx == smallestz.cumx - smallestz.pre.cumx) { 536 | 537 | if ( smallestz.cumz + cboxz == smallestz.pre.cumz ) { 538 | smallestz.pre.cumx = smallestz.cumx; 539 | smallestz.pre.pos = null; 540 | } else { 541 | smallestz.cumz = smallestz.cumz + cboxz; 542 | } 543 | } else { 544 | if ( smallestz.cumz + cboxz == smallestz.pre.cumz ) { 545 | smallestz.pre.cumx = smallestz.pre.cumx + cboxx; 546 | } else { 547 | smallestz.pre.pos = new scrappad(); 548 | 549 | smallestz.pre.pos.pre = smallestz.pre; 550 | smallestz.pre.pos.pos = smallestz; 551 | smallestz.pre = smallestz.pre.pos; 552 | smallestz.pre.cumx = smallestz.pre.pre.cumx + cboxx; 553 | smallestz.pre.cumz = smallestz.cumz + cboxz; 554 | } 555 | } 556 | volumecheck(); 557 | 558 | } else if ( smallestz.pre.cumz == smallestz.pos.cumz ) { 559 | //*** SITUATION-4: THERE ARE BOXES ON BOTH OF THE SIDES *** 560 | 561 | //*** SUBSITUATION-4A: SIDES ARE EQUAL TO EACH OTHER *** 562 | 563 | lenx = smallestz.cumx - smallestz.pre.cumx; 564 | lenz = smallestz.pre.cumz - smallestz.cumz; 565 | lpz = remainpz - smallestz.cumz; 566 | 567 | findbox(lenx, layerthickness, remainpy, lenz, lpz); 568 | checkfound(); 569 | 570 | if (layerdone) break; 571 | if (evened) continue; 572 | 573 | boxlist[cboxi].coy = packedy; 574 | boxlist[cboxi].coz = smallestz.cumz; 575 | if ( cboxx == smallestz.cumx - smallestz.pre.cumx ) { 576 | boxlist[cboxi].cox = smallestz.pre.cumx; 577 | if ( smallestz.cumz + cboxz == smallestz.pos.cumz ) { 578 | smallestz.pre.cumx = smallestz.pos.cumx; 579 | if ( smallestz.pos.pos ) { 580 | smallestz.pre.pos = smallestz.pos.pos; 581 | smallestz.pos.pos.pre = smallestz.pre; 582 | } else { 583 | smallestz.pre.pos = null; 584 | } 585 | } else { 586 | smallestz.cumz = smallestz.cumz + cboxz; 587 | } 588 | } else if ( smallestz.pre.cumx < px - smallestz.cumx ) { 589 | if ( smallestz.cumz + cboxz == smallestz.pre.cumz) { 590 | smallestz.cumx = smallestz.cumx - cboxx; 591 | boxlist[cboxi].cox = smallestz.cumx - cboxx; 592 | } else { 593 | boxlist[cboxi].cox = smallestz.pre.cumx; 594 | smallestz.pre.pos = new scrappad(); 595 | 596 | smallestz.pre.pos.pre = smallestz.pre; 597 | smallestz.pre.pos.pos = smallestz; 598 | smallestz.pre = smallestz.pre.pos; 599 | smallestz.pre.cumx = smallestz.pre.pre.cumx + cboxx; 600 | smallestz.pre.cumz = smallestz.cumz + cboxz; 601 | } 602 | } else { 603 | if ( smallestz.cumz + cboxz == smallestz.pre.cumz ) { 604 | smallestz.pre.cumx = smallestz.pre.cumx + cboxx; 605 | boxlist[cboxi].cox = smallestz.pre.cumx; 606 | } else { 607 | boxlist[cboxi].cox = smallestz.cumx - cboxx; 608 | smallestz.pos.pre = new scrappad(); 609 | 610 | smallestz.pos.pre.pos = smallestz.pos; 611 | smallestz.pos.pre.pre = smallestz; 612 | smallestz.pos = smallestz.pos.pre; 613 | smallestz.pos.cumx = smallestz.cumx; 614 | smallestz.pos.cumz = smallestz.cumz + cboxz; 615 | smallestz.cumx = smallestz.cumx - cboxx; 616 | } 617 | } 618 | volumecheck(); 619 | } else { 620 | //*** SUBSITUATION-4B: SIDES ARE NOT EQUAL TO EACH OTHER *** 621 | 622 | lenx = smallestz.cumx - smallestz.pre.cumx; 623 | lenz = smallestz.pre.cumz - smallestz.cumz; 624 | lpz = remainpz - smallestz.cumz; 625 | findbox(lenx, layerthickness, remainpy, lenz, lpz); 626 | checkfound(); 627 | 628 | if (layerdone) break; 629 | if (evened) continue; 630 | 631 | boxlist[cboxi].coy = packedy; 632 | boxlist[cboxi].coz = smallestz.cumz; 633 | boxlist[cboxi].cox = smallestz.pre.cumx; 634 | if ( cboxx == (smallestz.cumx - smallestz.pre.cumx) ) { 635 | if ( (smallestz.cumz + cboxz) == smallestz.pre.cumz) { 636 | smallestz.pre.cumx = smallestz.cumx; 637 | smallestz.pre.pos = smallestz.pos; 638 | smallestz.pos.pre = smallestz.pre; 639 | } else { 640 | smallestz.cumz = smallestz.cumz + cboxz; 641 | } 642 | } else { 643 | if ( (smallestz.cumz + cboxz) == smallestz.pre.cumz ) { 644 | smallestz.pre.cumx = smallestz.pre.cumx + cboxx; 645 | } else if ( smallestz.cumz + cboxz == smallestz.pos.cumz ) { 646 | boxlist[cboxi].cox = smallestz.cumx - cboxx; 647 | smallestz.cumx = smallestz.cumx - cboxx; 648 | } else { 649 | smallestz.pre.pos = new scrappad(); 650 | 651 | smallestz.pre.pos.pre = smallestz.pre; 652 | smallestz.pre.pos.pos = smallestz; 653 | smallestz.pre = smallestz.pre.pos; 654 | smallestz.pre.cumx = smallestz.pre.pre.cumx + cboxx; 655 | smallestz.pre.cumz = smallestz.cumz + cboxz; 656 | } 657 | } 658 | volumecheck(); 659 | } 660 | } 661 | return 0; 662 | } 663 | 664 | //********************************************************************** 665 | // FINDS THE MOST PROPER LAYER HIGHT BY LOOKING AT THE UNPACKED 666 | // BOXES AND THE REMAINING EMPTY SPACE AVAILABLE 667 | //********************************************************************** 668 | 669 | var findlayer = function( thickness ) 670 | { 671 | var exdim, dimdif, dimen2, dimen3, y, z; 672 | var layereval, eval; 673 | layerthickness = 0; 674 | eval = 1000000; 675 | for (x=1; x <= tbn; x++) 676 | { 677 | if (boxlist[x].packst) continue; 678 | for( y = 1; y <= 3; y++) 679 | { 680 | switch(y) 681 | { 682 | case 1: 683 | exdim = boxlist[x].dim1; 684 | dimen2 = boxlist[x].dim2; 685 | dimen3 = boxlist[x].dim3; 686 | break; 687 | case 2: 688 | exdim = boxlist[x].dim2; 689 | dimen2 = boxlist[x].dim1; 690 | dimen3 = boxlist[x].dim3; 691 | break; 692 | case 3: 693 | exdim = boxlist[x].dim3; 694 | dimen2 = boxlist[x].dim1; 695 | dimen3 = boxlist[x].dim2; 696 | break; 697 | } 698 | layereval = 0; 699 | if ( (exdim <= thickness) && (((dimen2 <= px) && (dimen3 <= pz)) || ((dimen3 <= px) && (dimen2 <= pz))) ) 700 | { 701 | for (z = 1; z <= tbn; z++) 702 | { 703 | if ( !(x == z) && !(boxlist[z].packst)) 704 | { 705 | dimdif = Math.abs(exdim - boxlist[z].dim1); 706 | if ( Math.abs(exdim - boxlist[z].dim2) < dimdif ) 707 | { 708 | dimdif = Math.abs(exdim - boxlist[z].dim2); 709 | } 710 | if ( Math.abs(exdim - boxlist[z].dim3) < dimdif ) 711 | { 712 | dimdif = Math.abs(exdim - boxlist[z].dim3); 713 | } 714 | layereval = layereval + dimdif; 715 | } 716 | } 717 | if (layereval < eval) 718 | { 719 | eval = layereval; 720 | layerthickness = exdim; 721 | } 722 | } 723 | } 724 | } 725 | if (layerthickness == 0 || layerthickness > remainpy) packing = 0; 726 | return 0; 727 | } 728 | 729 | //********************************************************************** 730 | // FINDS THE MOST PROPER BOXES BY LOOKING AT ALL SIX POSSIBLE 731 | // ORIENTATIONS, EMPTY SPACE GIVEN, ADJACENT BOXES, AND PALLET LIMITS 732 | //********************************************************************** 733 | 734 | var findbox = function( hmx, hy, hmy, hz, hmz) 735 | { 736 | var y; 737 | bfx = 32767; bfy = 32767; bfz = 32767; 738 | bbfx = 32767; bbfy = 32767; bbfz = 32767; 739 | boxi = 0; bboxi = 0; 740 | for (y = 1; y <= tbn; y = y + boxlist[y].n) 741 | { 742 | for (x = y; x < x + boxlist[y].n - 1; x++) 743 | { 744 | if (!boxlist[x].packst) break; 745 | } 746 | if (boxlist[x].packst) continue; 747 | if (x > tbn) return; 748 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim1, boxlist[x].dim2, boxlist[x].dim3); 749 | if ( (boxlist[x].dim1 == boxlist[x].dim3) && (boxlist[x].dim3 == boxlist[x].dim2) ) continue; 750 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim1, boxlist[x].dim3, boxlist[x].dim2); 751 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim2, boxlist[x].dim1, boxlist[x].dim3); 752 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim2, boxlist[x].dim3, boxlist[x].dim1); 753 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim3, boxlist[x].dim1, boxlist[x].dim2); 754 | analyzebox(hmx, hy, hmy, hz, hmz, boxlist[x].dim3, boxlist[x].dim2, boxlist[x].dim1); 755 | } 756 | } 757 | 758 | //********************************************************************** 759 | // ANALYZES EACH UNPACKED BOX TO FIND THE BEST FITTING ONE TO 760 | // THE EMPTY SPACE GIVEN 761 | //********************************************************************** 762 | 763 | var analyzebox = function( hmx, hy, hmy, hz, hmz, dim1, dim2, dim3) 764 | { 765 | if (dim1 <= hmx && dim2 <= hmy && dim3 <= hmz) 766 | { 767 | if (dim2 <= hy) 768 | { 769 | if (hy - dim2 < bfy) 770 | { 771 | boxx = dim1; 772 | boxy = dim2; 773 | boxz = dim3; 774 | bfx = hmx - dim1; 775 | bfy = hy - dim2; 776 | bfz = Math.abs(hz - dim3); 777 | boxi = x; 778 | } 779 | else if (hy - dim2 == bfy && hmx - dim1 < bfx) 780 | { 781 | boxx = dim1; 782 | boxy = dim2; 783 | boxz = dim3; 784 | bfx = hmx - dim1; 785 | bfy = hy - dim2; 786 | bfz = Math.abs(hz - dim3); 787 | boxi = x; 788 | } 789 | else if (hy - dim2 == bfy && hmx - dim1 == bfx && Math.abs(hz - dim3) < bfz) 790 | { 791 | boxx = dim1; 792 | boxy = dim2; 793 | boxz = dim3; 794 | bfx = hmx - dim1; 795 | bfy = hy - dim2; 796 | bfz = Math.abs(hz - dim3); 797 | boxi = x; 798 | } 799 | } 800 | else 801 | { 802 | if (dim2 - hy < bbfy) 803 | { 804 | bboxx = dim1; 805 | bboxy = dim2; 806 | bboxz = dim3; 807 | bbfx = hmx - dim1; 808 | bbfy = dim2-hy; 809 | bbfz = Math.abs(hz - dim3); 810 | bboxi = x; 811 | } 812 | else if (dim2 - hy == bbfy && hmx - dim1 < bbfx) 813 | { 814 | bboxx = dim1; 815 | bboxy = dim2; 816 | bboxz = dim3; 817 | bbfx = hmx - dim1; 818 | bbfy = dim2 - hy; 819 | bbfz = Math.abs(hz - dim3); 820 | bboxi = x; 821 | } 822 | else if (dim2 - hy == bbfy && hmx-dim1 == bbfx && Math.abs(hz - dim3) < bbfz) 823 | { 824 | bboxx = dim1; 825 | bboxy = dim2; 826 | bboxz = dim3; 827 | bbfx = hmx - dim1; 828 | bbfy = dim2 - hy; 829 | bbfz = Math.abs(hz - dim3); 830 | bboxi = x; 831 | } 832 | } 833 | } 834 | } 835 | 836 | //******************************************************** 837 | // FINDS THE FIRST TO BE PACKED GAP IN THE LAYER EDGE 838 | //******************************************************** 839 | var findsmallestz = function(){ 840 | scrapmemb = scrapfirst; 841 | smallestz = scrapmemb; 842 | 843 | while ( !scrapmemb.pos == null ){ 844 | if ( scrapmemb.pos.cumz < smallestz.cumz ){ 845 | smallestz = scrapmemb.pos; 846 | } 847 | scrapmemb = scrapmemb.pos; 848 | } 849 | return; 850 | } 851 | 852 | //************************************************************ 853 | // AFTER FINDING EACH BOX, THE CANDIDATE BOXES AND THE 854 | // CONDITION OF THE LAYER ARE EXAMINED 855 | //************************************************************ 856 | 857 | var checkfound = function() 858 | { 859 | evened = 0; 860 | if (boxi) 861 | { 862 | cboxi = boxi; 863 | cboxx = boxx; 864 | cboxy = boxy; 865 | cboxz = boxz; 866 | } 867 | else 868 | { 869 | if ( (bboxi > 0) && (layerinlayer || (!smallestz.pre && !smallestz.pos)) ) 870 | { 871 | if (!layerinlayer) 872 | { 873 | prelayer = layerthickness; 874 | lilz = smallestz.cumz; 875 | } 876 | cboxi = bboxi; 877 | cboxx = bboxx; 878 | cboxy = bboxy; 879 | cboxz = bboxz; 880 | layerinlayer = layerinlayer + bboxy - layerthickness; 881 | layerthickness = bboxy; 882 | } 883 | else 884 | { 885 | if ( !smallestz.pre && !smallestz.pos ) 886 | { 887 | layerdone = 1; 888 | } 889 | else 890 | { 891 | evened = 1; 892 | if (!smallestz.pre) 893 | { 894 | trash = smallestz.pos; 895 | smallestz.cumx = smallestz.pos.cumx; 896 | smallestz.cumz = smallestz.pos.cumz; 897 | smallestz.pos = smallestz.pos.pos; 898 | if (smallestz.pos) 899 | { 900 | smallestz.pos.pre = smallestz; 901 | } 902 | } 903 | else if (!smallestz.pos) 904 | { 905 | smallestz.pre.pos = null; 906 | smallestz.pre.cumx = smallestz.cumx; 907 | } 908 | else 909 | { 910 | if ( smallestz.pre.cumz == smallestz.pos.cumz ) 911 | { 912 | smallestz.pre.pos = smallestz.pos.pos; 913 | if (smallestz.pos.pos) 914 | { 915 | smallestz.pos.pos.pre = smallestz.pre; 916 | } 917 | smallestz.pre.cumx = smallestz.pos.cumx; 918 | 919 | 920 | } 921 | else 922 | { 923 | smallestz.pre.pos = smallestz.pos; 924 | smallestz.pos.pre = smallestz.pre; 925 | if (smallestz.pre.cumz < smallestz.pos.cumz) 926 | { 927 | smallestz.pre.cumx = smallestz.cumx; 928 | } 929 | } 930 | } 931 | } 932 | } 933 | } 934 | return; 935 | } 936 | 937 | //******************************************************************** 938 | // AFTER PACKING OF EACH BOX, 100% PACKING CONDITION IS CHECKED 939 | //******************************************************************** 940 | 941 | var volumecheck = function() 942 | { 943 | boxlist[cboxi].packst = 1; 944 | boxlist[cboxi].packx = cboxx; 945 | boxlist[cboxi].packy = cboxy; 946 | boxlist[cboxi].packz = cboxz; 947 | packedvolume = packedvolume + boxlist[cboxi].vol; 948 | packednumbox++; 949 | if (packingbest) 950 | { 951 | graphunpackedout(); 952 | outputboxlist(); 953 | } 954 | else if (packedvolume == totalvolume || packedvolume == totalboxvol) 955 | { 956 | packing = 0; 957 | hundredpercent = 1; 958 | } 959 | return ; 960 | } 961 | 962 | //********************************************************************* 963 | // DATA FOR THE VISUALIZATION PROGRAM IS WRITTEN TO THE 964 | // "VISUDAT" FILE AND THE LIST OF UNPACKED BOXES IS 965 | // MERGED TO THE END OF THE REPORT FILE 966 | //********************************************************************* 967 | 968 | var graphunpackedout = function() 969 | { 970 | var n = ""; 971 | if (!unpacked) 972 | { 973 | strox = boxlist[cboxi].cox; 974 | strcoy = boxlist[cboxi].coy; 975 | strcoz = boxlist[cboxi].coz; 976 | strpackx = boxlist[cboxi].packx; 977 | strpacky = boxlist[cboxi].packy; 978 | strpackz = boxlist[cboxi].packz; 979 | } 980 | else 981 | { 982 | n = cboxi; 983 | strpackx = boxlist[cboxi].dim1; 984 | strpacky = boxlist[cboxi].dim2; 985 | strpackz = boxlist[cboxi].dim3; 986 | } 987 | if (!unpacked) 988 | { 989 | printf(strcox, strcoy, strcoz, strpackx, strpacky, strpackz); 990 | } 991 | else 992 | { 993 | printf(n, strpackx, strpacky, strpackz); 994 | } 995 | } 996 | 997 | //********************************************************************* 998 | // TRANSFORMS THE FOUND COORDINATE SYSTEM TO THE ONE ENTERED 999 | // BY THE USER AND WRITES THEM TO THE REPORT FILE 1000 | //********************************************************************* 1001 | 1002 | var outputboxlist = function() 1003 | { 1004 | var strx = "", 1005 | strpackst = "", 1006 | strdim1 = "", strdim2 = "", strdim3 = "", 1007 | strcox = "", strcoy = "", strcoz = "", 1008 | strpackx = "", strpacky = "", strpackz = ""; 1009 | 1010 | var x, y, z, bx, by, bz; 1011 | 1012 | switch(bestvariant) 1013 | { 1014 | case 1: 1015 | x = boxlist[cboxi].cox; 1016 | y = boxlist[cboxi].coy; 1017 | z = boxlist[cboxi].coz; 1018 | bx = boxlist[cboxi].packx; 1019 | by = boxlist[cboxi].packy; 1020 | bz = boxlist[cboxi].packz; 1021 | break; 1022 | case 2: 1023 | x = boxlist[cboxi].coz; 1024 | y = boxlist[cboxi].coy; 1025 | z = boxlist[cboxi].cox; 1026 | bx = boxlist[cboxi].packz; 1027 | by = boxlist[cboxi].packy; 1028 | bz = boxlist[cboxi].packx; 1029 | break; 1030 | case 3: 1031 | x = boxlist[cboxi].coy; 1032 | y = boxlist[cboxi].coz; 1033 | z = boxlist[cboxi].cox; 1034 | bx = boxlist[cboxi].packy; 1035 | by = boxlist[cboxi].packz; 1036 | bz = boxlist[cboxi].packx; 1037 | break; 1038 | case 4: 1039 | x = boxlist[cboxi].coy; 1040 | y = boxlist[cboxi].cox; 1041 | z = boxlist[cboxi].coz; 1042 | bx = boxlist[cboxi].packy; 1043 | by = boxlist[cboxi].packx; 1044 | bz = boxlist[cboxi].packz; 1045 | break; 1046 | case 5: 1047 | x = boxlist[cboxi].cox; 1048 | y = boxlist[cboxi].coz; 1049 | z = boxlist[cboxi].coy; 1050 | bx = boxlist[cboxi].packx; 1051 | by = boxlist[cboxi].packz; 1052 | bz = boxlist[cboxi].packy; 1053 | break; 1054 | case 6: 1055 | x = boxlist[cboxi].coz; 1056 | y = boxlist[cboxi].cox; 1057 | z = boxlist[cboxi].coy; 1058 | bx = boxlist[cboxi].packz; 1059 | by = boxlist[cboxi].packx; 1060 | bz = boxlist[cboxi].packy; 1061 | break; 1062 | } 1063 | 1064 | strx = cboxi; 1065 | strpackst = boxlist[cboxi].packst; 1066 | strdim1 = boxlist[cboxi].dim1; 1067 | strdim2 = boxlist[cboxi].dim2; 1068 | strdim3 = boxlist[cboxi].dim3; 1069 | strcox = x; 1070 | strcoy = y; 1071 | strcoz = z; 1072 | strpackx = bx; 1073 | strpacky = by; 1074 | strpackz = bz; 1075 | 1076 | boxlist[cboxi].cox = x; 1077 | boxlist[cboxi].coy = y; 1078 | boxlist[cboxi].coz = z; 1079 | boxlist[cboxi].packx = bx; 1080 | boxlist[cboxi].packy = by; 1081 | boxlist[cboxi].packz = bz; 1082 | printf(strx, strpackst, strdim1, strdim2, strdim3, strcox, strcoy, strcoz, strpackx, strpacky, strpackz); 1083 | return; 1084 | } 1085 | 1086 | 1087 | //******************************************************************* 1088 | // USING THE PARAMETERS FOUND, PACKS THE BEST SOLUTION FOUND 1089 | // AND REPORS TO THE CONSOLE AND TO A TEXT FILE 1090 | //******************************************************************* 1091 | 1092 | var report = function(){ 1093 | quit = 0; 1094 | switch(bestvariant){ 1095 | case 1: 1096 | px = xx; py = yy; pz = zz; 1097 | break; 1098 | case 2: 1099 | px = zz; py = yy; pz = xx; 1100 | break; 1101 | case 3: 1102 | px = zz; py = xx; pz = yy; 1103 | break; 1104 | case 4: 1105 | px=yy; py=xx; pz = zz; 1106 | break; 1107 | case 5: 1108 | px = xx; py = zz; pz = yy; 1109 | break; 1110 | case 6: 1111 | px = yy; py = zz; pz = xx; 1112 | break; 1113 | } 1114 | packingbest = 1; 1115 | 1116 | strpx = px; 1117 | strpy = py; 1118 | strpz = pz; 1119 | 1120 | percentagepackedbox = bestvolume * 100 / totalboxvol; 1121 | percentageused = bestvolume * 100 / totalvolume; 1122 | 1123 | sc.innerHTML = ""; 1124 | printf("TOTAL NUMBER OF ITERATIONS DONE :", itenum); 1125 | printf("BEST SOLUTION FOUND AT ITERATION :", bestite, "OF VARIANT", bestvariant); 1126 | printf("TOTAL NUMBER OF BOXES :", tbn); 1127 | printf("PACKED NUMBER OF BOXES :", bestpackednum); 1128 | printf("TOTAL VOLUME OF ALL BOXES :", totalboxvol); 1129 | printf("PALLET VOLUME :", totalvolume); 1130 | printf("BEST SOLUTION'S VOLUME UTILIZATION :", bestvolume, "OUT OF", totalvolume); 1131 | printf("PERCENTAGE OF PALLET VOLUME USED :", percentageused); 1132 | printf("PERCENTAGE OF PACKED BOXES (VOLUME) :", percentagepackedbox); 1133 | printf("WHILE PALLET ORIENTATION X - Y - Z :", px, py, pz); 1134 | printf("---------------------------------------------------------------------------------------------\n"); 1135 | 1136 | listcanditlayers(); 1137 | layers[0].layereval= -1; 1138 | qsort(layers); 1139 | packedvolume = 0.0; 1140 | packedy = 0; 1141 | packing = 1; 1142 | 1143 | // layerthickness = layers[bestite].layerdim; 1144 | remainpy = py; 1145 | remainpz = pz; 1146 | 1147 | for (x = 1; x <= tbn; x++){ 1148 | boxlist[x].packst = 0; 1149 | } 1150 | 1151 | do { 1152 | layerinlayer = 0; 1153 | layerdone = 0; 1154 | packlayer(); 1155 | packedy = packedy + layerthickness; 1156 | remainpy = py - packedy; 1157 | 1158 | if (layerinlayer) { 1159 | prepackedy = packedy; 1160 | preremainpy = remainpy; 1161 | remainpy = layerthickness - prelayer; 1162 | packedy = packedy - layerthickness + prelayer; 1163 | remainpz = lilz; 1164 | layerthickness = layerinlayer; 1165 | layerdone = 0; 1166 | packlayer(); 1167 | packedy = prepackedy; 1168 | remainpy = preremainpy; 1169 | remainpz = pz; 1170 | } 1171 | 1172 | if (!quit) { 1173 | findlayer(remainpy); 1174 | } 1175 | } while (packing && !quit); 1176 | 1177 | printf("\n\n *** LIST OF UNPACKED BOXES ***\n"); 1178 | unpacked = 1; 1179 | 1180 | for (cboxi = 1; cboxi <= tbn; cboxi++) { 1181 | if (!boxlist[cboxi].packst) { 1182 | graphunpackedout(); 1183 | } 1184 | } 1185 | unpacked = 0; 1186 | 1187 | printf("\n"); 1188 | for (n = 1; n <= tbn; n++) { 1189 | if (boxlist[n].packst) { 1190 | printf(n, boxlist[n].dim1, boxlist[n].dim2, boxlist[n].dim3, boxlist[n].cox, boxlist[n].coy, boxlist[n].coz, boxlist[n].packx, boxlist[n].packy, boxlist[n].packz); 1191 | } 1192 | } 1193 | printf("TOTAL NUMBER OF ITERATIONS DONE :", itenum); 1194 | printf("BEST SOLUTION FOUND AT : ITERATION: "+bestite+" OF VARIANT:", bestvariant); 1195 | printf("TOTAL NUMBER OF BOXES :", tbn); 1196 | printf("PACKED NUMBER OF BOXES :", bestpackednum); 1197 | printf("TOTAL VOLUME OF ALL BOXES :", totalboxvol); 1198 | printf("PALLET VOLUME :",totalvolume); 1199 | printf("BEST SOLUTION'S VOLUME UTILIZATION : "+bestvolume+" OUT OF", bestvolume, totalvolume); 1200 | printf("PERCENTAGE OF PALLET VOLUME USED :", percentageused); 1201 | printf("PERCENTAGE OF PACKEDBOXES (VOLUME) :", percentagepackedbox); 1202 | printf("WHILE PALLET ORIENTATION : X="+px+"; Y="+py+"; Z="+pz); 1203 | } 1204 | --------------------------------------------------------------------------------