// Path: src/lattice/DoubleLattice.java
// public class DoubleLattice extends Lattice {
// 	/**
// 	 * @uml.property  name="data"
// 	 */
// 	private final double[][] data;
// 	public DoubleLattice(double[][] data, int ox, int oy) {
// 		super(ox,oy);
// 		this.data = data;
// 	}
// 	
//     public DoubleLattice(DoubleLattice lattice) {
//         this(lattice.data, lattice.ox, lattice.oy);
//     }
//     
//     /**
// 	 * @return
// 	 * @uml.property  name="data"
// 	 */
//     public double[][] getData() {
//         return data;
//     }
// }
// 
// Path: src/filter/InterpolatingArray.java
// public interface Factory {
//     InterpolatingArray getInstance(double[] points); 
// }
// 
// Path: src/filter/RectangleDiagonal.java
// static public class DiagonalParameters {
// 	final public int diagonalLength;
// 	final public int startX;
// 	final public int startY;
// 
// 	private DiagonalParameters(int diagonalLength, int startX, int startY) {
// 		this.diagonalLength = diagonalLength;
// 		this.startX = startX;
// 		this.startY = startY;
// 	}
// 
// 	public static DiagonalParameters getDiagonalParameters(int width,
// 			int height, int n) {
// 		if (width == height) {
// 			return getSquareDiagonalParameters(width, height, n);
// 		} else if (width < height) {
// 			return getTallRectangleDiagonalParameters(width, height, n);
// 		} else {
// 			return getLongRectangleDiagonalParameters(width, height, n);
// 		}
// 	}
// 
// 	private static DiagonalParameters getLongRectangleDiagonalParameters(
// 			int width, int height, int n) {
// 		final int diagonalLength;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 			diagonalLength = n + 1;
// 		} else {
// 			startX = n - height + 1;
// 			startY = height - 1;
// 			final int fromTheLastColumn = (width - 1) - startX;
// 			if (fromTheLastColumn < height - 1) {
// 				diagonalLength = fromTheLastColumn + 1;
// 			} else {
// 				diagonalLength = height;
// 			}
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// 
// 	private static DiagonalParameters getTallRectangleDiagonalParameters(
// 			int width, int height, int n) {
// 
// 		final int diagonalLength;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 			if (n < width - 1) {
// 				diagonalLength = n + 1;
// 			} else {
// 				diagonalLength = width;
// 			}
// 
// 		} else {
// 			startX = n - height + 1;
// 			startY = height - 1;
// 			final int fromTheLastColumn = (width - 1) - startX;
// 			diagonalLength = fromTheLastColumn + 1;
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// 
// 	private static DiagonalParameters getSquareDiagonalParameters(
// 			int width, int height, int n) {
// 
// 		final int distanceFromCornerDiagonal = Math.abs(n - (width - 1));
// 		final int diagonalLength = width - distanceFromCornerDiagonal;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 		} else {
// 			startX = n - width + 1;
// 			startY = height - 1;
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// }


import static java.lang.Math.sqrt;
import lattice.DoubleLattice;
import filter.InterpolatingArray.Factory;
import filter.RectangleDiagonal.DiagonalParameters;
package filter;

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


/**
 * Implementation of H2O transformation described in L.Condat,
 * B.Forster-Heinlein, D. Van De Ville,
 * "Reversible Hexagonal-Orthogonal Grid Conversion by 1-D Filtering", IEEE
 * ICIP, 2007, vol.II pg. 73-76
 * 
 * Copyright (C) 2012 Aleksejs Truhans
 **/
public class H2O {

    public final static double M1A = 1 - sqrt(2 / sqrt(3));
    public final static double M2B = sqrt(sqrt(3) / 2) - 1;
    public final static double M3C = sqrt(2 / sqrt(3)) - 1 - 1 / sqrt(3);

    /**
     * @author Aleksejs Truhans
     */
    public static enum Direction {
        O2H, H2O, TEST_O2H, TEST_H2O;
    }

    /**
     * Use it to convert from orthogonal to hexagonal lattice.
     * o2h doesn't change the passed raster.
     **/
// Path: src/lattice/DoubleLattice.java
// public class DoubleLattice extends Lattice {
// 	/**
// 	 * @uml.property  name="data"
// 	 */
// 	private final double[][] data;
// 	public DoubleLattice(double[][] data, int ox, int oy) {
// 		super(ox,oy);
// 		this.data = data;
// 	}
// 	
//     public DoubleLattice(DoubleLattice lattice) {
//         this(lattice.data, lattice.ox, lattice.oy);
//     }
//     
//     /**
// 	 * @return
// 	 * @uml.property  name="data"
// 	 */
//     public double[][] getData() {
//         return data;
//     }
// }
// 
// Path: src/filter/InterpolatingArray.java
// public interface Factory {
//     InterpolatingArray getInstance(double[] points); 
// }
// 
// Path: src/filter/RectangleDiagonal.java
// static public class DiagonalParameters {
// 	final public int diagonalLength;
// 	final public int startX;
// 	final public int startY;
// 
// 	private DiagonalParameters(int diagonalLength, int startX, int startY) {
// 		this.diagonalLength = diagonalLength;
// 		this.startX = startX;
// 		this.startY = startY;
// 	}
// 
// 	public static DiagonalParameters getDiagonalParameters(int width,
// 			int height, int n) {
// 		if (width == height) {
// 			return getSquareDiagonalParameters(width, height, n);
// 		} else if (width < height) {
// 			return getTallRectangleDiagonalParameters(width, height, n);
// 		} else {
// 			return getLongRectangleDiagonalParameters(width, height, n);
// 		}
// 	}
// 
// 	private static DiagonalParameters getLongRectangleDiagonalParameters(
// 			int width, int height, int n) {
// 		final int diagonalLength;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 			diagonalLength = n + 1;
// 		} else {
// 			startX = n - height + 1;
// 			startY = height - 1;
// 			final int fromTheLastColumn = (width - 1) - startX;
// 			if (fromTheLastColumn < height - 1) {
// 				diagonalLength = fromTheLastColumn + 1;
// 			} else {
// 				diagonalLength = height;
// 			}
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// 
// 	private static DiagonalParameters getTallRectangleDiagonalParameters(
// 			int width, int height, int n) {
// 
// 		final int diagonalLength;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 			if (n < width - 1) {
// 				diagonalLength = n + 1;
// 			} else {
// 				diagonalLength = width;
// 			}
// 
// 		} else {
// 			startX = n - height + 1;
// 			startY = height - 1;
// 			final int fromTheLastColumn = (width - 1) - startX;
// 			diagonalLength = fromTheLastColumn + 1;
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// 
// 	private static DiagonalParameters getSquareDiagonalParameters(
// 			int width, int height, int n) {
// 
// 		final int distanceFromCornerDiagonal = Math.abs(n - (width - 1));
// 		final int diagonalLength = width - distanceFromCornerDiagonal;
// 		final int startX;
// 		final int startY;
// 		if (n < height) {
// 			startX = 0;
// 			startY = n;
// 		} else {
// 			startX = n - width + 1;
// 			startY = height - 1;
// 		}
// 
// 		return new DiagonalParameters(diagonalLength, startX, startY);
// 	}
// }


// Path: src/filter/H2O.java
import static java.lang.Math.sqrt;
import lattice.DoubleLattice;
import filter.InterpolatingArray.Factory;
import filter.RectangleDiagonal.DiagonalParameters;

package filter;

/* This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


/**
 * Implementation of H2O transformation described in L.Condat,
 * B.Forster-Heinlein, D. Van De Ville,
 * "Reversible Hexagonal-Orthogonal Grid Conversion by 1-D Filtering", IEEE
 * ICIP, 2007, vol.II pg. 73-76
 * 
 * Copyright (C) 2012 Aleksejs Truhans
 **/
public class H2O {

    public final static double M1A = 1 - sqrt(2 / sqrt(3));
    public final static double M2B = sqrt(sqrt(3) / 2) - 1;
    public final static double M3C = sqrt(2 / sqrt(3)) - 1 - 1 / sqrt(3);

    /**
     * @author Aleksejs Truhans
     */
    public static enum Direction {
        O2H, H2O, TEST_O2H, TEST_H2O;
    }

    /**
     * Use it to convert from orthogonal to hexagonal lattice.
     * o2h doesn't change the passed raster.
     **/
    public static DoubleLattice o2h(double[][] raster) {