#include "Point.h"

#include "Transform.h"

#include <cmath>

Point::Point(double x, double y, double z)
    : mX(x),
      mY(y),
      mZ(z)
{
}

Point::Point(const DiscretePoint& point)
    : mX(static_cast<double>(point.getX())),
      mY(static_cast<double>(point.getY())),
      mZ(0)
{

}

Point::Point(const Point& reference, double offSetX, double offSetY, double offSetZ)
: mX(reference.getX() + offSetX),
  mY(reference.getY() + offSetY),
  mZ(reference.getZ() + offSetZ)
{

}

Point::~Point()
{
};

double Point::getX() const
{
    return mX;
}

double Point::getY() const
{
    return mY;
}

double Point::getZ() const
{
    return mZ;
}

double Point::getDistance(const Point& point) const
{
    const auto deltaX = getDeltaX(point);
    const auto deltaY = getDeltaY(point);
    const auto deltaZ = getDeltaZ(point);
    return std::sqrt(deltaX* deltaX + deltaY* deltaY + deltaZ* deltaZ);
}

Vector Point::getDelta(const Point& point) const
{
    return Vector(point.mX - mX, point.mY - mY, point.mZ - mZ);
}

double Point::getDeltaX(const Point& point) const
{
    return point.getX() - mX;
}

double Point::getDeltaY(const Point& point) const
{
    return point.getY() - mY;
}

double Point::getDeltaZ(const Point& point) const
{
    return point.getZ() - mZ;
}

bool Point::isAtOrigin() const
{
    return mX == 0.0 && mY == 0.0 && mZ == 0.0;
}

void Point::apply(const Transform& transform)
{
    mX -= transform.getLocation().getX();
    mY -= transform.getLocation().getY();
    mZ -= transform.getLocation().getZ();

    mX *= transform.getScale().mX;
    mY *= transform.getScale().mY;
    mZ *= transform.getScale().mZ;
}

void Point::move(double x, double y, double z)
{
    mX += x;
    mY += y;
    mZ += z;
}

void Point::move(const Vector& vector)
{
    move(vector.getX(), vector.getY(), vector.getZ());
}
