001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: *
005: * (C) 2003-2006, Geotools Project Managment Committee (PMC)
006: * (C) 2001, Institut de Recherche pour le Développement
007: *
008: * This library is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU Lesser General Public
010: * License as published by the Free Software Foundation; either
011: * version 2.1 of the License, or (at your option) any later version.
012: *
013: * This library is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
016: * Lesser General Public License for more details.
017: */
018: package org.geotools.referencing.operation.transform;
019:
020: // J2SE dependencies
021: import java.awt.Rectangle;
022: import java.awt.geom.Point2D;
023: import java.awt.geom.Rectangle2D;
024: import java.awt.image.RasterFormatException;
025:
026: // JAI dependencies
027: import javax.media.jai.Warp;
028:
029: // OpenGIS dependencies
030: import org.opengis.referencing.operation.MathTransform2D;
031: import org.opengis.referencing.operation.TransformException;
032:
033: // Geotools dependencies
034: import org.geotools.resources.i18n.Errors;
035: import org.geotools.resources.i18n.ErrorKeys;
036:
037: /**
038: * Wraps an arbitrary {@link MathTransform2D} into an image warp operation.
039: * This warp operation is used by {@link org.geotools.coverage.processing.operation.Resample}
040: * when no standard warp operation has been found applicable.
041: *
042: * @since 2.1
043: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/WarpAdapter.java $
044: * @version $Id: WarpAdapter.java 22482 2006-10-31 02:58:00Z desruisseaux $
045: * @author Martin Desruisseaux
046: */
047: final class WarpAdapter extends Warp {
048: /**
049: * The coverage name. Used for formatting error message.
050: */
051: private final CharSequence name;
052:
053: /**
054: * The <strong>inverse</strong> of the transform to apply for projecting an image.
055: * This transform maps destination pixels to source pixels.
056: */
057: private final MathTransform2D inverse;
058:
059: /**
060: * Constructs a new {@code WarpAdapter} using the given transform.
061: *
062: * @param name The coverage name. Used for formatting error message.
063: * @param inverse The <strong>inverse</strong> of the transformation to apply for projecting
064: * an image. This inverse transform maps destination pixels to source pixels.
065: */
066: public WarpAdapter(final CharSequence name,
067: final MathTransform2D inverse) {
068: this .name = name;
069: this .inverse = inverse;
070: }
071:
072: /**
073: * Returns the transform from image's destination pixels to source pixels.
074: */
075: public MathTransform2D getTransform() {
076: return inverse;
077: }
078:
079: /**
080: * Computes the source pixel positions for a given rectangular
081: * destination region, subsampled with an integral period.
082: */
083: public float[] warpSparseRect(final int xmin, final int ymin,
084: final int width, final int height, final int periodX,
085: final int periodY, float[] destRect) {
086: if (periodX < 1)
087: throw new IllegalArgumentException(String.valueOf(periodX));
088: if (periodY < 1)
089: throw new IllegalArgumentException(String.valueOf(periodY));
090:
091: final int xmax = xmin + width;
092: final int ymax = ymin + height;
093: final int count = ((width + (periodX - 1)) / periodX)
094: * ((height + (periodY - 1)) / periodY);
095: if (destRect == null) {
096: destRect = new float[2 * count];
097: }
098: int index = 0;
099: for (int y = ymin; y < ymax; y += periodY) {
100: for (int x = xmin; x < xmax; x += periodX) {
101: destRect[index++] = x + 0.5f;
102: destRect[index++] = y + 0.5f;
103: }
104: }
105: try {
106: inverse.transform(destRect, 0, destRect, 0, count);
107: } catch (TransformException exception) {
108: // At least one transformation failed. In Geotools MapProjection
109: // implementation, unprojected coordinates are set to (NaN,NaN).
110: RasterFormatException e = new RasterFormatException(Errors
111: .format(ErrorKeys.CANT_REPROJECT_$1, name));
112: e.initCause(exception);
113: throw e;
114: }
115: while (--index >= 0) {
116: destRect[index] -= 0.5f;
117: }
118: return destRect;
119: }
120:
121: /**
122: * Computes the source point corresponding to the supplied point.
123: *
124: * @param destPt The position in destination image coordinates
125: * to map to source image coordinates.
126: */
127: public Point2D mapDestPoint(final Point2D destPt) {
128: Point2D result = new Point2D.Double(destPt.getX() + 0.5, destPt
129: .getY() + 0.5);
130: try {
131: result = inverse.transform(result, result);
132: } catch (TransformException exception) {
133: IllegalArgumentException e = new IllegalArgumentException(
134: Errors.format(ErrorKeys.BAD_PARAMETER_$2, "destPt",
135: destPt));
136: e.initCause(exception);
137: throw e;
138: }
139: result.setLocation(result.getX() - 0.5, result.getY() - 0.5);
140: return result;
141: }
142:
143: /**
144: * Computes the destination point corresponding to the supplied point.
145: *
146: * @param sourcePt The position in source image coordinates
147: * to map to destination image coordinates.
148: */
149: public Point2D mapSourcePoint(final Point2D sourcePt) {
150: Point2D result = new Point2D.Double(sourcePt.getX() + 0.5,
151: sourcePt.getY() + 0.5);
152: try {
153: result = ((MathTransform2D) inverse.inverse()).transform(
154: result, result);
155: } catch (TransformException exception) {
156: IllegalArgumentException e = new IllegalArgumentException(
157: Errors.format(ErrorKeys.BAD_PARAMETER_$2,
158: "sourcePt", sourcePt));
159: e.initCause(exception);
160: throw e;
161: }
162: result.setLocation(result.getX() - 0.5, result.getY() - 0.5);
163: return result;
164: }
165: }
|