More drawing progress.

This commit is contained in:
That-One-Nerd 2024-08-03 14:05:59 -04:00
parent 9168e584ef
commit 51311a2d51
5 changed files with 253 additions and 14 deletions

View File

@ -1,9 +1,58 @@
#pragma once
#include <cstdint>
#include <numbers>
using std::numbers::pi;
namespace sharp
{
enum angle_type
{
DEGREES = 10,
RADIANS = 11,
GRADIANS = 12,
TURNS = 13
};
struct angle
{
private:
double value;
public:
angle();
angle(const angle& copy);
angle(double amount, angle_type unit);
double get(angle_type unit) const;
double degrees() const;
double radians() const;
double gradians() const;
double turns() const;
void set(double value, angle_type unit);
void degrees(double deg);
void radians(double rad);
void gradians(double grad);
void turns(double turns);
const angle operator+(const angle& other) const;
const angle operator-() const;
const angle operator-(const angle& other) const;
const angle operator*(double factor) const;
const angle operator/(double factor) const;
};
const angle operator""_deg(long double val);
const angle operator""_deg(unsigned long long val);
const angle operator""_rad(long double val);
const angle operator""_rad(unsigned long long val);
const angle operator""_grad(long double val);
const angle operator""_grad(unsigned long long val);
const angle operator""_turns(long double val);
const angle operator""_turns(unsigned long long val);
struct color
{
uint8_t r, g, b, a;
@ -61,6 +110,8 @@ namespace sharp
int_rect(int left, int top, int width, int height);
int_rect(const int2 pos, const int2 size);
static const int_rect from_corners(const int2& a, const int2& b);
const int2 tl() const; // Top left
const int2 tr() const; // Top right
const int2 bl() const; // Bottom left

View File

@ -72,7 +72,7 @@ namespace sharp
void draw_line(const color& color, const int2& start, const int2& end);
//void draw_rect(const color& color, const int_rect& rect);
//void fill_rect(const color& color, const int_rect& rect);
void fill_rect(const color& color, const int_rect& rect);
public:
const window_styles& style() const;

View File

@ -16,7 +16,7 @@ protected:
{
constexpr int points = 5;
int bigRadius = 100,
int bigRadius = 105,
smallRadius = 60;
sharp::int2 center = get_size() / 2;
@ -35,7 +35,7 @@ protected:
{
sharp::int2& this_point = arr[i],
next_point = arr[(i + 1) % (points * 2)];
draw_line(0xABCDEF, this_point, next_point);
fill_rect(0x28b56e, sharp::int_rect::from_corners(this_point, next_point));
}
}
void tick() override

View File

@ -3,6 +3,146 @@
using namespace sharp;
using std::max;
using std::min;
static constexpr double degrees_per_turn = 360;
static constexpr double radians_per_turn = 2 * pi;
static constexpr double gradians_per_turn = 400;
sharp::angle::angle()
{
value = 0;
}
sharp::angle::angle(const angle& copy)
{
value = copy.value;
}
sharp::angle::angle(double amount, angle_type unit)
{
set(amount, unit);
}
double sharp::angle::get(angle_type unit) const
{
switch (unit)
{
case DEGREES: return degrees();
case RADIANS: return radians();
case GRADIANS: return gradians();
case TURNS: return turns();
default: return 0.0;
}
}
double sharp::angle::degrees() const
{
return degrees_per_turn * value;
}
double sharp::angle::radians() const
{
return radians_per_turn * value;
}
double sharp::angle::gradians() const
{
return gradians_per_turn * value;
}
double sharp::angle::turns() const
{
return value;
}
void sharp::angle::set(double value, angle_type unit)
{
switch (unit)
{
case DEGREES: degrees(value);
case RADIANS: radians(value);
case GRADIANS: gradians(value);
case TURNS: turns(value);
default: return;
}
}
void sharp::angle::degrees(double deg)
{
value = deg / degrees_per_turn;
}
void sharp::angle::radians(double rad)
{
value = rad / radians_per_turn;
}
void sharp::angle::gradians(double grad)
{
value = grad / gradians_per_turn;
}
void sharp::angle::turns(double turns)
{
value = turns;
}
// Doing this somewhat convoluted set system because I don't
// want to run unneccessary unit detection, I know I'm working
// with the raw turns.
const angle sharp::angle::operator+(const angle& other) const
{
angle result = angle();
result.value = value + other.value;
return result;
}
const angle sharp::angle::operator-() const
{
angle result = angle();
result.value = -value;
return result;
}
const angle sharp::angle::operator-(const angle& other) const
{
angle result = angle();
result.value = value - other.value;
return result;
}
const angle sharp::angle::operator*(double factor) const
{
angle result = angle();
result.value = value * factor;
return result;
}
const angle sharp::angle::operator/(double factor) const
{
angle result = angle();
result.value = value / factor;
return result;
}
// These are shorthands.
const angle sharp::operator""_deg(long double val)
{
return angle(val, DEGREES);
}
const angle sharp::operator""_deg(unsigned long long val)
{
return angle(val, DEGREES);
}
const angle sharp::operator""_rad(long double val)
{
return angle(val, RADIANS);
}
const angle sharp::operator""_rad(unsigned long long val)
{
return angle(val, RADIANS);
}
const angle sharp::operator""_grad(long double val)
{
return angle(val, GRADIANS);
}
const angle sharp::operator""_grad(unsigned long long val)
{
return angle(val, GRADIANS);
}
const angle sharp::operator""_turns(long double val)
{
return angle(val, TURNS);
}
const angle sharp::operator""_turns(unsigned long long val)
{
return angle(val, TURNS);
}
sharp::color::color()
{
r = 0;
@ -140,7 +280,12 @@ sharp::int_rect::int_rect(const int2 pos, const int2 size)
width = size.x;
height = size.y;
}
const int_rect sharp::int_rect::from_corners(const int2& a, const int2& b)
{
int2 tl = int2(min(a.x, b.x), min(a.y, b.y));
int2 size = int2(max(a.x, b.x) - tl.x, max(a.y, b.y) - tl.y);
return int_rect(tl, size);
}
const int2 sharp::int_rect::tl() const
{
return int2(top, left);

View File

@ -72,24 +72,67 @@ void window_base::draw_pixel(const color& color, const int2& win_pos)
}
void window_base::draw_line(const color& color, const int2& pos_a, const int2& pos_b)
{
// FIXME: This causes artifacts occasionally along the top and bottom of the window.
// Why?
double slope = (double)(pos_b.y - pos_a.y) / (pos_b.x - pos_a.x),
inv_slope = (double)(pos_b.x - pos_a.x) / (pos_b.y - pos_a.y); // Prevent divide by zero errors.
int2 a = pos_a, b = pos_b;
if (a.x < 0) a = int2(0, -a.x * slope + a.y); // Left wall truncate for A.
else if (a.x >= width) a = int2(width - 1, ((width - 1) - a.x) * slope + a.y); // Right wall truncate for A.
if (a.y < 0) a = int2(-a.y * inv_slope + a.x, 0); // Bottom wall truncate for A.
else if (a.y >= height) a = int2(((height - 1) - a.y) * inv_slope + a.x, height - 1); // Top wall truncate for A.
if (a.x < 0)
{
if (b.x < 0) return; // Off screen.
// Left wall truncate for A.
a = int2(0, -a.x * slope + a.y);
}
else if (a.x >= width)
{
if (b.x >= width) return; // Off screen.
// Right wall truncate for A.
a = int2(width - 1, ((width - 1) - a.x) * slope + a.y);
}
if (a.y < 0)
{
if (b.y < 0) return;
// Bottom wall truncate for A.
a = int2(-a.y * inv_slope + a.x, 0);
}
else if (a.y >= height)
{
if (b.y >= height) return;
// Top wall truncate for A.
a = int2(((height - 1) - a.y) * inv_slope + a.x, height - 1);
}
// No checks for the other point need to be made here, because if both
// are off screen, it would have triggered in the checks above.
if (b.x < 0) b = int2(0, -a.x * slope + a.y); // Left wall truncate for B.
else if (b.x >= width) b = int2(width - 1, ((width - 1) - a.x) * slope + a.y); // Right wall truncate for B.
if (b.y < 0) b = int2(-a.y * inv_slope + a.x, 0); // Bottom wall truncate for B.
else if (b.y >= height) b = int2(((height - 1) - a.y) * inv_slope + a.x, height - 1); // Top wall truncate for B.
const int2 true_pos_a = to_screen(a),
true_pos_b = to_screen(b);
internal::draw_global_line(color, true_pos_a, true_pos_b);
const int2 true_a = to_screen(a),
true_b = to_screen(b);
internal::draw_global_line(color, true_a, true_b);
}
void window_base::fill_rect(const color& color, const int_rect& rect)
{
int2 a = rect.tl(), b = rect.br();
if (a.x < 0) a.x = 0;
else if (a.x >= width) a.x = width;
if (a.y < 0) a.y = 0;
else if (a.y >= height) a.y = height;
if (b.x < 0) b.x = 0;
else if (b.x >= width) b.x = width;
if (b.y < 0) b.y = 0;
else if (b.y >= height) b.y = height;
if (a.x == b.x || a.y == b.y) return; // Zero width or height, ignore.
const int2 true_a = to_screen(a),
true_b = to_screen(b);
internal::fill_global_rectangle(color, int_rect(true_a, true_b - true_a));
}