寻找空白空间的公式

本文关键字:空间 空白 寻找 | 更新日期: 2023-09-27 18:17:47

查看图片参考

大家好,

我需要一个逻辑的建议。我的场景是,

有一个空白,Size is Height: 200, Width 200

  • 我正在填充一些空间Height: 100, Width 100

  • 再次填充Height : 50 Width : 50

我只想找到有方向的空白。例如

如果我尝试占用Height = 100 and Width = 200,它是正确的

如果我试图占用Height = 200 and width = 100,它应该说这是错误的。

看图片看清楚

如何处理这种情况…什么好主意吗?


感谢大家的宝贵时间,我认为我的问题没有足够的细节,好的,这里添加一些更多的信息与例子,

我有一个大小为(200 × 200)(高×宽)的木头

  • 首先要切割尺寸为100 x 100的木材(这里我需要公式来检查这个值在这个木材中是否可用)
  • 现在公式应该显示Yes it is available

  • 再次想用50x50的尺寸剪切(这里我需要公式来检查这个值在这个木材中是否可用)-现在公式应该显示Yes it is available

  • 再次想要剪切的尺寸为100 * 200(高:200,宽:100)-现在公式应该显示,No this space is not available

  • 再次想要剪切的尺寸为200 * 100(高度:100,宽度:200)

    • 现在公式应该显示Yes it is available

注:切割尺寸可更改我希望你能理解我想说的话

谢谢

寻找空白空间的公式

你的问题不够明确,无法给你一个完整的答案。无论如何,在这篇文章中,你可以找到一个解决方案,将一系列矩形放置到一个封闭的矩形中。

解决方案的关键是在DynamicTwoDimensionArray类中:每次你在空闲空间中添加一个矩形时,你都会将你的区域切割成四个部分,其中三个仍然是空的。如果你记住了所有空闲空间的高度和宽度,你只需要测试新矩形是否可以容纳其中任何一个。

在OP编辑了它的问题之后,现在清楚了它的程序要做什么。

我给出的另一个答案是指一个完整的程序,很难遵循,很难在设计中使用,所以我决定从头开始做所有的东西。

也许对于任何被分配到二维装箱问题的学生来说,这将更容易理解和使用。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace WoodCutter {
    /// <summary>
    /// This class represents a continuous area of wood
    /// </summary>
    public class Freespace {
        private int x, y, height, width;
        /// <summary>
        /// Public constructor of the class
        /// </summary>
        /// <param name="x">Leftmost position of the area</param>
        /// <param name="y">Topmost position of the area</param>
        /// <param name="height">Vertical extent of the area</param>
        /// <param name="width">Horizontal extent of the area</param>
        public Freespace(int x, int y, int height, int width) {
            this.x = x;
            this.y = y;
            this.height = height;
            this.width = width;
        }
        /// <summary>
        /// Leftmost position of the area
        /// </summary>
        public int xLeft {
            get { return this.x; }
        }
        /// <summary>
        /// Topmost position of the area
        /// </summary>
        public int yUp {
            get { return this.y; }
        }
        /// <summary>
        /// Tests if this area can contain a cut of the given height and width
        /// </summary>
        /// <param name="height">Vertical extent of the needed cut</param>
        /// <param name="width">Horizontal extent of the needed cut</param>
        /// <returns>true if this Freespce can contain the needed cut else false</returns>
        public bool Contains(int height, int width) {
            if (this.width >= width && this.height >= height) {
                return true;
            }
            return false;
        }
        /// <summary>
        /// Creates cuts from this Freespace
        /// If the proposed cut does not intersect with this Freespace, do nothing and return a List containing this.
        /// If the proposed cut completely contains this Freespace, return an empty List.
        /// When the cut intersects the Freespace, cut the Freespace with the semiplanes around the desired cut
        /// </summary>
        /// <param name="x">Leftmost position of the cut</param>
        /// <param name="y">Topmost position of the cut</param>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        /// <returns>List of Freespaces created from the intersection of the Freespace and the cut</returns>
        public List<Freespace> Cut(int x, int y, int height, int width) {
            List<Freespace> res = new List<Freespace>();
            if ((x - this.x) >= this.width || 
                (y - this.y) >= this.height || 
                (x + width) < this.x || 
                (y + height) < this.y) {
                // no intersection, return myself
                res.Add(this);
                return res;
            }
            if (x <= this.x && 
                y <= this.y && 
                (x + width) >= (this.x + this.width) && 
                (y + height) >= (this.y + this.height)) {
                // the cut covers the whole freespce, return empty list
                return res;
            }
            if (x > this.x) {
                // cut this freespace with the semiplane of abscissas less than x
                res.Add(new Freespace(this.x, this.y, this.height, x - this.x));
            }
            if (y > this.y) {
                // cut this freespace with the semiplane of ordinates less than y
                res.Add(new Freespace(this.x, this.y, y - this.y, this.width));
            }
            if ((x + width) < (this.x + this.width)) {
                // cut this freespace with the semiplane of abscissas greater than x+width
                res.Add(new Freespace(x + width, this.y, this.height, this.width - width));
            }
            if ((y + height) < (this.y + this.height)) {   
                // cut this freespace with the semiplane of ordinates greater than y+height
                res.Add(new Freespace(x, y + height, this.height - height, this.width));
            }
            return res;
        }
        public void Write2Console() {
            Console.WriteLine("Freespace at {0},{1} of dimensions {2},{3}", this.x, this.y, this.width, this.height);
        }
    }
    /// <summary>
    /// This class holds a List of Freespaces that can be cut
    /// At the beginning you have only one Freespace covering the whole plane, 
    /// adding cuts the List gets populated with all the residual areas.
    /// </summary>
    public class Wood {
        private List<Freespace> freeSpaces;
        /// <summary>
        /// Public constructor
        /// </summary>
        /// <param name="height">Vertical extent of the area</param>
        /// <param name="width">Horizontal extent of the area</param>
        public Wood(int height, int width) {
            this.freeSpaces = new List<Freespace>();
            this.freeSpaces.Add(new Freespace(0, 0, height, width));
        }
        /// <summary>
        /// Returns the first Freespace (or null) that can contain the whole cut
        /// </summary>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        /// <returns>First Freespace completely containing the cut or null</returns>
        public Freespace canCut(int height, int width) {
            foreach (Freespace f in this.freeSpaces) {
                if (f.Contains(height, width)) {
                    return f;
                }
            }
            return null;
        }
        /// <summary>
        /// Makes the cut in the Wood.
        /// Intersects the desired cut with all the Freespaces in the List.
        /// WARNING. No check is made, at this point, if you can do the cut. 
        ///          You have to call the canCut function before using this method 
        ///          and take the adequate coordinates from the Freespace returned.
        /// </summary>
        /// <param name="x">Leftmost position of the cut</param>
        /// <param name="y">Topmost position of the cut</param>
        /// <param name="height">Vertical extent of the cut</param>
        /// <param name="width">Horizontal extent of the cut</param>
        public void Cut(int x, int y, int height, int width) {
            List<Freespace> freeSpaces = new List<Freespace>();
            foreach (Freespace f in this.freeSpaces) {
                freeSpaces.AddRange(f.Cut(x, y, height, width));
            }
            this.freeSpaces = freeSpaces;
        }
        public void Write2Console() {
            foreach (Freespace f in this.freeSpaces) {
                f.Write2Console();
            }
        }
    }
    class WoodCutter {
        /// <summary>
        /// Tests if a cut can be made in the wood and, if true
        /// cuts it at the upper leftmost coordinate of the first
        /// adequate Freespace found.
        /// </summary>
        /// <param name="wood">The wood to cut</param>
        /// <param name="width">The width of thr cut</param>
        /// <param name="heigth">The height of the cut</param>
        private static void testCut(Wood wood, int width, int heigth) {
            Freespace f;
            f = wood.canCut(heigth, width);
            if (f != null) {
                Console.WriteLine("Can cut a {0} by {1} piece", width, heigth);
                wood.Cut(f.xLeft, f.yUp, heigth, width);
            } else {
                Console.WriteLine("Cannot fit a {0} by {1} piece", width, heigth);
            }
        }
        static void Main(string[] args) {
            // Let's start with a 200X200 wood
            Wood wood = new Wood(200, 200);
            wood.Write2Console();
            //Try and cut a 100X100 piece
            testCut(wood, 100, 100);
            wood.Write2Console();
            //Try and cut a 50X50 piece
            testCut(wood, 50, 50);
            wood.Write2Console();
            //Try to cut a 100X200 piece (this should fail)
            testCut(wood, 100, 200);
            wood.Write2Console();
            //Try and cut a 200X100 piece
            testCut(wood, 200, 100);
            wood.Write2Console();
            Console.WriteLine("Program end.");
        }
    }
}

你能做的最好的事情就是运行代码并逐步了解它是如何工作的。以下是预期的输出:

Freespace at 0,0 of dimensions 200,200
Can cut a 100 by 100 piece
Freespace at 100,0 of dimensions 100,200
Freespace at 0,100 of dimensions 200,100
Can cut a 50 by 50 piece
Freespace at 150,0 of dimensions 50,200
Freespace at 100,50 of dimensions 100,150
Freespace at 0,100 of dimensions 200,100
Cannot fit a 100 by 200 piece
Freespace at 150,0 of dimensions 50,200
Freespace at 100,50 of dimensions 100,150
Freespace at 0,100 of dimensions 200,100
Can cut a 200 by 100 piece
Freespace at 150,0 of dimensions 50,100
Freespace at 100,50 of dimensions 100,50

希望它能有所帮助,有任何问题请投票和评论:d

此解决方案适用于假定填充的面积为常数的情况。

private static bool NewValueFit(int xfoo, int ybar)
{
    if (xfoo > 200 || ybar > 200)
        return false;            
    if (ybar <= 100)
        return true;
    else if (ybar <= 150)
    {
        if (xfoo <= 100)
            return true;
    else
            return false;
    }
    else if (xfoo <= 50)
        return true;
    else
        return false;
}