#ifndef POINT3D
#define POINT3D

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

struct Point3d {
public:
	double x;
	double y;
	double z;
	
	Point3d(double vx=0.0f, double vy=0.0f, double vz=0.0f):x{vx},y{vy},z{vz}{};
	void affiche(void);	

	inline double normal2() const { return x*x+y*y+z*z; }
	inline double normal() const { return sqrt(x*x+y*y+z*z); }

	
	Point3d operator+(const Point3d& other) const;
	Point3d operator*(const Point3d& other) const;
	Point3d operator-(const Point3d& other) const;
	Point3d operator/(const Point3d& other) const;
	Point3d operator*(const double t) const;
	Point3d operator/(const double t) const;
	bool operator==(const Point3d& other) const;
};

static inline double lerp(double a, double b, double t){
	return (a * (1.0f - t)) + (b * t);
}
extern inline Point3d lerp(const Point3d& a, const Point3d& b, double t){
	return Point3d{lerp(a.x, b.x, t), lerp(a.y, b.y, t), lerp(a.z, b.z, t)};
}

extern inline double dot(const Point3d& a, const Point3d& b,
						 const Point3d& axis = Point3d{1.0f, 1.0f,1.0f}){
	return axis.x * a.x * b.x + axis.y * a.y * b.y + axis.z * a.z * b.z;
}

extern inline Point3d normalize(const Point3d& a) {
	double norm = a.normal();
	if(norm !=0)
		return Point3d{a.x/norm,a.y/norm,a.z/norm};
	else
		return Point3d{0.0f,0.0f,0.0f};
}

extern inline Point3d cross(const Point3d& a, const Point3d& b){
	return Point3d{(a.y * b.z - a.z * b.y), (a.z * b.x - a.x * b.z), (a.x * b.y - a.y * b.x)};
}
#endif
