/***************************************************************************
                           side.h
                           -------------------
    copyright            : (C) 2004 by Jos van den Oever
    email                : jos@vandenoever.info
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#ifndef SIDE_H
#define SIDE_H

#include "matrix3d.h"
#include "rotenums.h"
#include <qmatrix.h>
#include <qobject.h>

class QPainter;
class Q3Picture;

/**
 *  A side for a 3D object.
 *  Sides are planes in a 3D space. A Side has three (x, y, z) points that
 *  define it's position in space. The points are the following three points
 *  of a side:\verbatim
      p1 *----* p2
         |    |
      p3 *----* p4\endverbatim
 *  Point p4 is easily inferred from the three other points (p4 = p3+p2-p1).
 *  The points are stored in an array of 12 doubles 
*/
class Side : public QObject {
Q_OBJECT
public:
	/** Default constructor. Constructs an empty Side */
	Side();
	/** Supply three coordinates (x, y, z) that define the Side. */
	Side(const double [9]);
	/** Copy constructor, nothing special.*/
	Side(const Side &);
	/** Destructor, needs to be overridden because QObject is inherited.*/
	virtual ~Side();
	/** Copy operator, nothing special.*/
	const Side &operator=(const Side &);
	/** Compare two Sides in the same object. This function is needed for
	 * drawing the Sides. The 'smallest' Side is drawn first.
	 * Smaller means 'further back'.
	 * Comparing Sides from different Objects is meaningless.*/
	int operator<(const Side &) const;

	/** Set new points that define this Side. */
	void setPoints(const double [9]);
	/** Assign a picture to the side.*/
	void setPicture(const Q3Picture *);
	/** Change the rotation of the QPicture on the Side. */
	void setRotation(short);
	/** Change the symmetry of the Side. This value must correspond to the
	 * symmetry of the QPicture. */
	void setSymmetry(Symmetry);
	void paintSide(QPainter *p) const;
	void rotate(Rotation);
	void updateMatrix(const Matrix3D &m3d);
	bool processClick(const QPoint &p);
	Rotation getRotation() const;
	double getMaxDistance() const;
	/** Return a pointer to the Side's QPicture. */
	const Q3Picture *picture() const;
	/** Return a pointer to the Side's WorldMatrix */
	const QMatrix *matrix() const;
	Symmetry symmetry() const;
	short number;
private:
	/**
	 * A QPicture drawn on the Side can be rotated in steps of 90 degrees.
	 * This values determines what the orientation of the QPicture on the
	 * Side is.
         */
	Rotation rot;
	/** The QPicture that is drawn on this Side can have 3 different
	 * symmetries. When comparing appearances of Sides, this value is
	 * needed. */
	Symmetry sym;
	/** This QPicture is drawn on the Side of an Object. It is scaled to fit
	 * the side. */
	const Q3Picture *pict;
	double *const p1, *const p2, *const p3, *const p4;
	double ipoints[12], opoints[12];
	QMatrix wm;

	double getZcoord(double, double) const;
	bool intersect(const Side &s, double &L1x, double &L1y, double &L2x,
	 double &L2y) const;
signals:
	/**
	 * Signal that the side was clicked on at position @p p.
	 */
	void clickedAt(QPoint p);
	/**
	 * Signal that the side was clicked on.
	 */
	void clicked();
};

#endif
