// ULinearAlgebra.h: interface for the ULinearAlgebra class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ULINEARALGEBRA_H__DC9EC61C_2E1E_4620_8693_9C4D44108FE2__INCLUDED_)
#define AFX_ULINEARALGEBRA_H__DC9EC61C_2E1E_4620_8693_9C4D44108FE2__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "math.h"
#include "D3D8.h"
#include "D3DUtil.h"
#include "DXUtil.h"
#include "AIGraphH.h"

#define PI (float)3.1415926535

#define PLUSMINUS .001 // this is used when comparing two floats probably neccessary
#define SMALLPLUSMINUS .001

//#define USEDOUBLE // tell the compiler to use double instead of float for the line stuff
#define USEFLOAT

class FPoint
{
public:
    #ifdef USEFLOAT
        float x;
        float y;
    #else
        double x;
        double y;
    #endif   

	FPoint();
	FPoint(float X, float Y);
	FPoint(GPOINT RHS);
	FPoint(CPoint RHS);
	
	
    /*FPoint&*/ operator= (CPoint RHS);
				operator= (GPOINT RHS);	
};

class CCPoint: public CPoint
{
public:
    CCPoint(FPoint RHS);
   operator= (FPoint RHS);
};

struct VERTEX
{
	D3DXVECTOR3 position; // Object space position for the vertex.
	//float w;
	DWORD color;		  // The vertex color.
	FLOAT tu,tv;		  // The texture co-ordinates
};


class FRect
{
public:
    #ifdef USEFLOAT
        float top;
        float bottom;
        float left;
        float right;
    #else
        double top;
        double bottom;
        double left;
        double right; 
    #endif
    inline float FRect::Height() const
	{ return bottom - top; }
     inline float FRect::Width() const
	{ return right - left; }
public:
     operator= (CRect RHS);
}; 

// quick conversion for FRect to CRect
class CCRect: public CRect
{
public:
   CCRect(FRect RHS);
   operator= (FRect RHS);
};

class ULinearAlgebra  
{
public:
    struct Matrix2X2
    { 
        #ifdef USEFLOAT
            float A;
            float B;
            float C;
        #else
            double A;
            double B;
            double C;
        #endif
    };

    struct Circle
    {
        CPoint Center;
        float Radius;
    };

    struct POINTLIST;

    typedef POINTLIST *PointListPtr, PointList;

    struct POINTLIST
    {
        CPoint thePoint;
        PointListPtr Next;
    };

    struct PREVLINE
    {
        int x; // + or -,1
        int y; // + or -,1
        int Quad;// 1 to 4
        CPoint PrevStart;
        CPoint PrevEnd;
    public:
    };



public:   
	float Sgn(float Input);
	void FormRect(FRect &Rect, FPoint Start, FPoint End);


    // clips a line,  Usefull for rendering
    void ClipLine(CRect Bounds, long &XStart, long &YStart, long &XEnd, long &YEnd);
    void ClipLine(CRect Bounds, CPoint &Start, CPoint &End); // wrapper


	Matrix2X2 PointstoLine(FPoint Point, float Angle);
    // forms a rectange out of two points
    CRect FormRect(CPoint ObjectStart, CPoint ObjectEnd, CPoint DeltaStart, CPoint DeltaEnd);
	FRect FormRect(FPoint Start, FPoint End);
    FRect FormRectF(FPoint ObjectStart, FPoint ObjectEnd, FPoint DeltaStart, FPoint DeltaEnd);
    CRect FormRect(CPoint Start, CPoint End);


	BOOL isPointonLine(FPoint Point, Matrix2X2 Line);

    // used in collision detection
	float GetDistanceTwoPLLLines(FPoint Start1, FPoint End1, FPoint Start2, FPoint End2);
    float ULinearAlgebra::GetDistanceTwoPLLLines(FPoint Start1, FPoint End1, FPoint Delta);
	BOOL IsBetweenLines(Matrix2X2 One, Matrix2X2 Two, FPoint Point);

    // rotates a point about center
	CPoint RotatePoint(CPoint OldPoint, CPoint Center, double Angle);
    FPoint RotatePoint(FPoint OldPoint, FPoint Center, double Angle);
    // checks if a line passes through a rect
	BOOL CheckifLineGoesinRect(CPoint LineStart, CPoint LineEnd, CRect Rect);

    // get equation of a circle that the radius has been increased
    Circle GetCircle(CPoint Start, CPoint Middle, CPoint End, int RInc, CPoint &NewMiddle);
    // get equation of a circle
	Circle GetCircle(CPoint Start, CPoint Middle, CPoint End);

    // transponse a line, keeping with prevuis direction
    void TransposeLine(CPoint OldStart, CPoint OldEnd, CPoint OldMiddle, CPoint &NewStart, CPoint &NewEnd, CPoint &NewMiddle, ULinearAlgebra::PREVLINE &PrevLine, int Distance);
    // transponse a line with a center point.
	void TransposeLine(CPoint OldStart, CPoint OldEnd, CPoint &NewStart, CPoint &NewEnd, CPoint CenterPoint, BOOL Inside, int distance);

    // return the centroid
    CPoint GetInsidePoint(CPoint Point1, CPoint Point2, CPoint Point3);

    // basic point functions
	double GetAngle(CPoint thePoint, CPoint Center);	
    double GetAngle(FPoint thePoint, FPoint Center);
	CPoint GetMidPoint(CPoint Start, CPoint End);
    FPoint GetMidPoint(FPoint Start, FPoint End);
    // basic distance functions
    float GetDistance(CPoint one, CPoint two);
    float GetDistance(FPoint one, FPoint two);
    float GetDistance(Matrix2X2 Line, CPoint Point);
    float GetDistance(Matrix2X2 Line, FPoint Point);
    // find the shortest distance while taking in considerating the line end points
	float GetDistance(CPoint LineStart, CPoint LineEnd, FPoint thePoint);
	
    // used by the quadtree to draw an arc.
	PointListPtr GetPointsofCircle(CPoint Start, CPoint Middle, CPoint End, int nodes);	
	
    // intersection functions
    FPoint FindIntersectionF(Matrix2X2 Line1, Matrix2X2 Line2);
	CPoint FindIntersection(Matrix2X2 Line1, Matrix2X2 Line2);
  	CPoint FindIntersection(Matrix2X2 Line, Circle circle, CPoint Closest);
    CPoint FindIntersection(CPoint start, CPoint end, CRect Quad);	
	
	// generates line equations
    Matrix2X2 PointstoPerpMidLine(CPoint Start, CPoint End);
    Matrix2X2 GetMatrix(CRect CalcRect, int whichone);
    Matrix2X2 PointstoLine(int x1, int y1, int x2, int y2);
	Matrix2X2 PointstoLine(CPoint start, CPoint end);
    // float versions
    Matrix2X2 PointstoLine(FPoint Start, Matrix2X2 Slope);	
	Matrix2X2 PointstoPerpLine(FPoint Start, Matrix2X2 Slope);
	Matrix2X2 PointstoPerpMidLine(FPoint Start, FPoint End);
	Matrix2X2 PointstoLine(FPoint start, FPoint end);

    // Simple functions
    float Mod360(float Angle);
    float Abs(float num);
    double Abs(double num);
    BOOL InRect(FPoint Point, FRect Rect);
    BOOL InRect(CPoint Point, CRect Rect);
    BOOL InRect(FPoint Point, CRect Rect);
    float FindSlope(int x1, int y1, int x2, int y2);    
    int Round(float toRound);
    long Round(double toRound);
    float sqr(long input);
	float sqr(float input);
    double sqr(double input);
    // allows a plus or minus in a = comparison
    BOOL IsEqual(float One, float Two, float plusminus);

	ULinearAlgebra();
	virtual ~ULinearAlgebra();

};

#endif // !defined(AFX_ULINEARALGEBRA_H__DC9EC61C_2E1E_4620_8693_9C4D44108FE2__INCLUDED_)
