package resampler;

import javax.vecmath.Color3f;
import javax.vecmath.Matrix3f;
import javax.vecmath.Point2f;
import javax.vecmath.Vector3f;

import resampler.ui.MainFrame;

public class PerspectiveResampler extends Resampler
{

    public PerspectiveResampler(Image inputImage, 
            Image outputImage, boolean clipToDestination)
    {
        super(inputImage, outputImage, clipToDestination);
    }
    
    protected void resample() {
        Matrix3f m = computeTransformation(inputPoints, outputPoints);
        resample(m);
    }

    /**
     * Do the actual resampling work here.
     * @param m
     *     the matrix that transform the points
     *     on the target image to the points on
     *     the source image.
     */
    protected void resample(Matrix3f m)
    {
        // TODO Add perspective resampling code here

    }
 
    /**
     * compute the matrix (recall in HW4) that
     * transforms points in ptsOutput to those in 
     * ptsInput  
     * @param ptsInput
     * @param ptsOutput
     * @return
     */
    protected static Matrix3f computeTransformation(Point2f[] ptsInput,
            Point2f[] ptsOutput)
    {
        // compute the transformation matrix here
        Matrix3f q = new Matrix3f( 
                ptsInput[0].x, ptsInput[1].x, ptsInput[2].x, 
                ptsInput[0].y, ptsInput[1].y, ptsInput[2].y, 
                1, 1, 1);
        Matrix3f invq = new Matrix3f();
        invq.invert(q);
        Vector3f q4 = new Vector3f(ptsInput[3].x, ptsInput[3].y, 1);
        invq.transform(q4);
        
        Matrix3f p = new Matrix3f( 
                ptsOutput[0].x, ptsOutput[1].x, ptsOutput[2].x, 
                ptsOutput[0].y, ptsOutput[1].y, ptsOutput[2].y, 
                1, 1, 1);
        Matrix3f invp = new Matrix3f();
        invp.invert(p);
        Vector3f p4 = new Vector3f(ptsOutput[3].x, ptsOutput[3].y, 1);
        invp.transform(p4);
        
        Matrix3f m = new Matrix3f();
        m.set(q);
        m.mul(new Matrix3f(q4.x / p4.x, 0, 0,
                           0, q4.y / p4.y, 0,
                           0, 0, q4.z / p4.z));
        m.mul(invp);
        return m;
    }

}
