Init
This commit is contained in:
commit
d508045ec3
6
.clang-format
Normal file
6
.clang-format
Normal file
@ -0,0 +1,6 @@
|
||||
BasedOnStyle: Microsoft
|
||||
DerivePointerAlignment: false
|
||||
PointerAlignment: Left
|
||||
IndentWidth: 4 # spaces per indent level
|
||||
TabWidth: 4 # width of a tab character
|
||||
UseTab: Never # options: Never, ForIndentation, Alwayss
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.cache/
|
||||
build/
|
||||
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.10)
|
||||
|
||||
project(CppDrawing)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
|
||||
add_executable(drawing
|
||||
"contexts/pgm_drawing_context.cpp"
|
||||
"math/transforms.cpp"
|
||||
"primitives/line.cpp"
|
||||
"primitives/rectangle.cpp"
|
||||
"primitives/circle.cpp"
|
||||
"main.cpp"
|
||||
"input_file.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(drawing PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
45
bitmap.hpp
Normal file
45
bitmap.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
struct Color
|
||||
{
|
||||
uint8_t l{};
|
||||
};
|
||||
|
||||
class Bitmap
|
||||
{
|
||||
public:
|
||||
Bitmap(size_t width, size_t height, const Color& clearColor)
|
||||
: m_width(width), m_height(height), m_data(width * height, clearColor)
|
||||
{
|
||||
}
|
||||
|
||||
// std::span<Color> operator[](size_t row)
|
||||
// {
|
||||
// return {&m_data[row * m_width], m_width};
|
||||
// };
|
||||
|
||||
// std::span<const Color> operator[](size_t row) const
|
||||
// {
|
||||
// return {&m_data[row * m_width], m_width};
|
||||
// };
|
||||
|
||||
Color* operator[](size_t row)
|
||||
{
|
||||
return &m_data[row * m_width];
|
||||
};
|
||||
|
||||
const Color* operator[](size_t row) const
|
||||
{
|
||||
return &m_data[row * m_width];
|
||||
};
|
||||
|
||||
private:
|
||||
size_t m_width, m_height;
|
||||
std::vector<Color> m_data;
|
||||
};
|
||||
14
contexts/drawing_context.hpp
Normal file
14
contexts/drawing_context.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "math/vector.hpp"
|
||||
|
||||
class DrawingContext
|
||||
{
|
||||
public:
|
||||
virtual void DrawLine(const math::Vector& p0, const math::Vector& p1) = 0;
|
||||
virtual void DrawRectangle(const math::Vector& pos, const math::Vector& size, float angle) = 0;
|
||||
virtual void DrawCircle(const math::Vector& center, float radius) = 0;
|
||||
|
||||
virtual void Flush() = 0;
|
||||
|
||||
virtual ~DrawingContext() = 0;
|
||||
};
|
||||
60
contexts/pgm_drawing_context.cpp
Normal file
60
contexts/pgm_drawing_context.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
#include "pgm_drawing_context.hpp"
|
||||
#include <cmath>
|
||||
|
||||
PgmDrawingContext::PgmDrawingContext(const std::filesystem::path& path, size_t width, size_t height)
|
||||
: m_bitmap(width, height, Color{0xFF})
|
||||
{
|
||||
}
|
||||
|
||||
void PgmDrawingContext::DrawLine(const math::Vector& p0, const math::Vector& p1)
|
||||
{
|
||||
RasterizeLine(static_cast<int>(p0.x), static_cast<int>(p0.y), static_cast<int>(p1.x), static_cast<int>(p1.y));
|
||||
}
|
||||
|
||||
void PgmDrawingContext::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;
|
||||
|
||||
PgmDrawingContext::DrawLine(pA, pB);
|
||||
PgmDrawingContext::DrawLine(pB, pC);
|
||||
PgmDrawingContext::DrawLine(pC, pD);
|
||||
PgmDrawingContext::DrawLine(pD, pA);
|
||||
}
|
||||
|
||||
void PgmDrawingContext::DrawCircle(const math::Vector& center, float radius)
|
||||
{
|
||||
}
|
||||
|
||||
void PgmDrawingContext::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 */
|
||||
}
|
||||
}
|
||||
25
contexts/pgm_drawing_context.hpp
Normal file
25
contexts/pgm_drawing_context.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "bitmap.hpp"
|
||||
#include "drawing_context.hpp"
|
||||
#include <cstddef>
|
||||
#include <filesystem>
|
||||
|
||||
class PgmDrawingContext : public DrawingContext
|
||||
{
|
||||
public:
|
||||
PgmDrawingContext(const std::filesystem::path& path, size_t width, size_t height);
|
||||
|
||||
void DrawLine(const math::Vector& p0, const math::Vector& p1) override;
|
||||
void DrawRectangle(const math::Vector& pos, const math::Vector& size, float angle) override;
|
||||
void DrawCircle(const math::Vector& center, float radius) override;
|
||||
|
||||
void Flush() override;
|
||||
|
||||
~PgmDrawingContext() override = default;
|
||||
|
||||
private:
|
||||
Bitmap m_bitmap;
|
||||
|
||||
void RasterizeLine(int x0, int y0, int x1, int y1);
|
||||
};
|
||||
2
input_file.cpp
Normal file
2
input_file.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#include "input_file.hpp"
|
||||
|
||||
17
input_file.hpp
Normal file
17
input_file.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
|
||||
#include "drawing_context.hpp"
|
||||
|
||||
class InputFile
|
||||
{
|
||||
public:
|
||||
InputFile(const std::filesystem::path& path);
|
||||
|
||||
void Parse(DrawingContext& ctx);
|
||||
|
||||
private:
|
||||
std::ifstream m_file;
|
||||
};
|
||||
8
main.cpp
Normal file
8
main.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
#include <iostream>
|
||||
#include "pgm_drawing_context.hpp"
|
||||
|
||||
int main()
|
||||
{
|
||||
std::cout << "sjeta" << std::endl;
|
||||
}
|
||||
20
math/transforms.cpp
Normal file
20
math/transforms.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "transforms.hpp"
|
||||
#include <cmath>
|
||||
|
||||
math::Vector math::RotatePoint(const Vector& center, float angle, const Vector& p)
|
||||
{
|
||||
const float sina = std::sin(angle);
|
||||
const float cosa = std::cos(angle);
|
||||
const Vector p1 = p - center;
|
||||
return Vector(p1.x * cosa - p1.y * sina, p1.x * sina + p1.y * cosa) + center;
|
||||
}
|
||||
|
||||
math::Vector math::ScalePoint(const Vector& center, float factor, const Vector& p)
|
||||
{
|
||||
return ((p - center) * factor) + center;
|
||||
}
|
||||
|
||||
float math::RotateAngle(float originalAngle, float rotationAngle)
|
||||
{
|
||||
return std::fmodf(originalAngle + rotationAngle, PI * 2.0f);
|
||||
}
|
||||
15
math/transforms.hpp
Normal file
15
math/transforms.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
constexpr float PI = 3.14159265358979323846f;
|
||||
|
||||
Vector RotatePoint(const Vector& center, float angle, const Vector& p);
|
||||
Vector ScalePoint(const Vector& center, float factor, const Vector& p);
|
||||
float RotateAngle(float originalAngle, float rotationAngle);
|
||||
|
||||
|
||||
} // namespace math
|
||||
62
math/vector.hpp
Normal file
62
math/vector.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
namespace math
|
||||
{
|
||||
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
Vector() : x{0.0f}, y{0.0f}
|
||||
{
|
||||
}
|
||||
|
||||
Vector(float x, float y) : x{x}, y{y}
|
||||
{
|
||||
}
|
||||
|
||||
// float& operator[](size_t idx) { return m_v[idx]; }
|
||||
// const float& operator[](size_t idx) const { return m_v[idx]; }
|
||||
|
||||
Vector operator+(const Vector& other) const
|
||||
{
|
||||
return Vector(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
Vector& operator+=(const Vector& other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector operator-(const Vector& other) const
|
||||
{
|
||||
return Vector(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
Vector& operator-=(const Vector& other)
|
||||
{
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector operator*(float factor) const
|
||||
{
|
||||
return Vector(x * factor, y * factor);
|
||||
}
|
||||
|
||||
Vector& operator*=(float factor)
|
||||
{
|
||||
x *= factor;
|
||||
y *= factor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
public:
|
||||
float x, y;
|
||||
};
|
||||
|
||||
} // namespace math
|
||||
24
primitives/circle.cpp
Normal file
24
primitives/circle.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "circle.hpp"
|
||||
#include "math/transforms.hpp"
|
||||
#include "contexts/drawing_context.hpp"
|
||||
|
||||
void primitives::Circle::Translate(const math::Vector& offset)
|
||||
{
|
||||
m_center += offset;
|
||||
}
|
||||
|
||||
void primitives::Circle::Rotate(const math::Vector& center, float angle)
|
||||
{
|
||||
m_center = math::RotatePoint(center, angle, m_center);
|
||||
}
|
||||
|
||||
void primitives::Circle::Scale(const math::Vector& center, float factor)
|
||||
{
|
||||
m_center = math::ScalePoint(center, factor, m_center);
|
||||
m_radius *= factor;
|
||||
}
|
||||
|
||||
void primitives::Circle::Draw(DrawingContext& ctx)
|
||||
{
|
||||
ctx.DrawCircle(m_center, m_radius);
|
||||
}
|
||||
38
primitives/circle.hpp
Normal file
38
primitives/circle.hpp
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "primitive.hpp"
|
||||
|
||||
namespace primitives
|
||||
{
|
||||
|
||||
class Circle : public Primitive
|
||||
{
|
||||
public:
|
||||
Circle(const math::Vector& center, float radius) : m_center(center), m_radius(radius)
|
||||
{
|
||||
}
|
||||
|
||||
const math::Vector& GetCenter() const
|
||||
{
|
||||
return m_center;
|
||||
}
|
||||
|
||||
float GetRadius() const
|
||||
{
|
||||
return m_radius;
|
||||
}
|
||||
|
||||
void Translate(const math::Vector& offset) override;
|
||||
void Rotate(const math::Vector& center, float angle) override;
|
||||
void Scale(const math::Vector& center, float factor) override;
|
||||
|
||||
void Draw(DrawingContext& ctx) override;
|
||||
|
||||
~Circle() override = default;
|
||||
|
||||
private:
|
||||
math::Vector m_center;
|
||||
float m_radius;
|
||||
};
|
||||
|
||||
} // namespace primitives
|
||||
26
primitives/line.cpp
Normal file
26
primitives/line.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
#include "line.hpp"
|
||||
#include "math/transforms.hpp"
|
||||
#include "contexts/drawing_context.hpp"
|
||||
|
||||
void primitives::Line::Translate(const math::Vector& offset)
|
||||
{
|
||||
m_p0 += offset;
|
||||
m_p1 += offset;
|
||||
}
|
||||
|
||||
void primitives::Line::Rotate(const math::Vector& center, float angle)
|
||||
{
|
||||
m_p0 = math::RotatePoint(center, angle, m_p0);
|
||||
m_p1 = math::RotatePoint(center, angle, m_p1);
|
||||
}
|
||||
|
||||
void primitives::Line::Scale(const math::Vector& center, float factor)
|
||||
{
|
||||
m_p0 = math::ScalePoint(center, factor, m_p0);
|
||||
m_p1 = math::ScalePoint(center, factor, m_p1);
|
||||
}
|
||||
|
||||
void primitives::Line::Draw(DrawingContext& ctx)
|
||||
{
|
||||
ctx.DrawLine(m_p0, m_p1);
|
||||
}
|
||||
27
primitives/line.hpp
Normal file
27
primitives/line.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "math/vector.hpp"
|
||||
#include "primitive.hpp"
|
||||
|
||||
namespace primitives
|
||||
{
|
||||
|
||||
class Line : public Primitive
|
||||
{
|
||||
public:
|
||||
Line(const math::Vector& p0, const math::Vector& p1) : m_p0(p0), m_p1(p1)
|
||||
{
|
||||
}
|
||||
|
||||
void Translate(const math::Vector& offset) override;
|
||||
void Rotate(const math::Vector& center, float angle) override;
|
||||
void Scale(const math::Vector& center, float factor) override;
|
||||
|
||||
void Draw(DrawingContext& ctx) override;
|
||||
|
||||
private:
|
||||
math::Vector m_p0;
|
||||
math::Vector m_p1;
|
||||
};
|
||||
|
||||
} // namespace primitives
|
||||
24
primitives/primitive.hpp
Normal file
24
primitives/primitive.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "math/vector.hpp"
|
||||
|
||||
class DrawingContext;
|
||||
|
||||
namespace primitives
|
||||
{
|
||||
|
||||
class Primitive
|
||||
{
|
||||
public:
|
||||
Primitive() = default;
|
||||
|
||||
virtual void Translate(const math::Vector& offset) = 0;
|
||||
virtual void Rotate(const math::Vector& center, float angle) = 0;
|
||||
virtual void Scale(const math::Vector& center, float factor) = 0;
|
||||
|
||||
virtual void Draw(DrawingContext& ctx) = 0;
|
||||
|
||||
virtual ~Primitive() = 0;
|
||||
};
|
||||
|
||||
} // namespace primitives
|
||||
25
primitives/rectangle.cpp
Normal file
25
primitives/rectangle.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
#include "rectangle.hpp"
|
||||
#include "math/transforms.hpp"
|
||||
#include "contexts/drawing_context.hpp"
|
||||
|
||||
void primitives::Rectangle::Translate(const math::Vector& offset)
|
||||
{
|
||||
m_pos += offset;
|
||||
}
|
||||
|
||||
void primitives::Rectangle::Rotate(const math::Vector& center, float angle)
|
||||
{
|
||||
m_pos = math::RotatePoint(center, angle, m_pos);
|
||||
m_angle = math::RotateAngle(m_angle, angle);
|
||||
}
|
||||
|
||||
void primitives::Rectangle::Scale(const math::Vector& center, float factor)
|
||||
{
|
||||
m_pos = math::ScalePoint(center, factor, m_pos);
|
||||
m_size *= factor;
|
||||
}
|
||||
|
||||
void primitives::Rectangle::Draw(DrawingContext& ctx)
|
||||
{
|
||||
ctx.DrawRectangle(m_pos, m_size, m_angle);
|
||||
}
|
||||
45
primitives/rectangle.hpp
Normal file
45
primitives/rectangle.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "math/vector.hpp"
|
||||
#include "primitive.hpp"
|
||||
|
||||
namespace primitives
|
||||
{
|
||||
|
||||
class Rectangle : public Primitive
|
||||
{
|
||||
public:
|
||||
Rectangle(const math::Vector& pos, const math::Vector& size) : m_pos(pos), m_size(size), m_angle(0.0f)
|
||||
{
|
||||
}
|
||||
|
||||
const math::Vector& GetPosition() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
const math::Vector& GetSize() const
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const float GetAngle() const
|
||||
{
|
||||
return m_angle;
|
||||
}
|
||||
|
||||
void Translate(const math::Vector& offset) override;
|
||||
void Rotate(const math::Vector& center, float angle) override;
|
||||
void Scale(const math::Vector& center, float factor) override;
|
||||
|
||||
void Draw(DrawingContext& ctx) override;
|
||||
|
||||
~Rectangle() override = default;
|
||||
|
||||
private:
|
||||
math::Vector m_pos;
|
||||
math::Vector m_size;
|
||||
float m_angle;
|
||||
};
|
||||
|
||||
} // namespace primitives
|
||||
Loading…
x
Reference in New Issue
Block a user