package org.poly2tri.transform.coordinate;

/**
 * A transform that aligns the XY plane normal [0,0,1] with any given target normal
 * <p>
 * http://www.cs.brown.edu/~jfh/papers/Moller-EBA-1999/paper.pdf
 *
 * @author thahlen@gmail.com
 */
public class XYToAnyTransform extends Matrix3Transform {
    /**
     * Assumes target normal is normalized
     */
    public XYToAnyTransform(double nx, double ny, double nz) {
        setTargetNormal(nx, ny, nz);
    }

    /**
     * Assumes target normal is normalized
     *
     * @param nx
     * @param ny
     * @param nz
     */
    public void setTargetNormal(double nx, double ny, double nz) {
        double h, f, c, vx, vy, hvx;

        vx = ny;
        vy = -nx;
        c = nz;

        h = (1 - c) / (1 - c * c);
        hvx = h * vx;
        f = (c < 0) ? -c : c;

        if (f < 1.0 - 1.0E-4) {
            m00 = c + hvx * vx;
            m01 = hvx * vy;
            m02 = -vy;
            m10 = hvx * vy;
            m11 = c + h * vy * vy;
            m12 = vx;
            m20 = vy;
            m21 = -vx;
            m22 = c;
        } else {
            // if "from" and "to" vectors are nearly parallel
            m00 = 1;
            m01 = 0;
            m02 = 0;
            m10 = 0;
            m11 = 1;
            m12 = 0;
            m20 = 0;
            m21 = 0;
            if (c > 0) {
                m22 = 1;
            } else {
                m22 = -1;
            }
        }

    }
}
