├── 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 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
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 |
--------------------------------------------------------------------------------