diff --git a/vcg/math/similarity2.h b/vcg/math/similarity2.h new file mode 100644 index 00000000..602f0d0f --- /dev/null +++ b/vcg/math/similarity2.h @@ -0,0 +1,60 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __VCG_SIMILARITY2_H +#define __VCG_SIMILARITY2_H +namespace vcg +{ + +/* + This class codify a similarity transformation in 2D + + The applied transformation is exactly the same of the Similarity class + Tra(Sca(Rot(P))) +*/ + +template +class Similarity2 +{ +public: + Similarity2():rotRad(0),tra(0,0),sca(1) {} + + SCALAR_TYPE rotRad; + Point2 tra; + SCALAR_TYPE sca; +}; + +template +Point2 operator*(const Similarity2 &m, const Point2 &p) { + Point2 r = p; + // Apply Rotation to point + r.Rotate(m.rotRad); + r *= m.sca; + r += m.tra; + return r; +} + +typedef Similarity2 Similarity2f; +typedef Similarity2 Similarity2d; + +} // end namespace vcg +#endif // __VCG_SIMILARITY2_H diff --git a/vcg/space/poly_packer.h b/vcg/space/poly_packer.h new file mode 100644 index 00000000..305addd3 --- /dev/null +++ b/vcg/space/poly_packer.h @@ -0,0 +1,169 @@ +/**************************************************************************** +* VCGLib o o * +* Visual and Computer Graphics Library o o * +* _ O _ * +* Copyright(C) 2004 \/)\/ * +* Visual Computing Lab /\/| * +* ISTI - Italian National Research Council | * +* \ * +* All rights reserved. * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * +* for more details. * +* * +****************************************************************************/ +#ifndef __VCG_POLY_PACKER_H__ +#define __VCG_POLY_PACKER_H__ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace vcg +{ + +template +class PolyPacker +{ + typedef typename vcg::Box2 Box2x; + typedef typename vcg::Point2 Point2x; + typedef typename vcg::Similarity2 Similarity2x; + +public: + + static Box2f getPolyBB(const std::vector &poly) + { + Box2f bb; + for(size_t i=0;i &poly, float &rot) + { + const int stepNum=16; + float bestAngle; + float bestArea = std::numeric_limits::max(); + Box2f bestBB; + + for(int i=0;i > &polyVec, + const Point2x containerSizeX, + std::vector &trVec, + Point2x &coveredContainer) +{ + int minSide = int( std::min(containerSizeX[0],containerSizeX[1])); + const vcg::Point2i containerSize(minSide,minSide); + int polyPerLine = ceil(sqrt(polyVec.size())); + int pixelPerPoly = minSide / (polyPerLine); + if(pixelPerPoly < 1) return false; + + trVec.clear(); + trVec.resize(polyVec.size()); + Box2f bbMax; + std::vector bbVec; + for(int i=0;iminSide) + { + baseY+=pixelPerPoly; + baseX=0; + } + } + return true; +} + +static bool PackAsAxisAlignedRect(const std::vector< std::vector > &polyVec, + const Point2x containerSizeX, + std::vector &trVec, + Point2x &coveredContainer) +{ + trVec.clear(); + trVec.resize(polyVec.size()); + std::vector bbVec; + for(int i=0;i0); + bbVec.push_back(getPolyBB(polyVec[i])); + } + return RectPacker::Pack(bbVec,containerSizeX,trVec,coveredContainer); +} + +static bool PackAsObjectOrientedRect(const std::vector< std::vector > &polyVec, + const Point2x containerSizeX, + std::vector &trVec, + Point2x &coveredContainer) +{ + trVec.clear(); + trVec.resize(polyVec.size()); + std::vector bbVec; + std::vector rotVec; + for(int i=0;i::Pack(bbVec,containerSizeX,trVec,coveredContainer); + + for(int i=0;i +#include +#include +#include +#include +#include + +namespace vcg +{ + +template +class RectPacker +{ + typedef typename vcg::Box2 Box2x; + typedef typename vcg::Point2 Point2x; + typedef typename vcg::Similarity2 Similarity2x; + +public: + static bool Pack(const std::vector & 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) + std::vector &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position + Point2x &coveredContainer) /// the sub portion of the container covered by the solution. +{ + float bestOccupancy=0,currOccupancy=0.1f; + std::vector currTrVec; + Point2x currCovered; + + bool ret=true; + while(ret) + { + ret=PackOccupancy(rectVec,containerSizeX,currOccupancy,currTrVec,currCovered); + if(ret) + { + assert(currOccupancy>bestOccupancy); + bestOccupancy = currOccupancy; + trVec=currTrVec; + coveredContainer=currCovered; + currOccupancy = (2.0*currOccupancy+1.0)/3.0; + } + } + if(bestOccupancy>0) return true; + return false; +} + + +static bool PackOccupancy(const std::vector & 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 SCALAR_TYPE occupancyRatio, /// the expected percentage of the container that has to be covered + std::vector &trVec, /// the result, a set of similarity transformation that have to be applied to the rect to get their position + 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]; + + for (size_t i=0;i sizes(rectVec.size()); + for (size_t i=0;i posiz; + vcg::Point2i global_size; + + bool res = PackInt(sizes,containerSize,posiz,global_size); + if(!res) return false; + + trVec.resize(rectVec.size()); + for (size_t i=0;i & v; + inline ComparisonFunctor( const std::vector & nv ) : v(nv) { } + + inline bool operator() ( int a, int b ) + { + const Point2i &va=v[a]; + const Point2i &vb=v[b]; + + return (va[1]!=vb[1])?(va[1]>vb[1]): + (va[0]>vb[0]); + } +}; + + +/* 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 & sizes, // the sizes of the rect to be packed + const vcg::Point2i & max_size, // the size of the container + std::vector & 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 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 perm(n); + for(i=0;imax_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=0 && x=0 && y=0 && j0 && 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=0 && carea) + { + 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=0 && x=0 && y