c++graphicsppm

How to create alternating rectangles that get smaller as they approach the center of the image


I want to replicate this pattern with C++.

enter image description here

This is the code that I have so far.

void alternating_rectangles(fstream& image_out, int width, int height, int rectangle_width, color first_color, color second_color) {
    int center_x = width / 2;
    int center_y = height / 2;
    
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int x_dist = abs(center_x - x);
            int y_dist = abs(center_y - y);
            
            bool is_first_color = (x_dist / rectangle_width) == (y_dist / rectangle_width) && (x_dist / rectangle_width) % 2 == 0;
            color pixel_color = is_start_color ? first_color : second_color;
            write_pixel(image_out, pixel_color);
        }
    }
}

I have a 'write_pixel' function that writes the color of a pixel to a .ppm file. The 'width' and 'height' parameters are the dimensions of the image. The 'rectangle_width' parameter is the thickness of each rectangle. (the width of each individual stripe if you like). Note: I'm handling the closing and the opening of the file inside the function that calls this one.

I have to create this pattern in one pass, so I can't just draw each smaller rectangle on top of the previous one. I can't overwrite pixels.

My code generates this (incomplete) pattern.

enter image description here

How can I generate the pattern in the first picture if I only know the dimensions of the image and the 'thickness' of each stripe?


Solution

  • You can compute the color directly from the x and y and the number of rings (width and height).

    Basically you want the min of:

    That tells you which ring you're in (counting from the outside).

    Then you can take the ring mod 2 to get the color.

        int width = 19; // for example
        int height = 15; // for example
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                int ring = std::min(std::min(x, y), std::min(width - 1 - x, height - 1 - y));
                bool is_first_color = ring % 2 == 0;
                // You can set pixel here.
                setPixel(x, y, is_first_color);
            }
        }