Removed wasted space determination code entirely - it'll be in my repository should I ever want to see it again ;)
git-svn-id: file:///srv/devel/repo-conversion/nusu@26 d2e56fa2-650e-0410-a79f-9358c0239efd
This commit is contained in:
parent
9157bf8454
commit
02cea246b5
|
@ -41,56 +41,6 @@ namespace Nuclex.Support.Packing {
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public class CygonRectanglePacker : RectanglePacker {
|
public class CygonRectanglePacker : RectanglePacker {
|
||||||
|
|
||||||
#if USE_WASTED_AREA
|
|
||||||
// An optimization idea of mine. With this, the packer not only tries to place
|
|
||||||
// rectangles as low in the packing area as possible, it also tried to choose
|
|
||||||
// locations where it doesn't block gaps where other rectangles might still fit
|
|
||||||
// in. This turned out to be counter-productive and a marginal improvement in
|
|
||||||
// space efficiency could be achieved by deliberately choosing positions where
|
|
||||||
// gaps where blocked for future rectangles.
|
|
||||||
//
|
|
||||||
// These are the results of a benchmark with different wastedAreaScoreWeights
|
|
||||||
//
|
|
||||||
// -10 579.315
|
|
||||||
// -5 582.140
|
|
||||||
// -4 582.886
|
|
||||||
// -3 583.166
|
|
||||||
// -2 583.792
|
|
||||||
// -1 583.975 (best)
|
|
||||||
// 0 583.791
|
|
||||||
// 1 583.960
|
|
||||||
// 2 583.469
|
|
||||||
// 3 582.444
|
|
||||||
// 4 580.259
|
|
||||||
// 5 578.400
|
|
||||||
// 10 570.467
|
|
||||||
//
|
|
||||||
// Needless to say, I chose to disable this splendid optimization.
|
|
||||||
|
|
||||||
/// <summary>By how much the wasted area influences a placement's score</summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// The score of a potential position for a new rectangle is how far the
|
|
||||||
/// rectangle is from the lower end of the packing area. The lower the
|
|
||||||
/// score, the better the position.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// Often, however, it's better to choose a position that's farther from
|
|
||||||
/// the lower end of the packing area to not block a gap in which a future
|
|
||||||
/// rectangle might still fit in. To account for this fact, the packer
|
|
||||||
/// calculates a "wasted area factor", which is the amount of area that
|
|
||||||
/// would forever go to waste in relation of the area the rectangle has.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// This value controls the weighting of this wasted area factor in the
|
|
||||||
/// potential position's score. Finding a value that works well for typical
|
|
||||||
/// packing problems is a matter of trial and error, as it seems :)
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
private const int WastedAreaScoreWeight = 10;
|
|
||||||
|
|
||||||
#endif // USE_WASTED_AREA
|
|
||||||
|
|
||||||
#region class SliceStartComparer
|
#region class SliceStartComparer
|
||||||
|
|
||||||
/// <summary>Compares the starting position of height slices</summary>
|
/// <summary>Compares the starting position of height slices</summary>
|
||||||
|
@ -189,32 +139,6 @@ namespace Nuclex.Support.Packing {
|
||||||
if((highest + rectangleHeight < PackingAreaHeight)) {
|
if((highest + rectangleHeight < PackingAreaHeight)) {
|
||||||
int score = highest;
|
int score = highest;
|
||||||
|
|
||||||
#if USE_WASTED_AREA // --------------------------------------------------------
|
|
||||||
|
|
||||||
// Calculate the amount of space that would go to waste if the rectangle
|
|
||||||
// would be placed at this location
|
|
||||||
int wastedArea = 0;
|
|
||||||
for(int index = leftSliceIndex; index < rightSliceIndex - 1; ++index) {
|
|
||||||
int sliceWidth = this.heightSlices[index + 1].X - this.heightSlices[index].X;
|
|
||||||
wastedArea += (highest - this.heightSlices[index].Y) * sliceWidth;
|
|
||||||
}
|
|
||||||
wastedArea +=
|
|
||||||
(highest - this.heightSlices[rightSliceIndex - 1].Y) *
|
|
||||||
(
|
|
||||||
(this.heightSlices[leftSliceIndex].X + rectangleWidth) -
|
|
||||||
this.heightSlices[rightSliceIndex - 1].X
|
|
||||||
);
|
|
||||||
|
|
||||||
// Limit wasted area to the area taken up by the rectangle. This prevents
|
|
||||||
// a "build-up" of wasted area that become more expensive the higher the packing
|
|
||||||
// area is filled.
|
|
||||||
wastedArea = Math.Min(wastedArea, rectangleArea);
|
|
||||||
|
|
||||||
// Alter the score by the amount of wasted area in relation to
|
|
||||||
score += (wastedArea * WastedAreaScoreWeight / rectangleArea);
|
|
||||||
|
|
||||||
#endif // USE_WASTED_AREA -----------------------------------------------------
|
|
||||||
|
|
||||||
if(score < bestScore) {
|
if(score < bestScore) {
|
||||||
bestSliceIndex = leftSliceIndex;
|
bestSliceIndex = leftSliceIndex;
|
||||||
bestSliceY = highest;
|
bestSliceY = highest;
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace Nuclex.Support.Packing {
|
||||||
|
|
||||||
/// <summary>Delegate for a Rectangle Packer factory method</summary>
|
/// <summary>Delegate for a Rectangle Packer factory method</summary>
|
||||||
/// <returns>A new rectangle packer</returns>
|
/// <returns>A new rectangle packer</returns>
|
||||||
protected delegate RectanglePacker BuildRectanglePacker();
|
protected delegate RectanglePacker RectanglePackerBuilder();
|
||||||
|
|
||||||
/// <summary>Determines the efficiency of a packer with a packing area of 70x70</summary>
|
/// <summary>Determines the efficiency of a packer with a packing area of 70x70</summary>
|
||||||
/// <param name="packer">Packer with a packing area of 70x70 units</param>
|
/// <param name="packer">Packer with a packing area of 70x70 units</param>
|
||||||
|
@ -59,14 +59,14 @@ namespace Nuclex.Support.Packing {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Benchmarks the provided rectangle packer using random data</summary>
|
/// <summary>Benchmarks the provided rectangle packer using random data</summary>
|
||||||
/// <param name="packerBuilder">
|
/// <param name="buildPacker">
|
||||||
/// Rectangle packer builder returning new rectangle packers
|
/// Rectangle packer build method returning new rectangle packers
|
||||||
/// with an area of 1024 x 1024
|
/// with an area of 1024 x 1024
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <returns>The achieved benchmark score</returns>
|
/// <returns>The achieved benchmark score</returns>
|
||||||
protected float Benchmark(BuildRectanglePacker packerBuilder) {
|
protected float Benchmark(RectanglePackerBuilder buildPacker) {
|
||||||
// How many runs to perform for getting a stable average
|
// How many runs to perform for getting a stable average
|
||||||
const int averagingRuns = 200;
|
const int averagingRuns = 1;
|
||||||
|
|
||||||
// Generates the random number seeds. This is used so that each run produces
|
// Generates the random number seeds. This is used so that each run produces
|
||||||
// the same number sequences and makes the comparison of different algorithms
|
// the same number sequences and makes the comparison of different algorithms
|
||||||
|
@ -77,7 +77,7 @@ namespace Nuclex.Support.Packing {
|
||||||
// Perform a number of runs to get a semi-stable average score
|
// Perform a number of runs to get a semi-stable average score
|
||||||
for(int averagingRun = 0; averagingRun < averagingRuns; ++averagingRun) {
|
for(int averagingRun = 0; averagingRun < averagingRuns; ++averagingRun) {
|
||||||
Random dimensionGenerator = new Random(seedGenerator.Next());
|
Random dimensionGenerator = new Random(seedGenerator.Next());
|
||||||
RectanglePacker packer = packerBuilder();
|
RectanglePacker packer = buildPacker();
|
||||||
|
|
||||||
// Try to cramp as many rectangles into the packing area as possible
|
// Try to cramp as many rectangles into the packing area as possible
|
||||||
for(;; ++rectanglesPacked) {
|
for(;; ++rectanglesPacked) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user