// 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;
        public DoubleLattice getResult() {
            int w = maxx - minx + 1;
            int h = maxy - miny + 1;
            double[][] result = new double[h][w];
            for (int y = miny; y <= maxy; y++) {
                for (int x = minx; x <= maxx; x++) {
                    result[y - miny][x - minx] = data[y][x];
                }
            }
            return new DoubleLattice(result, ox - minx, oy - miny);
        }

        public double[][] getRawData() {
            return data;
        }

        public void shearDownRightM2(double shift) {
            final int height = maxy - miny + 1;
            final int width = maxx - minx + 1;
            int ODiagonalNumber = ox - minx + oy - miny;
            int newmaxx = maxx;
            int newmaxy = maxy;
            int newminx = minx;
            int newminy = miny;

            for (int i = 0; i < (height + width - 1); i++) {
                int diagonalCoordinate = i - ODiagonalNumber;
                if (diagonalCoordinate == 0)
                    continue; // shift by 0 means no shift

// 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;

        public DoubleLattice getResult() {
            int w = maxx - minx + 1;
            int h = maxy - miny + 1;
            double[][] result = new double[h][w];
            for (int y = miny; y <= maxy; y++) {
                for (int x = minx; x <= maxx; x++) {
                    result[y - miny][x - minx] = data[y][x];
                }
            }
            return new DoubleLattice(result, ox - minx, oy - miny);
        }

        public double[][] getRawData() {
            return data;
        }

        public void shearDownRightM2(double shift) {
            final int height = maxy - miny + 1;
            final int width = maxx - minx + 1;
            int ODiagonalNumber = ox - minx + oy - miny;
            int newmaxx = maxx;
            int newmaxy = maxy;
            int newminx = minx;
            int newminy = miny;

            for (int i = 0; i < (height + width - 1); i++) {
                int diagonalCoordinate = i - ODiagonalNumber;
                if (diagonalCoordinate == 0)
                    continue; // shift by 0 means no shift

                DiagonalParameters dp = DiagonalParameters.getDiagonalParameters(width, height, i);