#include "pgm_renderer.hpp" #include #include PgmRenderer::PgmRenderer(const std::filesystem::path& path, size_t width, size_t height) : m_file(path), m_bitmap(width, height, Color{0xFF}) { if (m_file.bad()) { throw std::runtime_error("Could not open file for writing: " + path.string()); } } void PgmRenderer::DrawLine(const math::Vector& p0, const math::Vector& p1) { RasterizeLine(static_cast(p0.x), static_cast(p0.y), static_cast(p1.x), static_cast(p1.y)); } void PgmRenderer::DrawRectangle(const math::Vector& pos, const math::Vector& size, float angle) { const float sina = std::sin(angle); const float cosa = std::cos(angle); const math::Vector bX{cosa, sina}; const math::Vector bY{-sina, cosa}; const auto& pD = pos; const auto pA = pD + bY * size.y; const auto pB = pA + bX * size.x; const auto pC = pD + bX * size.x; PgmRenderer::DrawLine(pA, pB); PgmRenderer::DrawLine(pB, pC); PgmRenderer::DrawLine(pC, pD); PgmRenderer::DrawLine(pD, pA); } void PgmRenderer::DrawCircle(const math::Vector& center, float radius) { RasterizeCircle(center.x, center.y, radius); } void PgmRenderer::Flush() { m_file << "P2" << std::endl; m_file << "# KIV/CPP" << std::endl; m_file << m_bitmap.GetWidth() << ' ' << m_bitmap.GetHeight() << std::endl; m_file << 255 << std::endl; for (size_t y = 0; y < m_bitmap.GetHeight(); ++y) { for (size_t x = 0; x < m_bitmap.GetWidth(); ++x) { m_file << static_cast(m_bitmap[y][x].l) << ' '; } m_file << std::endl; } } void PgmRenderer::RasterizeLine(int x0, int y0, int x1, int y1) { int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1; int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1; int err = dx + dy, e2; /* error value e_xy */ for (;;) { /* loop */ m_bitmap[y0][x0].l = 0x00; if (x0 == x1 && y0 == y1) break; e2 = 2 * err; if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */ if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */ } } void PgmRenderer::RasterizeCircle(int xm, int ym, int r) { int x = -r, y = 0, err = 2 - 2 * r; /* II. Quadrant */ do { m_bitmap[ym + y][xm - x].l = 0x00; m_bitmap[ym - x][xm - y].l = 0x00; m_bitmap[ym - y][xm + x].l = 0x00; m_bitmap[ym + x][xm + y].l = 0x00; // setPixel(xm - x, ym + y); /* I. Quadrant */ // setPixel(xm - y, ym - x); /* II. Quadrant */ // setPixel(xm + x, ym - y); /* III. Quadrant */ // setPixel(xm + y, ym + x); /* IV. Quadrant */ r = err; if (r <= y) err += ++y * 2 + 1; /* e_xy+e_y < 0 */ if (r > x || err > y) err += ++x * 2 + 1; /* e_xy+e_x > 0 or no 2nd y-step */ } while (x < 0); }