Selaa lähdekoodia

Updated Figures

Vsevolod Levitan 11 kuukautta sitten
vanhempi
commit
e218e691d1
1 muutettua tiedostoa jossa 78 lisäystä ja 69 poistoa
  1. 78 69
      Figures/Figures/Figures.h

+ 78 - 69
Figures/Figures/Figures.h

@@ -3,8 +3,9 @@
 #include <cmath>
 #include <vector>
 #include <fstream>
-#define PI 3.14159265358979323846
+#include <iomanip>
 
+#define PI 3.14159265358979323846
 
 template<class T>
 class Point {
@@ -21,37 +22,37 @@ template<class T>
 class GeometricFigure {
 public:
     /// <summary>
-    /// Calculate area of the figure
+    /// Calculate the area of the figure
     /// </summary>
     /// <returns>The internal area of the figure</returns>
-    virtual T calc_area() = 0;
+    virtual T calc_area() const = 0;
 
     /// <summary>
-    /// Calculate perimeter of the figure
+    /// Calculate the perimeter of the figure
     /// </summary>
     /// <returns>The external perimeter of the figure</returns>
-    virtual T calc_perimeter() = 0;
-    
+    virtual T calc_perimeter() const = 0;
+
     /// <summary>
-    /// Get name of the figure
+    /// Get the name of the figure
     /// </summary>
-    virtual void name() = 0;
+    virtual void name() const = 0;
 
-    friend std::ostream& operator << (const std::ostream& out, const GeometricFigure& figure);
-};
+    friend std::ostream& operator<<(std::ostream& out, const GeometricFigure<T>& figure) {
+        figure.name();
+        out << " (perimeter: " << figure.calc_perimeter() << ", area: " << figure.calc_area() << ")";
+        return out;
+    }
 
-template<class T>
-std::ostream& operator << (const std::ostream& out, const GeometricFigure<T>& figure)
-{
-    out << figure.name << " (perimeter: " << figure.calc_perimeter() << ", area: " << figure.calc_area();
-    return out;
-}
+    virtual ~GeometricFigure() = default;
+};
 
 /// <summary>
 /// Represents a circle
 /// </summary>
 /// <typeparam name="T">Number value type</typeparam>
-template<class T> class Circle : public GeometricFigure<T> {
+template<class T>
+class Circle : public GeometricFigure<T> {
 private:
     Point<T> center;
     T radius;
@@ -64,24 +65,24 @@ public:
     /// <param name="r">Radius of the circle</param>
     Circle(Point<T> c, T r) : center(c), radius(r) {}
 
-    T calc_area() override;
-    T calc_perimeter() override;
-    void name() override;
+    T calc_area() const override;
+    T calc_perimeter() const override;
+    void name() const override;
 };
 
 template<class T>
-T Circle<T>::calc_area() {
+T Circle<T>::calc_area() const {
     return PI * radius * radius;
 }
 
 template<class T>
-T Circle<T>::calc_perimeter() {
+T Circle<T>::calc_perimeter() const {
     return 2 * PI * radius;
 }
 
 template<class T>
-void Circle<T>::name() {
-    std::cout << "Circle" << std::endl;
+void Circle<T>::name() const {
+    std::cout << "Circle";
 }
 
 /// <summary>
@@ -96,31 +97,32 @@ private:
 
 public:
     /// <summary>
-    /// Create an ellipse by its center point and two dimension
+    /// Create an ellipse by its center point and two dimensions
     /// </summary>
     /// <param name="c">Center of the ellipse</param>
     /// <param name="a">First dimension</param>
     /// <param name="b">Second dimension</param>
     Ellipse(Point<T> c, T a, T b) : center(c), a(a), b(b) {}
 
-    T calc_area() override;
-    T calc_perimeter() override;
-    void name() override;
+    T calc_area() const override;
+    T calc_perimeter() const override;
+    void name() const override;
 };
 
 template<class T>
-T Ellipse<T>::calc_area() {
+T Ellipse<T>::calc_area() const {
     return PI * a * b;
 }
 
 template<class T>
-T Ellipse<T>::calc_perimeter() {
-    return PI * (3 * (a + b) - sqrt((3 * a + b) * (a + 3 * b)));
+T Ellipse<T>::calc_perimeter() const {
+    // Approximation of the perimeter of an ellipse
+    return PI * (3 * (a + b) - std::sqrt((3 * a + b) * (a + 3 * b)));
 }
 
 template<class T>
-void Ellipse<T>::name() {
-    std::cout << "Ellipse" << std::endl;
+void Ellipse<T>::name() const {
+    std::cout << "Ellipse";
 }
 
 /// <summary>
@@ -132,6 +134,10 @@ class Triangle : public GeometricFigure<T> {
 private:
     Point<T> vertices[3];
 
+    T side_length(const Point<T>& p1, const Point<T>& p2) const {
+        return std::sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
+    }
+
 public:
     /// <summary>
     /// Create a triangle by three points
@@ -141,31 +147,31 @@ public:
     /// <param name="c">Point C</param>
     Triangle(Point<T> a, Point<T> b, Point<T> c) : vertices{ a, b, c } {}
 
-    T calc_area() override;
-    T calc_perimeter() override;
-    void name() override;
+    T calc_area() const override;
+    T calc_perimeter() const override;
+    void name() const override;
 };
 
 template<class T>
-T Triangle<T>::calc_area() {
-    T a = sqrt((vertices[1].x - vertices[0].x) * (vertices[1].x - vertices[0].x) + (vertices[1].y - vertices[0].y) * (vertices[1].y - vertices[0].y));
-    T b = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y));
-    T c = sqrt((vertices[0].x - vertices[2].x) * (vertices[0].x - vertices[2].x) + (vertices[0].y - vertices[2].y) * (vertices[0].y - vertices[2].y));
+T Triangle<T>::calc_area() const {
+    T a = side_length(vertices[0], vertices[1]);
+    T b = side_length(vertices[1], vertices[2]);
+    T c = side_length(vertices[2], vertices[0]);
     T s = (a + b + c) / 2;
-    return sqrt(s * (s - a) * (s - b) * (s - c));
+    return std::sqrt(s * (s - a) * (s - b) * (s - c));
 }
 
 template<class T>
-T Triangle<T>::calc_perimeter() {
-    T a = sqrt((vertices[1].x - vertices[0].x) * (vertices[1].x - vertices[0].x) + (vertices[1].y - vertices[0].y) * (vertices[1].y - vertices[0].y));
-    T b = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y));
-    T c = sqrt((vertices[0].x - vertices[2].x) * (vertices[0].x - vertices[2].x) + (vertices[0].y - vertices[2].y) * (vertices[0].y - vertices[2].y));
+T Triangle<T>::calc_perimeter() const {
+    T a = side_length(vertices[0], vertices[1]);
+    T b = side_length(vertices[1], vertices[2]);
+    T c = side_length(vertices[2], vertices[0]);
     return a + b + c;
 }
 
 template<class T>
-void Triangle<T>::name() {
-    std::cout << "Triangle" << std::endl;
+void Triangle<T>::name() const {
+    std::cout << "Triangle";
 }
 
 /// <summary>
@@ -177,6 +183,10 @@ class Rectangle : public GeometricFigure<T> {
 private:
     Point<T> vertices[4];
 
+    T side_length(const Point<T>& p1, const Point<T>& p2) const {
+        return std::sqrt((p2.x - p1.x) * (p2.x - p1.x) + (p2.y - p1.y) * (p2.y - p1.y));
+    }
+
 public:
     /// <summary>
     /// Create a rectangle by 4 points
@@ -187,28 +197,28 @@ public:
     /// <param name="d">Top-right point</param>
     Rectangle(Point<T> a, Point<T> b, Point<T> c, Point<T> d) : vertices{ a, b, c, d } {}
 
-    T calc_area() override;
-    T calc_perimeter() override;
-    void name() override;
+    T calc_area() const override;
+    T calc_perimeter() const override;
+    void name() const override;
 };
 
 template<class T>
-T Rectangle<T>::calc_area() {
-    T width = sqrt((vertices[1].x - vertices[0].x) * (vertices[1].x - vertices[0].x) + (vertices[1].y - vertices[0].y) * (vertices[1].y - vertices[0].y));
-    T height = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y));
+T Rectangle<T>::calc_area() const {
+    T width = side_length(vertices[0], vertices[1]);
+    T height = side_length(vertices[1], vertices[2]);
     return width * height;
 }
 
 template<class T>
-T Rectangle<T>::calc_perimeter() {
-    T width = sqrt((vertices[1].x - vertices[0].x) * (vertices[1].x - vertices[0].x) + (vertices[1].y - vertices[0].y) * (vertices[1].y - vertices[0].y));
-    T height = sqrt((vertices[2].x - vertices[1].x) * (vertices[2].x - vertices[1].x) + (vertices[2].y - vertices[1].y) * (vertices[2].y - vertices[1].y));
+T Rectangle<T>::calc_perimeter() const {
+    T width = side_length(vertices[0], vertices[1]);
+    T height = side_length(vertices[1], vertices[2]);
     return 2 * (width + height);
 }
 
 template<class T>
-void Rectangle<T>::name() {
-    std::cout << "Rectangle" << std::endl;
+void Rectangle<T>::name() const {
+    std::cout << "Rectangle";
 }
 
 /// <summary>
@@ -227,17 +237,16 @@ public:
     /// <param name="filename">Path to the file</param>
     Polygon(const std::string& filename);
 
-    T calc_area() override;
-    T calc_perimeter() override;
-    void name() override;
+    T calc_area() const override;
+    T calc_perimeter() const override;
+    void name() const override;
 };
 
 template<class T>
 Polygon<T>::Polygon(const std::string& filename) {
     std::ifstream file(filename);
     if (!file.is_open()) {
-        std::cerr << "Error opening file" << std::endl;
-        return;
+        throw std::runtime_error("Error opening file");
     }
     int numVertices;
     file >> numVertices;
@@ -250,7 +259,7 @@ Polygon<T>::Polygon(const std::string& filename) {
 }
 
 template<class T>
-T Polygon<T>::calc_area() {
+T Polygon<T>::calc_area() const {
     T area = 0.0;
     int n = vertices.size();
     for (int i = 0; i < n; ++i) {
@@ -260,16 +269,16 @@ T Polygon<T>::calc_area() {
 }
 
 template<class T>
-T Polygon<T>::calc_perimeter() {
+T Polygon<T>::calc_perimeter() const {
     T perimeter = 0.0;
     int n = vertices.size();
     for (int i = 0; i < n; ++i) {
-        perimeter += sqrt((vertices[(i + 1) % n].x - vertices[i].x) * (vertices[(i + 1) % n].x - vertices[i].x) + (vertices[(i + 1) % n].y - vertices[i].y) * (vertices[(i + 1) % n].y - vertices[i].y));
+        perimeter += std::sqrt((vertices[(i + 1) % n].x - vertices[i].x) * (vertices[(i + 1) % n].x - vertices[i].x) + (vertices[(i + 1) % n].y - vertices[i].y) * (vertices[(i + 1) % n].y - vertices[i].y));
     }
     return perimeter;
 }
 
 template<class T>
-void Polygon<T>::name() {
-    std::cout << "Polygon" << std::endl;
-}
+void Polygon<T>::name() const {
+    std::cout << "Polygon";
+}