diff --git a/src/drawing_assets.cpp b/src/drawing_assets.cpp index 313217a..42f7551 100644 --- a/src/drawing_assets.cpp +++ b/src/drawing_assets.cpp @@ -1,3 +1,4 @@ +#include #include "frame.hpp" #include "drawing_assets.hpp" diff --git a/src/drawing_assets.hpp b/src/drawing_assets.hpp index ca4a7b2..a809a36 100644 --- a/src/drawing_assets.hpp +++ b/src/drawing_assets.hpp @@ -1,8 +1,117 @@ #pragma once +#include + #include "frame.hpp" void draw_circle(Frame *frame, int cx, int cy, int radius, COLOR outline); +inline void draw_circle(Frame *frame, Point c, int radius, COLOR outline) { + draw_circle(frame, c.x, c.y, radius, outline); +} + void draw_line(Frame *frame, int x1, int y1, int x2, int y2, COLOR color); +inline void draw_line(Frame *frame, Point p1, Point p2, COLOR color) { + draw_line(frame, p1.x, p1.y, p2.x, p2.y, color); +} + +template +struct draw_polyline_ { + template + friend + void draw_polyline(Frame *frame, COLOR color, point_t ...points); + + template + friend + struct draw_polyline_; +private: +}; + + +template +struct draw_polyline_ { + template + friend + void draw_polyline(Frame *frame, COLOR color, point_t ...points); + + template + friend + struct draw_polyline_; +private: + static_assert(std::is_same_v); + static_assert(std::is_same_v); + + static void draw(Frame *frame, COLOR color, p0_t p0, p1_t p1, pp_t ...points) { + draw_line(frame, p0, p1, color); + draw_polyline_::draw(frame, color, p1, points...); + } + + static constexpr bool HAS_ANY = true; + + static Point first(p0_t p0, p1_t p1, pp_t ...points) { + return p0; + } + + static Point last(p0_t p0, p1_t p1, pp_t ...points) { + return draw_polyline_::last(p1, points...); + } +}; + +template +struct draw_polyline_ { + template + friend + void draw_polyline(Frame *frame, COLOR color, point_t ...points); + + template + friend + struct draw_polyline_; +private: + static_assert(std::is_same_v); + + static void draw(Frame *frame, COLOR color, p0_t p0) {} + + static constexpr bool HAS_ANY = true; + + + static Point first(p0_t p0) { + return p0; + } + + static Point last(p0_t p0) { + return p0; + } +}; + +template<> +struct draw_polyline_<> { + template + friend + void draw_polyline(Frame *frame, COLOR color, point_t ...points); + + template + friend + struct draw_polyline_; +private: + static void draw(Frame *frame, COLOR color) {} + + static constexpr bool HAS_ANY = false; + + static Point first() { + return Point{0, 0}; + } + + static Point last() { + return Point{0, 0}; + } +}; + +template +void draw_polyline(Frame *frame, COLOR color, point_t ...points) { + if constexpr (!draw_polyline_::HAS_ANY) {} + else { + draw_polyline_::draw(frame, color, points...); + draw_line(frame, draw_polyline_::last(points...), draw_polyline_::first(points...), color); + } +} \ No newline at end of file diff --git a/src/frame.hpp b/src/frame.hpp index 9798763..72ea130 100644 --- a/src/frame.hpp +++ b/src/frame.hpp @@ -15,38 +15,60 @@ struct COLOR { }; +class Point { +public: + int x; + int y; + + inline Point(int x, int y) : x{x}, y{y} {}; + + [[nodiscard]] Point rotated_around(int cx, int cy, double angle_radians) const { + return Point{ + static_cast((this->x - cx) * std::cos(angle_radians) - (this->y - cy) * std::sin(angle_radians) + cx), + static_cast((this->x - cx) * std::sin(angle_radians) + (this->y - cy) * std::cos(angle_radians) + cy) + }; + } + + [[nodiscard]] Point rotated_around(Point p, double angle_radians) const { + return this->rotated_around(p.x, p.y, angle_radians); + } + + [[nodiscard]] Point moved(int dx, int dy) const { + return Point{this->x + dx, this->y + dy}; + } +}; class Frame { COLOR *pixels; public: const int width, height; - Frame(int _width, int _height) : width{_width}, height{_height} { + inline Frame(int _width, int _height) : width{_width}, height{_height} { int size = width * height; this->pixels = new COLOR[size]; } private: - [[nodiscard]] COLOR _get_pixel(int x, int y) const { + [[nodiscard]]inline COLOR _get_pixel(int x, int y) const { return this->pixels[y * this->width + x]; } - [[nodiscard]] COLOR &_get_pixel(int x, int y) { + [[nodiscard]] inline COLOR &_get_pixel(int x, int y) { return this->pixels[y * this->width + x]; } public: - void set_pixel(int x, int y, COLOR color) { + inline void set_pixel(int x, int y, COLOR color) { this->_get_pixel(x, y) = color; } - [[nodiscard]] COLOR get_pixel(int x, int y) const { + [[nodiscard]] inline COLOR get_pixel(int x, int y) const { return this->_get_pixel(x, y); } - ~Frame() { + inline ~Frame() { delete[]this->pixels; } }; diff --git a/src/painter.cpp b/src/painter.cpp index 83e3932..c019675 100644 --- a/src/painter.cpp +++ b/src/painter.cpp @@ -5,9 +5,8 @@ class DemoPainter : public Painter { - +public: void draw(PainterState *state, Frame *frame) const override { - int W = frame->width, H = frame->height; // Размер рисунка возьмём меньше (7 / 8), чтобы он не касался границ экрана float a = 7.0f / 8 * ((W < H) ? W - 1 : H - 1) / sqrt(2); @@ -15,36 +14,19 @@ class DemoPainter : public Painter { float angle = state->angle; // Угол поворота a = a / 2; - // Инициализируем исходные координаты центра и вершин квадрата - struct { - float x; - float y; - } C = {(float) W / 2, (float) H / 2}, A[4] = {{C.x + a, C.y + a}, - {C.x + a, C.y - a}, - {C.x - a, C.y - a}, - {C.x - a, C.y + a}}; + Point center{W / 2, H / 2}; + draw_polyline( + frame, COLOR{200, 30, 45}, + center.moved(a, a).rotated_around(center, angle), + center.moved(a, -a).rotated_around(center, angle), + center.moved(-a, -a).rotated_around(center, angle), + center.moved(-a, a).rotated_around(center, angle) + ); - // Поворачиваем все вершины квадрата вокруг точки C на угол angle - for (int i = 0; i < 4; i++) { - float xi = A[i].x, yi = A[i].y; - A[i].x = (xi - C.x) * cos(angle) - (yi - C.y) * sin(angle) + C.x; - A[i].y = (xi - C.x) * sin(angle) + (yi - C.y) * cos(angle) + C.y; - } - - // Рисуем стороны квадрата - for (int i = 0; i < 4; i++) { - int i2 = (i + 1) % 4; - draw_line( - frame, - int(A[i].x + 0.5f), - int(A[i].y + 0.5f), - int(A[i2].x + 0.5f), - int(A[i2].y + 0.5f), COLOR(200, 30, 45)); - } // Рисуем описанную окружность - draw_circle(frame, (int) C.x, (int) C.y, int(a * sqrt(2) + 0.5f), COLOR(100, 100, 250)); + draw_circle(frame, center, int(a * sqrt(2) + 0.5f), COLOR(100, 100, 250)); // Рисуем пиксель, на который кликнул пользователь if (state->clicked_pixel.x >= 0 && state->clicked_pixel.x < W &&