using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using WiimoteLib;

namespace Log740
{
    public class Vecteur3F
    {
        public double X, Y, Z;

        public Vecteur3F()
        {
            this.X = 0;
            this.Y = 0;
            this.Z = 0;
        }

        public Vecteur3F(double x, double y, double z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }

        public Vecteur3F(Point3F p)
        {
            this.X = p.X;
            this.Y = p.Y;
            this.Z = p.Z;
        }

        public double R
        {
            get
            {
                return this.X;
            }

            set
            {
                this.X = value;
            }
        }

        public double G
        {
            get
            {
                return this.Y;
            }

            set
            {
                this.Y = value;
            }
        }

        public double B
        {
            get
            {
                return this.Z;
            }

            set
            {
                this.Z = value;
            }
        }

        public double Length
        {
            get
            {
                return Math.Sqrt(X * X + Y * Y + Z * Z);
            }
        }

        public double Angle(Vecteur3F B)
        {
            return Math.Acos((this * B) / (this.Length * B.Length));
        }

        public void Normalize()
        {
            double length = this.Length;

            if (length != 0)
            {
                this.X /= length;
                this.Y /= length;
                this.Z /= length;
            }
        }

        public Vecteur3F Cross(Vecteur3F b)
        {
            Vecteur3F c = new Vecteur3F();
            
            c.X = this.Y * b.Z - this.Z * b.Y;
            c.Y = this.Z * b.X - this.X * b.Z;
            c.Z = this.X * b.Y - this.Y * b.X;

            return c;
        }

        public override bool Equals(object obj)
        {
            if (obj.GetType() == this.GetType())
            {
                return this == (Vecteur3F)obj;
            }
            else
            {
                return false;
            }
        }

        static public bool LineIntersectsTriangle(Vecteur3F p1, Vecteur3F p2, Vecteur3F v0, Vecteur3F v1, Vecteur3F v2)
        {
	        Vecteur3F p, s, d, e1, e2, q;
	        double a, f, u, v, lambda;

            e1 = v1 - v0;
            e2 = v2 - v0;
            d = p2 - p1;

            p = d.Cross(e2);
            
            a = e1 * p;

            if (a > -0.000001 && a < 0.000001)
            {
                return false;
            }

	        f = 1.0f / a;

            s = p1 - v0;

            q = s.Cross(e1);
	        lambda = f * (e2 * q);
            if (lambda < 0.0 || lambda > 1.0)
            {
                return false;
            }
        	
	        u = f * (s * p);
            if (u < 0.0 || u > 1.0)
            {
                return false;
            }
        	
	        v = f * (d * q);
	        if (v < 0.0 || (u + v) > 1.0)
            {
                return false;
            }

	        return true;
        }

        public Vecteur3F Copy()
        {
            return new Vecteur3F(this.X, this.Y, this.Z);
        }

        public override int GetHashCode()
        {
            return (int)this.X ^ (int)this.Y ^ (int)this.Z;
        }

        static public double operator *(Vecteur3F A, Vecteur3F B)
        {
            return A.X * B.X + A.Y * B.Y + A.Z * B.Z;
        }

        static public Vecteur3F operator *(Double S, Vecteur3F A)
        {
            return new Vecteur3F(A.X * S, A.Y * S, A.Z * S);
        }

        static public Vecteur3F operator +(Vecteur3F A, Vecteur3F B)
        {
            return new Vecteur3F(A.X + B.X, A.Y + B.Y, A.Z + B.Z);
        }

        static public Vecteur3F operator -(Vecteur3F A, Vecteur3F B)
        {
            return new Vecteur3F(A.X - B.X, A.Y - B.Y, A.Z - B.Z);
        }

        static public bool operator ==(Vecteur3F A, Vecteur3F B)
        {
            return A.X == B.X && A.Y == B.Y && A.Z == B.Z;
        }

        static public bool operator !=(Vecteur3F A, Vecteur3F B)
        {
            return A.X != B.X || A.Y != B.Y || A.Z != B.Z;
        }

        static public implicit operator Vecteur3F(Point3F p)
        {
            return new Vecteur3F(p);
        }
    }
}
