From 5ab1b189a096b8cb27b316c07cde11d4a50a13c7 Mon Sep 17 00:00:00 2001 From: Andrea Maggiordomo Date: Fri, 1 Feb 2019 10:53:31 +0100 Subject: [PATCH] Added function to pack at fixed scale into a given number of container --- vcg/space/rasterized_outline2_packer.h | 129 +++++++++++++++++-------- 1 file changed, 88 insertions(+), 41 deletions(-) diff --git a/vcg/space/rasterized_outline2_packer.h b/vcg/space/rasterized_outline2_packer.h index a0f0149b..e4dfc721 100644 --- a/vcg/space/rasterized_outline2_packer.h +++ b/vcg/space/rasterized_outline2_packer.h @@ -175,15 +175,16 @@ public: template class ComparisonFunctor { + typedef std::vector> Outline2Type; public: - std::vector & v; - inline ComparisonFunctor( std::vector & nv ) : v(nv) { } + const std::vector & v; + inline ComparisonFunctor(const std::vector & nv ) : v(nv) { } inline bool operator() ( int a, int b ) { - float area1 = tri::OutlineUtil::Outline2Area(v[a].getPoints()); - float area2 = tri::OutlineUtil::Outline2Area(v[b].getPoints()); + float area1 = tri::OutlineUtil::Outline2Area(v[a]); + float area2 = tri::OutlineUtil::Outline2Area(v[b]); return area1 > area2; } @@ -702,7 +703,6 @@ public: float optimalScale = sqrt(gridArea / totalArea); - std::vector> trials; //create the vector of polys, starting for the poly points we received as parameter std::vector polyVec(polyPointsVec.size()); @@ -710,36 +710,7 @@ public: polyVec[i].setPoints(polyPointsVec[i]); } - { - // Build a permutation that holds the indexes of the polys ordered by their area - std::vector perm(polyVec.size()); - for(size_t i = 0; i < polyVec.size(); i++) - perm[i] = i; - sort(perm.begin(), perm.end(), ComparisonFunctor(polyVec)); - - trials.push_back(perm); - - // if using permutations, determine the number of random permutations and compute them - if (packingPar.permutations) { - int minObjNum = std::min(5, int(perm.size())); - float largestArea = tri::OutlineUtil::Outline2Area(polyPointsVec[perm[0]]); - float thresholdArea = largestArea * 0.5; - std::size_t i; - for (i = 0; i < polyVec.size(); ++i) - if (tri::OutlineUtil::Outline2Area(polyPointsVec[perm[i]]) < thresholdArea) - break; - int numPermutedObjects = std::max(minObjNum, int(i)); - //int permutationCount = numPermutedObjects < 5 ? 20 : numPermutedObjects * 20; - int permutationCount = numPermutedObjects * 5; - std::cout << "PACKING: trying " << permutationCount << " random permutations of the largest " - << numPermutedObjects << " elements" << std::endl; - std::srand(12345); - for (int k = 0; k < permutationCount; ++k) { - std::random_shuffle(perm.begin(), perm.begin() + numPermutedObjects); - trials.push_back(perm); - } - } - } + std::vector> trials = InitializePermutationVectors(polyPointsVec, packingPar); double bestEfficiency = 0; for (std::size_t i = 0; i < trials.size(); ++i) { @@ -803,6 +774,71 @@ public: return true; } + static std::vector> + InitializePermutationVectors(const std::vector>& polyPointsVec, + const Parameters& packingPar) + { + std::vector> trials; + + // Build a permutation that holds the indexes of the polys ordered by their area + std::vector perm(polyPointsVec.size()); + for(size_t i = 0; i < polyPointsVec.size(); i++) + perm[i] = i; + sort(perm.begin(), perm.end(), ComparisonFunctor(polyPointsVec)); + + trials.push_back(perm); + + // if packing with random permutations, compute a small number of randomized + // sequences. Each random sequence is generated from the initial permutation + // by shuffling only the larger polygons + if (packingPar.permutations) { + int minObjNum = std::min(5, int(perm.size())); + float largestArea = tri::OutlineUtil::Outline2Area(polyPointsVec[perm[0]]); + float thresholdArea = largestArea * 0.5; + std::size_t i; + for (i = 0; i < polyPointsVec.size(); ++i) + if (tri::OutlineUtil::Outline2Area(polyPointsVec[perm[i]]) < thresholdArea) + break; + int numPermutedObjects = std::max(minObjNum, int(i)); + int permutationCount = numPermutedObjects * 5; + //printf("PACKING: trying %d random permutations of the largest %d elements\n", permutationCount, numPermutedObjects); + for (int k = 0; k < permutationCount; ++k) { + std::random_shuffle(perm.begin(), perm.begin() + numPermutedObjects); + trials.push_back(perm); + } + } + + return trials; + } + + static bool PackAtFixedScale(std::vector> &polyPointsVec, + const std::vector &containerSizes, + std::vector &trVec, + std::vector &polyToContainer, + const Parameters &packingPar, + float scale) + { + //create the vector of polys, starting for the poly points we received as parameter + std::vector polyVec(polyPointsVec.size()); + for(size_t i=0;i> trials = InitializePermutationVectors(polyPointsVec, packingPar); + + for (std::size_t i = 0; i < trials.size(); ++i) { + std::vector trVecIter; + std::vector polyToContainerIter; + if (PolyPacking(polyPointsVec, containerSizes, trVecIter, polyToContainerIter, packingPar, scale, polyVec, trials[i])) { + trVec = trVecIter; + polyToContainer = polyToContainerIter; + return true; + } + } + + return false; + } + /* Function parameters: * outline2Vec (IN) vector of outlines to pack * containerSizes (IN) vector of container (grid) sizes @@ -810,6 +846,8 @@ public: * polyToContainer (OUT) vector of outline-to-container mappings. If polyToContainer[i] == -1 * then outline i did not fit in the packing grids, and the transformation trVec[i] is meaningless * + * Returns true if it packed at least one polygon into the container + * * The idea is that this function packs what it can in the given space without transforming the * outlines, and returns enough information to the caller in order to decide what to do */ static bool @@ -824,14 +862,23 @@ public: polyVec[i].setPoints(outline2Vec[i]); } - std::vector perm(polyVec.size()); - for(size_t i = 0; i < polyVec.size(); i++) - perm[i] = i; - sort(perm.begin(), perm.end(), ComparisonFunctor(polyVec)); + polyToContainer.resize(outline2Vec.size(), -1); - PolyPacking(outline2Vec, containerSizes, trVec, polyToContainer, packingPar, 1.0, polyVec, perm, true); + std::vector> trials = InitializePermutationVectors(outline2Vec, packingPar); + int bestNumPlaced = 0; + for (std::size_t i = 0; i < trials.size(); ++i) { + // TODO this should probably attempt at maximizing the occupancy and/or the number of placed polygons + std::vector trVecIter; + std::vector polyToContainerIter; + PolyPacking(outline2Vec, containerSizes, trVecIter, polyToContainerIter, packingPar, 1.0, polyVec, trials[i], true); + int numPlaced = outline2Vec.size() - std::count(polyToContainerIter.begin(), polyToContainerIter.end(), -1); + if (numPlaced > bestNumPlaced) { + trVec = trVecIter; + polyToContainer = polyToContainerIter; + } + } - return true; + return bestNumPlaced > 0; } //tries to pack polygons using the given gridSize and scaleFactor