Sat, 08 Apr 2023 22:09:29 +0300
Add settings import and export
#pragma once #include <QPolygonF> #include <glm/glm.hpp> #include <optional> enum Winding { NoWinding, Anticlockwise, Clockwise, }; //! \brief XOR operator for winding constexpr Winding operator^(Winding one, Winding other) { if (one == NoWinding or other == NoWinding) { return NoWinding; } else { const int xored = static_cast<int>(one) ^ static_cast<int>(other); return static_cast<Winding>(xored); } } constexpr Winding& operator^=(Winding& one, Winding other) { one = one ^ other; return one; } struct Plane { glm::vec3 normal; glm::vec3 anchor; }; template<int N, typename T = float, glm::qualifier Q = glm::defaultp> struct Line { glm::vec<N, T, Q> direction; glm::vec<N, T, Q> anchor; }; template<int N, typename T = float, glm::qualifier Q = glm::defaultp> struct Ray { glm::vec<N, T, Q> direction; glm::vec<N, T, Q> anchor; }; inline const glm::vec3 origin = {0, 0, 0}; inline const Plane XY = {{0, 0, 1}, origin}; inline const Plane XZ = {{0, 1, 0}, origin}; inline const Plane YZ = {{1, 0, 0}, origin}; struct LineSegment { glm::vec3 p1, p2; }; struct Triangle { glm::vec3 p1, p2, p3; }; struct Quadrilateral { glm::vec3 p1, p2, p3, p4; }; struct ConditionalEdge { glm::vec3 p1, p2; glm::vec3 c1, c2; }; struct LineSegment2D { glm::vec2 p1, p2; }; // get polygon type from amount of points template<int N> struct PolygonType {}; template<> struct PolygonType<2> { using type = LineSegment; }; template<> struct PolygonType<3> { using type = Triangle; }; template<> struct PolygonType<4> { using type = Quadrilateral; }; template<int N> using Polygon = typename PolygonType<N>::type; /** * @brief Computes a line from two points * @param point_1 * @param point_2 * @return line */ template<int N, typename T, glm::qualifier Q> Line<N, T, Q> lineFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) { return {point_2 - point_1, point_1}; } template<int N, typename T, glm::qualifier Q> Ray<N, T, Q> rayFromPoints(const glm::vec<N, T, Q>& point_1, const glm::vec<N, T, Q>& point_2) { return {point_2 - point_1, point_1}; } template<int N, typename T, glm::qualifier Q> Line<N, T, Q> rayToLine(const Ray<N, T, Q>& ray) { return {ray.direction, ray.anchor}; } enum class RectangleSide { Top, Left, Bottom, Right }; struct PointOnRectagle { glm::vec2 position; RectangleSide side; }; std::optional<glm::vec2> lineLineIntersection(const Line<2>& line_1, const Line<2>& line_2); std::optional<glm::vec2> rayLineSegmentIntersection(const Ray<2>& ray, const LineSegment2D& line); std::optional<PointOnRectagle> rayRectangleIntersection(const Ray<2>& ray, const QRectF& rectangle); Plane planeFromTriangle(const Triangle& triangle); glm::vec3 normalVector(const Triangle& triangle); std::optional<glm::vec3> linePlaneIntersection( const Line<3>& line, const Plane& plane, const float epsilon = 1e-6f); glm::vec3 scalingVector(const glm::mat4 matrix); LineSegment2D top(const QRectF& rectangle); LineSegment2D bottom(const QRectF& rectangle); LineSegment2D left(const QRectF& rectangle); LineSegment2D right(const QRectF& rectangle); bool isConvex(const Quadrilateral& quad); bool isConvex(const std::vector<glm::vec3>& polygon); Winding winding(const QPolygonF& polygon); struct ScalingExtract { glm::vec3 scaling; glm::mat4 unscaled; }; ScalingExtract extractScaling(const glm::mat4& matrix); struct NPolygon { std::vector<glm::vec3> points; }; inline constexpr bool isclose(const glm::vec3& a, const glm::vec3& b) { return qFuzzyCompare(a.x, b.x) and qFuzzyCompare(a.y, b.y) and qFuzzyCompare(a.z, b.z); } struct CircleF { QPointF center; qreal radius; }; /** * @brief Inscribes a circle * @param circle * @return a QRectF that inscribes the specified circle */ inline constexpr QRectF inscribe(const CircleF& circle) { return { circle.center.x() - circle.radius, circle.center.y() - circle.radius, circle.radius * 2, circle.radius * 2 }; } struct BezierCurve { glm::vec3 points[4]; const glm::vec3& operator[](int x) const { Q_ASSERT(x >= 0 and x < 4); return this->points[x]; } glm::vec3& operator[](int x) { Q_ASSERT(x >= 0 and x < 4); return this->points[x]; } }; glm::vec3 pointOnCurve(const BezierCurve& curve, float t); glm::vec3 derivativeOnCurve(const BezierCurve& curve, float t); template<typename Iter> std::optional<glm::mat3> calculateNormal(Iter&& begin, Iter&& end) { const long int n = end - begin; std::optional<glm::mat3> result; for (long int i = 0; i < n; ++i) { const glm::vec3& v1 = *(begin + (i + n - 1) % n); const glm::vec3& v2 = *(begin + i); const glm::vec3& v3 = *(begin + (i + 1) % n); const glm::vec3 xvec = v1 - v2; const glm::vec3 yvec = v3 - v2; constexpr float threshold = 1e-6f; if (glm::length(xvec) > threshold and glm::length(yvec) > threshold) { const glm::vec3 zvec = glm::cross(glm::normalize(xvec), glm::normalize(yvec)); if (glm::length(zvec) > threshold) { result = {xvec, yvec, zvec}; break; } } } return result; } constexpr QPointF vecToQPoint(const glm::vec2& a) { return {a.x, a.y}; }