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