src/geometry.cpp

changeset 201
5d201ee4a9c3
parent 200
ca23936b455b
child 206
654661eab7f3
equal deleted inserted replaced
200:ca23936b455b 201:5d201ee4a9c3
7 * @brief Computes line-plane intersection 7 * @brief Computes line-plane intersection
8 * @param line 8 * @param line
9 * @param plane 9 * @param plane
10 * @return point of intersection. Does not return a value if the line is in parallel to the plane. 10 * @return point of intersection. Does not return a value if the line is in parallel to the plane.
11 */ 11 */
12 std::optional<glm::vec3> geom::linePlaneIntersection( 12 std::optional<glm::vec3> linePlaneIntersection(
13 const geom::Line<3>& line, 13 const Line<3>& line,
14 const geom::Plane& plane, 14 const Plane& plane,
15 const float epsilon) 15 const float epsilon)
16 { 16 {
17 const float denominator = glm::dot(line.direction, plane.normal); 17 const float denominator = glm::dot(line.direction, plane.normal);
18 if (std::abs(denominator) < epsilon) 18 if (std::abs(denominator) < epsilon)
19 { 19 {
29 /** 29 /**
30 * @brief Computes the plane of a triangle 30 * @brief Computes the plane of a triangle
31 * @param triangle 31 * @param triangle
32 * @return plane 32 * @return plane
33 */ 33 */
34 geom::Plane geom::planeFromTriangle(const geom::Triangle& triangle) 34 Plane planeFromTriangle(const Triangle& triangle)
35 { 35 {
36 return geom::Plane{normalVector(triangle), triangle.p1}; 36 return Plane{normalVector(triangle), triangle.p1};
37 } 37 }
38 38
39 /** 39 /**
40 * @brief Computes the normal vector of a triangle 40 * @brief Computes the normal vector of a triangle
41 * @param triangle 41 * @param triangle
42 * @return normal vector 42 * @return normal vector
43 */ 43 */
44 glm::vec3 geom::normalVector(const geom::Triangle& triangle) 44 glm::vec3 normalVector(const Triangle& triangle)
45 { 45 {
46 return glm::normalize( 46 return glm::normalize(
47 glm::cross( 47 glm::cross(
48 triangle.p2 - triangle.p1, 48 triangle.p2 - triangle.p1,
49 triangle.p3 - triangle.p1)); 49 triangle.p3 - triangle.p1));
53 * @brief Extracts the scaling component of the specified matrix into a vector and returns both the scaling 53 * @brief Extracts the scaling component of the specified matrix into a vector and returns both the scaling
54 * components as well as the unscaled matrix. 54 * components as well as the unscaled matrix.
55 * @param matrix Matrix to compute 55 * @param matrix Matrix to compute
56 * @return scaling vector and unscaled matrix 56 * @return scaling vector and unscaled matrix
57 */ 57 */
58 geom::ScalingExtract geom::extractScaling(const glm::mat4& matrix) 58 ScalingExtract extractScaling(const glm::mat4& matrix)
59 { 59 {
60 geom::ScalingExtract result; 60 ScalingExtract result;
61 result.scaling = geom::scalingVector(matrix); 61 result.scaling = scalingVector(matrix);
62 result.unscaled = glm::scale(matrix, 1.0f / result.scaling); 62 result.unscaled = glm::scale(matrix, 1.0f / result.scaling);
63 return result; 63 return result;
64 } 64 }
65 65
66 /** 66 /**
67 * @brief Computes the scaling vector, which contains the scaling of the specified matrix 67 * @brief Computes the scaling vector, which contains the scaling of the specified matrix
68 * @param matrix 68 * @param matrix
69 * @return scaling vector 69 * @return scaling vector
70 */ 70 */
71 glm::vec3 geom::scalingVector(const glm::mat4 matrix) 71 glm::vec3 scalingVector(const glm::mat4 matrix)
72 { 72 {
73 auto component = [](const glm::mat4& matrix, const int i) -> float 73 auto component = [](const glm::mat4& matrix, const int i) -> float
74 { 74 {
75 return std::hypot(std::hypot(matrix[i][0], matrix[i][1]), matrix[i][2]); 75 return std::hypot(std::hypot(matrix[i][0], matrix[i][1]), matrix[i][2]);
76 }; 76 };
77 return glm::vec3{component(matrix, 0), component(matrix, 1), component(matrix, 2)}; 77 return glm::vec3{component(matrix, 0), component(matrix, 1), component(matrix, 2)};
78 } 78 }
79 79
80 std::optional<glm::vec2> geom::lineLineIntersection(const Line<2>& line_1, const Line<2>& line_2) 80 std::optional<glm::vec2> lineLineIntersection(const Line<2>& line_1, const Line<2>& line_2)
81 { 81 {
82 const float denominator = (line_1.direction.x * line_2.direction.y) - (line_1.direction.y * line_2.direction.x); 82 const float denominator = (line_1.direction.x * line_2.direction.y) - (line_1.direction.y * line_2.direction.x);
83 constexpr float epsilon = 1e-6f; 83 constexpr float epsilon = 1e-6f;
84 if (std::abs(denominator) < epsilon) 84 if (std::abs(denominator) < epsilon)
85 { 85 {
101 const float y = glm::determinant(glm::mat2{{a, b}, {c_y, d_y}}); 101 const float y = glm::determinant(glm::mat2{{a, b}, {c_y, d_y}});
102 return glm::vec2{x / denominator, y / denominator}; 102 return glm::vec2{x / denominator, y / denominator};
103 } 103 }
104 } 104 }
105 105
106 std::optional<glm::vec2> geom::rayLineSegmentIntersection(const Ray<2>& ray, const LineSegment2D& line) 106 std::optional<glm::vec2> rayLineSegmentIntersection(const Ray<2>& ray, const LineSegment2D& line)
107 { 107 {
108 std::optional<glm::vec2> result = lineLineIntersection( 108 std::optional<glm::vec2> result = lineLineIntersection(
109 rayToLine(ray), 109 rayToLine(ray),
110 lineFromPoints(line.p1, line.p2)); 110 lineFromPoints(line.p1, line.p2));
111 if (result.has_value()) 111 if (result.has_value())
125 } 125 }
126 } 126 }
127 return result; 127 return result;
128 } 128 }
129 129
130 std::optional<geom::PointOnRectagle> geom::rayRectangleIntersection(const Ray<2>& ray, const QRectF& rectangle) 130 std::optional<PointOnRectagle> rayRectangleIntersection(const Ray<2>& ray, const QRectF& rectangle)
131 { 131 {
132 std::optional<glm::vec2> position; 132 std::optional<glm::vec2> position;
133 std::optional<PointOnRectagle> result; 133 std::optional<PointOnRectagle> result;
134 // Try top 134 // Try top
135 position = rayLineSegmentIntersection(ray, top(rectangle)); 135 position = rayLineSegmentIntersection(ray, top(rectangle));
165 } 165 }
166 } 166 }
167 return result; 167 return result;
168 } 168 }
169 169
170 geom::LineSegment2D geom::top(const QRectF& rectangle) 170 LineSegment2D top(const QRectF& rectangle)
171 { 171 {
172 return { 172 return {
173 glm::vec2{rectangle.left(), rectangle.top()}, 173 glm::vec2{rectangle.left(), rectangle.top()},
174 glm::vec2{rectangle.right(), rectangle.top()} 174 glm::vec2{rectangle.right(), rectangle.top()}
175 }; 175 };
176 } 176 }
177 177
178 geom::LineSegment2D geom::bottom(const QRectF& rectangle) 178 LineSegment2D bottom(const QRectF& rectangle)
179 { 179 {
180 return { 180 return {
181 glm::vec2{rectangle.left(), rectangle.bottom()}, 181 glm::vec2{rectangle.left(), rectangle.bottom()},
182 glm::vec2{rectangle.right(), rectangle.bottom()} 182 glm::vec2{rectangle.right(), rectangle.bottom()}
183 }; 183 };
184 } 184 }
185 185
186 geom::LineSegment2D geom::left(const QRectF& rectangle) 186 LineSegment2D left(const QRectF& rectangle)
187 { 187 {
188 return { 188 return {
189 glm::vec2{rectangle.left(), rectangle.top()}, 189 glm::vec2{rectangle.left(), rectangle.top()},
190 glm::vec2{rectangle.left(), rectangle.bottom()} 190 glm::vec2{rectangle.left(), rectangle.bottom()}
191 }; 191 };
192 } 192 }
193 193
194 geom::LineSegment2D geom::right(const QRectF& rectangle) 194 LineSegment2D right(const QRectF& rectangle)
195 { 195 {
196 return { 196 return {
197 glm::vec2{rectangle.right(), rectangle.top()}, 197 glm::vec2{rectangle.right(), rectangle.top()},
198 glm::vec2{rectangle.right(), rectangle.bottom()} 198 glm::vec2{rectangle.right(), rectangle.bottom()}
199 }; 199 };
200 } 200 }
201 201
202 bool geom::isConvex(const std::vector<glm::vec3>& polygon) 202 bool isConvex(const std::vector<glm::vec3>& polygon)
203 { 203 {
204 const int n = polygon.size(); 204 const int n = polygon.size();
205 auto polygonRing = iter::ring(polygon, n); 205 auto polygonRing = iter::ring(polygon, n);
206 std::vector<glm::vec3> crosses; 206 std::vector<glm::vec3> crosses;
207 crosses.resize(n); 207 crosses.resize(n);
221 /** 221 /**
222 * @brief Determines the winding of a 2d polygon 222 * @brief Determines the winding of a 2d polygon
223 * @param polygon 223 * @param polygon
224 * @return winding 224 * @return winding
225 */ 225 */
226 Winding geom::winding(const QPolygonF &polygon) 226 Winding winding(const QPolygonF &polygon)
227 { 227 {
228 // based on https://stackoverflow.com/a/1165943 228 // based on https://stackoverflow.com/a/1165943
229 double sum = 0.0; 229 double sum = 0.0;
230 for (int i = 0; i < polygon.size(); i += 1) 230 for (int i = 0; i < polygon.size(); i += 1)
231 { 231 {
240 * @brief computes the point on a Bezier curve 240 * @brief computes the point on a Bezier curve
241 * @param curve 241 * @param curve
242 * @param t scalar between 0 and 1, with t=0 being P0 and t=1 being P3 242 * @param t scalar between 0 and 1, with t=0 being P0 and t=1 being P3
243 * @return point on curve 243 * @return point on curve
244 */ 244 */
245 glm::vec3 geom::pointOnCurve(const BezierCurve &curve, float t) 245 glm::vec3 pointOnCurve(const BezierCurve &curve, float t)
246 { 246 {
247 // clamp t as rounding errors might make it slightly out of bounds 247 // clamp t as rounding errors might make it slightly out of bounds
248 t = std::clamp(t, 0.0f, 1.0f); 248 t = std::clamp(t, 0.0f, 1.0f);
249 const float t_2 = t * t; 249 const float t_2 = t * t;
250 const float t_3 = t * t * t; 250 const float t_3 = t * t * t;
260 * @brief computes the derivative of a point on a Bezier curve 260 * @brief computes the derivative of a point on a Bezier curve
261 * @param curve 261 * @param curve
262 * @param t scalar between 0 and 1, with t=0 being P0 and t=1 being P3 262 * @param t scalar between 0 and 1, with t=0 being P0 and t=1 being P3
263 * @return point on curve 263 * @return point on curve
264 */ 264 */
265 glm::vec3 geom::derivativeOnCurve(const BezierCurve &curve, float t) 265 glm::vec3 derivativeOnCurve(const BezierCurve &curve, float t)
266 { 266 {
267 // clamp t as rounding errors might make it slightly out of bounds 267 // clamp t as rounding errors might make it slightly out of bounds
268 t = std::clamp(t, 0.0f, 1.0f); 268 t = std::clamp(t, 0.0f, 1.0f);
269 const float t_2 = t * t; 269 const float t_2 = t * t;
270 const float coeffs[4] = { 270 const float coeffs[4] = {

mercurial