using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace CSGBuilder {
    public class Point3Dh {
        // Homogén koordináták
        double x, y, z, w;
        Color color;

        public Point3Dh(double xp, double yp, double zp, double wp) {
            x = xp; y = yp; z = zp; w = wp; color = Color.Empty;
        }

        #region Public properties
        public double X { get { return x; } set { x = value; } }
        public double Y { get { return y; } set { y = value; } }
        public double Z { get { return z; } set { z = value; } }
        public double W { get { return w; } set { w = value; } }
        public Color Color { get { return color; } set { color = value; } }
        #endregion

        // Két vektor összege
        public static Point3Dh operator +(Point3Dh p1, Point3Dh p2) {
            return new Point3Dh(p1.X + p2.X, p1.Y + p2.Y, p1.Z + p2.Z, p1.W + p2.W);
        }

        // Két vektor különbsége
        public static Point3Dh operator -(Point3Dh p1, Point3Dh p2) {
            return new Point3Dh(p1.X - p2.X, p1.Y - p2.Y, p1.Z - p2.Z, p1.W - p2.W);
        }

        // Egy vektor skalárszorosa
        public static Point3Dh operator *(Point3Dh p, double d) {
            return new Point3Dh(p.X * d, p.Y * d, p.Z * d, p.W * d);
        }

        // Belső szorzat
        public static double operator *(Point3Dh p1, Point3Dh p2) {
            return (p1.X * p2.X + p1.Y * p2.Y + p1.Z * p2.Z + p1.W * p2.W);
        }

        // Vektoriális szorzat
        public static Point3Dh operator %(Point3Dh p1, Point3Dh p2) {
            //p1.ToDescartes();
            //p2.ToDescartes();
            return new Point3Dh(p1.Y * p2.Z - p1.Z * p2.Y, p1.Z * p2.X - p1.X * p2.Z, p1.X * p2.Y - p1.Y * p2.X, 1.0);
        }

        // Vektor osztva skalárral
        public static Point3Dh operator /(Point3Dh p, double d) {
            return new Point3Dh(p.X / d, p.Y / d, p.Z / d, p.W / d);
        }

        // Két pont egyenlősége
        //public static bool operator ==(Point3Dh p, Point3Dh q) {
        //    return (p.X == q.X && p.Y == q.Y && p.Z == q.Z && p.W == q.W);
        //}

        //public static bool operator !=(Point3Dh p, Point3Dh q) {
        //    return !(p == q);
        //}

        // Vektor hossza
        public double Norm() {
            return System.Math.Sqrt(x * x + y * y + z * z + w * w);
        }

        // Vektor normáltja
        public void Normal() {
            double length = Math.Sqrt(x * x + y * y + z * z + w * w);
            if (length == 0.0) return;
            x /= length;
            y /= length;
            z /= length;
            w /= length;
        }

        // Homogén -> Descartes
        public void ToDescartes() {
            if (w == 0.0) return;
            x /= w; y /= w; z /= w; w = 1.0;
        }

        public override string ToString() {
            return x.ToString("F2") + ", " + y.ToString("F2") + ", " + z.ToString("F2");
        }

        public static Point3Dh FromString(string s) {
            string[] w = s.Split(new char[] {','});
            double x = double.Parse(w[0]);
            double y = double.Parse(w[1]);
            double z = double.Parse(w[2]);
            return new Point3Dh(x, y, z, 1.0);
        }

        public Point3Dh Clone() {
            return new Point3Dh(x, y, z, w);
        }
    }
}
