/* UtilLib - Copyright (c) 2005-2011 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.mapeadores.util.geometry;

import java.awt.Point;
import java.awt.Dimension;


/**
 * Point considéré dans le repère cartésien classique, c'est à dire où l'axe des y est orienté vers le haut (alors que dans le repère utilisé dans java.awt à l'axe des y orienté vers le bas).
 *
 * @author  Vincent Calame
 */
public class CartesianPoint extends Point {

    public CartesianPoint(int x, int y) {
        super(x, y);
    }

    public CartesianPoint() {
        super();
    }

    public CartesianPoint(CartesianPoint cartesianPoint) {
        super(cartesianPoint);
    }

    /**
     * Convertit des coordonnées polaires en coordonnées cartésiennes.
     */
    static public CartesianPoint convertToCartesianPoint(final double theta, final double r) {
        int x = (int) Math.round(r * Math.cos(theta));
        int y = (int) Math.round(r * Math.sin(theta));
        return new CartesianPoint(x, y);
    }

    /**
     *Calcule l'angle entre (O<I>A</I>) et l'axe des x.
     *C'est le theta des coordonnèes polaires. Il est compris entre 0 et 2pi
     */
    public static double angle(CartesianPoint C, CartesianPoint A) {
        return angle(A.x - C.x, A.y - C.y);
    }

    public static double angle(CartesianPoint A) {
        return angle(A.x, A.y);
    }

    /**
     * Retourne un angle dontla valeur est comprise entre 0 et 2π
     */
    public static double angle(int x, int y) {
        double theta = Math.acos(x / norme(x, y));
        if (y < 0) {
            theta = 2 * Math.PI - theta;
        }
        return theta;
    }

    /**
     *Calcule la norme du point <I>A</I>.
     */
    public static double norme(CartesianPoint A) {
        return norme(A.x, A.y);
    }

    public static double norme(int x, int y) {
        return Math.sqrt((double) (x * x + y * y));
    }

    public static double norme(double x, double y) {
        return Math.sqrt(x * x + y * y);
    }

    public static double norme(CartesianPoint C, CartesianPoint A) {
        return norme(A.x - C.x, A.y - C.y);
    }

    public static CartesianPoint getCartesianPointOnEllipse(CartesianPoint C, double angle, Dimension ab) {
        double r = getNormeOnEllipse(angle, ab);
        int x = (int) Math.round(Math.cos(angle) * r);
        int y = (int) Math.round(Math.sin(angle) * r);
        return new CartesianPoint(x + C.x, y + C.y);
    }

    public static double getNormeOnEllipse(final double angle, Dimension ab) {
        double costheta = Math.cos(angle);
        double sintheta = Math.sin(angle);
        int acarre = ab.width * ab.width;
        int bcarre = ab.height * ab.height;
        double r = Math.sqrt(1 / ((costheta * costheta / acarre) + (sintheta * sintheta / bcarre)));

        return r;
    }

}
