Added function to pack at fixed scale into a given number of container
This commit is contained in:
parent
19adc39387
commit
5ab1b189a0
|
@ -175,15 +175,16 @@ public:
|
||||||
template <class ScalarType>
|
template <class ScalarType>
|
||||||
class ComparisonFunctor
|
class ComparisonFunctor
|
||||||
{
|
{
|
||||||
|
typedef std::vector<vcg::Point2<ScalarType>> Outline2Type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::vector<RasterizedOutline2> & v;
|
const std::vector<Outline2Type> & v;
|
||||||
inline ComparisonFunctor( std::vector<RasterizedOutline2> & nv ) : v(nv) { }
|
inline ComparisonFunctor(const std::vector<Outline2Type> & nv ) : v(nv) { }
|
||||||
|
|
||||||
inline bool operator() ( int a, int b )
|
inline bool operator() ( int a, int b )
|
||||||
{
|
{
|
||||||
float area1 = tri::OutlineUtil<ScalarType>::Outline2Area(v[a].getPoints());
|
float area1 = tri::OutlineUtil<ScalarType>::Outline2Area(v[a]);
|
||||||
float area2 = tri::OutlineUtil<ScalarType>::Outline2Area(v[b].getPoints());
|
float area2 = tri::OutlineUtil<ScalarType>::Outline2Area(v[b]);
|
||||||
|
|
||||||
return area1 > area2;
|
return area1 > area2;
|
||||||
}
|
}
|
||||||
|
@ -702,7 +703,6 @@ public:
|
||||||
float optimalScale = sqrt(gridArea / totalArea);
|
float optimalScale = sqrt(gridArea / totalArea);
|
||||||
|
|
||||||
|
|
||||||
std::vector<std::vector<int>> trials;
|
|
||||||
|
|
||||||
//create the vector of polys, starting for the poly points we received as parameter
|
//create the vector of polys, starting for the poly points we received as parameter
|
||||||
std::vector<RasterizedOutline2> polyVec(polyPointsVec.size());
|
std::vector<RasterizedOutline2> polyVec(polyPointsVec.size());
|
||||||
|
@ -710,36 +710,7 @@ public:
|
||||||
polyVec[i].setPoints(polyPointsVec[i]);
|
polyVec[i].setPoints(polyPointsVec[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
std::vector<std::vector<int>> trials = InitializePermutationVectors(polyPointsVec, packingPar);
|
||||||
// Build a permutation that holds the indexes of the polys ordered by their area
|
|
||||||
std::vector<int> perm(polyVec.size());
|
|
||||||
for(size_t i = 0; i < polyVec.size(); i++)
|
|
||||||
perm[i] = i;
|
|
||||||
sort(perm.begin(), perm.end(), ComparisonFunctor<float>(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<SCALAR_TYPE>::Outline2Area(polyPointsVec[perm[0]]);
|
|
||||||
float thresholdArea = largestArea * 0.5;
|
|
||||||
std::size_t i;
|
|
||||||
for (i = 0; i < polyVec.size(); ++i)
|
|
||||||
if (tri::OutlineUtil<SCALAR_TYPE>::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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double bestEfficiency = 0;
|
double bestEfficiency = 0;
|
||||||
for (std::size_t i = 0; i < trials.size(); ++i) {
|
for (std::size_t i = 0; i < trials.size(); ++i) {
|
||||||
|
@ -803,6 +774,71 @@ public:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<std::vector<int>>
|
||||||
|
InitializePermutationVectors(const std::vector<std::vector<Point2x>>& polyPointsVec,
|
||||||
|
const Parameters& packingPar)
|
||||||
|
{
|
||||||
|
std::vector<std::vector<int>> trials;
|
||||||
|
|
||||||
|
// Build a permutation that holds the indexes of the polys ordered by their area
|
||||||
|
std::vector<int> perm(polyPointsVec.size());
|
||||||
|
for(size_t i = 0; i < polyPointsVec.size(); i++)
|
||||||
|
perm[i] = i;
|
||||||
|
sort(perm.begin(), perm.end(), ComparisonFunctor<float>(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<SCALAR_TYPE>::Outline2Area(polyPointsVec[perm[0]]);
|
||||||
|
float thresholdArea = largestArea * 0.5;
|
||||||
|
std::size_t i;
|
||||||
|
for (i = 0; i < polyPointsVec.size(); ++i)
|
||||||
|
if (tri::OutlineUtil<SCALAR_TYPE>::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<std::vector<Point2x>> &polyPointsVec,
|
||||||
|
const std::vector<Point2i> &containerSizes,
|
||||||
|
std::vector<Similarity2x> &trVec,
|
||||||
|
std::vector<int> &polyToContainer,
|
||||||
|
const Parameters &packingPar,
|
||||||
|
float scale)
|
||||||
|
{
|
||||||
|
//create the vector of polys, starting for the poly points we received as parameter
|
||||||
|
std::vector<RasterizedOutline2> polyVec(polyPointsVec.size());
|
||||||
|
for(size_t i=0;i<polyVec.size();i++) {
|
||||||
|
polyVec[i].setPoints(polyPointsVec[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::vector<int>> trials = InitializePermutationVectors(polyPointsVec, packingPar);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < trials.size(); ++i) {
|
||||||
|
std::vector<Similarity2x> trVecIter;
|
||||||
|
std::vector<int> polyToContainerIter;
|
||||||
|
if (PolyPacking(polyPointsVec, containerSizes, trVecIter, polyToContainerIter, packingPar, scale, polyVec, trials[i])) {
|
||||||
|
trVec = trVecIter;
|
||||||
|
polyToContainer = polyToContainerIter;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* Function parameters:
|
/* Function parameters:
|
||||||
* outline2Vec (IN) vector of outlines to pack
|
* outline2Vec (IN) vector of outlines to pack
|
||||||
* containerSizes (IN) vector of container (grid) sizes
|
* containerSizes (IN) vector of container (grid) sizes
|
||||||
|
@ -810,6 +846,8 @@ public:
|
||||||
* polyToContainer (OUT) vector of outline-to-container mappings. If polyToContainer[i] == -1
|
* 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
|
* 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
|
* 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 */
|
* outlines, and returns enough information to the caller in order to decide what to do */
|
||||||
static bool
|
static bool
|
||||||
|
@ -824,14 +862,23 @@ public:
|
||||||
polyVec[i].setPoints(outline2Vec[i]);
|
polyVec[i].setPoints(outline2Vec[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int> perm(polyVec.size());
|
polyToContainer.resize(outline2Vec.size(), -1);
|
||||||
for(size_t i = 0; i < polyVec.size(); i++)
|
|
||||||
perm[i] = i;
|
|
||||||
sort(perm.begin(), perm.end(), ComparisonFunctor<float>(polyVec));
|
|
||||||
|
|
||||||
PolyPacking(outline2Vec, containerSizes, trVec, polyToContainer, packingPar, 1.0, polyVec, perm, true);
|
std::vector<std::vector<int>> 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<Similarity2x> trVecIter;
|
||||||
|
std::vector<int> 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
|
//tries to pack polygons using the given gridSize and scaleFactor
|
||||||
|
|
Loading…
Reference in New Issue