
using System;

namespace Math2D
{
	
	
	public class Vector2D
	{
		private float[] FCoords = new float[2];
		public Vector2D() {

		}
		
		public Vector2D(float x, float y)
		{
			Set(x, y);
		}
		
		public Vector2D(Vector2D v) {
			Set(v.X, v.Y);
		}
		
		public void Set(float x, float y) {
			X = x;
			Y = y;
		}
		
		public float Length {
			get { return (float)Math.Sqrt(X*X + Y*Y); }	
			set {
				if (Length == 0f) return;
				float dc = value/Length;
				X *= dc;
				Y *= dc;
			}
		}
		
		public float X {
			get { return FCoords[0]; }
			set { FCoords[0] = value; }
		}
		
		public float Y {
			get { return FCoords[1]; }
			set { FCoords[1] = value; }
		}
		
		public static Vector2D operator~ (Vector2D a) {
			return new Vector2D(-a.X, -a.Y);	
		}
		
		public static Vector2D operator+ (Vector2D a, Vector2D b) {
			return new Vector2D(a.X + b.X, a.Y + b.Y);	
		}
				
		public static Vector2D operator- (Vector2D a, Vector2D b) {
			return new Vector2D(a.X - b.X, a.Y - b.Y);	
		}
		
		public static Vector2D operator* (Vector2D a, float b) {
			return new Vector2D(a.X * b, a.Y * b);	
		}
		
		public static Vector2D operator* (Vector2D a, Vector2D b) {
			return new Vector2D(a.X * b.X, a.Y * b.Y);
		}
		
		public static Vector2D operator* (Vector2D a, Matrix2D b) {
			float[,] M = b.M;
			float x = a.X*M[0,0] + a.Y*M[1,0] + M[2,0];
			float y = a.X*M[0,1] + a.Y*M[1,1] + M[2,1];
			float w = a.X*M[0,2] + a.Y*M[1,2] + M[2,2];
			return new Vector2D(x/w, y/w);
		}
		
		public enum ClassifyResult {LEFT,  RIGHT,  BEYOND,  BEHIND, BETWEEN, ORIGIN, DESTINATION};
		
		//как расположена точка отностительно линии
		public ClassifyResult Classify(Vector2D p0,
		                               Vector2D p1) {
		  Vector2D p2 = this;
		  Vector2D a = p1 - p0;
		  Vector2D b = p2 - p0;
		  double sa = a.X * b.Y - b.X * a.Y;
		  if (sa > 0.0)
		    return ClassifyResult.LEFT;
		  if (sa < 0.0)
		    return ClassifyResult.RIGHT;
		  if ((a.X * b.X < 0.0) || (a.Y * b.Y < 0.0))
		    return ClassifyResult.BEHIND;
		  if (a.Length < b.Length)
		    return ClassifyResult.BEYOND;
		  if (p0 == p2)
		    return ClassifyResult.ORIGIN;
		  if (p1 == p2)
		    return ClassifyResult.DESTINATION;
		  return ClassifyResult.BETWEEN;
		}

	}
}
