/* * Geotools2 - OpenSource mapping toolkit * http://geotools.org * (C) 2002-2006, Geotools Project Managment Committee (PMC) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library 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 * Lesser General Public License for more details. */ package org.geotools.referencing.operation.builder; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.vecmath.MismatchedSizeException; import org.geotools.referencing.operation.builder.algorithm.MapTriangulationFactory; import org.geotools.referencing.operation.builder.algorithm.Quadrilateral; import org.geotools.referencing.operation.builder.algorithm.RubberSheetTransform; import org.geotools.referencing.operation.builder.algorithm.TINTriangle; import org.geotools.referencing.operation.builder.algorithm.TriangulationException; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.opengis.spatialschema.geometry.MismatchedDimensionException; import org.opengis.spatialschema.geometry.MismatchedReferenceSystemException; /** * Builds {@linkplain org.geotools.referencing.operation.builder.RubberSheetBuilder * RubberSheet} transformation from a list of {@linkplain * org.geotools.referencing.operation.builder.MappedPosition MappedPosition}. The * explanation of RubberSheet transformation can be seen <a href = * "http://planner.t.u-tokyo.ac.jp/member/fuse/rubber_sheeting.pdf">here</a>. * * @since 2.4 * @source $URL: http://svn.geotools.org/geotools/trunk/gt/modules/library/referencing/src/main/java/org/geotools/referencing/operation/builder/RubberSheetBuilder.java $ * @version $Id: RubberSheetBuilder.java 24925 2007-03-27 20:12:08Z jgarnett $ * @author Jan Jezek */ public class RubberSheetBuilder extends MathTransformBuilder { /** trianglesMap Map of the original and destination triangles. */ private HashMap trianglesMap; /** * trianglesToKeysMap Map of a original triangles and associated * AffineTransformation Objects. */ private HashMap trianglesToKeysMap; /** * Creates the transformation from specified pairs of points and * quadrilateral that deffines the area of transformation. * * * * @param vectors list of {@linkplain org.geotools.referencing.operation.builder.MappedPosition MappedPosition} * * @throws MismatchedSizeException * @throws MismatchedDimensionException * @throws MismatchedReferenceSystemException * @throws TriangulationException */ public RubberSheetBuilder(List vectors, Quadrilateral quad) throws MismatchedSizeException, MismatchedDimensionException, MismatchedReferenceSystemException, TriangulationException { super.setMappedPositions(vectors); checkQuad(quad); //Quadrilateral mQuad = mappedQuad(quad, vectors); MapTriangulationFactory trianglemap = new MapTriangulationFactory(quad, vectors); this.trianglesMap = (HashMap) trianglemap.getTriangleMap(); this.trianglesToKeysMap = mapTrianglesToKey(); } /** * Returns the minimum number of points required by this builder. * * @return 1 */ public int getMinimumPointCount() { return 1; } /** * Checks the Coordinate Reference System of the quad. * * @param quad to be tested * * @throws MismatchedReferenceSystemException */ private void checkQuad(Quadrilateral quad) throws MismatchedReferenceSystemException { CoordinateReferenceSystem crs; try { crs = getSourceCRS(); } catch (FactoryException e) { // Can't fetch the CRS. Use the one from the first quad point instead. crs = quad.p0.getCoordinateReferenceSystem(); } if ((quad.p0.getCoordinateReferenceSystem() != crs) || (quad.p1.getCoordinateReferenceSystem() != crs) || (quad.p2.getCoordinateReferenceSystem() != crs) || (quad.p3.getCoordinateReferenceSystem() != crs)) { throw new MismatchedReferenceSystemException( "Wrong Coordinate Reference System of the quad."); } } /** * Returns the map of source and destination triangles. * * @return The Map of source and destination triangles. */ public HashMap getMapTriangulation() { return trianglesMap; } /** * Calculates affine transformation prameters from the pair of * triagles. * * @return The HashMap where the keys are the original triangles and values * are AffineTransformation Objects. */ private HashMap mapTrianglesToKey() { AffineTransformBuilder calculator; HashMap trianglesToKeysMap = (HashMap) trianglesMap.clone(); Iterator it = trianglesToKeysMap.entrySet().iterator(); while (it.hasNext()) { Map.Entry a = (Map.Entry) it.next(); List pts = new ArrayList(); for (int i = 1; i <= 3; i++) { pts.add(new MappedPosition( ((TINTriangle) a.getKey()).getPoints()[i], ((TINTriangle) a.getValue()).getPoints()[i])); } try { calculator = new AffineTransformBuilder(pts); a.setValue(calculator.getMathTransform()); } catch (Exception e) { // should never reach here because AffineTransformBuilder(pts) // should not throw any Exception. e.printStackTrace(); } } return trianglesToKeysMap; } /** * Returns MathTransform transformation setup as RubberSheet. * * @return calculated MathTransform * * @throws FactoryException when the size of source and destination point * is not the same. */ protected MathTransform computeMathTransform() throws FactoryException { return new RubberSheetTransform(trianglesToKeysMap); } }