#include <iostream>
#include <vector>
#include <cmath>
#include <cassert>
#define M_PI 3.14159265358979323846
template<size_t size>
class Point {
protected:
double Data[size];
public:
template<typename... Args>
Point(Args &&... args) : Data{ forward<Args>(args)... } {}
~Point() {}
double& operator[](int value) { return Data[value]; }
const double& operator[](int value) const { return Data[value]; }
};
typedef Point<1> Point1D;
typedef Point<2> Point2D;
typedef Point<3> Point3D;
class Figure {
protected:
virtual void recalc() {};
public:
virtual ~Figure() {};
};
class Figure2D : public Figure {
protected:
Point2D Cord = {0, 0};
double Angle{ 0 }, _perimeter{ 0 }, _area{ 0 };
typedef enum { X, Y } dimensions;
public:
virtual ~Figure2D() {};
virtual std::vector<Point2D> get_cord() const {};
double perimeter() const { return _perimeter; };
double area() const { return _area; };
double get_x() const { return Cord[X]; };
double get_y() const { return Cord[Y]; };
double get_angle() const { return Angle; };
void set_x(const double x) { Cord[X] = x; };
void set_y(const double y) { Cord[Y] = y; };
void set_angle(const double angle) { Angle = fmod(angle, 360.); };
};
class Circle : public Figure2D {
protected:
double Radius{ 0 };
void recalc() {
_perimeter = M_PI * Radius * 2;
_area = M_PI * Radius * Radius;
};
double get_angle() const {};
void set_angle(const double angle) {};
public:
Circle(const double radius, const Point2D cord = {0, 0}) : Radius(radius) {
Cord[X] = cord[X]; Cord[Y] = cord[Y];
recalc();
};
~Circle() {};
vector<Point2D> get_cord() const { return std::vector<Point2D> { Cord }; };
double get_radius() const { return Radius; };
void set_radius(const double radius) { Radius = radius; recalc(); };
};
class Ellipse : public Figure2D {
protected:
double a{ 0 }, b{ 0 };
void recalc() {
_perimeter = 2. * M_PI * sqrt((pow(a,2) + pow(b,2)) / 2.);
_area = 2. * M_PI * sqrt((pow(2. * a, 2) + pow(2. * b, 2)) / 8.);
};
public:
Ellipse(const double radA, const double radB, const Point2D cord = { 0, 0 }, const double angle = 0.) : a(radA), b(radB) {
Cord[X] = cord[X]; Cord[Y] = cord[Y];
Angle = angle;
recalc();
};
~Ellipse() {};
vector<Point2D> get_cord() const { return std::vector<Point2D> { Cord }; };
double get_radA() const { return a; };
double get_radB() const { return b; };
void set_radA(const double radius) { a = radius; recalc(); };
void set_radB(const double radius) { b = radius; recalc(); };
};
class Rectangle : public Figure2D {
protected:
double A{ 0 }, B{ 0 };
void recalc() {
_perimeter = (A * 2) + (B * 2);
_area = A * B;
}
public:
Rectangle(const double a, const double b, const Point2D cord = {0, 0}, const double angle = 0) : A(a), B(b) {
Cord[X] = cord[X]; Cord[Y] = cord[Y];
Angle = angle;
recalc();
}
~Rectangle() {};
std::vector<Point2D> get_cord() const {
double sinA = sin(Angle), cosA = cos(Angle);
return std::vector<Point2D> {
Cord,
{ (Cord[X] + A) * sinA + Cord[Y] *cosA, (Cord[X] + A) * cosA - Cord[Y] * sinA },
{ (Cord[X] + A) * sinA + (Cord[Y] + B) * cosA, (Cord[X] + A) * cosA - (Cord[Y] + B) * sinA },
{ Cord[X] * sinA + (Cord[Y] + B) * cosA, Cord[X] * cosA - (Cord[Y] + B) * sinA }
};
};
double get_a() const { return A; }
void set_a(const double a) { A = a; recalc(); }
double get_b() const { return B; }
void set_b(const double b) { B = b; recalc(); }
};
class Triangle : public Figure2D {
private:
double distance(Point2D a, Point2D b) {
return sqrt(pow(a[X] - b[X], 2) + pow(a[Y] - b[Y], 2));
}
protected:
Point2D B{ 0, 0 }, C{ 0, 0 };
double a{ 0 }, b{ 0 }, c{ 0 }, _r{ 0 }, _R{ 0 };
void recalc() {
a = distance(Cord, B);
b = distance(B, C);
c = distance(C, Cord);
_perimeter = a + b + c;
double p = _perimeter / 2, temp = (p - a) * (p - b) * (p * c);
_area = sqrt(p * temp);
_r = sqrt(temp / p);
_R = (a * b * c) / (_area * 4.);
}
public:
Triangle(Point2D A = { 0, 0 }, Point2D B = { 0, 0 }, Point2D C = { 0, 0 }, double angle = 0) : B(B), C(C) {
Cord = A;
Angle = angle;
recalc();
}
~Triangle() {}
std::vector<Point2D> get_cord() const {
double sinA = sin(Angle), cosA = cos(Angle);
return std::vector<Point2D> {
Cord,
{ B[X] * sinA + B[Y] * cosA, B[X] * cosA - B[Y] * sinA },
{ C[X] * sinA + C[Y] * cosA, C[X] * cosA - C[Y] * sinA }
};
}
Point2D get_A() const { return Cord; }
Point2D get_B() const { return B; }
Point2D get_C() const { return C; }
void set_A(const Point2D A) { Cord = A; recalc(); }
void set_B(const Point2D B) { this->B = B; recalc(); }
void set_C(const Point2D C) { this->C = C; recalc(); }
double get_a() const { return a; }
double get_b() const { return b; }
double get_c() const { return c; }
double get_r() const { return _r; }
double get_R() const { return _R; }
};