module y4d_math.vector2d;

//----------------------------------------------------------------------------
//	2次元vectorライブラリ
//----------------------------------------------------------------------------
private import std.math;	// sqrt

///	2次元vectorライブラリ
struct vector2D {
public:
	///	保持しているベクター(x,y)
	double x=0.0,y=0.0;

/+
	//	変数x,yを初期化しないコンストラクタ(D言語の規約により0で初期化される)
	this() {}

	//	変数x,yを初期化するコンストラクタ
	this(double x_,double y_)
	{	x = x_; y = y_; }

	//	他のvectorで初期化するためのコンストラクタ
	this(vector2D v)
	{	x = v.x; y = v.y; }
+/

	///	(x,y)を設定するsetter
	void set(double x_,double y_)
	{	x = x_; y = y_; }

	///	内積を求める
	double innerProduct(vector2D v)
	{
		return x * v.x + y * v.y;
	}

	///	外積を求める(2次元の外積の結果は定数)
	double outerProduct(vector2D v)
	{
		return x * v.y - y * v.x;
	}

	///	他のベクトルを加算する
	void add(vector2D v)
	{
		x += v.x;
		y += v.y;
	}

	///	他のベクトルを減算する
	void sub(vector2D v)
	{
		x -= v.x;
		y -= v.y;
	}

	///	スカラー値を乗算する
	void mul(double a)
	{
		x *= a;
		y *= a;
	}

	///	スカラー値で除算する
	public void div(double a)
	{
		x /= a;
		y /= a;
	}

	///	絶対値を求める(sqrtが入るので遅い)
	double size()
	{
		return sqrt(x * x + y * y);
	}

	///	絶対値の二乗を求める(大小比較をする目的ならこちらで十分)
	double size2()
	{
		return x * x + y * y;
	}

	///	近似による距離(絶対値)の算出。sqrtを使っていない分だけ速い
	double dist(vector2D v)
	{
		double ax = fabs(x - v.x);
		double ay = fabs(y - v.y);
		if ( ax > ay ) {
			return ax + ay / 2;
		} else {
			return ay + ax / 2;
		}
	}

	//	以下は、各種オペレータ

	/// +=
	void opAddAssign(vector2D v) { add(v); }

	///	-=
	void opSubAssign(vector2D v) { sub(v); }

	/// *= (定数倍)
	void opMulAssign(double a) { mul(a); }

	/// /= (定数割)
	void opDivAssign(double a) { div(a); }

	/// +
	vector2D opAdd(vector2D v)
	{ vector2D r = *this; r+=v; return r; }

	/// -
	vector2D opSub(vector2D v)
	{ vector2D r = *this; r-=v; return r; }

	/// * 内積
	double opMul(vector2D v)
	{ return innerProduct(v); }

	/// / 外積
	double opDiv(vector2D v)
	{ return outerProduct(v); }

	/// * 定数倍
	vector2D opMul(double a)
	{ vector2D r = *this; r*=a; return r; }

	/// / 定数割
	vector2D opDiv(double a)
	{ vector2D r = *this; r/=a; return r; }

	///	== , != operator
	bool opEquals(vector2D v) { return cast(bool) ((x==v.x) && (y==v.y)); }

	//	「(5,10)」のようにベクトルを文字列化して返す↓この関数が無いのよ..
	//	char[] toString() { return "(" ~ atof(x) ~ "," ~ atof(y) ~ ")"; }

	///	デバッグ用に標準出力に値を表示する→「(5,10)」のように出力される
	void output()
	{ printf("(%f,%f)",x,y); }
}

