PackInt function made public

In order to make the new Ponchio's nexus work properly
This commit is contained in:
Matteo Dellepiane 2016-11-29 11:37:19 +01:00
parent 77b144b796
commit e977c746bd
1 changed files with 142 additions and 142 deletions

View File

@ -240,6 +240,148 @@ static bool PackOccupancyMulti(const std::vector<Box2x > & rectVec, /// the se
return true; return true;
} }
/* This is the low level function that packs a set of int rects onto a grid.
Based on the criptic code written by Claudio Rocchini
Greedy algorithm.
Sort the rect according their height (larger first)
and then place them in the position that minimize the area of the bbox of all the placed rectangles
To efficiently skip occupied areas it fills the grid with the id of the already placed rectangles.
*/
static bool PackInt(const std::vector<vcg::Point2i> & sizes, // the sizes of the rect to be packed
const vcg::Point2i & max_size, // the size of the container
std::vector<vcg::Point2i> & posiz, // the found positionsof each rect
vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect
{
int n = (int)(sizes.size());
assert(n>0 && max_size[0]>0 && max_size[1]>0);
int gridSize = max_size[0] * max_size[1]; // Size dell griglia
int i, j, x, y;
posiz.resize(n, Point2i(-1, -1));
std::vector<int> grid(gridSize, 0); // Creazione griglia
#define Grid(q,w) (grid[(q)+(w)*max_size[0]])
// Build a permutation that keeps the reordiering of the sizes vector according to their width
std::vector<int> perm(n);
for (i = 0; i<n; i++) perm[i] = i;
ComparisonFunctor cmp(sizes);
sort(perm.begin(), perm.end(), cmp);
if (sizes[perm[0]][0]>max_size[0] || sizes[perm[0]][1]>max_size[1])
return false;
// Posiziono il primo
j = perm[0];
global_size = sizes[j];
posiz[j] = Point2i(0, 0);
// Fill the grid with the id(+1) of the first
for (y = 0; y<global_size[1]; y++)
for (x = 0; x<global_size[0]; x++)
{
assert(x >= 0 && x<max_size[0]);
assert(y >= 0 && y<max_size[1]);
grid[x + y*max_size[0]] = j + 1;
}
// Posiziono tutti gli altri
for (i = 1; i<n; ++i)
{
j = perm[i];
assert(j >= 0 && j<n);
assert(posiz[j][0] == -1);
int bestx, besty, bestsx, bestsy, bestArea;
bestArea = -1;
int sx = sizes[j][0]; // Pe comodita' mi copio la dimensione
int sy = sizes[j][1];
assert(sx>0 && sy>0);
// Calcolo la posizione limite
int lx = std::min(global_size[0], max_size[0] - sx);
int ly = std::min(global_size[1], max_size[1] - sy);
assert(lx>0 && ly>0);
int finterior = 0;
for (y = 0; y <= ly; y++)
{
for (x = 0; x <= lx;)
{
int px;
int c = Grid(x, y + sy - 1);
// Intersection check
if (!c) c = Grid(x + sx - 1, y + sy - 1);
if (!c)
{
for (px = x; px<x + sx; px++)
{
c = Grid(px, y);
if (c) break;
}
}
if (c) // Salto il rettangolo
{
--c; // we store id+1...
assert(c >= 0 && c<n);
assert(posiz[c][0] != -1);
x = posiz[c][0] + sizes[c][0];
}
else // x,y are an admissible position where we can put the rectangle
{
int nsx = std::max(global_size[0], x + sx);
int nsy = std::max(global_size[1], y + sy);
int area = nsx*nsy;
if (bestArea == -1 || bestArea>area)
{
bestx = x;
besty = y;
bestsx = nsx;
bestsy = nsy;
bestArea = area;
if (bestsx == global_size[0] && bestsy == global_size[1])
finterior = 1;
}
break;
}
if (finterior) break;
}
if (finterior) break;
}
if (bestArea == -1)
{
return false;
}
posiz[j][0] = bestx;
posiz[j][1] = besty;
global_size[0] = bestsx;
global_size[1] = bestsy;
for (y = posiz[j][1]; y<posiz[j][1] + sy; y++)
for (x = posiz[j][0]; x<posiz[j][0] + sx; x++)
{
assert(x >= 0 && x<max_size[0]);
assert(y >= 0 && y<max_size[1]);
grid[x + y*max_size[0]] = j + 1;
}
}
#undef Grid
return true;
}
private: private:
@ -260,148 +402,6 @@ public:
}; };
/* This is the low level function that packs a set of int rects onto a grid.
Based on the criptic code written by Claudio Rocchini
Greedy algorithm.
Sort the rect according their height (larger first)
and then place them in the position that minimize the area of the bbox of all the placed rectangles
To efficiently skip occupied areas it fills the grid with the id of the already placed rectangles.
*/
static bool PackInt(const std::vector<vcg::Point2i> & sizes, // the sizes of the rect to be packed
const vcg::Point2i & max_size, // the size of the container
std::vector<vcg::Point2i> & posiz, // the found positionsof each rect
vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect
{
int n = (int)(sizes.size());
assert(n>0 && max_size[0]>0 && max_size[1]>0);
int gridSize = max_size[0]*max_size[1]; // Size dell griglia
int i,j,x,y;
posiz.resize(n,Point2i(-1,-1));
std::vector<int> grid(gridSize,0); // Creazione griglia
#define Grid(q,w) (grid[(q)+(w)*max_size[0]])
// Build a permutation that keeps the reordiering of the sizes vector according to their width
std::vector<int> perm(n);
for(i=0;i<n;i++) perm[i] = i;
ComparisonFunctor cmp(sizes);
sort(perm.begin(),perm.end(),cmp);
if(sizes[perm[0]][0]>max_size[0] || sizes[perm[0]][1]>max_size[1] )
return false;
// Posiziono il primo
j = perm[0];
global_size = sizes[j];
posiz[j] = Point2i(0,0);
// Fill the grid with the id(+1) of the first
for(y=0;y<global_size[1];y++)
for(x=0;x<global_size[0];x++)
{
assert(x>=0 && x<max_size[0]);
assert(y>=0 && y<max_size[1]);
grid[x+y*max_size[0]] = j+1;
}
// Posiziono tutti gli altri
for(i=1;i<n;++i)
{
j = perm[i];
assert(j>=0 && j<n);
assert(posiz[j][0]==-1);
int bestx,besty,bestsx,bestsy,bestArea;
bestArea = -1;
int sx = sizes[j][0]; // Pe comodita' mi copio la dimensione
int sy = sizes[j][1];
assert(sx>0 && sy>0);
// Calcolo la posizione limite
int lx = std::min(global_size[0],max_size[0]-sx);
int ly = std::min(global_size[1],max_size[1]-sy);
assert(lx>0 && ly>0);
int finterior = 0;
for(y=0;y<=ly;y++)
{
for(x=0;x<=lx;)
{
int px;
int c = Grid(x,y+sy-1);
// Intersection check
if(!c) c = Grid(x+sx-1,y+sy-1);
if(!c)
{
for(px=x;px<x+sx;px++)
{
c = Grid(px,y);
if(c) break;
}
}
if(c) // Salto il rettangolo
{
--c; // we store id+1...
assert(c>=0 && c<n);
assert(posiz[c][0]!=-1);
x = posiz[c][0] + sizes[c][0];
}
else // x,y are an admissible position where we can put the rectangle
{
int nsx = std::max(global_size[0],x+sx);
int nsy = std::max(global_size[1],y+sy);
int area = nsx*nsy;
if(bestArea==-1 || bestArea>area)
{
bestx = x;
besty = y;
bestsx = nsx;
bestsy = nsy;
bestArea = area;
if( bestsx==global_size[0] && bestsy==global_size[1] )
finterior = 1;
}
break;
}
if(finterior) break;
}
if( finterior ) break;
}
if(bestArea==-1)
{
return false;
}
posiz[j][0] = bestx;
posiz[j][1] = besty;
global_size[0] = bestsx;
global_size[1] = bestsy;
for(y=posiz[j][1];y<posiz[j][1]+sy;y++)
for(x=posiz[j][0];x<posiz[j][0]+sx;x++)
{
assert(x>=0 && x<max_size[0]);
assert(y>=0 && y<max_size[1]);
grid[x+y*max_size[0]] = j+1;
}
}
#undef Grid
return true;
}
// Versione multitexture // Versione multitexture
static bool PackIntMulti( const std::vector<Point2i> & sizes, static bool PackIntMulti( const std::vector<Point2i> & sizes,
const int ntexture, const int ntexture,