【问题标题】:Line Rasterization / 4-connected Bresenham线光栅化 / 4-connected Bresenham
【发布时间】:2012-11-24 16:07:53
【问题描述】:

对于碰撞测试,我需要光栅化一条线。 bresenham 算法几乎可以按预期工作,但存在如下缺陷:

我需要:

我目前的实现(基于http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#Simplification):

public boolean isInsideLine(int x1, int y1, int x2, int y2) {
    final int dx = abs(x2 - x1), dy = abs(y2 - y1);
    final int sx = x1 < x2 ? 1 : -1, sy = y1 < y2 ? 1 : -1;
    int err = dx - dy;

    while (true) {
        if (isInside(x1, y1)) //Lookup in pixel array
            return true;
        if (x1 == x2 && y1 == y2)
            break;
        final int e2 = err << 1;
        if (e2 > -dy) {
            err -= dy;
            x1 += sx;
        }
        if (e2 < dx) {
            err += dx;
            y1 += sy;
        }
    }
    return false;
}

我可以使用其他线光栅化算法吗,或者有谁知道如何修改 bresenham?

【问题讨论】:

  • 在我看来,Bresenham 的原始输出是 8 连接的,但您需要 4 连接。您可以对原始输出进行后处理以检测对角线链接,然后确定该线最接近哪个像素。
  • 请参阅stackoverflow.com/questions/5186939/… 了解类似问题的内容。
  • 出于兴趣:为什么需要光栅化线以进行碰撞检测?你不能只计算交叉点吗?
  • 用于(几乎)像素精确的 2d 碰撞。

标签: java raster rasterizing bresenham


【解决方案1】:

也许会有用,有我的非整数端点版本。这是GridMap 类的一种方法,我用于几何形状的空间索引,以加速二维地图中的碰撞检测。

int GridMap::insertLine( int lineId, double ax, double ay, double bx, double by ){
    // get index of endpoints in GridMap
    int ix    = getIx( ax ); 
    int iy    = getIy( ay );
    int ixb   = getIx( bx );
    int iyb   = getIy( by );
    // insert endpoints to GridMap
    insert( lineId, ix, iy   ); 
    insert( lineId, ixb, iyb );
    // raster central part of the line
    double dx = fabs( bx - ax );
    double dy = fabs( by - ay );
    int dix = ( ax < bx ) ? 1 : -1;
    int diy = ( ay < by ) ? 1 : -1;
    double x=0, y=0;
    while ( ( ix != ixb ) && ( iy != iyb  ) ) {
        if ( x < y ) {
            x  += dy;
            ix += dix;
        } else {
            y  += dx;
            iy += diy;
        }
        insert( lineId, ix, iy );
    }
};

【讨论】:

  • 不起作用。对于初学者来说,如果起点和终点落在同一个方格中,则该线将被添加两次到同一个方格中。其次,它不适用于水平/垂直线:对于水平线,iy 将等于 iyb。 while 循环的内容永远不会被执行:因为iy != iyb 永远不会为真。事实上,它比水平/垂直线不起作用更糟糕。那段代码根本没有正确绘制任何不是对角线的线的结尾。越接近水平/垂直,丢失的像素就越多。
【解决方案2】:

感谢 koan,有时候你只是缺少要搜索的关键字,Algorithm for drawing a 4-connected line 似乎解决了它:

public boolean isInsideLine(int x1, int y1, int x2, int y2) {
    final int dx = abs(x2 - x1), dy = abs(y2 - y1);
    final int sx = x1 < x2 ? 1 : -1, sy = y1 < y2 ? 1 : -1;
    int err = dx - dy;

    while (true) {
        if (isInside(x1, y1)) //Lookup in pixel array
            return true;
        if (x1 == x2 && y1 == y2)
            break;
        final int e2 = err << 1;
        if (e2 > -dy) {
            err -= dy;
            x1 += sx;
        } else if (e2 < dx) { // else if instead of if
            err += dx;
            y1 += sy;
        }
    }
    return false;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 2014-02-18
    • 1970-01-01
    • 2019-06-18
    • 2016-12-12
    • 1970-01-01
    相关资源
    最近更新 更多