Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C语言中,二进制数组将映射简化为矩形#_C#_Arrays_Algorithm_Optimization_Reduction - Fatal编程技术网

C# 在C语言中,二进制数组将映射简化为矩形#

C# 在C语言中,二进制数组将映射简化为矩形#,c#,arrays,algorithm,optimization,reduction,C#,Arrays,Algorithm,Optimization,Reduction,给定以下c#数组: 视觉上类似于这样: 是否有任何现有的方法将其转换为尽可能少的矩形区域 一个可能的解决方案可能是: var output = new List<Rectangle> { new Rectangle(0, 0, 4, 1), new Rectangle(5, 0, 3, 2), new Rectangle(8, 1, 1, 1), new Rectangle(0, 2, 10, 2),

给定以下c#数组:

视觉上类似于这样:

是否有任何现有的方法将其转换为尽可能少的矩形区域

一个可能的解决方案可能是:

    var output = new List<Rectangle>
    {
        new Rectangle(0, 0, 4, 1),
        new Rectangle(5, 0, 3, 2),
        new Rectangle(8, 1, 1, 1),
        new Rectangle(0, 2, 10, 2),
        // ... etc
    };

理想情况下,我正在寻找能够生成矩形列表的东西:

    public IEnumerable<Rectangle> ReduceMap(bool[,] map)
    {
        List<Rectangle> rects = new List<Rectangle>();
        int width = map.GetLength(0), height = map.GetLength(1);

        // Reduce
        // ....?

        return rects;
    }
public IEnumerable约简映射(bool[,]映射)
{
List rects=新列表();
int width=map.GetLength(0),height=map.GetLength(1);
//减少
// ....?
返回矩形;
}
其结果是:

    var output = new List<Rectangle>
    {
        new Rectangle(0, 0, 4, 1),
        new Rectangle(5, 0, 3, 2),
        new Rectangle(8, 1, 1, 1),
        new Rectangle(0, 2, 10, 2),
        // ... etc
    };
var输出=新列表
{
新矩形(0,0,4,1),
新矩形(5,0,3,2),
新矩形(8,1,1,1),
新矩形(0,2,10,2),
//…等等
};
速度也很重要,矩形越少越好,但找到一个合适的解决方案不应该在计算上过于昂贵


抱歉,如果之前有人回答过,如果有人知道该去哪里看,那就太好了

这是一个有趣的问题。
您是否看过以下文章?它提供了有关此主题的良好信息,并讨论了解决此问题的不同方法(四叉树、形态学、图形):
这来自Ojdo对这个问题的回答

我会开始看那里!希望这能有所帮助。

这是我自己能想到的最好办法,如果有人能在这方面有所改进,我很乐意将其作为答案

这种方法使用多个过程来合并阵列,似乎可以很好地减少阵列,大致与上面的图表一致,但肯定不是最优的

我为测试创建了一个小提琴:

使用系统;
使用System.Collections.Generic;
使用系统图;
公共课程
{
私有常量字符串模式1=@“
XXXX\U XXX__
_____XXXX_
XXXXXXXXX
XXXXXXXXX
_XXX_X_uuxx
_XXX_XX_XX
___XX_____
XX_XX_XXX_
_XX_uuuuuxxxxx
__XX_uuuxxxx
";
私有常量字符串模式2=@“
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXXXX
";
私有常量字符串模式3=@“
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXX
XXXXXXXXX
XXXXXXXXX
XXXXXXX\u XX
XXXXXXX\u XX
XXXXXXX\u XX
XXXXXXX\u XX
";
私有常量字符串模式4=@“
XXXXXXXX
X_XX__XXXX
XXXXXXXX
X_XXXX__XX
XXXXX\U XXXX
XXX_uuuuuxxxxx
XXXX_XX_XX
XXX_XXX_XX
XXXXX\u X\u XX
XXX_XXX_XX
";
私有常量字符串模式5=@“
XXXXXXXXX
__XXXXXXXX
____XXXXXX
_____XXXXX
______XXXX
______XXXX
_____XXXXX
____XXXXXX
__XXXXXXXX
XXXXXXXXX
";
公共静态void Main()
{
bool[,]map=PatternTo2DArray(pattern1);
//bool[,]map=PatternTo2DArray(pattern2);
//bool[,]map=PatternTo2DArray(pattern3);
//bool[,]map=PatternTo2DArray(pattern4);
//bool[,]map=PatternTo2DArray(pattern5);
var rects=还原映射(map);
int指数=0;
foreach(在rects中的var rect)
{
WriteLine({0}:{{{{1}、{2}、{3}、{4}}}、((索引+1).ToString().PadLeft(1,'0'))、rect.X、rect.Y、rect.Width、rect.Height);
索引++;
}
var总计=转储映射(映射);
WriteLine(\r\n从:{0}到{1}的优化映射,总计,索引);
}
公共静态IEnumerable约简映射(布尔[,]映射)
{
int width=map.GetLength(0),height=map.GetLength(1);
MapElement[,]bin=新的MapElement[宽度,高度];
//减少
//步骤1:转换为地图元素:
对于(int y=0;yusing System;
using System.Collections.Generic;
using System.Drawing;

public class Program
{
    private const string pattern1 = @"
XXXX_XXX__
_____XXXX_
XXXXXXXXXX
XXXXXXXXXX
_XXX_X__XX
_XXX_XX_XX
___XX_____
XX_XX_XXX_
_XX__XXXXX
__XX__XXXX
";

    private const string pattern2 = @"
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
";

    private const string pattern3 = @"
X_XXXXXXXX
X_XXXXXXXX
X_XXXXXXXX
X_XXXXXXXX
XXXXXXXXXX
XXXXXXXXXX
XXXXXXX_XX
XXXXXXX_XX
XXXXXXX_XX
XXXXXXX_XX
";

    private const string pattern4 = @"
X_XXXXXXXX
X_XX__XXXX
X_XXXXXXXX
X_XXXX__XX
XXXXX_XXXX
XXX__XXXXX
XXXX_XX_XX
XXX_XXX_XX
XXXXX_X_XX
XXX_XXX_XX
";

    private const string pattern5 = @"
XXXXXXXXXX
__XXXXXXXX
____XXXXXX
_____XXXXX
______XXXX
______XXXX
_____XXXXX
____XXXXXX
__XXXXXXXX
XXXXXXXXXX
";

    public static void Main()
    {
        bool[,] map = PatternTo2DArray(pattern1);
        //bool[,] map = PatternTo2DArray(pattern2);
        //bool[,] map = PatternTo2DArray(pattern3);
        //bool[,] map = PatternTo2DArray(pattern4);
        //bool[,] map = PatternTo2DArray(pattern5);

        var rects = ReduceMap(map);
        int index = 0;
        foreach (var rect in rects)
        {
            Console.WriteLine("{0}: {{ {1}, {2}, {3}, {4} }}", ((index + 1).ToString().PadLeft(1, '0')), rect.X, rect.Y, rect.Width, rect.Height);
            index++;
        }

        var total = DumpMap(map);
        Console.WriteLine("\r\nOptimised Map From: {0} to {1}", total, index);
    }

    public static IEnumerable<Rectangle> ReduceMap(bool[,] map)
    {
        int width = map.GetLength(0), height = map.GetLength(1);
        MapElement[,] bin = new MapElement[width, height];

        // Reduce
        // Step 1: Convert to map elements:
        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
            {
                if (map[x, y])
                    bin[x, y] = new MapElement() { X = x, Y = y, Width = 1, Height = 1, Set = true };
            }

        // Step 2: Process the bin map and generate a collection of Rectangles horizontally     
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // Only care about this if we are set.
                if (bin[x, y].Set)
                {
                    // Scan forward and link this tile with its following tiles
                    int xx = 0;
                    for (int xForward = x + 1; xForward < width; xForward++)
                    {
                        if (!bin[xForward, y].Set)
                            break;

                        // We can link this...
                        bin[xForward, y].Set = false;
                        bin[x, y].Width++;
                        xx++; // Skip over these tiles.
                    }

                    x += xx;
                }
            }
        }

        // Step 3: Process the bin map veritically and join any blocks that have equivalent blocks below them.
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // Only care about this if we are set.
                if (bin[x, y].Set)
                {
                    // Scan down and link this tile with its following tiles
                    for (int yDown = y + 1; yDown < height; yDown++)
                    {
                        if (!bin[x, yDown].Set || bin[x, yDown].Width != bin[x, y].Width)  // We might be able to link this if it's the same size
                            break;

                        bin[x, yDown].Set = false;
                        bin[x, y].Height++;
                    }
                }
            }
        }

        // Step 4: Convert map to rectangles
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                // Only care about this if we are set.
                if (bin[x, y].Set)
                {
                    var b = bin[x, y];
                    yield return new Rectangle(b.X, b.Y, b.Width, b.Height);
                }
            }
        }
    }

    public static int DumpMap(bool[,] map)
    {
        Console.WriteLine("");
        var @out = 0;
        int width = map.GetLength(0), height = map.GetLength(1);
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                Console.Write(map[x, y] ? "X" : "_");
                @out++;
            }

            Console.WriteLine();
        }

        return @out;
    }

    public static int CountDataPoints(bool[,] map)
    {
        var @out = 0;
        int width = map.GetLength(0), height = map.GetLength(1);
        for (int y = 0; y < height; y++)
            for (int x = 0; x < width; x++)
                if (map[x, y])
                    @out++;

        return @out;
    }

    public static bool[,] PatternTo2DArray(string pattern)
    {
        var lines = new List<string>(pattern.Split('\n'));
        for (int i = lines.Count - 1; i > -1; i--)
        {
            string line = lines[i].TrimEnd('\r');
            if (line.Length == 0)
                lines.RemoveAt(i);
            else
                lines[i] = line;
        }

        var @out = new bool[lines[0].Length, lines.Count];
        for (int y = 0; y < lines.Count; y++)
        {
            string line = lines[y];
            for (int x = 0; x < line.Length; x++)
            {
                @out[x, y] = !(line[x] == '_');
            }
        }

        return @out;
    }

    internal struct MapElement
    {
        public int X;
        public int Y;
        public int Width;
        public int Height;
        public bool Set;
    }
}