// Start the recursion. public void AlgFillByStripes(int bin_width, ImgRectangle[] rects) { // Sort by height. ImgRectangle[] best_rects = (ImgRectangle[])rects.Clone(); Array.Sort(best_rects, new HeightComparer()); // Make variables to track and record the best solution. bool[] is_positioned = new bool[best_rects.Length]; int num_unpositioned = best_rects.Length; // Fill by stripes. int max_y = 0; for (int i = 0; i <= rects.Length - 1; i++) { // See if this rectangle is positioned. if (!is_positioned[i]) { // Start a new stripe. num_unpositioned -= 1; is_positioned[i] = true; best_rects[i].X = 0; best_rects[i].Y = max_y; FillBoundedArea( best_rects[i].Width, bin_width, max_y, max_y + best_rects[i].Height, ref num_unpositioned, ref best_rects, ref is_positioned); if (num_unpositioned == 0) break; max_y += best_rects[i].Height; } } // Save the best solution. Array.Copy(best_rects, rects, rects.Length); }
// Use rectangles to fill the given sub-area. // Set the following for the best solution we find: // xmin, xmax, etc. - Bounds of the rectangle we are trying to fill. // num_unpositioned - The number of rectangles not yet positioned in this solution. // Used to control the recursion. // rects() - All rectangles for the problem, some positioned and others not. // Initially this is the partial solution we are working from. // At end, this is the best solution we could find. // is_positioned() - Indicates which rectangles are positioned in this solution. // max_y - The largest Y value for this solution. private void FillBoundedArea( int xmin, int xmax, int ymin, int ymax, ref int num_unpositioned, ref ImgRectangle[] rects, ref bool[] is_positioned) { // See if every rectangle has been positioned. if (num_unpositioned <= 0) return; // Save a copy of the solution so far. int best_num_unpositioned = num_unpositioned; ImgRectangle[] best_rects = (ImgRectangle[])rects.Clone(); bool[] best_is_positioned = (bool[])is_positioned.Clone(); // Currently we have no solution for this area. double best_density = 0; // Some rectangles have not been positioned. // Loop through the available rectangles. for (int i = 0; i <= rects.Length - 1; i++) { // See if this rectangle is not position and will fit. if ((!is_positioned[i]) && (rects[i].Width <= xmax - xmin) && (rects[i].Height <= ymax - ymin)) { // It will fit. Try it. // ************************************************** // Divide the remaining area horizontally. int test1_num_unpositioned = num_unpositioned - 1; ImgRectangle[] test1_rects = (ImgRectangle[])rects.Clone(); bool[] test1_is_positioned = (bool[])is_positioned.Clone(); test1_rects[i].X = xmin; test1_rects[i].Y = ymin; test1_is_positioned[i] = true; // Fill the area on the right. FillBoundedArea(xmin + rects[i].Width, xmax, ymin, ymin + rects[i].Height, ref test1_num_unpositioned, ref test1_rects, ref test1_is_positioned); // Fill the area on the bottom. FillBoundedArea(xmin, xmax, ymin + rects[i].Height, ymax, ref test1_num_unpositioned, ref test1_rects, ref test1_is_positioned); // Learn about the test solution. double test1_density = SolutionDensity( xmin + rects[i].Width, xmax, ymin, ymin + rects[i].Height, xmin, xmax, ymin + rects[i].Height, ymax, test1_rects, test1_is_positioned); // See if this is better than the current best solution. if (test1_density >= best_density) { // The test is better. Save it. best_density = test1_density; best_rects = test1_rects; best_is_positioned = test1_is_positioned; best_num_unpositioned = test1_num_unpositioned; } // ************************************************** // Divide the remaining area vertically. int test2_num_unpositioned = num_unpositioned - 1; ImgRectangle[] test2_rects = (ImgRectangle[])rects.Clone(); bool[] test2_is_positioned = (bool[])is_positioned.Clone(); test2_rects[i].X = xmin; test2_rects[i].Y = ymin; test2_is_positioned[i] = true; // Fill the area on the right. FillBoundedArea(xmin + rects[i].Width, xmax, ymin, ymax, ref test2_num_unpositioned, ref test2_rects, ref test2_is_positioned); // Fill the area on the bottom. FillBoundedArea(xmin, xmin + rects[i].Width, ymin + rects[i].Height, ymax, ref test2_num_unpositioned, ref test2_rects, ref test2_is_positioned); // Learn about the test solution. double test2_density = SolutionDensity( xmin + rects[i].Width, xmax, ymin, ymax, xmin, xmin + rects[i].Width, ymin + rects[i].Height, ymax, test2_rects, test2_is_positioned); // See if this is better than the current best solution. if (test2_density >= best_density) { // The test is better. Save it. best_density = test2_density; best_rects = test2_rects; best_is_positioned = test2_is_positioned; best_num_unpositioned = test2_num_unpositioned; } } // End trying this rectangle. } // End looping through the rectangles. // Return the best solution we found. is_positioned = best_is_positioned; num_unpositioned = best_num_unpositioned; rects = best_rects; }