

//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
//_/_/
//_/_/  This file is part of CMSDK version 2.0.0.170915_Beta4 (15 September 2017)
//_/_/  
//_/_/  developed by
//_/_/  
//_/_/  Communicative Machines Ltd. 
//_/_/    http://cmlabs.com/
//_/_/  Copyright (c) 2017
//_/_/  
//_/_/  in collaboration with 
//_/_/  
//_/_/  Icelandic Institute for Intelligent Machines ses
//_/_/    Menntavegur 1
//_/_/    101 Reykjavik
//_/_/    ICELAND
//_/_/    http://www.iiim.is/
//_/_/
//_/_/  and is released under the following
//_/_/  
//_/_/  EXTENDED BSD License
//_/_/
//_/_/  Redistribution and use in source and binary forms, with or without
//_/_/  modification, is permitted provided that the following conditions 
//_/_/  are met:
//_/_/
//_/_/  - Redistributions of source code must retain the above copyright 
//_/_/    and collaboration notice, this list of conditions and the following 
//_/_/    disclaimer.
//_/_/
//_/_/  - Redistributions in binary form must reproduce the above copyright 
//_/_/    notice, this list of conditions and the following disclaimer in the 
//_/_/    documentation and/or other materials provided with the distribution.
//_/_/
//_/_/  - Neither the name of its copyright holders nor the names of its 
//_/_/    contributors may be used to endorse or promote products derived from 
//_/_/    this software without specific prior written permission.
//_/_/
//_/_/  - CADIA Clause: The license granted in and to the software under this 
//_/_/    agreement is a limited-use license. The software may not be used in 
//_/_/    furtherance of: (i) intentionally causing bodily injury or severe 
//_/_/    emotional harm to any person; (ii) invading the personal privacy or 
//_/_/    violating the human rights of any person; or (iii) committing or 
//_/_/    preparing for any act of war. 
//_/_/
//_/_/  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
//_/_/  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
//_/_/  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
//_/_/  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
//_/_/  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
//_/_/  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
//_/_/  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
//_/_/  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
//_/_/  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
//_/_/  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
//_/_/  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//_/_/
//_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
#if !defined(_MATHCLASSES_H)
#define _MATHCLASSES_H

#define _USE_MATH_DEFINES
// #define __USE_GNU
#include <math.h>
#include <map>
#include <array>

#include "Utils.h"

namespace cmlabs {


const std::map<std::string, std::array<uint8, 3> > ColorMap = {
	{ "maroon",{ { 128,0,0 } } },
	{ "dark red",{ { 139,0,0 } } },
	{ "darkred",{ { 139,0,0 } } },
	{ "brown",{ { 165,42,42 } } },
	{ "firebrick",{ { 178,34,34 } } },
	{ "crimson",{ { 220,20,60 } } },
	{ "red",{ { 255,0,0 } } },
	{ "tomato",{ { 255,99,71 } } },
	{ "coral",{ { 255,127,80 } } },
	{ "indian red",{ { 205,92,92 } } },
	{ "indianred",{ { 205,92,92 } } },
	{ "light coral",{ { 240,128,128 } } },
	{ "lightcoral",{ { 240,128,128 } } },
	{ "dark salmon",{ { 233,150,122 } } },
	{ "darksalmon",{ { 233,150,122 } } },
	{ "salmon",{ { 250,128,114 } } },
	{ "light salmon",{ { 255,160,122 } } },
	{ "lightsalmon",{ { 255,160,122 } } },
	{ "orange red",{ { 255,69,0 } } },
	{ "orangered",{ { 255,69,0 } } },
	{ "dark orange",{ { 255,140,0 } } },
	{ "darkorange",{ { 255,140,0 } } },
	{ "orange",{ { 255,165,0 } } },
	{ "gold",{ { 255,215,0 } } },
	{ "dark golden rod",{ { 184,134,11 } } },
	{ "darkgoldenrod",{ { 184,134,11 } } },
	{ "golden rod",{ { 218,165,32 } } },
	{ "goldenrod",{ { 218,165,32 } } },
	{ "pale golden rod",{ { 238,232,170 } } },
	{ "palegoldenrod",{ { 238,232,170 } } },
	{ "dark khaki",{ { 189,183,107 } } },
	{ "darkkhaki",{ { 189,183,107 } } },
	{ "khaki",{ { 240,230,140 } } },
	{ "olive",{ { 128,128,0 } } },
	{ "yellow",{ { 255,255,0 } } },
	{ "yellow green",{ { 154,205,50 } } },
	{ "yellowgreen",{ { 154,205,50 } } },
	{ "dark olive green",{ { 85,107,47 } } },
	{ "darkolivegreen",{ { 85,107,47 } } },
	{ "olive drab",{ { 107,142,35 } } },
	{ "olivedrab",{ { 107,142,35 } } },
	{ "lawn green",{ { 124,252,0 } } },
	{ "lawngreen",{ { 124,252,0 } } },
	{ "chart reuse",{ { 127,255,0 } } },
	{ "chartreuse",{ { 127,255,0 } } },
	{ "green yellow",{ { 173,255,47 } } },
	{ "greenyellow",{ { 173,255,47 } } },
	{ "dark green",{ { 0,100,0 } } },
	{ "darkgreen",{ { 0,100,0 } } },
	{ "green",{ { 0,128,0 } } },
	{ "forest green",{ { 34,139,34 } } },
	{ "forestgreen",{ { 34,139,34 } } },
	{ "lime",{ { 0,255,0 } } },
	{ "lime green",{ { 50,205,50 } } },
	{ "limegreen",{ { 50,205,50 } } },
	{ "light green",{ { 144,238,144 } } },
	{ "lightgreen",{ { 144,238,144 } } },
	{ "pale green",{ { 152,251,152 } } },
	{ "palegreen",{ { 152,251,152 } } },
	{ "dark sea green",{ { 143,188,143 } } },
	{ "darkseagreen",{ { 143,188,143 } } },
	{ "medium spring green",{ { 0,250,154 } } },
	{ "mediumspringgreen",{ { 0,250,154 } } },
	{ "spring green",{ { 0,255,127 } } },
	{ "springgreen",{ { 0,255,127 } } },
	{ "sea green",{ { 46,139,87 } } },
	{ "seagreen",{ { 46,139,87 } } },
	{ "medium aqua marine",{ { 102,205,170 } } },
	{ "mediumaquamarine",{ { 102,205,170 } } },
	{ "medium sea green",{ { 60,179,113 } } },
	{ "mediumseagreen",{ { 60,179,113 } } },
	{ "light sea green",{ { 32,178,170 } } },
	{ "lightseagreen",{ { 32,178,170 } } },
	{ "dark slate gray",{ { 47,79,79 } } },
	{ "darkslategray",{ { 47,79,79 } } },
	{ "teal",{ { 0,128,128 } } },
	{ "dark cyan",{ { 0,139,139 } } },
	{ "darkcyan",{ { 0,139,139 } } },
	{ "aqua",{ { 0,255,255 } } },
	{ "cyan",{ { 0,255,255 } } },
	{ "light cyan",{ { 224,255,255 } } },
	{ "lightcyan",{ { 224,255,255 } } },
	{ "dark turquoise",{ { 0,206,209 } } },
	{ "darkturquoise",{ { 0,206,209 } } },
	{ "turquoise",{ { 64,224,208 } } },
	{ "medium turquoise",{ { 72,209,204 } } },
	{ "mediumturquoise",{ { 72,209,204 } } },
	{ "pale turquoise",{ { 175,238,238 } } },
	{ "paleturquoise",{ { 175,238,238 } } },
	{ "aqua marine",{ { 127,255,212 } } },
	{ "aquamarine",{ { 127,255,212 } } },
	{ "powder blue",{ { 176,224,230 } } },
	{ "powderblue",{ { 176,224,230 } } },
	{ "cadet blue",{ { 95,158,160 } } },
	{ "cadetblue",{ { 95,158,160 } } },
	{ "steel blue",{ { 70,130,180 } } },
	{ "steelblue",{ { 70,130,180 } } },
	{ "corn flower blue",{ { 100,149,237 } } },
	{ "cornflowerblue",{ { 100,149,237 } } },
	{ "deep sky blue",{ { 0,191,255 } } },
	{ "deepskyblue",{ { 0,191,255 } } },
	{ "dodger blue",{ { 30,144,255 } } },
	{ "dodgerblue",{ { 30,144,255 } } },
	{ "light blue",{ { 173,216,230 } } },
	{ "lightblue",{ { 173,216,230 } } },
	{ "sky blue",{ { 135,206,235 } } },
	{ "skyblue",{ { 135,206,235 } } },
	{ "light sky blue",{ { 135,206,250 } } },
	{ "lightskyblue",{ { 135,206,250 } } },
	{ "midnight blue",{ { 25,25,112 } } },
	{ "midnightblue",{ { 25,25,112 } } },
	{ "navy",{ { 0,0,128 } } },
	{ "dark blue",{ { 0,0,139 } } },
	{ "darkblue",{ { 0,0,139 } } },
	{ "medium blue",{ { 0,0,205 } } },
	{ "mediumblue",{ { 0,0,205 } } },
	{ "blue",{ { 0,0,255 } } },
	{ "royal blue",{ { 65,105,225 } } },
	{ "royalblue",{ { 65,105,225 } } },
	{ "blue violet",{ { 138,43,226 } } },
	{ "blueviolet",{ { 138,43,226 } } },
	{ "indigo",{ { 75,0,130 } } },
	{ "dark slate blue",{ { 72,61,139 } } },
	{ "darkslateblue",{ { 72,61,139 } } },
	{ "slate blue",{ { 106,90,205 } } },
	{ "slateblue",{ { 106,90,205 } } },
	{ "medium slate blue",{ { 123,104,238 } } },
	{ "mediumslateblue",{ { 123,104,238 } } },
	{ "medium purple",{ { 147,112,219 } } },
	{ "mediumpurple",{ { 147,112,219 } } },
	{ "dark magenta",{ { 139,0,139 } } },
	{ "darkmagenta",{ { 139,0,139 } } },
	{ "dark violet",{ { 148,0,211 } } },
	{ "darkviolet",{ { 148,0,211 } } },
	{ "dark orchid",{ { 153,50,204 } } },
	{ "darkorchid",{ { 153,50,204 } } },
	{ "medium orchid",{ { 186,85,211 } } },
	{ "mediumorchid",{ { 186,85,211 } } },
	{ "purple",{ { 128,0,128 } } },
	{ "thistle",{ { 216,191,216 } } },
	{ "plum",{ { 221,160,221 } } },
	{ "violet",{ { 238,130,238 } } },
	{ "magenta",{ { 255,0,255 } } },
	{ "fuchsia",{ { 255,0,255 } } },
	{ "orchid",{ { 218,112,214 } } },
	{ "medium violet red",{ { 199,21,133 } } },
	{ "mediumvioletred",{ { 199,21,133 } } },
	{ "pale violet red",{ { 219,112,147 } } },
	{ "palevioletred",{ { 219,112,147 } } },
	{ "deep pink",{ { 255,20,147 } } },
	{ "deeppink",{ { 255,20,147 } } },
	{ "hot pink",{ { 255,105,180 } } },
	{ "hotpink",{ { 255,105,180 } } },
	{ "light pink",{ { 255,182,193 } } },
	{ "lightpink",{ { 255,182,193 } } },
	{ "pink",{ { 255,192,203 } } },
	{ "antique white",{ { 250,235,215 } } },
	{ "antiquewhite",{ { 250,235,215 } } },
	{ "beige",{ { 245,245,220 } } },
	{ "bisque",{ { 255,228,196 } } },
	{ "blanched almond",{ { 255,235,205 } } },
	{ "blanchedalmond",{ { 255,235,205 } } },
	{ "wheat",{ { 245,222,179 } } },
	{ "corn silk",{ { 255,248,220 } } },
	{ "cornsilk",{ { 255,248,220 } } },
	{ "lemon chiffon",{ { 255,250,205 } } },
	{ "lemonchiffon",{ { 255,250,205 } } },
	{ "light golden rod yellow",{ { 250,250,210 } } },
	{ "lightgoldenrodyellow",{ { 250,250,210 } } },
	{ "light yellow",{ { 255,255,224 } } },
	{ "lightyellow",{ { 255,255,224 } } },
	{ "saddle brown",{ { 139,69,19 } } },
	{ "saddlebrown",{ { 139,69,19 } } },
	{ "sienna",{ { 160,82,45 } } },
	{ "chocolate",{ { 210,105,30 } } },
	{ "peru",{ { 205,133,63 } } },
	{ "sandy brown",{ { 244,164,96 } } },
	{ "sandybrown",{ { 244,164,96 } } },
	{ "burly wood",{ { 222,184,135 } } },
	{ "burlywood",{ { 222,184,135 } } },
	{ "tan",{ { 210,180,140 } } },
	{ "rosy brown",{ { 188,143,143 } } },
	{ "rosybrown",{ { 188,143,143 } } },
	{ "moccasin",{ { 255,228,181 } } },
	{ "navajo white",{ { 255,222,173 } } },
	{ "navajowhite",{ { 255,222,173 } } },
	{ "peach puff",{ { 255,218,185 } } },
	{ "peachpuff",{ { 255,218,185 } } },
	{ "misty rose",{ { 255,228,225 } } },
	{ "mistyrose",{ { 255,228,225 } } },
	{ "lavender blush",{ { 255,240,245 } } },
	{ "lavenderblush",{ { 255,240,245 } } },
	{ "linen",{ { 250,240,230 } } },
	{ "old lace",{ { 253,245,230 } } },
	{ "oldlace",{ { 253,245,230 } } },
	{ "papaya whip",{ { 255,239,213 } } },
	{ "papayawhip",{ { 255,239,213 } } },
	{ "sea shell",{ { 255,245,238 } } },
	{ "seashell",{ { 255,245,238 } } },
	{ "mint cream",{ { 245,255,250 } } },
	{ "mintcream",{ { 245,255,250 } } },
	{ "slate gray",{ { 112,128,144 } } },
	{ "slategray",{ { 112,128,144 } } },
	{ "light slate gray",{ { 119,136,153 } } },
	{ "lightslategray",{ { 119,136,153 } } },
	{ "light steel blue",{ { 176,196,222 } } },
	{ "lightsteelblue",{ { 176,196,222 } } },
	{ "lavender",{ { 230,230,250 } } },
	{ "floral white",{ { 255,250,240 } } },
	{ "floralwhite",{ { 255,250,240 } } },
	{ "alice blue",{ { 240,248,255 } } },
	{ "aliceblue",{ { 240,248,255 } } },
	{ "ghost white",{ { 248,248,255 } } },
	{ "ghostwhite",{ { 248,248,255 } } },
	{ "honeydew",{ { 240,255,240 } } },
	{ "ivory",{ { 255,255,240 } } },
	{ "azure",{ { 240,255,255 } } },
	{ "snow",{ { 255,250,250 } } },
	{ "black",{ { 0,0,0 } } },
	{ "dim gray",{ { 105,105,105 } } },
	{ "dimgray",{ { 105,105,105 } } },
	{ "dim grey",{ { 105,105,105 } } },
	{ "dimgrey",{ { 105,105,105 } } },
	{ "gray",{ { 128,128,128 } } },
	{ "grey",{ { 128,128,128 } } },
	{ "dark grey",{ { 169,169,169 } } },
	{ "darkgrey",{ { 169,169,169 } } },
	{ "dark gray",{ { 169,169,169 } } },
	{ "darkgray",{ { 169,169,169 } } },
	{ "silver",{ { 192,192,192 } } },
	{ "light gray",{ { 211,211,211 } } },
	{ "lightgray",{ { 211,211,211 } } },
	{ "light grey",{ { 211,211,211 } } },
	{ "lightgrey",{ { 211,211,211 } } },
	{ "gainsboro",{ { 220,220,220 } } },
	{ "white smoke",{ { 245,245,245 } } },
	{ "whitesmoke",{ { 245,245,245 } } },
	{ "white",{ { 255,255,255 } } }
};

class Color
{
public:
	Color();
	Color(uint8 red, uint8 green, uint8 blue);
	Color(const char* name);
	Color(const Color &color);
	virtual ~Color();

	Color mixOn(Color& color, double weight);
	Color getReverseColor();
	uint8 getGreyValue();

	uint8 r, g, b;
	uint32 size;

	double distance(Color &otherColor);
	//bool setNoColor();
	//bool isValid();
	//bool isNoColor();

	static std::vector<Color> createColorsMaxDifference(uint32 count, bool mix = false);
	std::string toRGBString() {
		return utils::StringFormat("%u,%u,%u", r, g, b);
	}

private:
	bool init(uint8 red, uint8 green, uint8 blue);
	bool init(const char* colorName);
};


/////////////////////////////////////////////////////////////////////
// Size Class
/////////////////////////////////////////////////////////////////////

class Size
{
public:
	Size();
	Size(double width, double height, double depth = 0);
	virtual ~Size();

	double w;
	double h;
	double d;

	bool equals(const Size& size) const;
	bool operator==(const Size &p) const;

	double getHeight() const;
	double getWidth() const;
	double getDepth() const;

	bool setHeight(double height);
	bool setWidth(double width);
	bool setDepth(double depth);

	bool isNonZero() const;
	double getArea() const;
	double getDiagonalLenth() const;

	std::string print() ;
};


/////////////////////////////////////////////////////////////////////
// Point Class
/////////////////////////////////////////////////////////////////////

class PointFloat;

class Point
{
public:
	Point();
	Point(int px, int py, int pz=0, Size psize=Size());
	virtual ~Point();

	operator PointFloat() const;

	int x;
	int y;
	int z;
	Size size;

	int operator[](int n) const;
	bool operator==(const Point &p) const;
	bool operator==(const PointFloat &p) const;
	Point operator-(const Point &p) const;
	PointFloat operator-(const PointFloat &p) const;
	Point operator+(const Point &p) const;
	PointFloat operator+(const PointFloat &p) const;
	Point operator*(const Point &p) const;
	PointFloat operator*(const PointFloat &p) const;
	Point operator-(double a) const;
	Point operator+(double a) const;
	Point operator*(double a) const;

	int getX() const;
	int getY() const;
	int getZ() const;
	Size getSize() const;

	bool set(int x, int y, int z=0);
	bool setX(int n);
	bool setY(int n);
	bool setZ(int n);
	bool setSize(Size s);

	double getDistanceTo(Point &p) const;
	double getDistanceTo(PointFloat &p) const;

	std::string print() ;
};


/////////////////////////////////////////////////////////////////////
// PointFloat Class
/////////////////////////////////////////////////////////////////////

class PointFloat
{
public:
	PointFloat();
	PointFloat(double px, double py, double pz=0, Size psize=Size());
	virtual ~PointFloat();

	operator Point() const;

	double x;
	double y;
	double z;
	Size size;

	double operator[](int n) const;
	bool operator==(const Point &p) const;
	bool operator==(const PointFloat &p) const;
	PointFloat operator-(const Point &p) const;
	PointFloat operator-(const PointFloat &p) const;
	PointFloat operator+(const Point &p) const;
	PointFloat operator+(const PointFloat &p) const;
	PointFloat operator*(const Point &p) const;
	PointFloat operator*(const PointFloat &p) const;
	PointFloat operator-(double a) const;
	PointFloat operator+(double a) const;
	PointFloat operator*(double a) const;

	double getX() const;
	double getY() const;
	double getZ() const;
	Size getSize() const;

	bool set(double x, double y, double z=0);
	bool setX(double v);
	bool setY(double v);
	bool setZ(double v);
	bool setSize(Size s);

	double getDistanceTo(const Point &p) const;
	double getDistanceTo(const PointFloat &p) const;

	std::string print();
};


/////////////////////////////////////////////////////////////////////
// Line Class
/////////////////////////////////////////////////////////////////////

class Line
{
public:
	Line();
	Line(PointFloat startpoint, PointFloat endpoint, double width = 0);
	virtual ~Line();

	PointFloat startPoint;
	PointFloat endPoint;
	double lineWidth;

	PointFloat getStartPoint() const;
	PointFloat getEndPoint() const;
	double getLineWidth() const;

	bool setStartPoint(PointFloat point);
	bool setEndPoint(PointFloat point);
	bool setLineWidth(double width);

	std::string print();
};


/////////////////////////////////////////////////////////////////////
// PolyLine Class
/////////////////////////////////////////////////////////////////////

class PolyLine
{
public:
	PolyLine();
	virtual ~PolyLine();

	std::vector<Line> lines;

	uint32 getLineCount() const;
	Line getLine(uint32 pos) const;
	bool addLine(Line line);
	bool replaceLine(uint32 pos, Line newline);
	bool removeLine(uint32 pos);

	std::string print();
};


/////////////////////////////////////////////////////////////////////
// Box Class
/////////////////////////////////////////////////////////////////////

class Box
{
public:
	Box();
	Box(PointFloat upperleft, Size boxsize, double linewidth = 0);
	Box(PointFloat upperleft, PointFloat lowerright, double linewidth = 0);
	Box(double x, double y, double w, double h, double linewidth = 0);
	virtual ~Box();

	PointFloat upperLeft;
	Size size;
	double lineWidth;
	std::string name;
	std::string comment;
	double orientation;

	double getUpperY() const;
	double getLowerY() const;
	double getLeftX() const;
	double getRightX() const;
	double getArea() const;

	double getCMX() const;
	double getCMY() const;
	PointFloat getCM() const;

	PointFloat getUpperLeft() const;
	PointFloat getUpperRight() const;
	PointFloat getLowerLeft() const;
	PointFloat getLowerRight() const;
	double getLineWidth() const;
	Size getSize() const;
	double getWidth() const;
	double getHeight() const;

	bool move(double dx, double dy);
	bool moveTo(double x, double y);
	bool set(double x, double y, double w, double h, double linewidth = 0);
	bool setUpperLeft(const PointFloat& point);
	bool setSize(const Size& boxsize);
	bool setLineWidth(double width);
	bool grow(double dw, double dh);

	bool isPointWithin(const PointFloat& point) const;
	bool isPointWithin(int x, int y) const;
	PointFloat getCentreMass() const;

	bool hasZeroSize() const;
	bool equals(const Box &otherbox) const;
	bool equals(const Box &otherbox, double maxerror) const;
	Box getBoundingBox(const Box &otherbox) const;
	bool growToBoundingBox(const Box &otherbox);
	bool growToIncludePoint(const Point& point, int padX = 0, int padY = 0);
	Box getOverlapBox(const Box &otherbox) const;
	double percentOverlap(const Box &otherbox) const;

	Box getDoubleSizeSameCenter();
	bool constrainTo(const Box& box);
	bool constrainTo(double x, double y, double w, double h);
	Box getConstrainedCopy(const Box& box);
	Box getConstrainedCopy(double x, double y, double w, double h);

	std::string print();
};


/////////////////////////////////////////////////////////////////////
// Vector2D Class
/////////////////////////////////////////////////////////////////////

class Vector2D
{
public:
	Vector2D();
	Vector2D(double x, double y);
	virtual ~Vector2D();

	double x;
	double y;

	double operator[](int n) const;
	bool operator==(const Vector2D &v) const;
	Vector2D operator-(const Vector2D &v) const;
	Vector2D operator+(const Vector2D &v) const;
	double operator*(const Vector2D &v) const;
	Vector2D operator-(double a) const;
	Vector2D operator+(double a) const;
	Vector2D operator*(double a) const;
	const Vector2D& operator-=(const Vector2D &v);
	const Vector2D& operator+=(const Vector2D &v);
	const Vector2D& operator-=(double a);
	const Vector2D& operator+=(double a);
	const Vector2D& operator*=(double a);

	double getX() const;
	double getY() const;

	bool set(const PointFloat& p1, const PointFloat& p2);
	bool set(double x1, double y1, double x2, double y2);
	bool set(double x, double y);
	bool setX(double v);
	bool setY(double v);

	double length() const;
	double det(const Vector2D &v) const;
	bool isOrthogonalWith(const Vector2D &v) const;
	bool isParallelWith(const Vector2D &v) const;
	Vector2D getProjectionOn(const Vector2D &v) const;
	Vector2D getUnitVector() const;
	Vector2D getOrthogonalVector() const;
	double getAngle(const Vector2D &v) const;
	double getArea(const Vector2D &v) const;
	
	std::string print();
};


/////////////////////////////////////////////////////////////////////
// Vector3D Class
/////////////////////////////////////////////////////////////////////

class Vector3D
{
public:
	Vector3D();
	Vector3D(double x, double y, double z);
	virtual ~Vector3D();

	double x;
	double y;
	double z;

	double operator[](int n) const;
	bool operator==(const Vector3D &v) const;
	Vector3D operator-(const Vector3D &v) const;
	Vector3D operator+(const Vector3D &v) const;
	double operator*(const Vector3D &v) const;
	Vector3D operator-(double a) const;
	Vector3D operator+(double a) const;
	Vector3D operator*(double a) const;
	const Vector3D& operator-=(const Vector3D &v);
	const Vector3D& operator+=(const Vector3D &v);
	const Vector3D& operator-=(double a);
	const Vector3D& operator+=(double a);
	const Vector3D& operator*=(double a);

	double getX() const;
	double getY() const;
	double getZ() const;

	bool set(const PointFloat& p1, const PointFloat& p2);
	bool set(double x1, double y1, double z1, double x2, double y2, double z2);
	bool set(double x, double y, double z);
	bool setX(double v);
	bool setY(double v);
	bool setZ(double v);

	double length() const;
	Vector3D product(const Vector3D &v) const;
	bool isOrthogonalWith(const Vector3D &v) const;
	bool isParallelWith(const Vector3D &v) const;
	Vector3D getProjectionOn(const Vector3D &v) const;
	Vector3D getUnitVector() const;
	double getAngle(const Vector3D &v) const;
	double getArea(const Vector3D &v) const;
	
	std::string print();
};

/////////////////////////////////////////////////////////////////////
// RandomPathGenerator Class
/////////////////////////////////////////////////////////////////////

class RandomPathGenerator {
public:
	RandomPathGenerator();
	~RandomPathGenerator();

	bool setStartPoint(double x, double y);
	bool setDirection(double dx, double dy);
	bool setVariation(double var);

	PointFloat generateNextPoint();

	uint64 lastPointTime;
	PointFloat lastPoint;
	Vector2D direction;
	Vector2D variation;

};

} // namespace cmlabs

#endif // !defined(_MATHCLASSES_H)
