src/geometry.h

Wed, 09 Mar 2022 13:14:40 +0200

author
Teemu Piippo <teemu@hecknology.net>
date
Wed, 09 Mar 2022 13:14:40 +0200
changeset 174
3016b494685c
parent 168
24590af32ad6
child 187
30204975694a
permissions
-rw-r--r--

show unnamed tabs as "<unnamed>" in the tab list

#pragma once
#include <QPolygonF>
#include "basics.h"

namespace geom
{
	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;
	};

	template<int N>
	struct Polygon
	{
		std::array<glm::vec3, N> points;
	};

	template<int N>
	struct Polygon2D
	{
		glm::vec2 points[N];
	};

	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};
	using Triangle = Polygon<3>;
	using LineSegment2D = Polygon2D<2>;

	/**
	 * @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 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
		};
	}
}

mercurial