我正在寻找一种算法,可以获得在3d应用程序中绘制矩阵标记区域所需的数据。
输入如下:
对于每个区域,我需要以CCW顺序找到其外边界的顶点。 我已经可以通过查看邻居来找到所有水平或垂直边的顶点,但是我的实现从左到右,从上到下而不是在CCW顺序中找到顶点。这是我的代码。
for (int i = 1; i < columns-1; i++)
for (int j = 1; j < rows - 1; j++) {
if (grid[i][j] > 0) { // not background
if ((grid[i + 1][j] != id) && (grid[i][j - 1] != id)) {
getCellTopLeftCoord(i, j, &x, &y);
polyPath[id]->Add(gcnew mPoint(x + width, y));
}
if ((grid[i - 1][j] != id) && (grid[i][j - 1] != id)) {
getCellTopLeftCoord(i, j, &x, &y);
polyPath[id]->Add(gcnew mPoint(x, y));
}
... // etc..
这是我感兴趣的界限:
答案 0 :(得分:1)
如果没有任何未连接的表面带有重复标签,则以下步骤应该有效:
从上到下,从左到右遍历矩阵。如果遇到带有尚未处理的标签的非空单元格,请为该标签创建路径。
您发现的观点肯定是东北角。把这一点放在你的道路上。
现在创建一个方向列表,然后从南方开始。因为你逆时针沿着边界走,你应该总是左边有一个被占用的单元,右边有一个未被占用的单元。 (此处占用的是指具有所需标签的单元格。)
当您尝试查找下一个方向时,请继续沿最后一个方向并检查右侧和左侧的单元格。如果两者都未被占用,请向左转。如果至少有一个被占用,请右转。否则,继续直行。
更改方向时,请将当前点附加到路径。
根据当前方向更新坐标。重复,直到达到原始坐标。
此方法不会为您提供草图中标记为4的区域周围的对角线;它将遵循轴对齐的锯齿状轮廓。
这是Javascript中的一个示例实现。单元数据包含在二维数组m
中。 cell
查找单元格,但会查找超出范围的查找。 path
为单个标签创建路径。 paths
创建路径列表;它调用path
:
function cell(x, y) {
if (y < 0) return 0;
if (y >= m.length) return 0;
if (x < 0) return 0;
if (x >= m[y].length) return 0;
return m[y][x];
}
function path(x, y, c) {
var x0 = x;
var y0 = y;
var res = [{x: x, y: y}];
var dir = "s";
var l, r;
y++;
while (x != x0 || y != y0) {
var old = dir;
switch (dir) {
case "n": l = (cell(x - 1, y - 1) == c) ? 1 : 0;
r = (cell(x, y - 1) == c) ? 2 : 0;
dir = ["w", "n", "e", "e"][l + r];
break;
case "e": l = (cell(x, y - 1) == c) ? 1 : 0;
r = (cell(x, y) == c) ? 2 : 0;
dir = ["n", "e", "s", "s"][l + r];
break;
case "s": l = (cell(x, y) == c) ? 1 : 0;
r = (cell(x - 1, y) == c) ? 2 : 0;
dir = ["e", "s", "w", "w"][l + r];
break;
case "w": l = (cell(x - 1, y) == c) ? 1 : 0;
r = (cell(x - 1, y - 1) == c) ? 2 : 0;
dir = ["s", "w", "n", "n"][l + r];
break;
}
if (dir != old) res.push({x: x, y: y});
switch (dir) {
case "n": y--; break;
case "e": x++; break;
case "s": y++; break;
case "w": x--; break;
}
}
return res;
}
function paths() {
var res = {};
for (var y = 0; y < m.length; y++) {
for (var x = 0; x < m[y].length; x++) {
var c = m[y][x];
if (c && !(c in res)) {
res[c] = path(x, y, c);
}
}
}
return res;
}