【问题标题】:Render Line From Rectangles从矩形渲染线
【发布时间】:2012-12-23 08:51:51
【问题描述】:

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

The issue with this is that the points overlap when the selection rectangle is larger than one tile.结果如下所示。

我的问题是给出一条线上的所有点,以及选择大小,我怎样才能得到这样的结果?请注意,一旦超过point2,我想停止绘制选择。

这是我目前在不考虑选择大小的情况下渲染线条的方法。

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);
}

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

【问题讨论】:

    标签: c# line overlapping bresenham


    【解决方案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);
    }
    

    【讨论】:

    • 真是天才!我不敢相信我没有想到这一点。非常感谢杰森!但是,为了将来参考,lastPoint 应该是(points.Count - 1) / incr,否则您会超出积分列表。再次感谢:)
    • 注意 - 我会调整答案以供参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 1970-01-01
    • 2012-05-25
    • 2014-03-17
    • 1970-01-01
    相关资源
    最近更新 更多