2012-12-23 121 views
0

我目前已经为我正在开发的基于图块的世界编辑器实现了Bresenham线条算法。对于移位 + 点击功能,我想渲染一个基于瓦片集的选择矩形的线。这很简单,因为我可以使用该算法找到从point1point2的线上的点并在每个点处绘制选择。从矩形渲染线条

与此相关的问题是,当选择矩形大于一个图块时,点重叠。结果如下所示。

Current

我的问题是给定一个行中的所有点,和选择的尺寸,我怎么能得到这样的结果呢?请注意,我想在选择过去point2时停止绘制选择。

Desired

这是我目前有渲染管线而不考虑选择的尺寸。

void renderPoint(Point point, bool invalidate = false) 
{ 
    Rectangle selection = world.SelectionRectangle; 

    int width = selection.Width/world.Settings.TileSize.Width, 
     height = selection.Height/world.Settings.TileSize.Height, 
     offsetX = (int)Math.Floor((float)width/2), 
     offsetY = (int)Math.Floor((float)height/2); 

    for (int x = point.X, sx = 0; x < point.X + width; x++, sx++) 
    { 
     for (int y = point.Y, sy = 0; y < point.Y + height; y++, sy++) 
     { 
      Point change = new Point(x - offsetX, y - offsetY); 

      if (!changesUndo.ContainsKey(change)) 
       changesUndo[change] = world.GetTile(change); 

      WorldTile tile = new WorldTile(selection.X + (sx * world.Settings.TileSize.Width), selection.Y + (sy * world.Settings.TileSize.Height), 0); 

      world.SetTile(change.X, change.Y, tile); 

      changesRedo[change] = tile; 
     } 
    } 

    lastRenderedPoint = point; 

    if (invalidate) 
     world.InvalidateCanvas(); 
} 

void renderLine(Point p1, Point p2) 
{ 
    List<Point> points = pointsOnLine(p1, p2); 

    for (int i = 0; i < points.Count; i++) 
     renderPoint(points[i], i == points.Count - 1); 
} 

如果您需要我的代码的更多上下文,请留下评论。

回答

1

如果用Bresenham渲染点,则必须跳过'n'点中的每个'n-1'点,其中'n'是该线主要方向的选择尺寸(即,如果它是大部分是水平线,宽度)。

这样的事情? :

void renderLine(Point p1, Point p2) 
{ 
    List<Point> points = pointsOnLine(p1, p2); 

    int dx = Abs(p2.x - p1.x); 
    int dy = Abs(p2.y - p1.y); 

    Rectangle selection = world.SelectionRectangle; 

    int incr = selection.Width/world.Settings.TileSize.Width; 
    if(dy > dx) 
    { 
     incr = selection.Height/world.Settings.TileSize.Height; 
    } 

    int lastPoint = (points.Count-1)/incr; 
    lastPoint *= incr; 

    for (int i = 0; i <= lastPoint; i+=incr) 
     renderPoint(points[i], i == lastPoint); 
} 
+0

这是天才!我不敢相信我没有想到这一点。非常感谢杰森!然而,为了将来的参考,'lastPoint'应该是'(points.Count - 1)/ incr',否则你会到达点列表之外。再次感谢:) –

+1

注意到 - 我会调整答案以供参考。 – JasonD