/*
* JGrass - Free Open Source Java GIS http://www.jgrass.org
* (C) HydroloGIS - www.hydrologis.com
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Library General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option) any
* later version.
*
* 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 Library General Public License for more
* details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; if not, write to the Free Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jgrasstools.gears.modules.r.transformer;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_AUTHORCONTACTS;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_AUTHORNAMES;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_DOCUMENTATION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_KEYWORDS;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_LABEL;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_LICENSE;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_NAME;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_STATUS;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_DO_FLIP_HORIZONTAL_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_DO_FLIP_VERTICAL_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_IN_RASTER_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_OUT_BOUNDS_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_OUT_RASTER_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_ANGLE_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_EAST_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_INTERPOLATION_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_NORTH_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_SCALE_X_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_SCALE_Y_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_TRANS_X_DESCRIPTION;
import static org.jgrasstools.gears.i18n.GearsMessages.OMSRASTERTRANSFORMER_P_TRANS_Y_DESCRIPTION;
import static org.jgrasstools.gears.libs.modules.Variables.BICUBIC;
import static org.jgrasstools.gears.libs.modules.Variables.BILINEAR;
import static org.jgrasstools.gears.libs.modules.Variables.NEAREST_NEIGHTBOUR;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.EAST;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.NORTH;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.SOUTH;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.WEST;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.XRES;
import static org.jgrasstools.gears.utils.coverage.CoverageUtilities.YRES;
import java.awt.geom.AffineTransform;
import java.awt.image.RenderedImage;
import javax.media.jai.Interpolation;
import javax.media.jai.RenderedOp;
import javax.media.jai.operator.RotateDescriptor;
import javax.media.jai.operator.ScaleDescriptor;
import javax.media.jai.operator.TranslateDescriptor;
import javax.media.jai.operator.TransposeDescriptor;
import oms3.annotations.Author;
import oms3.annotations.Description;
import oms3.annotations.Documentation;
import oms3.annotations.Execute;
import oms3.annotations.In;
import oms3.annotations.Keywords;
import oms3.annotations.Label;
import oms3.annotations.License;
import oms3.annotations.Name;
import oms3.annotations.Out;
import oms3.annotations.Status;
import oms3.annotations.UI;
import oms3.annotations.Unit;
import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.geometry.Envelope2D;
import org.geotools.geometry.jts.JTS;
import org.geotools.referencing.operation.transform.AffineTransform2D;
import org.jgrasstools.gears.libs.modules.JGTConstants;
import org.jgrasstools.gears.libs.modules.JGTModel;
import org.jgrasstools.gears.libs.monitor.IJGTProgressMonitor;
import org.jgrasstools.gears.utils.RegionMap;
import org.jgrasstools.gears.utils.coverage.CoverageUtilities;
import org.jgrasstools.gears.utils.features.FeatureUtilities;
import org.jgrasstools.gears.utils.geometry.GeometryUtilities;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
@Description(OMSRASTERTRANSFORMER_DESCRIPTION)
@Documentation(OMSRASTERTRANSFORMER_DOCUMENTATION)
@Author(name = OMSRASTERTRANSFORMER_AUTHORNAMES, contact = OMSRASTERTRANSFORMER_AUTHORCONTACTS)
@Keywords(OMSRASTERTRANSFORMER_KEYWORDS)
@Label(OMSRASTERTRANSFORMER_LABEL)
@Name(OMSRASTERTRANSFORMER_NAME)
@Status(OMSRASTERTRANSFORMER_STATUS)
@License(OMSRASTERTRANSFORMER_LICENSE)
public class OmsRasterTransformer extends JGTModel {
@Description(OMSRASTERTRANSFORMER_IN_RASTER_DESCRIPTION)
@In
public GridCoverage2D inRaster;
@Description(OMSRASTERTRANSFORMER_P_INTERPOLATION_DESCRIPTION)
@UI("combo:" + NEAREST_NEIGHTBOUR + "," + BILINEAR + "," + BICUBIC)
@In
public String pInterpolation = NEAREST_NEIGHTBOUR;
@Description(OMSRASTERTRANSFORMER_P_TRANS_X_DESCRIPTION)
@Unit("m")
@In
public Double pTransX;
@Description(OMSRASTERTRANSFORMER_P_TRANS_Y_DESCRIPTION)
@Unit("m")
@In
public Double pTransY;
@Description(OMSRASTERTRANSFORMER_P_SCALE_X_DESCRIPTION)
@In
public Double pScaleX;
@Description(OMSRASTERTRANSFORMER_P_SCALE_Y_DESCRIPTION)
@In
public Double pScaleY;
@Description(OMSRASTERTRANSFORMER_DO_FLIP_HORIZONTAL_DESCRIPTION)
@In
public boolean doFlipHorizontal;
@Description(OMSRASTERTRANSFORMER_DO_FLIP_VERTICAL_DESCRIPTION)
@In
public boolean doFlipVertical;
@Description(OMSRASTERTRANSFORMER_P_NORTH_DESCRIPTION)
@UI(JGTConstants.NORTHING_UI_HINT)
@In
public Double pNorth;
@Description(OMSRASTERTRANSFORMER_P_EAST_DESCRIPTION)
@UI(JGTConstants.EASTING_UI_HINT)
@In
public Double pEast;
@Description(OMSRASTERTRANSFORMER_P_ANGLE_DESCRIPTION)
@Unit("degrees")
@In
public Double pAngle;
@Description(OMSRASTERTRANSFORMER_OUT_RASTER_DESCRIPTION)
@Out
public GridCoverage2D outRaster = null;
@Description(OMSRASTERTRANSFORMER_OUT_BOUNDS_DESCRIPTION)
@Out
public SimpleFeatureCollection outBounds = null;
@Execute
public void process() throws Exception {
if (!concatOr(outRaster == null, doReset)) {
return;
}
Interpolation interpolation = Interpolation.getInstance(Interpolation.INTERP_NEAREST);
if (pInterpolation.equals(BILINEAR)) {
interpolation = Interpolation.getInstance(Interpolation.INTERP_BILINEAR);
} else if (pInterpolation.equals(BICUBIC)) {
interpolation = Interpolation.getInstance(Interpolation.INTERP_BICUBIC);
}
RenderedImage inRasterRI = inRaster.getRenderedImage();
RegionMap sourceRegion = CoverageUtilities.gridGeometry2RegionParamsMap(inRaster.getGridGeometry());
Envelope2D envelope2d = inRaster.getEnvelope2D();
Envelope targetEnvelope = new Envelope(envelope2d.getMinX(), envelope2d.getMaxX(), envelope2d.getMinY(),
envelope2d.getMaxY());
Geometry targetGeometry = null;
GeometryFactory gf = GeometryUtilities.gf();
RenderedOp finalImg = null;
if (pAngle != null) {
pm.beginTask("Rotate raster by angle: " + pAngle, IJGTProgressMonitor.UNKNOWN);
float centerX = 0f;
float centerY = 0f;
if (pEast == null) {
centerX = (float) envelope2d.getCenterX();
} else {
centerX = pEast.floatValue();
}
if (pNorth == null) {
centerY = (float) envelope2d.getCenterY();
} else {
centerY = pNorth.floatValue();
}
finalImg = RotateDescriptor.create(inRasterRI, centerX, centerY, (float) Math.toRadians(pAngle), interpolation, null,
null);
// also keep track of the transforming envelope
AffineTransform rotationAT = new AffineTransform();
rotationAT.translate(centerX, centerY);
rotationAT.rotate(Math.toRadians(-pAngle));
rotationAT.translate(-centerX, -centerY);
MathTransform rotationTransform = new AffineTransform2D(rotationAT);
Envelope jtsEnv = new Envelope(targetEnvelope.getMinX(), targetEnvelope.getMaxX(), targetEnvelope.getMinY(),
targetEnvelope.getMaxY());
targetEnvelope = JTS.transform(jtsEnv, rotationTransform);
Geometry rotGeometry = gf.toGeometry(jtsEnv);
targetGeometry = JTS.transform(rotGeometry, rotationTransform);
pm.done();
}
if (doFlipHorizontal) {
pm.beginTask("Flip horizontally...", IJGTProgressMonitor.UNKNOWN);
if (finalImg != null) {
finalImg = TransposeDescriptor.create(finalImg, TransposeDescriptor.FLIP_HORIZONTAL, null);
} else {
finalImg = TransposeDescriptor.create(inRasterRI, TransposeDescriptor.FLIP_HORIZONTAL, null);
}
Envelope jtsEnv = new Envelope(targetEnvelope.getMinX(), targetEnvelope.getMaxX(), targetEnvelope.getMinY(),
targetEnvelope.getMaxY());
targetGeometry = gf.toGeometry(jtsEnv);
pm.done();
}
if (doFlipVertical) {
pm.beginTask("Flip vertically...", IJGTProgressMonitor.UNKNOWN);
if (finalImg != null) {
finalImg = TransposeDescriptor.create(finalImg, TransposeDescriptor.FLIP_VERTICAL, null);
} else {
finalImg = TransposeDescriptor.create(inRasterRI, TransposeDescriptor.FLIP_VERTICAL, null);
}
Envelope jtsEnv = new Envelope(targetEnvelope.getMinX(), targetEnvelope.getMaxX(), targetEnvelope.getMinY(),
targetEnvelope.getMaxY());
targetGeometry = gf.toGeometry(jtsEnv);
pm.done();
}
if (pScaleX != null || pScaleY != null) {
float scaleX = 1f;
float scaleY = 1f;
if (pScaleX == null) {
scaleX = 1f;
} else {
scaleX = pScaleX.floatValue();
}
if (pScaleY == null) {
scaleY = 1f;
} else {
scaleY = pScaleY.floatValue();
}
pm.beginTask("Scale raster by: " + scaleX + " and " + scaleY, IJGTProgressMonitor.UNKNOWN);
// float centerX = (float) envelope2d.getCenterX();
// float centerY = (float) envelope2d.getCenterY();
if (finalImg != null) {
finalImg = ScaleDescriptor.create(finalImg, new Float(scaleX), new Float(scaleY), new Float(0.0f),
new Float(0.0f), interpolation, null);
} else {
finalImg = ScaleDescriptor.create(inRasterRI, new Float(scaleX), new Float(scaleY), new Float(0.0f), new Float(
0.0f), interpolation, null);
}
// also keep track of the transforming envelope
AffineTransform scaleAT = new AffineTransform();
// scaleAT.translate(centerX, centerY);
scaleAT.scale(scaleX, scaleY);
// scaleAT.translate(-centerX, -centerY);
MathTransform scaleTransform = new AffineTransform2D(scaleAT);
Envelope jtsEnv = new Envelope(targetEnvelope.getMinX(), targetEnvelope.getMaxX(), targetEnvelope.getMinY(),
targetEnvelope.getMaxY());
targetEnvelope = JTS.transform(jtsEnv, scaleTransform);
Geometry scaledGeometry = gf.toGeometry(jtsEnv);
targetGeometry = JTS.transform(scaledGeometry, scaleTransform);
pm.done();
}
if (pTransX != null || pTransY != null) {
float transX = 1f;
float transY = 1f;
if (pTransX == null) {
transX = 1f;
} else {
transX = pTransX.floatValue();
}
if (pTransY == null) {
transY = 1f;
} else {
transY = pTransY.floatValue();
}
pm.beginTask("Translate raster by: " + transX + " and " + transY, IJGTProgressMonitor.UNKNOWN);
if (finalImg != null) {
finalImg = TranslateDescriptor.create(finalImg, transX, transY, interpolation, null);
} else {
finalImg = TranslateDescriptor.create(inRasterRI, transX, transY, interpolation, null);
}
// also keep track of the transforming envelope
AffineTransform translationAT = new AffineTransform();
translationAT.translate(transX, transY);
MathTransform translateTransform = new AffineTransform2D(translationAT);
if (targetGeometry == null) {
targetGeometry = gf.toGeometry(targetEnvelope);
}
targetEnvelope = JTS.transform(targetEnvelope, translateTransform);
targetGeometry = JTS.transform(targetGeometry, translateTransform);
pm.done();
}
if (finalImg != null) {
RegionMap targetRegion = new RegionMap();
targetRegion.put(NORTH, targetEnvelope.getMaxY());
targetRegion.put(SOUTH, targetEnvelope.getMinY());
targetRegion.put(WEST, targetEnvelope.getMinX());
targetRegion.put(EAST, targetEnvelope.getMaxX());
targetRegion.put(XRES, sourceRegion.getXres());
targetRegion.put(YRES, sourceRegion.getYres());
// targetRegion.put(ROWS, (double) height);
// targetRegion.put(COLS, (double) width);
CoordinateReferenceSystem crs = inRaster.getCoordinateReferenceSystem();
outRaster = CoverageUtilities.buildCoverage("out", finalImg, targetRegion, crs);
outBounds = FeatureUtilities.featureCollectionFromGeometry(crs, targetGeometry);
}
pm.done();
}
}