#ifndef GEOMETRY_H
#define GEOMETRY_H

#include <QtGui\qmatrix4x4.h>

/*!
\file
Contains general-purpose geometric helpers, like the \ref Cube structure and Line-Plane intersection algorithm.
*/

/*!
Describes a equilateral cube, centered on the origin.
Note that this is not a QObject. The constructor takes the side length of the cube
*/
class Cube final
{
public:
	/*!
	Defines the 8 corner points of the cube, in XYZ format.
	The vertices returned by this class are in exactly the order as specified in this array.
	*/
	enum Corner
	{
		MinMinMin = 0,
		MaxMinMin,
		MinMaxMin,
		MaxMaxMin,
		MinMinMax,
		MaxMinMax,
		MinMaxMax,
		MaxMaxMax,
		COUNT // = 8
	};

	/*!
	Creates a cube with the specified side length.
	The default side length is 1.0.
	The resulting vertices have coordinates equivalent to \f$ \pm \frac{sideLength}{2} \f$ on each axis.

	\param sideLength The side length of the cube.
	*/
	explicit Cube(float sideLength = 1.0f);
	~Cube();

	/*!
	Returns the 8 vertices of the cube. This array must not be modified.
	\returns an 8-element array that contains the vertices of this cube.
	*/
	const QVector3D * const getVertices() const;

	/*!
	6 * 2 * 3 = 36 indices for a triangle representation of the cube, vertices ordered CCW.
	*/
	static const ushort triangleIndices[36];
	/*!
	Number of triangles in \ref triangleIndices (=12)
	*/
	static const ushort triangleCount = 12;

	/*!
	6 * 4 = 24 indices for a quad representation of the cube (faces), vertices ordered CCW.
	*/
	static const ushort quadIndices[24];
	/*!
	Number of quads in \ref quadIndices (=6)
	*/
	static const ushort quadCount = 6;

	/*!
	12 * 2 = 24 indices for a line representation of the cube (edges)
	*/
	static const ushort lineIndices[24];
	/*!
	Number of lines in \ref lineIndices (=12)
	*/
	static const ushort lineCount=12;


	/*!
	Multiplies the vertices with the given matrix and returns the result.
	The returned values can be freely used.

	The vectors with indices 0-7 are the transformed vertices corresponding to the original vertices with indices 0-7.
	\param mat The matrix to multiply with
	\returns a \c QVector of size 8, can be used as required.
	*/
	QVector<QVector4D> transform(const QMatrix4x4& mat) const;

	/*!
	Multiplies the vertices with the given matrix and returns the result.
	The returned values can be freely used.

	The vectors with indices 0-7 are the transformed vertices corresponding to the original vertices with indices 0-7.
	The other parameters contain the minmal and maximal values on each axis.
	\param mat The matrix to multiply with
	\param minPos contains the minimal value of the transformed points in each axis
	\param maxPos contains the maximal value of the transformed points in each axis
	\returns a \c QVector of size 8, can be used as required.
	*/
	QVector<QVector4D> transform(const QMatrix4x4& mat,QVector4D& minPos,QVector4D& maxPos) const;

	/*!
	Same as \ref transform, but with the w components omitted.
	*/
	QVector<QVector3D> transform3D(const QMatrix4x4& mat,QVector3D& minPos,QVector3D& maxPos) const;

private:
	/*!
	The side length of the cube
	*/
	float m_sidelength;
	/*!
	The 8 vertices of the cube, in the order defined by \ref Corner
	*/
	QVector3D* m_vertices;
	//const unsigned short triIndices[],lineIndices[];
};


/*!
	Perform Line-Plane intersection.
	This is a specialized case of Ray-Plane intersection (without infinite length lines).
	The line is identified by its start point and the line vector. The plane is identified by any point lying on it, and its normal.

	The formula used can be found here: <a href="https://en.wikipedia.org/w/index.php?title=Line-plane_intersection&amp;oldid=607075438#Algebraic_form">Wikipedia</a>
	It has been adapted to only return true when the line crosses the plane, instead of the infinite length rays.

	\param lineStart The start point of the line
	\param lineVec The line vector, i.e. \f$ \mathrm{lineStart} + \mathrm{lineVec} = \mathrm{lineEnd} \$
	\param planePoint Any point lying on the plane
	\param planeNormal The normal of the plane.
	\param d If there is an intersection, it lies at \f$ \mathrm{lineA} + d * \mathrm{lineVec} \f$, so it always holds that \f$  d \in [0,1] \f$
	\return if true, there is an intersection of this ray with this plane. The point can be calculated by using \c d, as seen above
*/
bool LineIntersectPlane(const QVector3D& lineStart, const QVector3D& lineVec, const QVector3D& planePoint,const QVector3D& planeNormal, float& d);


#endif