Application Center - Maplesoft

App Preview:

Stacking Patterns for Boxes within a Volume

You can switch back to the summary page by clicking here.

Learn about Maple
Download Application


 

Image 

Loading Patterns of Boxes Within a Volume 

Lee R. Partin 

23 December 2007 

lpartin@chartertn.net 

Copyright 2007, L R Partin 

 

The model calculates potential loading patterns of boxes within a volume (a larger box).  It places the boxes within a given orderly pattern for the main filling of the volume.  It then tries to place more boxes in the remaining open spaces.  More boxes may be manually added by the user if sufficient free space remains after the automated filling process.  Several orientations are tested. 

 

Restart 

Restart the Maple kernel to prepare for the model calculations. 

> restart;
 

Application Coding 

Miscellaneous Code 

 

> with(plottools):
with(StringTools):
 

Pattern Module 

The programming for the box filling pattern calculations is done within a module called Pattern. 

> module Pattern()
 description "Calculate filling patterns for boxes within a given volume";
 local i;
 export Initialize, Stacks, Plot, Coordinates, Add;
 Stacks:={};
 Initialize:=proc() description "calculate and initialize a pattern object";
   local j, makeStack, Pname, xBox, yBox, zBox, xVol, yVol, zVol,
     newStack, xCount, yCount, zCount, Count, xOrigin, yOrigin,
     zOrigin, test1, test2, test3, name1, name2, name3, name4,
     name5, name6,
     maxPt0, maxPtx, maxPty, maxPtz, direction,
     xExtra, yExtra, zExtra, TrialCount, Trials, maxTrial,
     TrialSelect, orient, boxes1, boxes2, boxes3, boxes4,
     boxes5, boxes6, StacksL,
     FreeSpace1, FreeSpace2;
   makeStack:=proc(f::`name`,xBoxi,yBoxi,zBoxi,xVoli,yVoli,zVoli,
              xCounti,yCounti,zCounti, Counti, xOrigini,
              yOrigini, zOrigini)
      description "make a stacking record";
      f:=module() export xBox, yBox, zBox, xVol, yVol, zVol,
           xCount, yCount, zCount, Count, xOrigin, yOrigin, zOrigin;
         xBox:=xBoxi; yBox:=yBoxi; zBox:=zBoxi;
         xVol:=xVoli; yVol:=yVoli; zVol:=zVoli;
         xCount:=xCounti; yCount:=yCounti; zCount:=zCounti;
         Count:=Counti; xOrigin:=xOrigini; yOrigin:=yOrigini;
         zOrigin:=zOrigini;
      end module;
      f;
   end proc;
   if nargs<>10 then error "Initialize requires 10 arguments." fi;
   Pname:=args[1];
   if type(args[2],`numeric`) then xBox:=args[2]
      else error "Initialize argument 2 must be numeric for xBox" fi;
   if type(args[3],`numeric`) then yBox:=args[3]
      else error "Initialize argument 3 must be numeric for yBox" fi;
   if type(args[4],`numeric`) then zBox:=args[4]
      else error "Initialize argument 4 must be numeric for zBox" fi;
   if type(args[5],`numeric`) then xVol:=args[5]
      else error "Initialize argument 5 must be numeric for xVol" fi;
   if type(args[6],`numeric`) then yVol:=args[6]
      else error "Initialize argument 6 must be numeric for yVol" fi;
   if type(args[7],`numeric`) then zVol:=args[7]
      else error "Initialize argument 7 must be numeric for zVol" fi;
   if type(args[8],`name`) then test1:=args[8]
      else error "Initialize argument 8 must be a name (x, y or z) for the direction to first test for additional filling of the volume" fi;
   if type(args[9],`name`) then test2:=args[9]
      else error "Initialize argument 9 must be a name (x, y or z) for the direction of the second test for additional filling of the volume" fi;
   if type(args[10],`name`) then test3:=args[10]
      else error "Initialize argument 10 must be a name (x, y or z) for the direction of the third test for additional filling of the volume" fi;
   if {test1,test2,test3} <> {x,y,z} then error "Initialize arguments 8, 9 and 10 must be x, y and z in any order" fi;
   xOrigin:=0; yOrigin:=0; zOrigin:=0; # for initial volume fill
   maxPt0:=[0,0,0];
   maxPtx:=maxPt0; maxPty:=maxPt0; maxPtz:=maxPt0;
   boxes1:=0; boxes2:=0; boxes3:=0; boxes4:=0; boxes5:=0; boxes6:=0;
   StacksL:={};
   # doing the initial volume filling from origin (0,0,0)
   xCount:=trunc(xVol/xBox);
   yCount:=trunc(yVol/yBox);
   zCount:=trunc(zVol/zBox);
   Count:=xCount*yCount*zCount;
   boxes1:=Count;
   i:=1;
   name1:=convert(cat(Pname,"_",i),`name`);
   newStack:=makeStack(name1, xBox, yBox, zBox, xVol, yVol,
             zVol, xCount, yCount, zCount, Count, xOrigin, yOrigin,
             zOrigin);
   Stacks:=Stacks minus {newStack};
   Stacks:=Stacks union {newStack};
   StacksL:={newStack};
   maxPt0:=[xCount*xBox, yCount*yBox, zCount*zBox];
   printf("Stack Name: %s \n", name1);
   printf("Stack Count = %d; %d x %d x %d \n", Count,
          xCount, yCount, zCount);
   printf("Maximum Point of Stack: x=%g, y=%g, z=%g \n",
     xBox*xCount+xOrigin, yBox*yCount+yOrigin,
     zBox*zCount+zOrigin);
   # do the volume filling for the free volume in the three directions
   FreeSpace1:=[0,0,0]; FreeSpace2:=[0,0,0];
   for direction in [test1, test2, test3] do
     if (direction=x and maxPt0[1]<xVol) then
       printf("filling the extra x-space \n");
       xExtra:=xVol-maxPt0[1];
       if maxPtz[1]>maxPt0[1] then zExtra:=maxPt0[3]
       else zExtra:=zVol  fi;
       if maxPty[2]>maxPt0[2] then yExtra:=yVol-maxPty[2]
       else yExtra:=yVol  fi;
       # find which way to orient the box to get the most to fit
       j:=0;
       maxTrial:=0;
       TrialSelect:=0;
       for orient in combinat[permute]([xBox,yBox,zBox]) do
         j:=j+1;
         TrialCount:=trunc(xExtra/orient[1])*trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
         Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
         if TrialCount>maxTrial then
            TrialSelect:=j;
            maxTrial:=TrialCount;
         fi;   
       end do;
       # create the new collection of boxes within the volume
       if TrialSelect>0 then
         xCount:=trunc(xExtra/Trials[TrialSelect][1]);
         yCount:=trunc(yExtra/Trials[TrialSelect][2]);
         zCount:=trunc(zExtra/Trials[TrialSelect][3]);
         FreeSpace1[1]:=xExtra-xCount*Trials[TrialSelect][1];
         FreeSpace1[2]:=yExtra-yCount*Trials[TrialSelect][2];
         FreeSpace1[3]:=zExtra-zCount*Trials[TrialSelect][3];
         Count:=xCount*yCount*zCount;
         boxes2:=Count;
         i:=i+1;
         name2:=convert(cat(Pname,"_",i),`name`);
         maxPtx:=[xCount*Trials[TrialSelect][1],
                  yCount*Trials[TrialSelect][2],
                  zCount*Trials[TrialSelect][3]];
         newStack:=makeStack(name2, Trials[TrialSelect][1],
           Trials[TrialSelect][2], Trials[TrialSelect][3],
           xVol, yVol, zVol, xCount, yCount, zCount,
           Count, xVol-maxPtx[1], 0, 0);
         Stacks:=Stacks minus {newStack};
         Stacks:=Stacks union {newStack};
         StacksL:=StacksL union {newStack};
         printf("Stack Name: %s \n", name2);
         printf("Stack Count = %d; %d x %d x %d \n", Count,
                xCount, yCount, zCount);
       else
         printf("no boxes fit in the space \n")
       fi;
        # try fitting more boxes into the space next to the boxes just entered into the volume
       if FreeSpace1[2]>=min(xBox,yBox,zBox) then
         yExtra:=FreeSpace1[2];
         # find which way to orient the box to get the most to fit
         j:=0;
         maxTrial:=0;
         TrialSelect:=0;
         for orient in combinat[permute]([xBox,yBox,zBox]) do
           j:=j+1;
           TrialCount:=trunc(xExtra/orient[1])
              *trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
           Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
           if TrialCount>maxTrial then
              TrialSelect:=j;
              maxTrial:=TrialCount;
           fi;   
         end do;
         # create the new collection of boxes within the volume
         if TrialSelect>0 then
           xCount:=trunc(xExtra/Trials[TrialSelect][1]);
           yCount:=trunc(yExtra/Trials[TrialSelect][2]);
           zCount:=trunc(zExtra/Trials[TrialSelect][3]);
           Count:=xCount*yCount*zCount;
           boxes6:=Count;
           i:=i+1;
           name6:=convert(cat(Pname,"_",i),`name`);
           maxPtx:=[xCount*Trials[TrialSelect][1],
                    maxPtx[2]+yCount*Trials[TrialSelect][2],
                    zCount*Trials[TrialSelect][3]];
           newStack:=makeStack(name6, Trials[TrialSelect][1],
              Trials[TrialSelect][2], Trials[TrialSelect][3],
              xVol, yVol, zVol, xCount, yCount, zCount,
              Count, xVol-maxPtx[1],
              maxPtx[2]-yCount*Trials[TrialSelect][2], 0);
           Stacks:=Stacks minus {newStack};
           Stacks:=Stacks union {newStack};
           StacksL:=StacksL union {newStack};
           printf("Stack Name: %s \n", name6);
           printf("Stack Count = %d; %d x %d x %d \n", Count,
                  xCount, yCount, zCount);
         fi;
       fi;
     fi;
     if (direction=y and maxPt0[2]<yVol) then
       printf("filling the extra y-space \n");
       yExtra:=yVol-maxPt0[2];
       if maxPtz[2]>maxPt0[2] then zExtra:=maxPt0[3]
       else zExtra:=zVol  fi;
       if maxPtx[2]>maxPt0[2] then xExtra:=xVol-maxPtx[1]
       else xExtra:=xVol  fi;
       # find which way to orient the box to get the most to fit
       j:=0;
       maxTrial:=0;
       TrialSelect:=0;
       for orient in combinat[permute]([xBox,yBox,zBox]) do
         j:=j+1;
         TrialCount:=trunc(xExtra/orient[1])*trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
         Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
         if TrialCount>maxTrial then
            TrialSelect:=j;
            maxTrial:=TrialCount;
         fi;   
       end do;
       # create the new collection of boxes within the volume
       if TrialSelect>0 then
         xCount:=trunc(xExtra/Trials[TrialSelect][1]);
         yCount:=trunc(yExtra/Trials[TrialSelect][2]);
         zCount:=trunc(zExtra/Trials[TrialSelect][3]);
         FreeSpace2[1]:=xExtra-xCount*Trials[TrialSelect][1];
         FreeSpace2[2]:=yExtra-yCount*Trials[TrialSelect][2];
         FreeSpace2[3]:=zExtra-zCount*Trials[TrialSelect][3];
         Count:=xCount*yCount*zCount;
         boxes3:=Count;
         i:=i+1;
         name3:=convert(cat(Pname,"_",i),`name`);
         maxPty:=[xCount*Trials[TrialSelect][1],
                  yCount*Trials[TrialSelect][2],
                  zCount*Trials[TrialSelect][3]];
         newStack:=makeStack(name3, Trials[TrialSelect][1],
           Trials[TrialSelect][2], Trials[TrialSelect][3],
           xVol, yVol, zVol, xCount, yCount, zCount,
           Count, 0, yVol-maxPty[2], 0);
         Stacks:=Stacks minus {newStack};
         Stacks:=Stacks union {newStack};
         StacksL:=StacksL union {newStack};
         printf("Stack Name: %s \n", name3);
         printf("Stack Count = %d; %d x %d x %d \n", Count,
                xCount, yCount, zCount);
       else
         printf("no boxes fit in the space \n")
       fi;
       # try fitting more boxes into the space next to the boxes just entered into the volume
       if FreeSpace2[1]>=min(xBox,yBox,zBox) then
         xExtra:=FreeSpace2[1];
         # find which way to orient the box to get the most to fit
         j:=0;
         maxTrial:=0;
         TrialSelect:=0;
         for orient in combinat[permute]([xBox,yBox,zBox]) do
           j:=j+1;
           TrialCount:=trunc(xExtra/orient[1])
              *trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
           Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
           if TrialCount>maxTrial then
              TrialSelect:=j;
              maxTrial:=TrialCount;
           fi;   
         end do;
         # create the new collection of boxes within the volume
         if TrialSelect>0 then
           xCount:=trunc(xExtra/Trials[TrialSelect][1]);
           yCount:=trunc(yExtra/Trials[TrialSelect][2]);
           zCount:=trunc(zExtra/Trials[TrialSelect][3]);
           Count:=xCount*yCount*zCount;
           boxes5:=Count;
           i:=i+1;
           name5:=convert(cat(Pname,"_",i),`name`);
           maxPty:=[maxPty[1]+xCount*Trials[TrialSelect][1],
                    yCount*Trials[TrialSelect][2],
                    zCount*Trials[TrialSelect][3]];
           newStack:=makeStack(name5, Trials[TrialSelect][1],
              Trials[TrialSelect][2], Trials[TrialSelect][3],
              xVol, yVol, zVol, xCount, yCount, zCount,
              Count, maxPty[1]-xCount*Trials[TrialSelect][1],
              yVol-maxPty[2], 0);
           Stacks:=Stacks minus {newStack};
           Stacks:=Stacks union {newStack};
           StacksL:=StacksL union {newStack};
           printf("Stack Name: %s \n", name5);
           printf("Stack Count = %d; %d x %d x %d \n", Count,
                  xCount, yCount, zCount);
         fi;
       fi;   
     fi;
     if (direction=z and maxPt0[3]<zVol) then
       printf("filling the extra z-space \n");
       zExtra:=zVol-maxPt0[3];
       if maxPtx[3]>maxPt0[3] then xExtra:= xVol-maxPtx[1]
       else xExtra:=xVol  fi;
       if maxPty[3]>maxPt0[3] then yExtra:=yVol-maxPty[2]
       else yExtra:=yVol  fi;
       # find which way to orient the box to get the most to fit
       j:=0;
       maxTrial:=0;
       TrialSelect:=0;
       for orient in combinat[permute]([xBox,yBox,zBox]) do
         j:=j+1;
         TrialCount:=trunc(xExtra/orient[1])*trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
         Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
         if TrialCount>maxTrial then
            TrialSelect:=j;
            maxTrial:=TrialCount;
         fi;   
       end do;
       # create the new collection of boxes within the volume
       if TrialSelect>0 then
         xCount:=trunc(xExtra/Trials[TrialSelect][1]);
         yCount:=trunc(yExtra/Trials[TrialSelect][2]);
         zCount:=trunc(zExtra/Trials[TrialSelect][3]);
         Count:=xCount*yCount*zCount;
         boxes4:=Count;
         i:=i+1;
         name4:=convert(cat(Pname,"_",i),`name`);
         newStack:=makeStack(name4, Trials[TrialSelect][1],
           Trials[TrialSelect][2], Trials[TrialSelect][3],
           xVol, yVol, zVol, xCount, yCount, zCount,
           Count, 0, 0, maxPt0[3]);
         Stacks:=Stacks minus {newStack};
         Stacks:=Stacks union {newStack};
         StacksL:=StacksL union {newStack};
         maxPtz:=[xCount*Trials[TrialSelect][1],
                  yCount*Trials[TrialSelect][2],
                  zCount*Trials[TrialSelect][3]];
         printf("Stack Name: %s \n", name4);
         printf("Stack Count = %d; %d x %d x %d \n", Count,
                xCount, yCount, zCount);
       else
         printf("no boxes fit in the space \n")
       fi;
     fi;
   end do;          
   RETURN([sort(convert(StacksL,list)),
           boxes1+boxes2+boxes3+boxes4+boxes5+boxes6]);
 end proc;

 Plot:=proc(Pvals::list)
   description "create a 3D plot of the box patterns";  
   local i,i1,i2,i3,P,l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12,
         x1,y1,z1,x2,y2,z2;
   P:=Pvals[1];
   if member(P,Stacks)=false then error "the first entry in the list has not been defined as a pattern" fi;
   l1:=line([0,0,0],[P:-xVol,0,0],color=red);
   l2:=line([P:-xVol,0,0],[P:-xVol,P:-yVol,0],color=red);
   l3:=line([P:-xVol,P:-yVol,0],[0,P:-yVol,0],color=red);
   l4:=line([0,P:-yVol,0],[0,0,0],color=red);
   l5:=line([0,0,P:-zVol],[P:-xVol,0,P:-zVol],color=red);
   l6:=line([P:-xVol,0,P:-zVol],[P:-xVol,P:-yVol,P:-zVol]
            ,color=red);
   l7:=line([P:-xVol,P:-yVol,P:-zVol],[0,P:-yVol,P:-zVol]
            ,color=red);
   l8:=line([0,P:-yVol,P:-zVol],[0,0,P:-zVol],color=red);
   l9:=line([0,0,0],[0,0,P:-zVol],color=red);
   l10:=line([P:-xVol,0,0],[P:-xVol,0,P:-zVol],color=red);
   l11:=line([P:-xVol,P:-yVol,0],[P:-xVol,P:-yVol,P:-zVol]
             ,color=red);
   l12:=line([0,P:-yVol,0],[0,P:-yVol,P:-zVol],color=red);
   i:=0;
   for P in Pvals do    
    for i1 from 0 to P:-xCount-1 do
     for i2 from 0 to P:-yCount-1 do
      for i3 from 0 to P:-zCount-1 do
       x1:=P:-xOrigin + i1*P:-xBox;
       y1:=P:-yOrigin + i2*P:-yBox;
       z1:=P:-zOrigin + i3*P:-zBox;
       x2:=x1 + P:-xBox;
       y2:=y1 + P:-yBox;
       z2:=z1 + P:-zBox;
       i:=i+1;
       c||i:=cuboid([x1,y1,z1],[x2,y2,z2]);
      end do;
     end do;
    end do;
   end do;
   plots[display]([seq(c||j,j=1..i),
       l1,l2,l3,l4,l5,l6,l7,l8,l9,l10,l11,l12],
       title="Box Patterns", scaling=constrained,
       style=PATCH, axes=NORMAL);  
 end proc;
 Coordinates:=proc()
   description "return the starting and ending coordinates of a pattern";
   local Pname, Start, Finish;
   if nargs<>1 then error "Coordinate requires one argument." fi;
   Pname:=args[1];
   if member(Pname,Stacks)=false then
      error("the first argument must be a name from existing patterns.")
   fi;
   Start:=[Pname:-xOrigin,Pname:-yOrigin,Pname:-zOrigin];
   Finish:=[Start[1]+Pname:-xCount*Pname:-xBox,
            Start[2]+Pname:-yCount*Pname:-yBox,
            Start[3]+Pname:-zCount*Pname:-zBox];
   RETURN([Pname,Start,Finish]);    
 end proc;
 Add:=proc()
   description "add a new box filling pattern";
   local i, j, Pname, Start, Finish, bases, nextItem, firstItem,
         items, maxTrial, TrialSelect, orient, TrialCount, Trials,
         xCount, yCount, zCount, Count, newStack, StacksL,
         xExtra, yExtra, zExtra, BoxSum, makeStack;
   makeStack:=proc(f::`name`,xBoxi,yBoxi,zBoxi,xVoli,yVoli,zVoli,
              xCounti,yCounti,zCounti, Counti, xOrigini,
              yOrigini, zOrigini)
      description "make a stacking record";
      f:=module() export xBox, yBox, zBox, xVol, yVol, zVol,
           xCount, yCount, zCount, Count, xOrigin, yOrigin, zOrigin;
         xBox:=xBoxi; yBox:=yBoxi; zBox:=zBoxi;
         xVol:=xVoli; yVol:=yVoli; zVol:=zVoli;
         xCount:=xCounti; yCount:=yCounti; zCount:=zCounti;
         Count:=Counti; xOrigin:=xOrigini; yOrigin:=yOrigini;
         zOrigin:=zOrigini;
      end module;
      f;
   end proc;
   if nargs<>3 then error "Add requires 3 arguments." fi;
   Pname:=args[1];
   # find base names in Patterns
   bases:=[seq(StringTools:-SubString(convert(Stacks[i],`string`),
      1..StringTools:-FirstFromLeft("_",convert(Stacks[i],
      `string`))-1), i=1..nops(Stacks))];
   if member(convert(Pname,`string`),bases)=false then
      error "the first argument is not a base name of the existing patterns"
   fi;
   j:=0;
   for i from 1 to nops(bases) do
       if bases[i]=convert(Pname,`string`) then j:=j+1 fi;
   end do;
   items:=j+1;
   firstItem:=convert(cat(convert(Pname,`string`),"_",1),`name`);
   nextItem:=convert(cat(convert(Pname,`string`),"_",items),`name`);
   if type(args[2],`list`) then Start:=args[2]
   else  error "the second argument must be a list for starting coordinate ([x,y,z])."
   fi;
   if type(args[3],`list`) then Finish:=args[3]
   else  error "the third argument must be a list for ending coordinate ([x,y,z])."
   fi;
   if Start[1]<Finish[1] and Start[2]<Finish[2] and
      Start[3]<Finish[3] then
       printf("filling the space \n");
       xExtra:=Finish[1]-Start[1];
       yExtra:=Finish[2]-Start[2];
       zExtra:=Finish[3]-Start[3];
       # find which way to orient the box to get the most to fit
       j:=0;
       maxTrial:=0;
       TrialSelect:=0;
       for orient in combinat[permute]([firstItem:-xBox,
                     firstItem:-yBox,firstItem:-zBox]) do
         j:=j+1;
         TrialCount:=trunc(xExtra/orient[1])*trunc(yExtra/orient[2])
              *trunc(zExtra/orient[3]);
         Trials[j]:=[orient[1],orient[2],orient[3],TrialCount];
         if TrialCount>maxTrial then
            TrialSelect:=j;
            maxTrial:=TrialCount;
         fi;   
       end do;
       # create the new collection of boxes within the volume
       if TrialSelect>0 then
         xCount:=trunc(xExtra/Trials[TrialSelect][1]);
         yCount:=trunc(yExtra/Trials[TrialSelect][2]);
         zCount:=trunc(zExtra/Trials[TrialSelect][3]);
         Count:=xCount*yCount*zCount;
         i:=i+1;
         newStack:=makeStack(nextItem, Trials[TrialSelect][1],
           Trials[TrialSelect][2], Trials[TrialSelect][3],
           firstItem:-xVol, firstItem:-yVol,
           firstItem:-zVol, xCount, yCount, zCount,
           Count, Start[1], Start[2], Start[3]);
         Stacks:=Stacks minus {newStack};
         Stacks:=Stacks union {newStack};
         printf("Stack Name: %s \n", nextItem);
         printf("Stack Count = %d; %d x %d x %d \n", Count,
                xCount, yCount, zCount);
       else
         printf("no boxes fit in the space \n");
         items:=items-1;
       fi;
   else
       error "Start [x,y,z] must be larger than Ending [x,y,z]"
   fi;
   StacksL:=[seq(convert(cat(convert(Pname,`string`),"_",i),`name`)
             ,i=1..items)];
   BoxSum:=add(StacksL[i]:-Count,i=1..nops(StacksL));
   RETURN([StacksL,BoxSum]);
 end proc;
  
end module;
 

module Pattern () description
module Pattern () description
module Pattern () description
module Pattern () description
module Pattern () description
module Pattern () description
(2.2.1)
 

Application of Model 

Data / Dimensions 

The length, width and height of the box and the fill volume are required.  The orientation of the fill volume remains fixed for the calculations.  The boxes are assumed to lay flat on one of the sides.  They are packed within the volume in orderly structures. 

> BoxLength1:=1:
BoxLength2:=2:
BoxLength3:=3:
VolLength1:=11:
VolLength2:=13:
VolLength3:=14:
 

Packing Calculations 

Upper Bound on Boxes within the Volume 

The upper bound on the amount of boxes that will fit into the volume is calculated by a simple ratio of their volumes. 

> Volume:=VolLength1*VolLength2*VolLength3;
BoxVolume:=BoxLength1*BoxLength2*BoxLength3;
MaximumBoxes:=trunc(Volume/BoxVolume);
 

 

 

2002
6
333 (3.2.1.1)
 

Trial Packing Patterns 

The packing patterns are calculated 6 times since there are six potential orientations of the box for the initial packing structure.  Most of the boxes are placed in the initial orientation.  The program then tries to fit more boxes with the extra x-axis space.  Next, it tries to fit more boxes within the extra y-axis space.  Finally, it tries to fit more boxes into the extra z-axis space.
 

The Initialize routine of the Pattern module has 10 arguments: 

 arg[1] = name for the series of pattern fits to the volume 

 arg[2] = box length along the x-axis dimension 

 arg[3] = box length along the y-axis dimension 

 arg[4] = box length along the z-axis dimension 

 arg[5] = volume x dimension 

 arg[6] = volume y dimension 

 arg[7] = volume z dimension 

 arg[8] = x, y or z to set which extra space to 1st try fitting extra boxes 

 arg[9] = x, y or z to set which extra space to 2nd try fitting extra boxes
 arg[10] = x, y or z to set which extra space to 3rd try fitting extra boxes
 

 

The resulting box loading patterns and the total number of boxes loaded are stored within the Result variable. 

 

> Result[1]:=Pattern:-Initialize(P1,BoxLength1,BoxLength2,
  BoxLength3,VolLength1,VolLength2,VolLength3,x,y,z);
Result[2]:=Pattern:-Initialize(P2,BoxLength2,BoxLength1,
  BoxLength3,VolLength1,VolLength2,VolLength3,x,y,z);
Result[3]:=Pattern:-Initialize(P3,BoxLength1,BoxLength3,
  BoxLength2,VolLength1,VolLength2,VolLength3,x,y,z);
Result[4]:=Pattern:-Initialize(P4,BoxLength3,BoxLength2,
  BoxLength1,VolLength1,VolLength2,VolLength3,x,y,z);
Result[5]:=Pattern:-Initialize(P5,BoxLength2,BoxLength3,
  BoxLength1,VolLength1,VolLength2,VolLength3,x,y,z);
Result[6]:=Pattern:-Initialize(P6,BoxLength3,BoxLength1,
  BoxLength2,VolLength1,VolLength2,VolLength3,x,y,z);
 

 

Stack Name: P1_1
Stack Count = 264; 11 x 6 x 4
Maximum Point of Stack: x=11, y=12, z=12
filling the extra y-space
 

 

 

 

 

 

 

 

 

 

 

Stack Name: P1_2
Stack Count = 21; 3 x 1 x 7
Stack Name: P1_3
Stack Count = 4; 1 x 1 x 4
filling the extra z-space
Stack Name: P1_4
Stack Count = 44; 11 x 4 x 1
[[P1_1, P1_2, P1_3, P1_4], 333]
Stack Name: P2_1
Stack Count = 260; 5 x 13 x 4
Maximum Point of Stack: x=10, y=13, z=12
filling the extra x-space
Stack Name: P2_2
Stack Count = 28; 1 x 4 x 7
filling the extra z-space
Stack Name: P2_3
Stack Count = 40; 5 x 4 x 2
[[P2_1, P2_2, P2_3], 328]
Stack Name: P3_1
Stack Count = 308; 11 x 4 x 7
Maximum Point of Stack: x=11, y=12, z=14
filling the extra y-space
Stack Name: P3_2
Stack Count = 21; 3 x 1 x 7
Stack Name: P3_3
Stack Count = 4; 1 x 1 x 4
[[P3_1, P3_2, P3_3], 333]
Stack Name: P4_1
Stack Count = 252; 3 x 6 x 14
Maximum Point of Stack: x=9, y=12, z=14
filling the extra x-space
Stack Name: P4_2
Stack Count = 56; 1 x 4 x 14
Stack Name: P4_3
Stack Count = 4; 1 x 1 x 4
filling the extra y-space
Stack Name: P4_4
Stack Count = 21; 3 x 1 x 7
[[P4_1, P4_2, P4_3, P4_4], 333]
Stack Name: P5_1
Stack Count = 280; 5 x 4 x 14
Maximum Point of Stack: x=10, y=12, z=14
filling the extra x-space
Stack Name: P5_2
Stack Count = 28; 1 x 4 x 7
filling the extra y-space
Stack Name: P5_3
Stack Count = 21; 3 x 1 x 7
Stack Name: P5_4
Stack Count = 4; 1 x 1 x 4
[[P5_1, P5_2, P5_3, P5_4], 333]
Stack Name: P6_1
Stack Count = 273; 3 x 13 x 7
Maximum Point of Stack: x=9, y=13, z=14
filling the extra x-space
Stack Name: P6_2
Stack Count = 56; 2 x 4 x 7
Stack Name: P6_3
Stack Count = 4; 1 x 1 x 4
[[P6_1, P6_2, P6_3], 333] (3.2.2.1)
 

Plot a Packing Pattern 

The Plot routine of the Pattern module plots the loading patterns that define a given way of filling the volume.  The list of loading patterns for a given volume filling  was returned as the first element in the solution from Pattern:-Initialize.  Enter your desired volume filling  number as the variable i.  It can be 1 through 6. 

> i:=1:
cat("Solution ",i);
cat(Result[i][2]," boxes");
Pattern:-Plot(Result[i][1]);
 

 

 

Solution 1
`333 boxes`
Plot
 

The first volume filling has 4 different patterns of box placement.  You may view a single box pattern as follows: 

> i:=1:  # volume filling number
j:=3:  # box pattern number within the filling
Pattern:-Plot([Result[2][i][j]]);
 

Plot
 

Adding More Boxes to a Pattern 

The volume filling routine may not find all of the feasible locations to place boxes.  You may add more box patterns manually through the Add routine.  The Coordinates routine help in determining data needed in the Add routine.  Here is an example. 

 

Result 2 did not fill all of the available space as shown in the plot below.  More boxes may be placed into the volume. 

> i:=2: Pattern:-Plot(Result[i][1]);
 

Plot
 

The Coordinates routine provides data on the individual box patterns within a Result from above.  It gives the name, starting coordinate [x,y,z] and ending coordinate [x,y,z] for each of the individual patterns.  The starting coordinate is where the first box is placed.  The next boxes are placed at increasing values of [x,y,z].  The ending coordinate is the point in the individual fill volume that is diagonal and furthest from the starting coordinate. 

> for item in Result[i][1] do
  Pattern:-Coordinates(item)  end do;
 

 

 

[P2_1, [0, 0, 0], [10, 13, 12]]
[P2_2, [10, 0, 0], [11, 12, 14]]
[P2_3, [0, 0, 12], [10, 12, 14]] (3.4.1)
 

The filling pattern from Result 2 has free volume from [0,12,12] to [11,13,14].  It also has a small cavity from [10,12,0] to [11,13,14] that is not big enough to have more boxes.  A new filling pattern is now added for the free volume.  The Add routine is applied.  It has three arguments: 

 arg[1], the base name of the volume filling  (P1, P2, P3, P4, P5 and P6 were used above.  It is one of these values.)
 arg[2], starting coordinate as [x1,y1,z1]  (the first box is placed here with more boxes added in increasing [x,y,z]
 

            directions) 

 arg[3], ending coordinate as [x2,y2,z2]  (the ending coordinate defines the volume of the fill box;  therefore, x2>x1, 

            y2>y1, and z2>z1) 

> NewResult2:=Pattern:-Add(P2,[0,12,12],[11,13,14]);
 

 

filling the space
Stack Name: P2_4
Stack Count = 3; 3 x 1 x 1
[[P2_1, P2_2, P2_3, P2_4], 331] (3.4.2)
 

Here is a plot of the new set of filling patterns: 

> Pattern:-Plot(NewResult2[1]);
 

Plot
 

>
 

 

Legal Notice: The copyright for this application is owned by the author. Neither Maplesoft nor the author are responsible for any errors contained within and are not liable for any damages resulting from the use of this material. This application is intended for non-commercial, non-profit use only. Contact the author for permission if you wish to use this application in for-profit activities. 

Image