Algorithm 对多边形进行排序';用于绘图的s点
我有一个矩阵(0表示无,1表示地形),代表我游戏中的一个等级。矩阵对应于我的屏幕被分割成的网格,并指示我的地形走向 我的地形实际上是由网格内每个块角上的4个点组成的。当您有多个连接的块时,我使用合并单元算法来删除重复点和任何内部点。结果是,我得到了一个点列表,这些点只表示多边形的外边缘 要画这个多边形,我需要点按某种顺序(顺时针或逆时针)排列,这样每个点后面都有它的相邻点。显然,第一点和最后一点必须是邻居。因为这些都在一个网格中,所以我知道相邻点之间的确切距离 问题是,我很难想出一个算法,让我“走”周围的多边形边缘,而把点的顺序。我认为应该有一种方法来利用这样一个事实,即我有表示几何体的矩阵,这意味着只有一种可能的方法来绘制多边形(即使它是凹的) 我尝试了几种使用贪婪型算法的方法,但似乎找不到一种方法来知道,在每种情况下,我想朝哪个方向旅行。考虑到任何特定点最多可以有3个相邻点(第四个不包括在内,因为它是“起点”,这意味着我已经对其进行了排序),我需要一种知道移动方式的方法 更新 我一直在尝试的另一种方法是按点的X(带Y的分界线)对点进行排序,这给了我最上面/最左边的边。这也保证了我是从外缘开始的。然而,我仍在努力寻找一种算法,以保证我留在外面而不跨越 以下是一个示例矩阵: 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 1 0 0 对应于此(黑点代表我的点):Algorithm 对多边形进行排序';用于绘图的s点,algorithm,sorting,math,polygon,Algorithm,Sorting,Math,Polygon,我有一个矩阵(0表示无,1表示地形),代表我游戏中的一个等级。矩阵对应于我的屏幕被分割成的网格,并指示我的地形走向 我的地形实际上是由网格内每个块角上的4个点组成的。当您有多个连接的块时,我使用合并单元算法来删除重复点和任何内部点。结果是,我得到了一个点列表,这些点只表示多边形的外边缘 要画这个多边形,我需要点按某种顺序(顺时针或逆时针)排列,这样每个点后面都有它的相邻点。显然,第一点和最后一点必须是邻居。因为这些都在一个网格中,所以我知道相邻点之间的确切距离 问题是,我很难想出一个算法,让我“
我想有不同的方法可以做到这一点,我想对于对角线连接的单元被计算为不同轮廓的情况,有一种非常简单的方法: 你只需要保持牢房和角落的方向。例如,您从某个地球单元的右上角开始(它假设上单元或右单元,或者如果它是bourder,则两者均为零),并希望顺时针移动 如果右边的单元格是“地”,则将当前单元格更改为“地”,并将“角”更改为左上角(即同一点)。然后进入下一个迭代 在另一种情况下,若你们从某个地球单元的右上角开始,想顺时针走。如果右边的单元格不是地,则不更改当前单元格,也不更改右下角(这是下一个点) 所以你们也有其他三个可能的角点的对称情况,你们可以进入下一个迭代,直到回到起点 这是我编写的伪代码,它使用与图片相同的索引,并假设边界上的所有单元格都是自由的,否则需要检查索引id是否超出范围 我还需要额外的数组,它的尺寸几乎与矩阵相同,用来标记处理过的轮廓,它需要比矩阵宽1个单元格,因为我要标记垂直线,每条垂直线的右边应该有单元格的坐标。请注意,当您需要标记垂直线时,上面只描述了2种情况
int mark[,] = new int[height,width+1]
start_i = i = 0;
start_j = j = 0;
direction = start_direction = top_left;
index = 0;
//outer cycle through different contours
while(true)
{
++index;
//scanning for contours through all the matrix
//continue from the same place, we stopped last time
for(/*i = i*/; i < n; i++)
{
for(/*j = j*/; j < n; j++)
{
//if we found earth
if(m[i,j] == 1)
{
//check if previous cell is nothing
//check if line between this and previous contour doesn't already added
if(m[i,j - 1] == 0 && mark[i,j] == 0)
{
direction = bottom_left;
break;
}
//the same for next cell
if(m[i,j + 1] == 0 && mark[i,j+1] == 0)
{
direction = top_right;
break;
}
}
}
//break if we found contour
if(i != start_i || j != start_j)
break;
}
//stop if we didn't find any contour
if(i == start_i && j == start_j)
{
break;
}
polygon = new polygon;
start_i = i;
start_j = j;
start_direction = direction;
//now the main part of algorithm described above
do
{
if(direction == top_left)
{
if(n(i-1,j) == 1)
{
direction = bottom_left;
position = (i-1,j)
}
else
{
direction = top_right;
polygon.Add(i,j+1);
}
}
if(direction == top_right;)
{
if(n[i,j + 1] == 1)
{
direction = top_left;
position = (i,j + 1)
}
else
{
direction = bottom_right;
mark[i, j + 1] = index;//don't forget to mark edges!
polygon.Add(i+1,j+1);
}
}
if(direction == bottom_right;
{
if(n[i+1,j] == 1)
{
direction = top_right;
position = (i+1,j)
}
else
{
direction = bottom_left;
polygon.Add(i+1,j);
}
}
if(direction == bottom_left)
{
if(n[i,j - 1] == 1)
{
direction = bottom_right;
position = [i,j - 1]
}
else
{
direction = top_left;
mark[i, j] = index;//don't forget to mark edges!
polygon.Add(i,j);
}
}
//and we can stop as we reached the starting state
}while(i != start_i || j != start_j || direction != start_direction);
//stop if it was last cell
if(i == n-1 && j == n- 1)
{
break;
}
}
int标记[,]=新int[高度、宽度+1]
启动i=i=0;
启动_j=j=0;
方向=开始方向=左上方;
指数=0;
//通过不同轮廓的外循环
while(true)
{
++指数;
//通过所有矩阵扫描轮廓
//从同一个地方继续,我们上次停了下来
对于(/*i=i*/;i ...
//continue from the same place, we stopped last time
for(/*i = i*/; i < n; i++)
{
for(/*j = j*/; j < n; j++)
{
if(mark[i,j] != 0)
{
if(stack.top() == mark [i,j])
{
stack.pop();
}
else
{
stack.push(mark [i,j]);
}
}
//if we found earth
if(m[i,j] == 1)
{
...
while your matrix is not empty
move to first "1" value. This is the rectangle top left corner
from this corner, extend the rectangle in x and y to maximize its surface
store the rectangle in a list and clear all corresponding "1" values
data = [[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
[ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 ],
[ 0, 1, 0, 0, 1, 0, 1, 1, 0, 0 ],
[ 0, 1, 0, 0, 1, 0, 1, 1, 1, 0 ],
[ 0, 1, 1, 1, 1, 0, 0, 1, 1, 0 ],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]]
rows = len(data)
cols = len(data[0])
walls = [[2*(data[r][c] != data[r][c+1]) + (data[r][c] != data[r+1][c])
for c in range(cols-1)]
for r in range(rows-1)]
result = []
for r in range(rows-1):
for c in range(cols-1):
if walls[r][c] & 1:
i, j = r+1, c
cycle = [(i, j)]
while True:
if i < rows-1 and walls[i][j-1] & 2:
ii, jj = i+1, j
walls[i][j-1] -= 2
elif i > 0 and walls[i-1][j-1] & 2:
ii, jj = i-1, j
walls[i-1][j-1] -= 2
elif j < cols-1 and walls[i-1][j] & 1:
ii, jj = i, j+1
walls[i-1][j] -= 1
elif j > 0 and walls[i-1][j-1] & 1:
ii, jj = i, j-1
walls[i-1][j-1] -= 1
else:
break
i, j = ii, jj
cycle.append((ii, jj))
result.append(cycle)
result = []
index = [[-1] * cols for x in range(rows)]
for r in range(rows-1):
for c in range(cols-1):
if walls[r][c] & 1:
i, j = r+1, c
cycle = [(i, j)]
index[i][j] = 0
while True:
if i > 0 and walls[i-1][j-1] & 2:
ii, jj = i-1, j
walls[i-1][j-1] -= 2
elif j > 0 and walls[i-1][j-1] & 1:
ii, jj = i, j-1
walls[i-1][j-1] -= 1
elif i < rows-1 and walls[i][j-1] & 2:
ii, jj = i+1, j
walls[i][j-1] -= 2
elif j < cols-1 and walls[i-1][j] & 1:
ii, jj = i, j+1
walls[i-1][j] -= 1
else:
break
i, j = ii, jj
cycle.append((ii, jj))
ix = index[i][j]
if ix >= 0:
# closed a loop
result.append(cycle[ix:])
for i_, j_ in cycle[ix:]:
index[i_][j_] = -1
cycle = cycle[:ix+1]
index[i][j] = len(cycle)-1