VIPRA Documentation
Loading...
Searching...
No Matches
triangle.hpp
1#pragma once
2
3#include <array>
4
5#include "vipra/geometry/definitions.hpp"
6#include "vipra/geometry/f3d.hpp"
7#include "vipra/geometry/line.hpp"
8#include "vipra/geometry/rectangle.hpp"
9#include "vipra/types/float.hpp"
10
11namespace VIPRA::Geometry {
12
13class Circle;
14class Rectangle;
15class Polygon;
16
17class Triangle {
18 public:
19 VIPRA_POLY_FUNC auto is_point_inside(f3d point) const noexcept -> bool;
20 VIPRA_POLY_FUNC auto bounding_box() const noexcept -> Rectangle;
21 VIPRA_POLY_FUNC auto sides() const noexcept -> std::array<Line, 3>;
22 VIPRA_POLY_FUNC auto center() const noexcept -> f3d;
23
24 [[nodiscard]] auto random_point(Random::Engine& engine) const noexcept -> f3d;
25
26 VIPRA_POLY_FUNC auto area() const noexcept -> f_pnt { return _area; }
27 VIPRA_POLY_FUNC auto points() const noexcept -> std::array<f3d, 3> const&
28 {
29 return _points;
30 }
31
32 private:
33 std::array<f3d, 3> _points;
34 f_pnt _area{};
35
36 public:
37 Triangle(f3d const& point1, f3d const& point2, f3d const& point3)
38 : _points({point1, point2, point3}),
39 _area(std::abs(point1.x * (point2.y - point3.y) +
40 point2.x * (point3.y - point1.y) +
41 point3.x * (point1.y - point2.y)) /
42 2.0)
43 {
44 }
45
46 Triangle() = default;
47 ~Triangle() = default;
48 Triangle(Triangle const&) = default;
49 auto operator=(Triangle const&) -> Triangle& = default;
50 Triangle(Triangle&&) noexcept = default;
51 auto operator=(Triangle&&) noexcept -> Triangle& = default;
52};
53
54VIPRA_POLY_FUNC auto Triangle::is_point_inside(f3d point) const noexcept -> bool
55{
56 auto const sign = [](f3d point1, f3d point2, f3d point3) -> f_pnt {
57 return (point1.x - point3.x) * (point2.y - point3.y) -
58 (point2.x - point3.x) * (point1.y - point3.y);
59 };
60
61 const f_pnt dir1 = sign(point, _points[0], _points[1]);
62 const f_pnt dir2 = sign(point, _points[1], _points[2]);
63 const f_pnt dir3 = sign(point, _points[2], _points[0]);
64
65 return ((dir1 >= 0) && (dir2 >= 0) && (dir3 >= 0)) ||
66 ((dir1 <= 0) && (dir2 <= 0) && (dir3 <= 0));
67}
68
69inline auto Triangle::random_point(Random::Engine& engine) const noexcept -> f3d
70{
71 const Rectangle box = bounding_box();
72 f3d point = box.random_point(engine);
73
74 while ( ! is_point_inside(point) ) {
75 point = box.random_point(engine);
76 }
77
78 return point;
79}
80
81VIPRA_POLY_FUNC auto Triangle::bounding_box() const noexcept -> Rectangle
82{
83 f3d botLeft{std::numeric_limits<VIPRA::f_pnt>::max(),
84 std::numeric_limits<VIPRA::f_pnt>::max()};
85 f3d topRight{std::numeric_limits<VIPRA::f_pnt>::min(),
86 std::numeric_limits<VIPRA::f_pnt>::min()};
87 for ( auto const& point : _points ) {
88 topRight.x = std::max(topRight.x, point.x);
89 topRight.y = std::max(topRight.y, point.y);
90 botLeft.x = std::min(botLeft.x, point.x);
91 botLeft.y = std::min(botLeft.y, point.y);
92 }
93
94 f3d topLeft = f3d{botLeft.x, topRight.y};
95 f3d botRight = f3d{topRight.x, botLeft.y};
96
97 return Rectangle{botLeft, topLeft, topRight, botRight};
98}
99
100VIPRA_POLY_FUNC auto Triangle::sides() const noexcept -> std::array<Line, 3>
101{
102 std::array<Line, 3> lines;
103 for ( size_t i = 0; i < 3; ++i ) {
104 lines[i] = Line{_points[i], _points[i + 1]};
105 }
106 lines.back() = Line{_points.back(), _points.front()};
107 return lines;
108}
109
110VIPRA_POLY_FUNC auto Triangle::center() const noexcept -> f3d
111{
112 f3d center;
113 for ( f3d point : _points ) {
114 center += point;
115 }
116 return center / 3;
117}
118
119} // namespace VIPRA::Geometry
Definition circle.hpp:9
Definition polygon.hpp:18
Definition rectangle.hpp:20
Psuedo Random number engine.
Definition random.hpp:22
Definition line.hpp:11
Definition f3d.hpp:27