Updated version of the oldpolyrect packer. Reasonably extended to multiple domain. To be tested/replaced
This commit is contained in:
parent
5aaa6f4720
commit
f156a5a82c
|
@ -22,6 +22,7 @@
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
#include <QtOpenGL/QtOpenGL>
|
#include <QtOpenGL/QtOpenGL>
|
||||||
#include<vcg/space/box2.h>
|
#include<vcg/space/box2.h>
|
||||||
|
#include<vcg/space/box3.h>
|
||||||
#include<vcg/math/random_generator.h>
|
#include<vcg/math/random_generator.h>
|
||||||
#include<wrap/qt/col_qt_convert.h>
|
#include<wrap/qt/col_qt_convert.h>
|
||||||
#include <vcg/space/rect_packer.h>
|
#include <vcg/space/rect_packer.h>
|
||||||
|
@ -98,31 +99,58 @@ void buildRandPolySet(int polyNum, vector< vector<Point2f> > &polyVec)
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
QApplication pippo(argc,argv);
|
vector<Similarity2f> trVec;
|
||||||
|
vector<Similarity2f> trPolyVec;
|
||||||
|
vector< vector<Point2f> > polySet;
|
||||||
|
vector< vector<Point2f> > multiPolySet;
|
||||||
|
Point2f finalSize;
|
||||||
|
std::vector<Point2f> finalSizeVec;
|
||||||
|
const Point2f containerSize(1000,1000);
|
||||||
|
PolyDumperParam pp;
|
||||||
|
std::vector<int> contInd;
|
||||||
|
|
||||||
vector<Box2f> rectVec;
|
vector<Box2f> rectVec;
|
||||||
buildRandRectSet(1000, rectVec);
|
buildRandRectSet(10,rectVec);
|
||||||
vector<Similarity2f> trVec;
|
// RectPacker<float>::Pack(rectVec,containerSize,trVec,finalSize);
|
||||||
vector< vector<Point2f> > polySet;
|
RectPacker<float>::PackMulti(rectVec,containerSize,3,trVec,contInd,finalSizeVec);
|
||||||
Point2f finalSize;
|
RectPacker<float>::Stat s = RectPacker<float>::stat();
|
||||||
|
printf("RectPacker attempt %i time %5.3f %5.3f\n",s.pack_attempt_num,s.pack_total_time,s.pack_attempt_time);
|
||||||
|
|
||||||
|
// PolyDumper::rectSetToPolySet(rectVec,polySet);
|
||||||
|
|
||||||
|
// PolyDumper::multiRectSetToSinglePolySet(rectVec,trVec,contInd,0,polySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq0.png",polySet,trPolyVec,pp);
|
||||||
|
// PolyDumper::multiRectSetToSinglePolySet(rectVec,trVec,contInd,1,polySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq1.png",polySet,trPolyVec,pp);
|
||||||
|
// PolyDumper::multiRectSetToSinglePolySet(rectVec,trVec,contInd,2,polySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq2.png",polySet,trPolyVec,pp);
|
||||||
|
|
||||||
|
|
||||||
|
// buildRandPolySet(100,polySet);
|
||||||
|
// PolyPacker<float>::PackMultiAsObjectOrientedRect(polySet,containerSize,3,trVec,contInd,finalSizeVec);
|
||||||
|
|
||||||
|
// PolyDumper::multiPolySetToSinglePolySet(polySet,trVec,contInd,0,multiPolySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq0.png",multiPolySet,trPolyVec,pp);
|
||||||
|
|
||||||
|
// PolyDumper::multiPolySetToSinglePolySet(polySet,trVec,contInd,1,multiPolySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq1.png",multiPolySet,trPolyVec,pp);
|
||||||
|
|
||||||
|
// PolyDumper::multiPolySetToSinglePolySet(polySet,trVec,contInd,2,multiPolySet,trPolyVec);
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyEq2.png",multiPolySet,trPolyVec,pp);
|
||||||
|
|
||||||
|
// PolyDumper::dumpPolySetPNG("testpolyOO.png",polySet,trVec,pp);
|
||||||
|
|
||||||
|
|
||||||
buildRandPolySet(100,polySet);
|
buildRandPolySet(100,polySet);
|
||||||
PolyDumperParam pp;
|
|
||||||
/* PolyPacker<float>::PackAsEqualSquares(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
|
||||||
dumpPolySet("testpolyEq.png",polySet,trVec,pp);
|
|
||||||
PolyPacker<float>::PackAsAxisAlignedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
|
||||||
dumpPolySet("testpolyAA.png",polySet,trVec,pp);
|
|
||||||
PolyPacker<float>::PackAsObjectOrientedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
|
||||||
dumpPolySet("testpolyOO.png",polySet,trVec,pp);*/
|
|
||||||
|
|
||||||
//PolyPacker<float>::PackAsAxisAlignedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
PolyPacker<float>::PackAsEqualSquares(polySet,containerSize,trVec,finalSize);
|
||||||
PolyPacker<float>::PackAsObjectOrientedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
PolyDumper::dumpPolySetPNG("testpolyEq.png",polySet,trVec,pp);
|
||||||
//dumpPolySetPNG("testpolyEq.png",polySet,trVec,pp);
|
|
||||||
PolyDumper::dumpPolySetSVG("testpolyEq.svg",polySet,trVec,pp);
|
|
||||||
|
|
||||||
/*PolyPacker<float>::PackAsAxisAlignedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
PolyPacker<float>::PackAsAxisAlignedRect(polySet,containerSize,trVec,finalSize);
|
||||||
dumpPolySetSVG("testpolyAA.svg",polySet,trVec,pp);
|
PolyDumper::dumpPolySetPNG("testpolyAA.png",polySet,trVec,pp);
|
||||||
PolyPacker<float>::PackAsObjectOrientedRect(polySet,Point2f(1024.0f,1024.0f),trVec,finalSize);
|
|
||||||
dumpPolySetSVG("testpolyOO.svg",polySet,trVec,pp);*/
|
PolyPacker<float>::PackAsObjectOrientedRect(polySet,containerSize,trVec,finalSize);
|
||||||
|
PolyDumper::dumpPolySetPNG("testpolyOO.png",polySet,trVec,pp);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,25 @@ class RectPacker
|
||||||
typedef typename vcg::Box2<SCALAR_TYPE> Box2x;
|
typedef typename vcg::Box2<SCALAR_TYPE> Box2x;
|
||||||
typedef typename vcg::Point2<SCALAR_TYPE> Point2x;
|
typedef typename vcg::Point2<SCALAR_TYPE> Point2x;
|
||||||
typedef typename vcg::Similarity2<SCALAR_TYPE> Similarity2x;
|
typedef typename vcg::Similarity2<SCALAR_TYPE> Similarity2x;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
class Stat
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void clear() {
|
||||||
|
pack_attempt_num=0;
|
||||||
|
pack_attempt_time=0;
|
||||||
|
pack_total_time=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pack_attempt_num;
|
||||||
|
float pack_attempt_time;
|
||||||
|
float pack_total_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static Stat &stat() { static Stat _s; return _s; }
|
||||||
|
|
||||||
|
|
||||||
static bool Pack(const std::vector<Box2x > & rectVec, /// the set of rectangles that have to be packed (generic floats, no req.)
|
static bool Pack(const std::vector<Box2x > & rectVec, /// the set of rectangles that have to be packed (generic floats, no req.)
|
||||||
const Point2x containerSizeX, /// the size of the container where they has to be fitted (usually in pixel size)
|
const Point2x containerSizeX, /// the size of the container where they has to be fitted (usually in pixel size)
|
||||||
std::vector<Similarity2x> &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position
|
std::vector<Similarity2x> &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position
|
||||||
|
@ -49,11 +66,15 @@ public:
|
||||||
float bestOccupancy=0,currOccupancy=0.1f;
|
float bestOccupancy=0,currOccupancy=0.1f;
|
||||||
std::vector<Similarity2x> currTrVec;
|
std::vector<Similarity2x> currTrVec;
|
||||||
Point2x currCovered;
|
Point2x currCovered;
|
||||||
|
int start_t=clock();
|
||||||
|
stat().clear();
|
||||||
bool ret=true;
|
bool ret=true;
|
||||||
while(ret)
|
while(ret)
|
||||||
{
|
{
|
||||||
|
stat().pack_attempt_num++;
|
||||||
|
int t0=clock();
|
||||||
ret=PackOccupancy(rectVec,containerSizeX,currOccupancy,currTrVec,currCovered);
|
ret=PackOccupancy(rectVec,containerSizeX,currOccupancy,currTrVec,currCovered);
|
||||||
|
stat().pack_attempt_time = float(clock()-t0)/float(CLOCKS_PER_SEC);
|
||||||
if(ret)
|
if(ret)
|
||||||
{
|
{
|
||||||
assert(currOccupancy>bestOccupancy);
|
assert(currOccupancy>bestOccupancy);
|
||||||
|
@ -63,6 +84,7 @@ public:
|
||||||
currOccupancy = (2.0*currOccupancy+1.0)/3.0;
|
currOccupancy = (2.0*currOccupancy+1.0)/3.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
stat().pack_total_time=float(clock()-start_t)/float(CLOCKS_PER_SEC);;
|
||||||
if(bestOccupancy>0) return true;
|
if(bestOccupancy>0) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -123,6 +145,100 @@ static bool PackOccupancy(const std::vector<Box2x > & rectVec, /// the set of
|
||||||
coveredContainer = Point2x::Construct(global_size);
|
coveredContainer = Point2x::Construct(global_size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
static bool PackMulti(const std::vector<Box2x > & rectVec, /// the set of rectangles that have to be packed (generic floats, no req.)
|
||||||
|
const Point2x containerSizeX, /// the size of the container where they has to be fitted (usually in pixel size)
|
||||||
|
const int containerNum,
|
||||||
|
std::vector<Similarity2x> &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position
|
||||||
|
std::vector<int> &indVec,
|
||||||
|
std::vector<Point2x> &coveredContainer) /// the sub portion of the container covered by the solution.
|
||||||
|
{
|
||||||
|
float bestOccupancy=0,currOccupancy=0.1f;
|
||||||
|
std::vector<Similarity2x> currTrVec;
|
||||||
|
std::vector<int> currIndVec;
|
||||||
|
std::vector<Point2x> currCovered;
|
||||||
|
int start_t=clock();
|
||||||
|
stat().clear();
|
||||||
|
bool ret=true;
|
||||||
|
while(ret && bestOccupancy < 0.99f)
|
||||||
|
{
|
||||||
|
stat().pack_attempt_num++;
|
||||||
|
int t0=clock();
|
||||||
|
ret=PackOccupancyMulti(rectVec,containerSizeX,containerNum,currOccupancy,currTrVec, currIndVec, currCovered);
|
||||||
|
stat().pack_attempt_time = float(clock()-t0)/float(CLOCKS_PER_SEC);
|
||||||
|
if(ret)
|
||||||
|
{
|
||||||
|
printf("CurrOccupancy %f\n",currOccupancy);
|
||||||
|
assert(currOccupancy>bestOccupancy);
|
||||||
|
bestOccupancy = currOccupancy;
|
||||||
|
trVec=currTrVec;
|
||||||
|
indVec=currIndVec;
|
||||||
|
coveredContainer=currCovered;
|
||||||
|
currOccupancy = (2.0*currOccupancy+1.0)/3.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stat().pack_total_time=float(clock()-start_t)/float(CLOCKS_PER_SEC);;
|
||||||
|
if(bestOccupancy>0) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool PackOccupancyMulti(const std::vector<Box2x > & rectVec, /// the set of rectangles that have to be packed
|
||||||
|
const Point2x containerSizeX, /// the size of the container where they has to be fitted (usually in pixel size)
|
||||||
|
const int containerNum,
|
||||||
|
const SCALAR_TYPE occupancyRatio, /// the expected percentage of the container that has to be covered
|
||||||
|
std::vector<Similarity2x> &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position
|
||||||
|
std::vector<int> &indVec,
|
||||||
|
std::vector<Point2x> &coveredContainer) /// the sub portion of the container covered by the solution.
|
||||||
|
{
|
||||||
|
Point2x maxSize(0,0);
|
||||||
|
const vcg::Point2i containerSize=Point2i::Construct(containerSizeX);
|
||||||
|
SCALAR_TYPE areaSum=0;
|
||||||
|
SCALAR_TYPE areaContainer = containerSize[0]*containerSize[1]*containerNum;
|
||||||
|
|
||||||
|
for (size_t i=0;i<rectVec.size();++i)
|
||||||
|
{
|
||||||
|
maxSize[0]=std::max(maxSize[0],rectVec[i].DimX());
|
||||||
|
maxSize[1]=std::max(maxSize[1],rectVec[i].DimY());
|
||||||
|
areaSum += rectVec[i].DimX() * rectVec[i].DimY();
|
||||||
|
}
|
||||||
|
|
||||||
|
Point2x scaleFactor2(containerSize[0]/maxSize[0],containerSize[1]/maxSize[1]);
|
||||||
|
|
||||||
|
SCALAR_TYPE scaleFactor = (sqrt(areaContainer)/sqrt(areaSum))*sqrt(occupancyRatio);
|
||||||
|
|
||||||
|
// printf("unitScaleFactor %6.3f\n",unitScaleFactor);
|
||||||
|
// printf("scaleFactor %6.3f\n",scaleFactor);
|
||||||
|
// printf("areaContainer %6.3f\n",areaContainer);
|
||||||
|
// printf("areaSum %6.3f\n",areaSum);
|
||||||
|
std::vector<vcg::Point2i> sizes(rectVec.size());
|
||||||
|
for (size_t i=0;i<rectVec.size();++i)
|
||||||
|
{
|
||||||
|
sizes[i][0]=ceil(rectVec[i].DimX()*scaleFactor);
|
||||||
|
sizes[i][1]=ceil(rectVec[i].DimY()*scaleFactor);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<vcg::Point2i> posiz;
|
||||||
|
std::vector<vcg::Point2i> global_sizeVec;
|
||||||
|
|
||||||
|
bool res = PackIntMulti(sizes,containerNum,containerSize,posiz,indVec,global_sizeVec);
|
||||||
|
if(!res) return false;
|
||||||
|
|
||||||
|
trVec.resize(rectVec.size());
|
||||||
|
for (size_t i=0;i<rectVec.size();++i)
|
||||||
|
{
|
||||||
|
trVec[i].tra = Point2x::Construct(posiz[i]) - rectVec[i].min*scaleFactor;
|
||||||
|
trVec[i].sca = scaleFactor;
|
||||||
|
|
||||||
|
// qDebug("rectVec[ %5i ] (%6.2f %6.2f) - (%6.2f %6.2f) : SizeI (%6i %6i) Posiz (%6i %6i)",i,
|
||||||
|
// rectVec[i].min[0],rectVec[i].min[1], rectVec[i].max[0],rectVec[i].max[1],
|
||||||
|
// sizes[i][0],sizes[i][1], posiz[i][0],posiz[i][1]);
|
||||||
|
}
|
||||||
|
// printf("globalSize (%6i %6i)\n",global_size[0],global_size[1]);
|
||||||
|
coveredContainer.resize(containerNum);
|
||||||
|
for(int i=0;i<containerNum;++i)
|
||||||
|
coveredContainer[i] = Point2x::Construct(global_sizeVec[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
@ -158,7 +274,7 @@ static bool PackInt(const std::vector<vcg::Point2i> & sizes, // the sizes of the
|
||||||
std::vector<vcg::Point2i> & posiz, // the found positionsof each rect
|
std::vector<vcg::Point2i> & posiz, // the found positionsof each rect
|
||||||
vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect
|
vcg::Point2i & global_size) // the size of smallest rect covering all the packed rect
|
||||||
{
|
{
|
||||||
int n = (int)(sizes.size());
|
int n = (int)(sizes.size());
|
||||||
assert(n>0 && max_size[0]>0 && max_size[1]>0);
|
assert(n>0 && max_size[0]>0 && max_size[1]>0);
|
||||||
|
|
||||||
int gridSize = max_size[0]*max_size[1]; // Size dell griglia
|
int gridSize = max_size[0]*max_size[1]; // Size dell griglia
|
||||||
|
@ -283,8 +399,211 @@ static bool PackInt(const std::vector<vcg::Point2i> & sizes, // the sizes of the
|
||||||
#undef Grid
|
#undef Grid
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Versione multitexture
|
||||||
|
static bool PackIntMulti( const std::vector<Point2i> & sizes,
|
||||||
|
const int ntexture,
|
||||||
|
const vcg::Point2i & max_size,
|
||||||
|
std::vector<Point2i> & posiz,
|
||||||
|
std::vector<int> & texin,
|
||||||
|
std::vector<Point2i> & globalsize )
|
||||||
|
{
|
||||||
|
int n = sizes.size();
|
||||||
|
assert(n>0);
|
||||||
|
assert(max_size[0]>0);
|
||||||
|
assert(max_size[1]>0);
|
||||||
|
|
||||||
|
|
||||||
|
int gdim = max_size[0]*max_size[1]; // Size dell griglia
|
||||||
|
|
||||||
|
int i,j,k,x,y;
|
||||||
|
|
||||||
|
globalsize.resize(ntexture); // creazione globalsize
|
||||||
|
|
||||||
|
posiz.resize(n);
|
||||||
|
texin.resize(n);
|
||||||
|
for(i=0;i<n;i++) // Azzero le posizioni e indici
|
||||||
|
{
|
||||||
|
posiz[i].X() = -1;
|
||||||
|
texin[i] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector< std::vector<int> > grid; // Creazione griglie
|
||||||
|
grid.resize(ntexture);
|
||||||
|
for(k=0;k<ntexture;++k)
|
||||||
|
{
|
||||||
|
grid[k].resize(gdim);
|
||||||
|
for(i=0;i<gdim;++i)
|
||||||
|
grid[k][i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define Grid(k,q,w) (grid[k][(q)+(w)*max_size[0]])
|
||||||
|
|
||||||
|
std::vector<int> perm(n); // Creazione permutazione
|
||||||
|
for(i=0;i<n;i++) perm[i] = i;
|
||||||
|
ComparisonFunctor conf(sizes);
|
||||||
|
sort(perm.begin(),perm.end(),conf);
|
||||||
|
|
||||||
|
if(sizes[perm[0]].X()>max_size[0] || // Un pezzo piu' grosso del contenitore
|
||||||
|
sizes[perm[0]].Y()>max_size[1] )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(n<ntexture) // Piu' contenitore che pezzi
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Posiziono i primi
|
||||||
|
for(k=0;k<ntexture;++k)
|
||||||
|
{
|
||||||
|
j = perm[k];
|
||||||
|
globalsize[k].X() = sizes[j].X();
|
||||||
|
globalsize[k].Y() = sizes[j].Y();
|
||||||
|
posiz[j].X() = 0;
|
||||||
|
posiz[j].Y() = 0;
|
||||||
|
texin[j] = k;
|
||||||
|
for(y=0;y<globalsize[k].Y();y++)
|
||||||
|
for(x=0;x<globalsize[k].X();x++)
|
||||||
|
{
|
||||||
|
assert(x>=0);
|
||||||
|
assert(x<max_size[0]);
|
||||||
|
assert(y>=0);
|
||||||
|
assert(y<max_size[1]);
|
||||||
|
Grid(k,x,y) = j+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Posiziono tutti gli altri
|
||||||
|
for(i=ntexture;i<n;++i)
|
||||||
|
{
|
||||||
|
j = perm[i];
|
||||||
|
assert(j>=0);
|
||||||
|
assert(j<n);
|
||||||
|
assert(posiz[j].X()==-1);
|
||||||
|
|
||||||
|
|
||||||
|
int sx = sizes[j].X(); // Pe comodita' mi copio la dimensione
|
||||||
|
int sy = sizes[j].Y();
|
||||||
|
assert(sx>0);
|
||||||
|
assert(sy>0);
|
||||||
|
|
||||||
|
|
||||||
|
int gbestx,gbesty,gbestsx,gbestsy,gbestk;
|
||||||
|
int gbesta = -1;
|
||||||
|
|
||||||
|
for(k=0;k<ntexture;++k)
|
||||||
|
{
|
||||||
|
int bestx,besty,bestsx,bestsy,besta;
|
||||||
|
int starta;
|
||||||
|
|
||||||
|
besta = -1;
|
||||||
|
|
||||||
|
// Calcolo la posizione limite
|
||||||
|
int lx = std::min(globalsize[k].X(),max_size[0]-sx);
|
||||||
|
int ly = std::min(globalsize[k].Y(),max_size[1]-sy);
|
||||||
|
|
||||||
|
starta = globalsize[k].X()*globalsize[k].Y();
|
||||||
|
|
||||||
|
assert(lx>0);
|
||||||
|
assert(ly>0);
|
||||||
|
|
||||||
|
int finterior = 0;
|
||||||
|
|
||||||
|
for(y=0;y<=ly;y++)
|
||||||
|
{
|
||||||
|
for(x=0;x<=lx;)
|
||||||
|
{
|
||||||
|
int px;
|
||||||
|
int c;
|
||||||
|
// Controllo intersezione
|
||||||
|
c = Grid(k,x,y+sy-1);
|
||||||
|
if(!c) c = Grid(k,x+sx-1,y+sy-1);
|
||||||
|
if(!c)
|
||||||
|
{
|
||||||
|
for(px=x;px<x+sx;px++)
|
||||||
|
{
|
||||||
|
c = Grid(k,px,y);
|
||||||
|
if(c) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(c) // Salto il rettangolo
|
||||||
|
{
|
||||||
|
--c;
|
||||||
|
assert(c>=0);
|
||||||
|
assert(c<n);
|
||||||
|
assert(posiz[c].X()!=-1);
|
||||||
|
x = posiz[c].X() + sizes[c].X();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int nsx = std::max(globalsize[k].X(),x+sx);
|
||||||
|
int nsy = std::max(globalsize[k].Y(),y+sy);
|
||||||
|
int a = nsx*nsy;
|
||||||
|
|
||||||
|
if(besta==-1 || besta>a)
|
||||||
|
{
|
||||||
|
bestx = x;
|
||||||
|
besty = y;
|
||||||
|
bestsx = nsx;
|
||||||
|
bestsy = nsy;
|
||||||
|
besta = a;
|
||||||
|
if( bestsx==globalsize[k].X() && bestsy==globalsize[k].Y() )
|
||||||
|
finterior = 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(finterior) break;
|
||||||
|
}
|
||||||
|
if( finterior ) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(besta==-1) continue; // non c'e' spazio
|
||||||
|
|
||||||
|
besta -= starta;
|
||||||
|
|
||||||
|
if(gbesta==-1 || gbesta>besta)
|
||||||
|
{
|
||||||
|
gbesta = besta;
|
||||||
|
gbestx = bestx;
|
||||||
|
gbesty = besty;
|
||||||
|
gbestsx = bestsx;
|
||||||
|
gbestsy = bestsy;
|
||||||
|
gbestk = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(gbesta==-1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(gbestx>=0);
|
||||||
|
assert(gbesty>=0);
|
||||||
|
assert(gbestk>=0);
|
||||||
|
assert(gbestx<=max_size[0]);
|
||||||
|
assert(gbesty<=max_size[1]);
|
||||||
|
assert(gbestk<ntexture);
|
||||||
|
|
||||||
|
posiz[j].X() = gbestx;
|
||||||
|
posiz[j].Y() = gbesty;
|
||||||
|
texin[j] = gbestk;
|
||||||
|
globalsize[gbestk].X() = gbestsx;
|
||||||
|
globalsize[gbestk].Y() = gbestsy;
|
||||||
|
for(y=posiz[j].Y();y<posiz[j].Y()+sy;y++)
|
||||||
|
for(x=posiz[j].X();x<posiz[j].X()+sx;x++)
|
||||||
|
{
|
||||||
|
assert(x>=0);
|
||||||
|
assert(x<max_size[0]);
|
||||||
|
assert(y>=0);
|
||||||
|
assert(y<max_size[1]);
|
||||||
|
Grid(gbestk,x,y) = j+1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef Grid
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}; // end class
|
}; // end class
|
||||||
} // end namespace vcg
|
} // end namespace vcg
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,6 +20,41 @@ void PolyDumper::rectSetToPolySet(vector< Box2f > &rectVec, vector< vector<Point
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PolyDumper::multiRectSetToSinglePolySet(vector< Box2f > &rectVec, vector<Similarity2f> &trVec, vector<int> &indVec,
|
||||||
|
int ind, vector< vector<Point2f> > &polyVec, vector<Similarity2f> &trPolyVec)
|
||||||
|
{
|
||||||
|
polyVec.clear();
|
||||||
|
trPolyVec.clear();
|
||||||
|
|
||||||
|
for(size_t i=0;i<rectVec.size();++i)
|
||||||
|
if(indVec[i]==ind)
|
||||||
|
{
|
||||||
|
trPolyVec.push_back(trVec[i]);
|
||||||
|
Box2f &b=rectVec[i];
|
||||||
|
polyVec.resize(polyVec.size()+1);
|
||||||
|
polyVec.back().push_back(b.min);
|
||||||
|
polyVec.back().push_back(Point2f(b.max[0],b.min[1]));
|
||||||
|
polyVec.back().push_back(b.max);
|
||||||
|
polyVec.back().push_back(Point2f(b.min[0],b.max[1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyDumper::multiPolySetToSinglePolySet(std::vector< std::vector<Point2f> > &multiPolyVec, std::vector<Similarity2f> &multiTrVec, std::vector<int> &indVec,
|
||||||
|
int ind, std::vector< std::vector<Point2f> > &singlePolyVec, std::vector<Similarity2f> &singleTrVec)
|
||||||
|
{
|
||||||
|
singlePolyVec.clear();
|
||||||
|
singleTrVec.clear();
|
||||||
|
|
||||||
|
for(size_t i=0;i<multiPolyVec.size();++i)
|
||||||
|
if(indVec[i]==ind)
|
||||||
|
{
|
||||||
|
singleTrVec.push_back(multiTrVec[i]);
|
||||||
|
singlePolyVec.resize(singlePolyVec.size()+1);
|
||||||
|
singlePolyVec.back()=multiPolyVec[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void PolyDumper::dumpPolySetSVG(const char * imageName, vector< vector<Point2f> > &polyVec, vector<Similarity2f> &trVec, PolyDumperParam &pp)
|
void PolyDumper::dumpPolySetSVG(const char * imageName, vector< vector<Point2f> > &polyVec, vector<Similarity2f> &trVec, PolyDumperParam &pp)
|
||||||
{
|
{
|
||||||
vector< vector< vector<Point2f> > > polyVecVec(polyVec.size());
|
vector< vector< vector<Point2f> > > polyVecVec(polyVec.size());
|
||||||
|
@ -270,7 +305,7 @@ void PolyDumper::dumpPolySetPNG(const char * imageName,
|
||||||
///FIND THE BARYCENTER
|
///FIND THE BARYCENTER
|
||||||
int radius;
|
int radius;
|
||||||
Point2f bc;
|
Point2f bc;
|
||||||
bc=GetIncenter(polyVecVec[i],trVec[i],radius,100);
|
bc=GetIncenter(polyVecVec[i],trVec[i],radius,10);
|
||||||
|
|
||||||
if (pp.randomColor)
|
if (pp.randomColor)
|
||||||
bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(polyVecVec.size(),i)));
|
bb.setColor(vcg::ColorConverter::ToQColor(Color4b::Scatter(polyVecVec.size(),i)));
|
||||||
|
|
|
@ -70,10 +70,14 @@ class PolyDumper
|
||||||
///this is used to write labels within the polygon, it handle polygons with holes too
|
///this is used to write labels within the polygon, it handle polygons with holes too
|
||||||
static vcg::Point2f GetIncenter(const std::vector< std::vector<vcg::Point2f> > &polyVec,
|
static vcg::Point2f GetIncenter(const std::vector< std::vector<vcg::Point2f> > &polyVec,
|
||||||
const vcg::Similarity2f &tra1,int &radius,int resolution=100);
|
const vcg::Similarity2f &tra1,int &radius,int resolution=100);
|
||||||
|
public:
|
||||||
|
|
||||||
static void rectSetToPolySet(std::vector< vcg::Box2f > &rectVec, std::vector< std::vector<vcg::Point2f> > &polyVec);
|
static void rectSetToPolySet(std::vector< vcg::Box2f > &rectVec, std::vector< std::vector<vcg::Point2f> > &polyVec);
|
||||||
|
static void multiRectSetToSinglePolySet(std::vector< vcg::Box2f > &rectVec, std::vector<vcg::Similarity2f> &trVec, std::vector<int> &indVec,
|
||||||
|
int ind, std::vector< std::vector<vcg::Point2f> > &polyVec, std::vector<vcg::Similarity2f> &trPolyVec);
|
||||||
|
static void multiPolySetToSinglePolySet(std::vector< std::vector< vcg::Point2f> > &multipolyVec, std::vector< vcg::Similarity2f> &trVec, std::vector<int> &indVec,
|
||||||
|
int ind, std::vector< std::vector< vcg::Point2f> > &polyVec, std::vector< vcg::Similarity2f> &trPolyVec);
|
||||||
|
|
||||||
public:
|
|
||||||
///write a polygon on a PNG file, format of the polygon is vector of vector of contours...nested contours are holes
|
///write a polygon on a PNG file, format of the polygon is vector of vector of contours...nested contours are holes
|
||||||
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
///takes the name of the image in input, the set of polygons, the set of per polygons transformation,
|
||||||
///the label to be written and the global parameter for drawing style
|
///the label to be written and the global parameter for drawing style
|
||||||
|
|
Loading…
Reference in New Issue