【发布时间】:2016-08-09 09:12:03
【问题描述】:
我有一条由 2D 点组成的开放或封闭折线(多边形)。
我需要将该折线表示为链码。如果我理解正确,我需要使用 Bresenham 算法对折线段进行光栅化,并从该光栅构造链码。但是有更好的算法吗?
将折线(多边形)转换为链码的最佳算法是什么?
【问题讨论】:
标签: algorithm polygon vector-graphics polyline rasterizing
我有一条由 2D 点组成的开放或封闭折线(多边形)。
我需要将该折线表示为链码。如果我理解正确,我需要使用 Bresenham 算法对折线段进行光栅化,并从该光栅构造链码。但是有更好的算法吗?
将折线(多边形)转换为链码的最佳算法是什么?
【问题讨论】:
标签: algorithm polygon vector-graphics polyline rasterizing
是的,将点直接绘制到傅里叶变换中会明显更快。跳过栅格并从中制作链码,毕竟您需要正确地按照折线所采用的方向排列点,因为我假设是 Kuhl-Giardiana 1982 算法使用。您希望所有像素都以正确的顺序排列,您可以通过将像素绘制到算法本身而不是光栅化任何东西来直接获得它。事实上,这基本上会跳过链码和光栅。
所有行都将采用 y = mx+b 的形式,最快的方法是 Bresenham 的。不过,根据最终用途,您可能会选择 Wu 的算法,这样您就可以确保包含抗锯齿,这往往会使线条看起来更清晰(并且需要您保存 alpha)。假设您需要特定内容的链码,是的,您需要该线将产生的实际像素,这意味着使用线条绘制算法。
您的大多数绘图 API 都会为您提供光栅化图像,而不是链码。可以选择将折线绘制到大小合适的黑色白色图像上,然后遍历整个图像并列出每个黑色像素。它很容易编码,但速度慢且不需要,而且在关键任务操作中将是一个不启动。
代码将非常简单,只需执行 bresenham,然后将点扔到链码中添加点的位置。
public void plotLines(int[] twodshape, Chaincode chain) {
for (int i = 0, s = twodshape.length-4; i < s; i+=2) {
plotLine(twodshape[i],twodshape[i+1],twodshape[i+2],twodshape[i+3],chain);
}
}
public void plotLine(int x0, int y0, int x1, int y1, Chaincode chain) {
int dy = y1 - y0; //BRESENHAM LINE DRAW ALGORITHM
int dx = x1 - x0;
int stepx, stepy;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
if (dx > dy) {
dy <<= 1; // dy is now 2*dy
dx <<= 1;
int fraction = dy - (dx >> 1); // same as 2*dy - dx
chain.add(x0,y0);
while (x0 != x1) {
if (fraction >= 0) {
y0 += stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x0 += stepx;
fraction += dy; // same as fraction += 2*dy
chain.add(x0,y0);
}
chain.add(x0,y0);
} else {
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
int fraction = dx - (dy >> 1);
chain.add(x0,y0);
while (y0 != y1) {
if (fraction >= 0) {
x0 += stepx;
fraction -= dy;
}
y0 += stepy;
fraction += dx;
chain.add(x0,y0);
}
chain.add(x0,y0);
}
}
更新: 我删除了递归位,对于从 A 点到 B 点绘制的线不能保证从 B 到 A 相同的特定问题,我需要它。由于斜率的舍入。例如,如果您要向上 1 个像素并向右 5 个像素。有两种同样有效的方法可以做到这一点,但它并没有给我一个一致的答案。
如果您在链码中非常需要它:
public int convertToChaincode(int cx, int cy) {
if ((cx == 1) && (cy == 0)) return 0;
if ((cx == 1) && (cy == 1)) return 1;
if ((cx == 0) && (cy == 1)) return 2;
if ((cx == -1) && (cy == 1)) return 3;
if ((cx == -1) && (cy == 0)) return 4;
if ((cx == -1) && (cy == -1)) return 5;
if ((cx == 0) && (cy == -1)) return 6;
if ((cx == 1) && (cy == -1)) return 7;
return -1; //error.
}
public void plotLine(int x0, int y0, int x1, int y1, ChainCode chain) {
int dy = y1 - y0; //BRESENHAM LINE DRAW ALGORITHM
int dx = x1 - x0;
int stepx, stepy;
int cx = 0;
int cy = 0;
if (dy < 0) {
dy = -dy;
stepy = -1;
} else {
stepy = 1;
}
if (dx < 0) {
dx = -dx;
stepx = -1;
} else {
stepx = 1;
}
if (dx > dy) {
dy <<= 1; // dy is now 2*dy
dx <<= 1;
int fraction = dy - (dx >> 1); // same as 2*dy - dx
//typically set start point.
while (x0 != x1) {
if (fraction >= 0) {
y0 += stepy;
cy = stepy;
fraction -= dx; // same as fraction -= 2*dx
}
x0 += stepx;
cx = stepx;
fraction += dy; // same as fraction += 2*dy
chain.add(convertToChaincode(cx,cy));
}
} else {
dy <<= 1; // dy is now 2*dy
dx <<= 1; // dx is now 2*dx
int fraction = dx - (dy >> 1);
//typically set start point
while (y0 != y1) {
if (fraction >= 0) {
x0 += stepx;
cx = stepx;
fraction -= dy;
}
y0 += stepy;
cy = stepy;
fraction += dx;
chain.add(convertToChaincode(cx,cy));
}
}
}
【讨论】: