我的算法在 1D 数组中渲染矩形有什么问题

What is wrong with my algorithm to render rectangle in 1D array?

本文关键字:什么 问题 算法 1D 数组 我的      更新时间:2023-10-16

我正在尝试制作最佳算法以将矩形绘制到一维数组上。我写了这个函数:

/** Draws a rectangle in 1D array
 * Arguments:
 *   pixmap      - 1D array of Color
 *   color       - rectangle color
 *   w           - rectangle width
 *   h           - rectanhle height
 *   x           - x position, negative coordinates are outside draw area
 *   y           - y position, negative coordinates are outside draw area
 *   pixmapWidth - width of the image (height can be deducted from width if needed but is practically unnecessary) */
void rectangle(std::vector<int>& pixmap, const int& color, const int w, const int h, int x, const int y, const int pixmapWidth)
{
    if(x>=pixmapWidth)
        return;
    if(x+w<0)
        return;
    if(y+h<0)
        return;
    // Width of one consistent line of color of the rectangle
    // if the rectangle is partially out of pixmap area,
    // thw width is smaller than rectangle width
    const int renderWidth = std::min(w, pixmapWidth-x);
    // offset in the arrray where the rendering starts
    // 0 would be for [0,0] coordinate
    int tg_offset = y*pixmapWidth+x;
    // maximum offset to ever render, which is the array size
    const int tg_end = pixmap.size();
    int lines = 0;
    for(; tg_offset<tg_end && lines<h; tg_offset+=pixmapWidth) {
        for(int cx=0; cx<renderWidth; ++cx) {
            // This check keeps failing and my program crashes
            if(tg_offset+cx >= pixmap.size())
                throw "Oh no, what a bad thing to happen!";
            pixmap[tg_offset+cx] = color;
        }
        lines++;
    }
}

请注意,我知道有很多图片绘图库,但我正在尝试通过这样做来学习。但现在我被困住了,我需要帮助。

问题是在内部循环中,条件if(tg_offset+cx >= pixmap.size())不断失败,这意味着我正在尝试在数组之外渲染。我不知道为什么这种情况一直发生。

有问题的代码示例:

const int pixmap_width = 20;
const int pixmap_height = 20;
std::vector<int> pixmap(pixmap_width*pixmap_height);
// tries to render outside the array
rectangle(pixmap, 0, 10, 10, -1, 18, pixmap_width);

下面是一个测试用例,包括像素图的 ASCII 输出: http://ideone.com/SoJPFF我不知道我怎样才能再改进这个问题了......

不进行任何更改将生成四边形。这不是所需的功能吗?

    for(; tg_offset<tg_end && lines<h; tg_offset+=pixmapWidth) {
        cout <<"" << endl;
        for(int cx=0; cx<renderWidth; ++cx) {
            cout << " " << pixmap[tg_offset+cx]; 
            // This check keeps failing and my program crashes
            if(tg_offset+cx >= pixmap.size())
                throw "Oh no, what a bad thing to happen!";
            pixmap[tg_offset+cx] = color;
        }
        lines++;
    }
}
int main()
{
    std::vector<int> pixmap(16);
    pixmap = { 1,1,1,1,1,0,0,1,1,0,0,1,1,1,1,1 };
    int color = 0;
    int w = 4;
    int h = 4;
    int x = 0;
    int y = 0;
    int pixmapWidth = 4;
   cout << "Hello World" << endl; 
   rectangle(pixmap, color, w, h, x, y, pixmapWidth);
   return 0;
}

生产:

Hello World
 1 1 1 1
 1 0 0 1
 1 0 0 1
 1 1 1 1

我认为你的函数的很大一部分问题是它比它需要的要复杂得多。这是函数的一个更简单的版本,只需循环遍历xy即可完成。

void rectangle(std::vector<int>& pixmap, const int& color, const int width, const int height,
               int left, const int top, const int pixmapWidth)
{
    for (int x = std::max(left, 0); x < left + width && x < pixmapWidth; x++)
    for (int y = std::max(top, 0); y < top + height && y*pixmapWidth + x < pixmap.size(); y++)
        pixmap[y*pixmapWidth + x] = color;
}

我不确定当 x 或 y 为负时你想要的输出是什么。在你的实际算法中,如果x是负数,由于tg_offset会返回,所以tg_offset + cx可能会失败。

要解决此问题,您可以限制第二个for以避免这种情况,如下所示:

for(int cx=0; cx<std::min(renderWidth, tg_end - tg_offset); ++cx)

但我认为将 x 和 y 限制为仅为正更正确:

if ( x < 0 ) x = 0;
if ( y < 0 ) y = 0;