1 #pragma once |
1 #pragma once |
2 #include <QPolygonF> |
2 #include <QPolygonF> |
3 #include "basics.h" |
3 #include "basics.h" |
4 |
4 |
5 namespace geom |
5 struct Plane |
6 { |
6 { |
7 struct Plane |
7 glm::vec3 normal; |
|
8 glm::vec3 anchor; |
|
9 }; |
|
10 |
|
11 template<int N, typename T = float, glm::qualifier Q = glm::defaultp> |
|
12 struct Line |
|
13 { |
|
14 glm::vec<N, T, Q> direction; |
|
15 glm::vec<N, T, Q> anchor; |
|
16 }; |
|
17 |
|
18 template<int N, typename T = float, glm::qualifier Q = glm::defaultp> |
|
19 struct Ray |
|
20 { |
|
21 glm::vec<N, T, Q> direction; |
|
22 glm::vec<N, T, Q> anchor; |
|
23 }; |
|
24 |
|
25 inline const glm::vec3 origin = {0, 0, 0}; |
|
26 inline const Plane XY = {{0, 0, 1}, origin}; |
|
27 inline const Plane XZ = {{0, 1, 0}, origin}; |
|
28 inline const Plane YZ = {{1, 0, 0}, origin}; |
|
29 |
|
30 struct LineSegment |
|
31 { |
|
32 glm::vec3 p1, p2; |
|
33 }; |
|
34 struct Triangle |
|
35 { |
|
36 glm::vec3 p1, p2, p3; |
|
37 }; |
|
38 struct Quadrilateral |
|
39 { |
|
40 glm::vec3 p1, p2, p3, p4; |
|
41 }; |
|
42 struct ConditionalEdge |
|
43 { |
|
44 glm::vec3 p1, p2; |
|
45 glm::vec3 c1, c2; |
|
46 }; |
|
47 struct LineSegment2D |
|
48 { |
|
49 glm::vec2 p1, p2; |
|
50 }; |
|
51 |
|
52 // get polygon type from amount of points |
|
53 template<int N> |
|
54 struct PolygonType {}; |
|
55 template<> |
|
56 struct PolygonType<2> { using type = LineSegment; }; |
|
57 template<> |
|
58 struct PolygonType<3> { using type = Triangle; }; |
|
59 template<> |
|
60 struct PolygonType<4> { using type = Quadrilateral; }; |
|
61 template<int N> |
|
62 using Polygon = typename PolygonType<N>::type; |
|
63 |
|
64 /** |
|
65 * @brief Computes a line from two points |
|
66 * @param point_1 |
|
67 * @param point_2 |
|
68 * @return line |
|
69 */ |
|
70 template<int N, typename T, glm::qualifier Q> |
|
71 Line<N, T, Q> lineFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) |
|
72 { |
|
73 return {point_2 - point_1, point_1}; |
|
74 } |
|
75 |
|
76 template<int N, typename T, glm::qualifier Q> |
|
77 Ray<N, T, Q> rayFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) |
|
78 { |
|
79 return {point_2 - point_1, point_1}; |
|
80 } |
|
81 |
|
82 template<int N, typename T, glm::qualifier Q> |
|
83 Line<N, T, Q> rayToLine(const Ray<N, T, Q>& ray) |
|
84 { |
|
85 return {ray.direction, ray.anchor}; |
|
86 } |
|
87 |
|
88 enum class RectangleSide |
|
89 { |
|
90 Top, |
|
91 Left, |
|
92 Bottom, |
|
93 Right |
|
94 }; |
|
95 |
|
96 struct PointOnRectagle |
|
97 { |
|
98 glm::vec2 position; |
|
99 RectangleSide side; |
|
100 }; |
|
101 |
|
102 std::optional<glm::vec2> lineLineIntersection(const Line<2>& line_1, const Line<2>& line_2); |
|
103 std::optional<glm::vec2> rayLineSegmentIntersection(const Ray<2>& ray, const LineSegment2D& line); |
|
104 std::optional<PointOnRectagle> rayRectangleIntersection(const Ray<2>& ray, const QRectF& rectangle); |
|
105 Plane planeFromTriangle(const Triangle& triangle); |
|
106 glm::vec3 normalVector(const Triangle& triangle); |
|
107 std::optional<glm::vec3> linePlaneIntersection( |
|
108 const Line<3>& line, |
|
109 const Plane& plane, const float epsilon = 1e-6f); |
|
110 glm::vec3 scalingVector(const glm::mat4 matrix); |
|
111 LineSegment2D top(const QRectF& rectangle); |
|
112 LineSegment2D bottom(const QRectF& rectangle); |
|
113 LineSegment2D left(const QRectF& rectangle); |
|
114 LineSegment2D right(const QRectF& rectangle); |
|
115 bool isConvex(const std::vector<glm::vec3>& polygon); |
|
116 Winding winding(const QPolygonF& polygon); |
|
117 struct ScalingExtract |
|
118 { |
|
119 glm::vec3 scaling; |
|
120 glm::mat4 unscaled; |
|
121 }; |
|
122 ScalingExtract extractScaling(const glm::mat4& matrix); |
|
123 |
|
124 struct NPolygon |
|
125 { |
|
126 std::vector<glm::vec3> points; |
|
127 }; |
|
128 |
|
129 inline constexpr bool isclose(const glm::vec3& a, const glm::vec3& b) |
|
130 { |
|
131 return qFuzzyCompare(a.x, b.x) |
|
132 and qFuzzyCompare(a.y, b.y) |
|
133 and qFuzzyCompare(a.z, b.z); |
|
134 } |
|
135 |
|
136 struct CircleF |
|
137 { |
|
138 QPointF center; |
|
139 qreal radius; |
|
140 }; |
|
141 |
|
142 /** |
|
143 * @brief Inscribes a circle |
|
144 * @param circle |
|
145 * @return a QRectF that inscribes the specified circle |
|
146 */ |
|
147 inline constexpr QRectF inscribe(const CircleF& circle) |
|
148 { |
|
149 return { |
|
150 circle.center.x() - circle.radius, |
|
151 circle.center.y() - circle.radius, |
|
152 circle.radius * 2, |
|
153 circle.radius * 2 |
|
154 }; |
|
155 } |
|
156 |
|
157 struct BezierCurve |
|
158 { |
|
159 glm::vec3 points[4]; |
|
160 const glm::vec3& operator[](int x) const |
8 { |
161 { |
9 glm::vec3 normal; |
162 Q_ASSERT(x >= 0 and x < 4); |
10 glm::vec3 anchor; |
163 return this->points[x]; |
11 }; |
164 } |
|
165 glm::vec3& operator[](int x) |
|
166 { |
|
167 Q_ASSERT(x >= 0 and x < 4); |
|
168 return this->points[x]; |
|
169 } |
|
170 }; |
12 |
171 |
13 template<int N, typename T = float, glm::qualifier Q = glm::defaultp> |
172 glm::vec3 pointOnCurve(const BezierCurve& curve, float t); |
14 struct Line |
173 glm::vec3 derivativeOnCurve(const BezierCurve& curve, float t); |
15 { |
|
16 glm::vec<N, T, Q> direction; |
|
17 glm::vec<N, T, Q> anchor; |
|
18 }; |
|
19 |
|
20 template<int N, typename T = float, glm::qualifier Q = glm::defaultp> |
|
21 struct Ray |
|
22 { |
|
23 glm::vec<N, T, Q> direction; |
|
24 glm::vec<N, T, Q> anchor; |
|
25 }; |
|
26 |
|
27 inline const glm::vec3 origin = {0, 0, 0}; |
|
28 inline const Plane XY = {{0, 0, 1}, origin}; |
|
29 inline const Plane XZ = {{0, 1, 0}, origin}; |
|
30 inline const Plane YZ = {{1, 0, 0}, origin}; |
|
31 |
|
32 struct LineSegment |
|
33 { |
|
34 glm::vec3 p1, p2; |
|
35 }; |
|
36 struct Triangle |
|
37 { |
|
38 glm::vec3 p1, p2, p3; |
|
39 }; |
|
40 struct Quadrilateral |
|
41 { |
|
42 glm::vec3 p1, p2, p3, p4; |
|
43 }; |
|
44 struct ConditionalEdge |
|
45 { |
|
46 glm::vec3 p1, p2; |
|
47 glm::vec3 c1, c2; |
|
48 }; |
|
49 struct LineSegment2D |
|
50 { |
|
51 glm::vec2 p1, p2; |
|
52 }; |
|
53 |
|
54 // get polygon type from amount of points |
|
55 template<int N> |
|
56 struct PolygonType {}; |
|
57 template<> |
|
58 struct PolygonType<2> { using type = LineSegment; }; |
|
59 template<> |
|
60 struct PolygonType<3> { using type = Triangle; }; |
|
61 template<> |
|
62 struct PolygonType<4> { using type = Quadrilateral; }; |
|
63 template<int N> |
|
64 using Polygon = typename PolygonType<N>::type; |
|
65 |
|
66 /** |
|
67 * @brief Computes a line from two points |
|
68 * @param point_1 |
|
69 * @param point_2 |
|
70 * @return line |
|
71 */ |
|
72 template<int N, typename T, glm::qualifier Q> |
|
73 Line<N, T, Q> lineFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) |
|
74 { |
|
75 return {point_2 - point_1, point_1}; |
|
76 } |
|
77 |
|
78 template<int N, typename T, glm::qualifier Q> |
|
79 Ray<N, T, Q> rayFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) |
|
80 { |
|
81 return {point_2 - point_1, point_1}; |
|
82 } |
|
83 |
|
84 template<int N, typename T, glm::qualifier Q> |
|
85 Line<N, T, Q> rayToLine(const Ray<N, T, Q>& ray) |
|
86 { |
|
87 return {ray.direction, ray.anchor}; |
|
88 } |
|
89 |
|
90 enum class RectangleSide |
|
91 { |
|
92 Top, |
|
93 Left, |
|
94 Bottom, |
|
95 Right |
|
96 }; |
|
97 |
|
98 struct PointOnRectagle |
|
99 { |
|
100 glm::vec2 position; |
|
101 RectangleSide side; |
|
102 }; |
|
103 |
|
104 std::optional<glm::vec2> lineLineIntersection(const Line<2>& line_1, const Line<2>& line_2); |
|
105 std::optional<glm::vec2> rayLineSegmentIntersection(const Ray<2>& ray, const LineSegment2D& line); |
|
106 std::optional<PointOnRectagle> rayRectangleIntersection(const Ray<2>& ray, const QRectF& rectangle); |
|
107 Plane planeFromTriangle(const Triangle& triangle); |
|
108 glm::vec3 normalVector(const Triangle& triangle); |
|
109 std::optional<glm::vec3> linePlaneIntersection( |
|
110 const Line<3>& line, |
|
111 const Plane& plane, const float epsilon = 1e-6f); |
|
112 glm::vec3 scalingVector(const glm::mat4 matrix); |
|
113 LineSegment2D top(const QRectF& rectangle); |
|
114 LineSegment2D bottom(const QRectF& rectangle); |
|
115 LineSegment2D left(const QRectF& rectangle); |
|
116 LineSegment2D right(const QRectF& rectangle); |
|
117 bool isConvex(const std::vector<glm::vec3>& polygon); |
|
118 Winding winding(const QPolygonF& polygon); |
|
119 struct ScalingExtract |
|
120 { |
|
121 glm::vec3 scaling; |
|
122 glm::mat4 unscaled; |
|
123 }; |
|
124 ScalingExtract extractScaling(const glm::mat4& matrix); |
|
125 |
|
126 struct NPolygon |
|
127 { |
|
128 std::vector<glm::vec3> points; |
|
129 }; |
|
130 |
|
131 inline constexpr bool isclose(const glm::vec3& a, const glm::vec3& b) |
|
132 { |
|
133 return qFuzzyCompare(a.x, b.x) |
|
134 and qFuzzyCompare(a.y, b.y) |
|
135 and qFuzzyCompare(a.z, b.z); |
|
136 } |
|
137 |
|
138 struct CircleF |
|
139 { |
|
140 QPointF center; |
|
141 qreal radius; |
|
142 }; |
|
143 |
|
144 /** |
|
145 * @brief Inscribes a circle |
|
146 * @param circle |
|
147 * @return a QRectF that inscribes the specified circle |
|
148 */ |
|
149 inline constexpr QRectF inscribe(const CircleF& circle) |
|
150 { |
|
151 return { |
|
152 circle.center.x() - circle.radius, |
|
153 circle.center.y() - circle.radius, |
|
154 circle.radius * 2, |
|
155 circle.radius * 2 |
|
156 }; |
|
157 } |
|
158 |
|
159 struct BezierCurve |
|
160 { |
|
161 glm::vec3 points[4]; |
|
162 const glm::vec3& operator[](int x) const |
|
163 { |
|
164 Q_ASSERT(x >= 0 and x < 4); |
|
165 return this->points[x]; |
|
166 } |
|
167 glm::vec3& operator[](int x) |
|
168 { |
|
169 Q_ASSERT(x >= 0 and x < 4); |
|
170 return this->points[x]; |
|
171 } |
|
172 }; |
|
173 |
|
174 glm::vec3 pointOnCurve(const BezierCurve& curve, float t); |
|
175 glm::vec3 derivativeOnCurve(const BezierCurve& curve, float t); |
|
176 } |
|
177 using namespace geom; |
|