#include "shape.hpp"

//private
void shape::_copyShape(const shape& S)
{
    _tab = S._tab;
    _radius = S._radius;
}

//constructeur par defau
shape::shape()
{
    _tab.push_back(point());
    _radius=0;
}

//Copieur par defaut
shape::shape(const shape& S)
{
    _copyShape(S);
}

//destructeur
shape::~shape()
{
    _tab.clear();
}

//setteur
void shape::setX(int i, float X)
{
    assert(i+1<_tab.size());
    _tab[i+1].setX(X);
}

void shape::setY(int i, float Y)
{
    assert(i+1<_tab.size());
    _tab[i+1].setY(Y);
}

void shape::setZ(int i, float Z)
{
    assert(i+1<_tab.size());
    _tab[i+1].setZ(Z);
}

//modifie la shape avec un nouveau point
void shape::setPoint(int i, point P)
{
    assert(i+1<_tab.size());
    _tab[i+1] = P;
}

//determine le point centrale d'une shape
void shape::setCenter(point P)
{
    assert(_tab.size());
    _tab[0] = P;
}

//determine létendu de la shape
void shape::setRadius(float r)
{
    _radius = r;
}

//ajouter un point dans la shape
void shape::addPoint(const point& p)
{
    _tab.push_back(p);
}

//getteur
//retourne les X du point voulus
float shape::getX(int i)const
{
    assert(i+1<_tab.size());
    return _tab[i+1].getX();
}

float shape::getY(int i)const
{
    assert(i+1<_tab.size());
    return _tab[i+1].getY();
}

float shape::getZ(int i)const
{
    assert(i+1<_tab.size());
    return _tab[i+1].getZ();
}

const point& shape::getPoint(int i)const
{
    assert(i+1<_tab.size());
    return _tab[i+1];
}

//determine le nombre de point que la shape constitu
int shape::numPoint()const
{
    return _tab.size()-1;
}

//retourne la position du point central de la shape
const point& shape::getCenter()const
{
    assert(_tab.size());
    return _tab[0];
}

float shape::getRadius()const
{
    return _radius;
}

float shape::getRadiusSQ()const
{
    return _radius*_radius;
}

//detection de colision avec un point
bool shape::collide(const point& pos)const
{
    return (pos-getCenter()).magSQ() < _radius*_radius;
}

//detection de colision avec une autre shape
bool shape::collide(const shape& other)const
{
    return (other.getCenter()-getCenter()).magSQ() < (_radius+other._radius)*(_radius+other._radius);//getRadiusSQ()+other.getRadiusSQ();
}

//======================================Operations sur les points===============================================
//adition d'une shape et d'un point
void shape::add(const point& p)
{
    for(int i = 0; i<_tab.size(); i++)
        _tab[i] = _tab[i] + p;
}

//soustraction d'une shape et d'un point
void shape::sous(const point& p)
{
    for(int i = 0; i<_tab.size(); i++)
        _tab[i] = _tab[i] - p;
}

//=================================Operation avec scalaires================================
//multiplication par un scalaire
void shape::mulS(float scalaire)
{
    for(int i = 0; i<_tab.size(); i++)
        _tab[i] = _tab[i] * scalaire;
    _radius *= scalaire;
}

//division par un scalaire
void shape::divS (float scalaire)
{
    for(int i = 0; i<_tab.size(); i++)
        _tab[i] = _tab[i]/scalaire;
    _radius /= scalaire;
}

//-----------------------------Rotation------------------------------------------------
//petite modif par martin par soucil d'uniformité, fonction retour,
//pluto que methode mutator,
//ainsi eliminer l'appel de deux fois les fonctions trigonometrique
//qui sont lourde

//Rotation de toutes les points d'une shape
//rotation sur les X
void shape::rotX(float angle)
{
    double s = sin(angle),  //le caller deux fois c'est aussi long qu'une SQRT
           c = cos(angle);
    for(int i = 0; i<_tab.size(); i++)
    {
        float y = _tab[i].getY(),
               z = _tab[i].getZ();
        _tab[i].setY(y*c - z*s);
        _tab[i].setZ(y*s + z*c);
    }
}

 //rotation sur les Y
void shape::rotY(float angle)
{
    double s = sin(angle),  //le caller deux fois c'est aussi long qu'une SQRT
           c = cos(angle);
    for(int i = 0; i<_tab.size(); i++)
    {
        float x = _tab[i].getX(),
               z = _tab[i].getZ();
        _tab[i].setX(z*s + x*c);
        _tab[i].setZ(z*c - x*s);
    }
}

//rotation sur les Z
void shape::rotZ(float angle)
{
    double s = sin(angle),  //le caller deux fois c'est aussi long qu'une SQRT
           c = cos(angle);
    for(int i = 0; i<_tab.size(); i++)
    {
        float x = _tab[i].getX(),
               y = _tab[i].getY();
        _tab[i].setX(x*c - y*s);
        _tab[i].setY(x*s + y*c);
    }
}

 //==================================Cross Product===============================================================
void shape::cross(const point& p)
 {
    for(int i = 0; i<_tab.size(); i++)
        _tab[i].cross(p);
 }

//======================================Surcharge des operateurs a l'interne=====================================
point& shape::operator[] (int i)
{
    return _tab[i];
}
