如何将折线或多边形转换为链码?

时间:2016-04-17 18:11:53

标签: algorithm polygon vector-graphics polyline rasterizing

我有一个开放或封闭的折线(多边形),由一组2D点组成。

我需要将折线表示为链码。如果我正确理解,我需要使用Bresenham的算法栅格化折线段并构建栅格的链码形式。但是有更好的算法吗?

将折线(多边形)转换为链码的最佳算法是什么?

1 个答案:

答案 0 :(得分:0)

是的,简单地将点直接绘制到傅立叶变换中会快得多。跳过光栅并从中制作一个链码,毕竟你需要正确的点按照折线所采用的方向,我假设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));
        }
    }
}