有个项目,有些不规则区域,想转成尽可能少的小矩形。 用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
stack = new Stack(); - 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个区域,递归找到更小的矩形。