Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -----------------------------------------------------------------------
- main.cpp
- -----------------------------------------------------------------------
- #include "canvas.h"
- #include "shapes.h"
- #include <cassert>
- #include <sstream>
- std::unique_ptr<Texture> MakeTextureCow() {
- Image image = {R"(^__^ )", //
- R"((oo)\_______ )", //
- R"((__)\ )\/\)", //
- R"( ||----w | )", //
- R"( || || )"};
- return std::make_unique<Texture>(move(image));
- }
- std::unique_ptr<Texture> MakeTextureSolid(Size size, char pixel) {
- Image image(size.height, std::string(size.width, pixel));
- return std::make_unique<Texture>(move(image));
- }
- std::unique_ptr<Texture> MakeTextureCheckers(Size size, char pixel1, char pixel2) {
- Image image(size.height, std::string(size.width, pixel1));
- for (int i = 0; i < size.height; ++i) {
- for (int j = 0; j < size.width; ++j) {
- if ((i + j) % 2 != 0) {
- image[i][j] = pixel2;
- }
- }
- }
- return std::make_unique<Texture>(move(image));
- }
- void TestCpp() {
- Canvas canvas(Size{77, 17});
- canvas.AddShape(ShapeType::ELLIPSE, {2, 1}, {30, 15},
- MakeTextureCheckers({100, 100}, 'c', 'C'));
- canvas.AddShape(ShapeType::ELLIPSE, {8, 4}, {30, 9}, MakeTextureSolid({100, 100}, ' '));
- auto h1 = canvas.AddShape(ShapeType::RECTANGLE, {54, 7}, {22, 3},
- MakeTextureSolid({100, 100}, '+'));
- canvas.DuplicateShape(h1, {30, 7});
- auto v1 = canvas.DuplicateShape(h1, {62, 3});
- canvas.ResizeShape(v1, {6, 11});
- canvas.DuplicateShape(v1, {38, 3});
- std::stringstream output;
- canvas.Print(output);
- const auto answer
- = "###############################################################################\n"
- "# #\n"
- "# cCcCcCcCcC #\n"
- "# CcCcCcCcCcCcCcCcCc #\n"
- "# cCcCcCcCcCcCcCcCcCcCcC ++++++ ++++++ #\n"
- "# CcCcCcCcCcCc ++++++ ++++++ #\n"
- "# CcCcCcCcC ++++++ ++++++ #\n"
- "# cCcCcCc ++++++ ++++++ #\n"
- "# cCcCcC ++++++++++++++++++++++ ++++++++++++++++++++++ #\n"
- "# CcCcCc ++++++++++++++++++++++ ++++++++++++++++++++++ #\n"
- "# cCcCcC ++++++++++++++++++++++ ++++++++++++++++++++++ #\n"
- "# cCcCcCc ++++++ ++++++ #\n"
- "# CcCcCcCcC ++++++ ++++++ #\n"
- "# CcCcCcCcCcCc ++++++ ++++++ #\n"
- "# cCcCcCcCcCcCcCcCcCcCcC ++++++ ++++++ #\n"
- "# CcCcCcCcCcCcCcCcCc #\n"
- "# cCcCcCcCcC #\n"
- "# #\n"
- "###############################################################################\n";
- assert(answer == output.str());
- }
- void TestCow() {
- Canvas canvas{{18, 5}};
- canvas.AddShape(ShapeType::RECTANGLE, {1, 0}, {16, 5}, MakeTextureCow());
- std::stringstream output;
- canvas.Print(output);
- const auto answer =
- R"(####################)""\n"
- R"(# ^__^ #)""\n"
- R"(# (oo)\_______ #)""\n"
- R"(# (__)\ )\/\ #)""\n"
- R"(# ||----w | #)""\n"
- R"(# || || #)""\n"
- R"(####################)""\n";
- assert(answer == output.str());
- }
- int main() {
- TestCow();
- TestCpp();
- }
- -----------------------------------------------------------------------
- texture.h
- -----------------------------------------------------------------------
- #pragma once
- #include "common.h"
- class Texture {
- public:
- explicit Texture(Image image)
- : image_(std::move(image)) {
- }
- Size GetSize() const {
- if (image_.empty()) {
- return {0, 0};
- }
- return {int(image_[0].size()), int(image_.size())};
- }
- char GetPixelColor(Point p) const {
- if (int(image_.size()) <= p.y || int(image_[0].size()) <= p.x || p.x < 0 || p.y < 0) {
- return '.';
- }
- return image_[p.y][p.x];
- }
- private:
- Image image_;
- };
- -----------------------------------------------------------------------
- shapes.h
- -----------------------------------------------------------------------
- #pragma once
- #include "texture.h"
- #include <memory>
- enum class ShapeType {RECTANGLE, ELLIPSE};
- class Shape {
- public:
- explicit Shape(ShapeType type) : type_(type) {}
- void SetPosition(Point pos) {
- pos_ = pos;
- }
- void SetSize(Size size) {
- size_ = size;
- }
- void SetTexture(std::shared_ptr<Texture> texture) {
- texture_ = std::move(texture);
- }
- void Draw(Image& image) const {
- const auto image_size = GetImageSize(image);
- int y_ = 0;
- int x_ = 0;
- char helper;
- for (int y = 0; y < size_.height; ++y) {
- for (int x = 0; x < size_.width; ++x) {
- y_ = pos_.y + y;
- x_ = pos_.x + x;
- if (y_ < 0 ||
- x_ < 0 ||
- y_ >= image_size.height ||
- x_ >= image_size.width) {
- continue;
- }
- if (!texture_) {
- helper = '.';
- } else {
- helper = texture_->GetPixelColor({x, y});
- }
- if ((type_ == ShapeType::ELLIPSE
- && IsPointInEllipse({x, y}, size_))
- || (type_ == ShapeType::RECTANGLE)) {
- image[y_][x_] = helper;
- }
- }
- }
- }
- private:
- ShapeType type_;
- Point pos_;
- Size size_;
- std::shared_ptr<Texture> texture_;
- };
- -----------------------------------------------------------------------
- common.h
- -----------------------------------------------------------------------
- #pragma once
- #include <string>
- #include <vector>
- struct Size {
- int width = 0;
- int height = 0;
- };
- struct Point {
- int x = 0;
- int y = 0;
- };
- using Image = std::vector<std::string>;
- inline Size GetImageSize(const Image& image) {
- const int width = image.empty() ? 0 : static_cast<int>(image[0].size());
- const int height = static_cast<int>(image.size());
- return {width, height};
- }
- inline bool IsPointInEllipse(Point p, Size size) {
- double x = (p.x + 0.5) / (size.width / 2.0) - 1;
- double y = (p.y + 0.5) / (size.height / 2.0) - 1;
- return x * x + y * y <= 1;
- }
- -----------------------------------------------------------------------
- canvas.h
- -----------------------------------------------------------------------
- #include "shapes.h"
- #include <iostream>
- #include <map>
- #include <string_view>
- class Canvas {
- public:
- using ShapeId = size_t;
- explicit Canvas(Size size)
- : size_(size) {
- }
- void SetSize(Size size) {
- size_ = size;
- }
- ShapeId AddShape(ShapeType shape_type, Point position, Size size,
- std::shared_ptr<Texture> texture) {
- auto shape = std::make_unique<Shape>(shape_type);
- shape->SetPosition(position);
- shape->SetSize(size);
- shape->SetTexture(std::move(texture));
- return InsertShape(std::move(shape));
- }
- ShapeId DuplicateShape(ShapeId source_id, Point target_position) {
- auto shape = std::make_unique<Shape>(*GetShapeNodeById(source_id)->second);
- shape->SetPosition(target_position);
- return InsertShape(std::move(shape));
- }
- void RemoveShape(ShapeId id) {
- shapes_.erase(GetShapeNodeById(id));
- }
- void MoveShape(ShapeId id, Point position) {
- GetShapeNodeById(id)->second->SetPosition(position);
- }
- void ResizeShape(ShapeId id, Size size) {
- GetShapeNodeById(id)->second->SetSize(size);
- }
- int GetShapesCount() const {
- return static_cast<int>(shapes_.size());
- }
- void Print(std::ostream& output) const {
- using namespace std::literals;
- Image image(size_.height, std::string(size_.width, ' '));
- for (const auto& [id, shape] : shapes_) {
- shape->Draw(image);
- }
- output << '#' << std::string(size_.width, '#') << "#\n"sv;
- for (const auto& line : image) {
- output << '#' << line << "#\n"sv;
- }
- output << '#' << std::string(size_.width, '#') << "#\n"sv;
- }
- private:
- using Shapes = std::map<ShapeId, std::unique_ptr<Shape>>;
- Shapes::iterator GetShapeNodeById(ShapeId id) {
- auto it = shapes_.find(id);
- if (it == shapes_.end()) {
- throw std::out_of_range("No shape with given ID");
- }
- return it;
- }
- ShapeId InsertShape(std::unique_ptr<Shape> shape) {
- shapes_[current_id_] = std::move(shape);
- return current_id_++;
- }
- Size size_ = {};
- ShapeId current_id_ = 0;
- Shapes shapes_;
- };
Advertisement
Add Comment
Please, Sign In to add comment