GCC Code Coverage Report


Directory: ./
File: Shape.hpp
Date: 2026-03-21 20:51:59
Exec Total Coverage
Lines: 3 3 100.0%
Functions: 3 3 100.0%
Branches: 0 0 -%

Line Branch Exec Source
1 #pragma once
2 #include <memory>
3 #include <tuple>
4
5 ////////////////////////////////////////////////////////////////////////////////
6
7 class Point {
8 public:
9 static Point rectangular(double x, double y);
10 static Point polar(double radius, double angle);
11 [[nodiscard]] double x() const;
12 [[nodiscard]] double y() const;
13 [[nodiscard]] double radius() const;
14 [[nodiscard]] double angle() const;
15
16 private:
17 Point(double x, double y);
18 double x_{0.0};
19 double y_{0.0};
20 };
21
22 double distance(const Point& a, const Point& b);
23
24 ////////////////////////////////////////////////////////////////////////////////
25
26 // Forward declarations.
27 class Circle;
28 class Rectangle;
29
30 // See [What is a "virtual constructor"?](https://isocpp.org/wiki/faq/virtual-functions#virtual-ctors)
31 // See [Non-virtual interface pattern](https://en.wikipedia.org/wiki/Non-virtual_interface_pattern)
32 class Shape {
33 public:
34 118 virtual ~Shape() noexcept = default;
35 [[nodiscard]] std::unique_ptr<Shape> clone() const; // Create a copy.
36 [[nodiscard]] double area() const; // Area.
37 [[nodiscard]] Circle boundingCircle() const; // Bounding circle.
38 [[nodiscard]] Rectangle boundingBox() const; // Bounding rectangle.
39 Shape& scaleTo(double s); // Set scale.
40 Shape& scaleBy(double ds); // Adjust scale.
41 Shape& rotateTo(double radians); // Set rotation angle.
42 Shape& rotateBy(double dradians); // Adjust rotation angle.
43 Shape& moveTo(double x, double y); // Set position.
44 Shape& moveBy(double dx, double dy); // Adjust position.
45
46 protected:
47 43 Shape() noexcept = default;
48 16 Shape(const Shape&) = default;
49 Shape(Shape&&) noexcept = default;
50 Shape& operator=(const Shape&) = default;
51 Shape& operator=(Shape&&) noexcept = default;
52
53 private:
54 // By convention, derived classes implement a virtual constructor
55 // with a covariant return type, which is not possible with smart pointers.
56 [[nodiscard]] virtual Shape* cloneImpl() const = 0;
57
58 // Not affected by rotation or position.
59 [[nodiscard]] virtual double areaImpl(double scale) const = 0;
60
61 // Not affected by rotation or position.
62 [[nodiscard]] virtual double boundingRadiusImpl(double scale) const = 0;
63
64 // Not affected by position. Returns width and height.
65 [[nodiscard]] virtual std::tuple<double, double> boundingBoxImpl(
66 double scale, double rotation) const = 0;
67
68 double scale_{1.0};
69 double rotation_{0.0};
70 Point position_{Point::rectangular(0.0, 0.0)};
71 };
72
73 ////////////////////////////////////////////////////////////////////////////////
74
75 class Rectangle : public Shape {
76 public:
77 Rectangle(double width, double height);
78
79 private:
80 [[nodiscard]] Rectangle* cloneImpl() const override;
81 [[nodiscard]] double areaImpl(double scale) const override;
82 [[nodiscard]] double boundingRadiusImpl(double scale) const override;
83 [[nodiscard]] std::tuple<double, double> boundingBoxImpl(
84 double scale, double rotation) const override;
85 double width_{0.0}; // Initial width.
86 double height_{0.0}; // Initial height.
87 };
88
89 ////////////////////////////////////////////////////////////////////////////////
90
91 class Square : public Rectangle {
92 public:
93 Square(double side);
94
95 private:
96 [[nodiscard]] Square* cloneImpl() const override;
97 };
98
99 ////////////////////////////////////////////////////////////////////////////////
100
101 class Ellipse : public Shape {
102 public:
103 Ellipse(double width, double height);
104
105 private:
106 [[nodiscard]] Ellipse* cloneImpl() const override;
107 [[nodiscard]] double areaImpl(double scale) const override;
108 [[nodiscard]] double boundingRadiusImpl(double scale) const override;
109 [[nodiscard]] std::tuple<double, double> boundingBoxImpl(
110 double scale, double rotation) const override;
111 [[nodiscard]] double radius(double angle) const;
112 double a_; // Initial length of semi-major axis.
113 double b_; // Initial length of semi-minor axis.
114 double e_; // Eccentricity.
115 };
116
117 ////////////////////////////////////////////////////////////////////////////////
118
119 class Circle : public Ellipse {
120 public:
121 Circle(double radius);
122
123 private:
124 [[nodiscard]] Circle* cloneImpl() const override;
125 };
126