#ifndef AUXMATH_H_INCLUDED
#define AUXMATH_H_INCLUDED

#include<math.h>
#include<iostream>

template <class T> class Point2D{
public:
 T x;
 T y;

 Point2D(){};

 Point2D(T x, T y){
   this->x = x;
   this->y = y;
 }
};

template <class T> class Point3D{
public:
 T x;
 T y;
 T z;

 Point3D(){};

 Point3D(T x, T y, T z){
   this->x = x;
   this->y = y;
   this->z = z;
 }
};

template <class T> class Vector3D{
public:
 T x;
 T y;
 T z;

 Vector3D(){};

 Vector3D(T x, T y, T z){
   this->x = x;
   this->y = y;
   this->z = z;
 }

 T dotProduct(Vector3D v){
   return this->x*v.x+this->y*v.y+this->z*v.z;
 }

 Vector3D crossProduct(Vector3D v){
    Vector3D _normal;
    _normal.x = y*v.z-v.y*z;
    _normal.y = z*v.x-v.z*x;
    _normal.z = x*v.y-v.x*y;
    return _normal;
 }

 Vector3D _normalize(){

   Vector3D w;
   T _norm = sqrt(x*x+y*y+z*z);

   if (_norm!=0){
     w.x = x/_norm;
     w.y = y/_norm;
     w.z = z/_norm;
   }
   else
     std::cout << "Cannot normalize vector (0,0,0)" << std::endl;

   return w;
 }
};

template <class T> class Plane{
public:
  Vector3D<T> _normal;
  Point3D<T> p;

  Plane(Vector3D<T> _normal, Point3D<T> p){
    this->_normal = _normal;
    this->p = p;
  }

  Point2D<T> intersect(Point3D<T> p0, Point3D<T> p1){
    Vector3D<T> v0(p0.x-p.x,p0.y-p.y,p0.z-p.z);
    Vector3D<T> v1(p1.x-p0.x,p1.y-p0.y,p1.z-p0.z);


    T t = -_normal.dotProduct(v0)/_normal.dotProduct(v1);

    return Point2D<T>(p0.x+t*v1.x,p0.y+t*v1.y);
  }
};

template <class T> class Line{
public:
   Point2D<T> p0,p1;

   Line(Point2D<T> p0, Point2D<T> p1){
      this->p0 = p0;
	  this->p1 = p1;
   }
};

#endif // AUXMATH_H_INCLUDED
