C#实现不规则图形分割成多个矩形组合可视化工具, 核心是一个找最大内切矩形的算法

4 篇文章 0 订阅
2 篇文章 0 订阅

有个项目,有些不规则区域,想转成尽可能少的小矩形。 用C#做了一个可视化的工具:

忽略面积<= 4的:

核心算法:一组二维数据找到其中最大内切矩形区域,并扩展了一下,把四周剩余区域切割递归找矩形。


找最大矩形参考代码:
https://stackoverflow.com/questions/7245/puzzle-find-largest-rectangle-maximal-rectangle-problem/20039017#20039017
https://www.drdobbs.com/database/the-maximal-rectangle-problem/184410529?pgno=1

其中最核心的找最大矩形类算法类:
 


        public class Rect
        {
            public int x1 = 0;
            public int y1 = 0;
            public int x2 = 0;
            public int y2 = 0;
            public Rect() { }
            public Rect(int _x1, int _y1, int _x2, int _y2)
            {
                x1 = _x1;
                y1 = _y1;
                x2 = _x2;
                y2 = _y2;
            }

            public override string ToString()
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("[(");
                sb.Append(x1);
                sb.Append(",");
                sb.Append(y1);
                sb.Append(")-(");
                sb.Append(x2);
                sb.Append(",");
                sb.Append(y2);
                sb.Append(")]");
                return sb.ToString();
            }
        }

        class Point
        {
            public int x = 0;
            public int y = 0;
            public Point(int _x, int _y)
            {
                x = _x;
                y = _y;
            }
        }


        public class FindBiggestRectangle
        {            
            public static int[] updateCache(int[] cache, byte[] matrixRow, int MaxX)
            {
                for (int m = 0; m < MaxX; m++)
                {
                    if (0 == matrixRow[m])
                    {
                        cache[m] = 0;
                    }
                    else
                    {
                        cache[m]++;
                    }
                }
                return cache;
            }

            public static void findMaxRectangle(byte[,] matrix, int width, int hight, ref Rect rect)
            {
                Point best_ll = new Point(0, 0);
                Point best_ur = new Point(-1, -1);
                int best_area = 0;

                int MaxX = width;
                int MaxY = hight;

                Stack<Point> stack = new Stack<Point>();
                int[] cache = new int[MaxX + 1];

                for (int m = 0; m != MaxX + 1; m++)
                {
                    cache[m] = 0;
                }

                for (int n = 0; n != MaxY; n++)
                {
                    int openWidth = 0;
                    byte[] matrixRow = new byte[MaxX];
                    for (int m = 0; m != MaxX; m++)
                    {
                        matrixRow[m] = matrix[m,n];
                    }
                    cache = updateCache(cache, matrixRow, MaxX);
                    for (int m = 0; m != MaxX + 1; m++)
                    {
                        if (cache[m] > openWidth)
                        {
                            stack.Push(new Point(m, openWidth));
                            openWidth = cache[m];
                        }
                        else if (cache[m] < openWidth)
                        {
                            int area;
                            Point p;
                            do
                            {
                                p = stack.Pop();
                                area = openWidth * (m - p.x);
                                if (area > best_area)
                                {
                                    best_area = area;
                                    best_ll.x = p.x;
                                    best_ll.y = n;
                                    best_ur.x = m - 1;
                                    best_ur.y = n - openWidth + 1;
                                }
                                openWidth = p.y;
                            } while (cache[m] < openWidth);
                            openWidth = cache[m];
                            if (openWidth != 0)
                            {
                                stack.Push(p);
                            }
                        }
                    }
                }

                //Console.Out.Write("The maximal rectangle has area {0}.\n", best_area);
                //Console.Out.Write("Location: [col={0}, row={1}] to [col={2}, row={3}]\n", best_ll.x + 1, best_ll.y + 1, best_ur.x + 1, best_ur.y + 1);
                rect.x1 = best_ll.x;
                rect.y1 = best_ur.y;
                rect.x2 = best_ur.x;
                rect.y2 = best_ll.y;
            }

        }

 

完整项目代码:
https://download.csdn.net/download/zhenmu/86242488

 牵涉到的知识点:
1. 图片的加载和像素解析,绘制到pictureBox上
2.控制pitctureBox缩放(ctrl+滚轮)和移动
3.动态生成bitmap,绘制点和矩形,显示到pictureBox上
4.找出属于不同区域的相连的不规则图形对应的数据块
5.不规则图形数据查找最大内嵌矩形算法
6.拆分剩余上下左右4个区域,递归找到更小的矩形。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值