tweaked rasterized packer
This commit is contained in:
parent
acf2331c70
commit
6c02f53fb1
|
@ -241,6 +241,10 @@ public:
|
||||||
//the width (in pixels) of the gutter added around the outline
|
//the width (in pixels) of the gutter added around the outline
|
||||||
int gutterWidth;
|
int gutterWidth;
|
||||||
|
|
||||||
|
// if false, then do not combine the costs when doubeHorizon is used. This
|
||||||
|
// can help to keep the packing area in a rectangular region
|
||||||
|
bool minmax;
|
||||||
|
|
||||||
///default constructor
|
///default constructor
|
||||||
Parameters()
|
Parameters()
|
||||||
{
|
{
|
||||||
|
@ -250,6 +254,7 @@ public:
|
||||||
permutations=false;
|
permutations=false;
|
||||||
rotationNum = 16;
|
rotationNum = 16;
|
||||||
gutterWidth = 0;
|
gutterWidth = 0;
|
||||||
|
minmax = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -267,11 +272,7 @@ public:
|
||||||
//the bottomHorizon stores the height of the i-th column in the current solution
|
//the bottomHorizon stores the height of the i-th column in the current solution
|
||||||
std::vector<int> mBottomHorizon;
|
std::vector<int> mBottomHorizon;
|
||||||
|
|
||||||
// secondary horizons, these keep track of the space between the bottom of the
|
// inner horizons base and extent (number of free cells)
|
||||||
// grid and the already placed polygons
|
|
||||||
std::vector<int> mSecLeftHorizon;
|
|
||||||
std::vector<int> mSecBottomHorizon;
|
|
||||||
|
|
||||||
std::vector<int> mInnerBottomHorizon;
|
std::vector<int> mInnerBottomHorizon;
|
||||||
std::vector<int> mInnerBottomExtent;
|
std::vector<int> mInnerBottomExtent;
|
||||||
|
|
||||||
|
@ -290,9 +291,6 @@ public:
|
||||||
mBottomHorizon.resize(size.X(), 0);
|
mBottomHorizon.resize(size.X(), 0);
|
||||||
mLeftHorizon.resize(size.Y(), 0);
|
mLeftHorizon.resize(size.Y(), 0);
|
||||||
|
|
||||||
mSecBottomHorizon.resize(size.X(), size.Y() - 1);
|
|
||||||
mSecLeftHorizon.resize(size.Y(), size.X() - 1);
|
|
||||||
|
|
||||||
mInnerBottomHorizon.resize(size.X(), 0);
|
mInnerBottomHorizon.resize(size.X(), 0);
|
||||||
mInnerBottomExtent.resize(size.X(), 0);
|
mInnerBottomExtent.resize(size.X(), 0);
|
||||||
|
|
||||||
|
@ -351,35 +349,22 @@ public:
|
||||||
for (size_t i = 0; i < bottom.size(); ++i) {
|
for (size_t i = 0; i < bottom.size(); ++i) {
|
||||||
int y = mInnerBottomHorizon[col + i] - bottom[i];
|
int y = mInnerBottomHorizon[col + i] - bottom[i];
|
||||||
if (y > y_max) {
|
if (y > y_max) {
|
||||||
if (y + poly.gridHeight(rast_i) >= mSize.Y())
|
if (y + poly.gridHeight(rast_i) >= mSize.Y()) {
|
||||||
return INVALID_POSITION;
|
return INVALID_POSITION;
|
||||||
|
}
|
||||||
y_max = y;
|
y_max = y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// check if the placement is feasible
|
// check if the placement is feasible
|
||||||
for (size_t i = 0; i < bottom.size(); ++i) {
|
for (size_t i = 0; i < bottom.size(); ++i) {
|
||||||
if (y_max + bottom[i] < mBottomHorizon[col + i]
|
if (y_max + bottom[i] < mBottomHorizon[col + i]
|
||||||
&& y_max + bottom[i] + deltaY[i] > mInnerBottomHorizon[col + i] + mInnerBottomExtent[col + i])
|
&& y_max + bottom[i] + deltaY[i] > mInnerBottomHorizon[col + i] + mInnerBottomExtent[col + i]) {
|
||||||
return INVALID_POSITION;
|
return INVALID_POSITION;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return y_max;
|
return y_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pushY(RasterizedOutline2& poly, int col, int rast_i) {
|
|
||||||
std::vector<int>& bottom = poly.getBottom(rast_i);
|
|
||||||
std::vector<int>& deltaY = poly.getDeltaY(rast_i);
|
|
||||||
int y_min = INT_MAX;
|
|
||||||
for (size_t i = 0; i < bottom.size(); ++i) {
|
|
||||||
int y = mSecBottomHorizon[col + i] - (bottom[i] + deltaY[i]);
|
|
||||||
if (y < y_min) {
|
|
||||||
if (y < 0)
|
|
||||||
return INVALID_POSITION;
|
|
||||||
y_min = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return y_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
//given a poly and the row at which it is placed,
|
//given a poly and the row at which it is placed,
|
||||||
//this returns the X at which the wasted space is minimum
|
//this returns the X at which the wasted space is minimum
|
||||||
//i.e. the X at which the polygon touches the left horizon
|
//i.e. the X at which the polygon touches the left horizon
|
||||||
|
@ -418,21 +403,6 @@ public:
|
||||||
return x_max;
|
return x_max;
|
||||||
}
|
}
|
||||||
|
|
||||||
int pushX(RasterizedOutline2& poly, int row, int rast_i) {
|
|
||||||
std::vector<int>& left = poly.getLeft(rast_i);
|
|
||||||
std::vector<int>& deltaX = poly.getDeltaX(rast_i);
|
|
||||||
int x_min = INT_MAX;
|
|
||||||
for (size_t i = 0; i < left.size(); ++i) {
|
|
||||||
int x = mSecLeftHorizon[row + i] - (left[i] + deltaX[i]);
|
|
||||||
if (x < x_min) {
|
|
||||||
if (x < 0)
|
|
||||||
return INVALID_POSITION;
|
|
||||||
x_min = x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return x_min;
|
|
||||||
}
|
|
||||||
|
|
||||||
int costYWithPenaltyOnX(RasterizedOutline2& poly, Point2i pos, int rast_i) {
|
int costYWithPenaltyOnX(RasterizedOutline2& poly, Point2i pos, int rast_i) {
|
||||||
std::vector<int>& left = poly.getLeft(rast_i);
|
std::vector<int>& left = poly.getLeft(rast_i);
|
||||||
std::vector<int>& deltaX = poly.getDeltaX(rast_i);
|
std::vector<int>& deltaX = poly.getDeltaX(rast_i);
|
||||||
|
@ -508,20 +478,20 @@ public:
|
||||||
{
|
{
|
||||||
//return pos.Y() + poly.gridHeight(rast_i);
|
//return pos.Y() + poly.gridHeight(rast_i);
|
||||||
|
|
||||||
int cost = -INT_MAX;
|
int maxY = -INT_MAX;
|
||||||
std::vector<int>& bottom = poly.getBottom(rast_i);
|
std::vector<int>& bottom = poly.getBottom(rast_i);
|
||||||
std::vector<int>& deltaY = poly.getDeltaY(rast_i);
|
std::vector<int>& deltaY = poly.getDeltaY(rast_i);
|
||||||
for (unsigned i = 0; i < bottom.size(); ++i) {
|
for (unsigned i = 0; i < bottom.size(); ++i) {
|
||||||
int currentCost;
|
int yi = 0;
|
||||||
if (pos.Y() + bottom[i] + deltaY[i] < mBottomHorizon[pos.X() + i]) {
|
if (pos.Y() + bottom[i] + deltaY[i] < mBottomHorizon[pos.X() + i]) {
|
||||||
currentCost = -(pos.Y() + bottom[i]);
|
yi = -(pos.Y() + bottom[i]);
|
||||||
} else {
|
} else {
|
||||||
currentCost = pos.Y() + bottom[i] + deltaY[i];
|
yi = pos.Y() + bottom[i] + deltaY[i];
|
||||||
}
|
}
|
||||||
if (currentCost > cost)
|
if (yi > maxY)
|
||||||
cost = currentCost;
|
maxY = yi;
|
||||||
}
|
}
|
||||||
return cost;
|
return maxY;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -529,20 +499,20 @@ public:
|
||||||
{
|
{
|
||||||
//return pos.X() + poly.gridWidth(rast_i);
|
//return pos.X() + poly.gridWidth(rast_i);
|
||||||
|
|
||||||
int cost = -INT_MAX;
|
int maxX = -INT_MAX;
|
||||||
std::vector<int>& left = poly.getLeft(rast_i);
|
std::vector<int>& left = poly.getLeft(rast_i);
|
||||||
std::vector<int>& deltaX = poly.getDeltaX(rast_i);
|
std::vector<int>& deltaX = poly.getDeltaX(rast_i);
|
||||||
for (unsigned i = 0; i < left.size(); ++i) {
|
for (unsigned i = 0; i < left.size(); ++i) {
|
||||||
int currentCost = 0;
|
int xi = 0;
|
||||||
if (pos.X() + left[i] + deltaX[i] < mLeftHorizon[pos.Y() + i]) {
|
if (pos.X() + left[i] + deltaX[i] < mLeftHorizon[pos.Y() + i]) {
|
||||||
currentCost = -(pos.X() + left[i]);
|
xi = -(pos.X() + left[i]);
|
||||||
} else {
|
} else {
|
||||||
currentCost = pos.X() + left[i] + deltaX[i];
|
xi = pos.X() + left[i] + deltaX[i];
|
||||||
}
|
}
|
||||||
if (currentCost > cost)
|
if (xi > maxX)
|
||||||
currentCost = cost;
|
maxX = xi;
|
||||||
}
|
}
|
||||||
return cost;
|
return maxX;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the number of empty cells between the poly's left side and the
|
/* Returns the number of empty cells between the poly's left side and the
|
||||||
|
@ -614,16 +584,8 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int secBtmHor = pos.Y() + bottom[i];
|
|
||||||
if (secBtmHor < mSecBottomHorizon[pos.X() + i])
|
|
||||||
mSecBottomHorizon[pos.X() + i] = secBtmHor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (params.costFunction != Parameters::MixedCost
|
|
||||||
&& !params.doubleHorizon) return;
|
|
||||||
*/
|
|
||||||
|
|
||||||
//update left horizon
|
//update left horizon
|
||||||
for (int i = 0; i < poly.gridHeight(rast_i); i++) {
|
for (int i = 0; i < poly.gridHeight(rast_i); i++) {
|
||||||
int tmpHor = pos.X() + left[i] + deltaX[i];
|
int tmpHor = pos.X() + left[i] + deltaX[i];
|
||||||
|
@ -656,10 +618,6 @@ public:
|
||||||
mInnerLeftExtent[pos.Y() + i] = 0;
|
mInnerLeftExtent[pos.Y() + i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int secLeftHor = pos.X() + left[i];
|
|
||||||
if (secLeftHor < mSecLeftHorizon[pos.Y() + i])
|
|
||||||
mSecLeftHorizon[pos.Y() + i] = secLeftHor;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -811,51 +769,36 @@ public:
|
||||||
return trials;
|
return trials;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PackAtFixedScale(std::vector<std::vector<Point2x>> &polyPointsVec,
|
/*
|
||||||
const std::vector<Point2i> &containerSizes,
|
* Pack charts using a best effort policy. The idea is that this function
|
||||||
std::vector<Similarity2x> &trVec,
|
* packs what it can in the given space without scaling the outlines.
|
||||||
std::vector<int> &polyToContainer,
|
*
|
||||||
const Parameters &packingPar,
|
* Returns the number of charts actually packed.
|
||||||
float scale)
|
*
|
||||||
{
|
* Function parameters:
|
||||||
//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:
|
|
||||||
* 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
|
||||||
* trVec (OUT) vector of transformations that must be applied to the objects
|
* trVec (OUT) vector of transformations that must be applied to the objects
|
||||||
* 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
|
static int
|
||||||
*
|
|
||||||
* 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
|
|
||||||
PackBestEffort(std::vector<std::vector<Point2x>> &outline2Vec,
|
PackBestEffort(std::vector<std::vector<Point2x>> &outline2Vec,
|
||||||
const std::vector<Point2i> &containerSizes,
|
const std::vector<Point2i> &containerSizes,
|
||||||
std::vector<Similarity2x> &trVec,
|
std::vector<Similarity2x> &trVec,
|
||||||
std::vector<int> &polyToContainer,
|
std::vector<int> &polyToContainer,
|
||||||
const Parameters &packingPar)
|
const Parameters &packingPar)
|
||||||
|
{
|
||||||
|
return PackBestEffortAtScale(outline2Vec, containerSizes, trVec, polyToContainer, packingPar, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Same as PackBestEffort() but allows to specify the outlines scaling factor */
|
||||||
|
static int
|
||||||
|
PackBestEffortAtScale(std::vector<std::vector<Point2x>> &outline2Vec,
|
||||||
|
const std::vector<Point2i> &containerSizes,
|
||||||
|
std::vector<Similarity2x> &trVec,
|
||||||
|
std::vector<int> &polyToContainer,
|
||||||
|
const Parameters &packingPar, float scaleFactor)
|
||||||
{
|
{
|
||||||
std::vector<RasterizedOutline2> polyVec(outline2Vec.size());
|
std::vector<RasterizedOutline2> polyVec(outline2Vec.size());
|
||||||
for(size_t i=0;i<polyVec.size();i++) {
|
for(size_t i=0;i<polyVec.size();i++) {
|
||||||
|
@ -867,18 +810,18 @@ public:
|
||||||
std::vector<std::vector<int>> trials = InitializePermutationVectors(outline2Vec, packingPar);
|
std::vector<std::vector<int>> trials = InitializePermutationVectors(outline2Vec, packingPar);
|
||||||
int bestNumPlaced = 0;
|
int bestNumPlaced = 0;
|
||||||
for (std::size_t i = 0; i < trials.size(); ++i) {
|
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<Similarity2x> trVecIter;
|
||||||
std::vector<int> polyToContainerIter;
|
std::vector<int> polyToContainerIter;
|
||||||
PolyPacking(outline2Vec, containerSizes, trVecIter, polyToContainerIter, packingPar, 1.0, polyVec, trials[i], true);
|
PolyPacking(outline2Vec, containerSizes, trVecIter, polyToContainerIter, packingPar, scaleFactor, polyVec, trials[i], true);
|
||||||
int numPlaced = outline2Vec.size() - std::count(polyToContainerIter.begin(), polyToContainerIter.end(), -1);
|
int numPlaced = outline2Vec.size() - std::count(polyToContainerIter.begin(), polyToContainerIter.end(), -1);
|
||||||
if (numPlaced > bestNumPlaced) {
|
if (numPlaced > bestNumPlaced) {
|
||||||
trVec = trVecIter;
|
trVec = trVecIter;
|
||||||
polyToContainer = polyToContainerIter;
|
polyToContainer = polyToContainerIter;
|
||||||
|
bestNumPlaced = numPlaced;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestNumPlaced > 0;
|
return bestNumPlaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
//tries to pack polygons using the given gridSize and scaleFactor
|
//tries to pack polygons using the given gridSize and scaleFactor
|
||||||
|
@ -942,11 +885,13 @@ public:
|
||||||
//look for the best position, dropping from top
|
//look for the best position, dropping from top
|
||||||
for (int col = 0; col < maxCol; col++) {
|
for (int col = 0; col < maxCol; col++) {
|
||||||
int currPolyY;
|
int currPolyY;
|
||||||
|
if (!placedUsingSecondaryHorizon) {
|
||||||
currPolyY = packingFields[grid_i].dropY(polyVec[i],col, rast_i);
|
currPolyY = packingFields[grid_i].dropY(polyVec[i],col, rast_i);
|
||||||
if (currPolyY != INVALID_POSITION) {
|
if (currPolyY != INVALID_POSITION) {
|
||||||
assert(currPolyY + polyVec[i].gridHeight(rast_i) < gridSizes[grid_i].Y() && "drop");
|
assert(currPolyY + polyVec[i].gridHeight(rast_i) < gridSizes[grid_i].Y() && "drop");
|
||||||
int currCost = packingFields[grid_i].getCostX(polyVec[i], Point2i(col, currPolyY), rast_i) +
|
int currCost = packingFields[grid_i].getCostY(polyVec[i], Point2i(col, currPolyY), rast_i);
|
||||||
packingFields[grid_i].getCostY(polyVec[i], Point2i(col, currPolyY), rast_i);
|
if (packingPar.doubleHorizon && (packingPar.minmax == true))
|
||||||
|
currCost += packingFields[grid_i].getCostX(polyVec[i], Point2i(col, currPolyY), rast_i);
|
||||||
if (currCost < bestCost) {
|
if (currCost < bestCost) {
|
||||||
bestContainer = grid_i;
|
bestContainer = grid_i;
|
||||||
bestCost = currCost;
|
bestCost = currCost;
|
||||||
|
@ -956,13 +901,15 @@ public:
|
||||||
placedUsingSecondaryHorizon = false;
|
placedUsingSecondaryHorizon = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (packingPar.innerHorizon) {
|
if (packingPar.innerHorizon) {
|
||||||
currPolyY = packingFields[grid_i].dropYInner(polyVec[i],col, rast_i);
|
currPolyY = packingFields[grid_i].dropYInner(polyVec[i],col, rast_i);
|
||||||
if (currPolyY != INVALID_POSITION) {
|
if (currPolyY != INVALID_POSITION) {
|
||||||
assert(currPolyY + polyVec[i].gridHeight(rast_i) < gridSizes[grid_i].Y() && "drop_inner");
|
assert(currPolyY + polyVec[i].gridHeight(rast_i) < gridSizes[grid_i].Y() && "drop_inner");
|
||||||
int currCost = packingFields[grid_i].getCostX(polyVec[i], Point2i(col, currPolyY), rast_i) +
|
int currCost = packingFields[grid_i].getCostY(polyVec[i], Point2i(col, currPolyY), rast_i);
|
||||||
packingFields[grid_i].getCostY(polyVec[i], Point2i(col, currPolyY), rast_i);
|
if (packingPar.doubleHorizon && (packingPar.minmax == true))
|
||||||
if (currCost < bestCost) {
|
currCost += packingFields[grid_i].getCostX(polyVec[i], Point2i(col, currPolyY), rast_i);
|
||||||
|
if (!placedUsingSecondaryHorizon || currCost < bestCost) {
|
||||||
bestContainer = grid_i;
|
bestContainer = grid_i;
|
||||||
bestCost = currCost;
|
bestCost = currCost;
|
||||||
bestRastIndex = rast_i;
|
bestRastIndex = rast_i;
|
||||||
|
@ -979,11 +926,13 @@ public:
|
||||||
|
|
||||||
for (int row = 0; row < maxRow; row++) {
|
for (int row = 0; row < maxRow; row++) {
|
||||||
int currPolyX;
|
int currPolyX;
|
||||||
|
if (!placedUsingSecondaryHorizon) {
|
||||||
currPolyX = packingFields[grid_i].dropX(polyVec[i],row, rast_i);
|
currPolyX = packingFields[grid_i].dropX(polyVec[i],row, rast_i);
|
||||||
if (currPolyX != INVALID_POSITION) {
|
if (currPolyX != INVALID_POSITION) {
|
||||||
assert(currPolyX + polyVec[i].gridWidth(rast_i) < gridSizes[grid_i].X() && "drop");
|
assert(currPolyX + polyVec[i].gridWidth(rast_i) < gridSizes[grid_i].X() && "drop");
|
||||||
int currCost = packingFields[grid_i].getCostY(polyVec[i], Point2i(currPolyX, row), rast_i) +
|
int currCost = packingFields[grid_i].getCostX(polyVec[i], Point2i(currPolyX, row), rast_i);
|
||||||
packingFields[grid_i].getCostX(polyVec[i], Point2i(currPolyX, row), rast_i);
|
if (packingPar.doubleHorizon && (packingPar.minmax == true))
|
||||||
|
currCost += packingFields[grid_i].getCostY(polyVec[i], Point2i(currPolyX, row), rast_i);
|
||||||
if (currCost < bestCost) {
|
if (currCost < bestCost) {
|
||||||
bestContainer = grid_i;
|
bestContainer = grid_i;
|
||||||
bestCost = currCost;
|
bestCost = currCost;
|
||||||
|
@ -993,14 +942,15 @@ public:
|
||||||
placedUsingSecondaryHorizon = false;
|
placedUsingSecondaryHorizon = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (packingPar.innerHorizon) {
|
if (packingPar.innerHorizon) {
|
||||||
currPolyX = packingFields[grid_i].dropXInner(polyVec[i],row, rast_i);
|
currPolyX = packingFields[grid_i].dropXInner(polyVec[i],row, rast_i);
|
||||||
if (currPolyX != INVALID_POSITION) {
|
if (currPolyX != INVALID_POSITION) {
|
||||||
assert(currPolyX + polyVec[i].gridWidth(rast_i) < gridSizes[grid_i].X() && "drop_inner");
|
assert(currPolyX + polyVec[i].gridWidth(rast_i) < gridSizes[grid_i].X() && "drop_inner");
|
||||||
int currCost = packingFields[grid_i].getCostY(polyVec[i], Point2i(currPolyX, row), rast_i) +
|
int currCost = packingFields[grid_i].getCostX(polyVec[i], Point2i(currPolyX, row), rast_i);
|
||||||
packingFields[grid_i].getCostX(polyVec[i], Point2i(currPolyX, row), rast_i);
|
if (packingPar.doubleHorizon && (packingPar.minmax == true))
|
||||||
if (currCost < bestCost) {
|
currCost += packingFields[grid_i].getCostY(polyVec[i], Point2i(currPolyX, row), rast_i);
|
||||||
|
if (!placedUsingSecondaryHorizon || currCost < bestCost) {
|
||||||
bestContainer = grid_i;
|
bestContainer = grid_i;
|
||||||
bestCost = currCost;
|
bestCost = currCost;
|
||||||
bestRastIndex = rast_i;
|
bestRastIndex = rast_i;
|
||||||
|
|
|
@ -39,8 +39,9 @@ void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
|
||||||
// and adding the gutter width.
|
// and adding the gutter width.
|
||||||
int sizeX = (int)ceil(bb.DimX()*scale);
|
int sizeX = (int)ceil(bb.DimX()*scale);
|
||||||
int sizeY = (int)ceil(bb.DimY()*scale);
|
int sizeY = (int)ceil(bb.DimY()*scale);
|
||||||
sizeX += gutterWidth;
|
int safetyBuffer = 2;
|
||||||
sizeY += gutterWidth;
|
sizeX += (gutterWidth + safetyBuffer);
|
||||||
|
sizeY += (gutterWidth + safetyBuffer);
|
||||||
|
|
||||||
QImage img(sizeX,sizeY,QImage::Format_RGB32);
|
QImage img(sizeX,sizeY,QImage::Format_RGB32);
|
||||||
QColor backgroundColor(Qt::transparent);
|
QColor backgroundColor(Qt::transparent);
|
||||||
|
@ -66,7 +67,7 @@ void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
|
||||||
painter.setPen(qp);
|
painter.setPen(qp);
|
||||||
|
|
||||||
painter.resetTransform();
|
painter.resetTransform();
|
||||||
painter.translate(QPointF(-(bb.min.X()*scale) + gutterWidth/2.0f, -(bb.min.Y()*scale) + gutterWidth/2.0f));
|
painter.translate(QPointF(-(bb.min.X()*scale) + (gutterWidth + safetyBuffer)/2.0f, -(bb.min.Y()*scale) + (gutterWidth + safetyBuffer)/2.0f));
|
||||||
painter.rotate(math::ToDeg(rotRad));
|
painter.rotate(math::ToDeg(rotRad));
|
||||||
painter.scale(scale,scale);
|
painter.scale(scale,scale);
|
||||||
|
|
||||||
|
@ -102,7 +103,7 @@ void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
|
||||||
painter.setPen(qp);
|
painter.setPen(qp);
|
||||||
|
|
||||||
painter.resetTransform();
|
painter.resetTransform();
|
||||||
painter.translate(QPointF(-(bb.min.X()*scale) + gutterWidth/2.0f, -(bb.min.Y()*scale) + gutterWidth/2.0f));
|
painter.translate(QPointF(-(bb.min.X()*scale) + (gutterWidth + safetyBuffer)/2.0f, -(bb.min.Y()*scale) + (gutterWidth + safetyBuffer)/2.0f));
|
||||||
painter.rotate(math::ToDeg(rotRad));
|
painter.rotate(math::ToDeg(rotRad));
|
||||||
painter.scale(scale,scale);
|
painter.scale(scale,scale);
|
||||||
|
|
||||||
|
@ -195,10 +196,11 @@ void QtOutline2Rasterizer::rasterize(RasterizedOutline2 &poly,
|
||||||
for (int y = 0; y < img.height(); y++) {
|
for (int y = 0; y < img.height(); y++) {
|
||||||
const uchar* line = img.scanLine(y);
|
const uchar* line = img.scanLine(y);
|
||||||
for(int x = 0; x < img.width(); ++x) {
|
for(int x = 0; x < img.width(); ++x) {
|
||||||
if (((QRgb*)line)[x] == yellow)
|
if (((QRgb*)line)[x] == yellow) {
|
||||||
tetrisGrid[y][x] = 1;
|
tetrisGrid[y][x] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//create the 4 rasterizations (one every 90°) using the discrete representation grid we've just created
|
//create the 4 rasterizations (one every 90°) using the discrete representation grid we've just created
|
||||||
int rotationOffset = rotationNum/4;
|
int rotationOffset = rotationNum/4;
|
||||||
|
|
Loading…
Reference in New Issue