Issue #3030 Avoid GeoTools Resampler2D infinite recursion.

Change-Id: Ie2dc0a66e8f15648b1a76a0d54efb36795223345

Former-commit-id: 76c5bb67a5 [formerly 76c5bb67a5 [formerly 123ddd451854e93063f518b0ece746b1109df9d1]]
Former-commit-id: d7e6ab67d6
Former-commit-id: 8583e0fb64
This commit is contained in:
Ron Anderson 2014-04-18 10:31:16 -05:00
parent db4bb7b6c6
commit 281ffc1ecc
3 changed files with 73 additions and 194 deletions

View file

@ -19,21 +19,28 @@
**/
package com.raytheon.viz.grid.data;
import java.nio.FloatBuffer;
import java.util.Arrays;
import java.util.List;
import javax.media.jai.Interpolation;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.data.AliasRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.datastorage.Request;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
import com.raytheon.uf.common.datastorage.records.IDataRecord;
import com.raytheon.uf.common.geospatial.data.GeographicDataSource;
import com.raytheon.uf.common.geospatial.interpolation.BicubicInterpolation;
import com.raytheon.uf.common.geospatial.interpolation.GridReprojection;
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
import com.raytheon.uf.common.geospatial.interpolation.PrecomputedGridReprojection;
import com.raytheon.uf.common.gridcoverage.GridCoverage;
import com.raytheon.uf.common.inventory.data.AbstractRequestableData;
import com.raytheon.uf.common.inventory.data.AliasRequestableData;
import com.raytheon.uf.common.inventory.exception.DataCubeException;
import com.raytheon.uf.common.numeric.buffer.FloatBufferWrapper;
import com.raytheon.uf.common.numeric.source.DataSource;
import com.raytheon.uf.common.time.DataTime;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.viz.grid.util.CoverageUtils;
import com.raytheon.viz.grid.util.SliceUtil;
/**
@ -69,6 +76,7 @@ public class ImportRequestableData extends AliasRequestableData {
this.dataTime = dataTime;
}
@Override
public Object getDataValue(Object arg) throws DataCubeException {
Request req = Request.ALL;
if (arg instanceof Request) {
@ -87,26 +95,26 @@ public class ImportRequestableData extends AliasRequestableData {
float w2 = (millis2 - dataTime.getValidTime().getTimeInMillis())
/ w1;
w1 = 1 - w2;
if (rval instanceof FloatDataRecord
&& interp2 instanceof FloatDataRecord) {
if ((rval instanceof FloatDataRecord)
&& (interp2 instanceof FloatDataRecord)) {
// multiply in place so rval will hold correct value after
// calculation
interpolate(((FloatDataRecord) rval).getFloatData(),
((FloatDataRecord) interp2).getFloatData(), w2, w1);
} else if (rval instanceof FloatDataRecord[]
&& interp2 instanceof FloatDataRecord) {
} else if ((rval instanceof FloatDataRecord[])
&& (interp2 instanceof FloatDataRecord)) {
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
FloatDataRecord[] recs2 = (FloatDataRecord[]) interp2;
for (int i = 0; i < recs.length && i < recs2.length; i++) {
for (int i = 0; (i < recs.length) && (i < recs2.length); i++) {
interpolate(recs[i].getFloatData(),
recs2[i].getFloatData(), w2, w1);
}
} else if (rval instanceof IDataRecord[]) {
IDataRecord[] recs = (IDataRecord[]) rval;
IDataRecord[] recs2 = (IDataRecord[]) interp2;
for (int i = 0; i < recs.length && i < recs2.length; i++) {
if (recs[i] instanceof FloatDataRecord
&& recs2[i] instanceof FloatDataRecord) {
for (int i = 0; (i < recs.length) && (i < recs2.length); i++) {
if ((recs[i] instanceof FloatDataRecord)
&& (recs2[i] instanceof FloatDataRecord)) {
interpolate(((FloatDataRecord) recs[i]).getFloatData(),
((FloatDataRecord) recs2[i]).getFloatData(),
w2, w1);
@ -115,32 +123,27 @@ public class ImportRequestableData extends AliasRequestableData {
}
}
CoverageUtils covUtil = CoverageUtils.getInstance();
GridCoverage sourceGrid = (GridCoverage) sourceRecord.getSpace();
GridCoverage destGrid = (GridCoverage) getSpace();
Interpolation interpolation = Interpolation
.getInstance(Interpolation.INTERP_BICUBIC);
Interpolation interpolation = new BicubicInterpolation();
try {
if (rval instanceof FloatDataRecord) {
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid, destGrid,
(FloatDataRecord) rval, interpolation)
.getFloatDataRecord();
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
(FloatDataRecord) rval, interpolation);
rval = SliceUtil.slice(fdr, req);
} else if (rval instanceof FloatDataRecord[]) {
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
for (int i = 0; i < recs.length; i++) {
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid,
destGrid, recs[i], interpolation)
.getFloatDataRecord();
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
recs[i], interpolation);
recs[i] = SliceUtil.slice(fdr, req);
}
} else if (rval instanceof IDataRecord[]) {
IDataRecord[] recs = (IDataRecord[]) rval;
for (int i = 0; i < recs.length; i++) {
if (recs[i] instanceof FloatDataRecord) {
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid,
destGrid, (FloatDataRecord) recs[i],
interpolation).getFloatDataRecord();
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
(FloatDataRecord) recs[i], interpolation);
recs[i] = SliceUtil.slice(fdr, req);
}
}
@ -152,6 +155,50 @@ public class ImportRequestableData extends AliasRequestableData {
return rval;
}
/**
* remap gridded data to a new grid coverage
*
* @param sourceGrid
* source grid coverage
* @param destGrid
* destination grid coverage
* @param fdr
* source float data record
* @param interpolation
* interpolation algorithm
* @return destination float data record
* @throws VizException
*/
protected FloatDataRecord remapGrid(GridCoverage sourceGrid,
GridCoverage destGrid, FloatDataRecord fdr,
Interpolation interpolation) throws VizException {
try {
GridGeometry2D sourceGeometry = sourceGrid.getGridGeometry();
GridGeometry2D destGeometry = destGrid.getGridGeometry();
GridReprojection interp = PrecomputedGridReprojection
.getReprojection(sourceGeometry, destGeometry);
DataSource source = new GeographicDataSource(FloatBuffer.wrap(fdr
.getFloatData()), sourceGeometry);
FloatBufferWrapper dest = new FloatBufferWrapper(
destGeometry.getGridRange2D());
interp.reprojectedGrid(interpolation, source, dest);
FloatDataRecord rval = new FloatDataRecord(fdr.getName(),
fdr.getGroup(), dest.getArray(),
destGeometry.getDimension(), new long[] { dest.getNx(),
dest.getNy() });
return rval;
} catch (Exception e) {
throw new VizException(e.getLocalizedMessage(), e);
}
}
/**
* Performs the following calc in place at arr1: arr1 = arr1 * val1 + arr2 *
* val2
@ -165,7 +212,7 @@ public class ImportRequestableData extends AliasRequestableData {
float val2) {
if (arr1.length == arr2.length) {
for (int i = 0; i < arr1.length; i++) {
arr1[i] = arr1[i] * val1 + arr2[i] * val2;
arr1[i] = (arr1[i] * val1) + (arr2[i] * val2);
}
} else {
// world implodes

View file

@ -183,99 +183,6 @@ public class CoverageUtils implements IAlertObserver {
}
}
public RemappedImage remapGrid(GridCoverage sourceGrid,
GridCoverage destinationGrid, FloatDataRecord inputData,
Interpolation interpolation) throws VizException {
if (sourceGrid.getId().equals(destinationGrid.getId())) {
// we don't need to remap anything. the grids are the same
return new RemappedImage(inputData);
}
long[] sizes = inputData.getSizes();
GridCoverage2D inputGC = null;
if (sizes.length == 2) {
// Map the data into an array
GridCoverageFactory factory = new GridCoverageFactory();
Envelope inputEnvelope = sourceGrid.getGridGeometry().getEnvelope();
float[][] dataPoints = new float[(int) sizes[1]][(int) sizes[0]];
float[] dataVals = inputData.getFloatData();
int index = 0;
for (int y = 0; y < sizes[1]; y++) {
for (int x = 0; x < sizes[0]; x++) {
dataPoints[y][x] = dataVals[index++];
// Switch -999999 to NaN?
if (dataPoints[y][x] == -999999) {
dataPoints[y][x] = Float.NaN;
}
}
}
inputGC = factory.create("in", dataPoints, inputEnvelope);
} else {
throw new VizException(
"Failed to reproject coverage. FloatData not a 2d array: "
+ Arrays.toString(sizes));
}
Raster remappedImage = null;
GridCoverage2D croppedGrid;
/*
* Check the CRSs to see if they are the same. If they are, then
* reprojection is not necessary, only resampling
*/
if (sourceGrid.getCrsWKT().equals(destinationGrid.getCrsWKT())
&& sourceGrid.getGeometry().getEnvelope()
.equals(destinationGrid.getGeometry().getEnvelope())) {
float scaleX = (float) ((float) destinationGrid.getNx() / (float) sourceGrid
.getNx());
float scaleY = (float) ((float) destinationGrid.getNy() / (float) sourceGrid
.getNy());
PlanarImage image = scaleGrid(inputGC.getRenderedImage(), scaleX,
scaleY);
remappedImage = image.getData();
} else {
GridGeometry2D destGeom = destinationGrid.getGridGeometry();
// Construct the source grid coverage object
croppedGrid = CoverageUtils.getInstance().cropGrid(inputGC,
destGeom, interpolation);
RenderedImage renderedImage = croppedGrid.getRenderedImage();
try {
MapUtil.jaiMlibWarpPolynomialTableOpImageWorkAround(renderedImage);
} catch (Exception e) {
throw new VizException(
"Unable to successfully apply JAI workaround!", e);
}
remappedImage = renderedImage.getData();
}
// Remap the the output data into a Grid2DFloat object
float[] floatData = null;
int ny = destinationGrid.getNy();
int nx = destinationGrid.getNx();
floatData = remappedImage.getPixels(remappedImage.getMinX(),
remappedImage.getMinY(), nx, ny, floatData);
int size = floatData.length;
for (int i = 0; i < size; i++) {
if (Float.isNaN(floatData[i])) {
floatData[i] = -999999;
}
}
inputData.setFloatData(floatData);
inputData.setSizes(new long[] { nx, ny });
inputData.setDimension(2);
JAI.getDefaultInstance().getTileCache().flush();
return new RemappedImage(inputData, destinationGrid.getGridGeometry());
}
/**
* Resamples the grid to a new resolution using scale values
*

View file

@ -1,75 +0,0 @@
package com.raytheon.viz.grid.util;
import org.geotools.coverage.grid.GridGeometry2D;
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
/**
* Remapped image data and geometry
*
* <pre>
*
* SOFTWARE HISTORY
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Jun 17, 2010 rgeorge Initial creation
*
* </pre>
*
* @author rgeorge
* @version 1.0
*/
public class RemappedImage {
private FloatDataRecord floatDataRecord;
private GridGeometry2D gridGeometry;
/**
* @param floatDataRecord
*/
public RemappedImage(FloatDataRecord floatDataRecord) {
this.floatDataRecord = floatDataRecord;
}
/**
* @param inputData
* @param gridGeometry
*/
public RemappedImage(FloatDataRecord floatDataRecord,
GridGeometry2D gridGeometry) {
this.floatDataRecord = floatDataRecord;
this.gridGeometry = gridGeometry;
}
/**
* @return the floatDataRecord
*/
public FloatDataRecord getFloatDataRecord() {
return floatDataRecord;
}
/**
* @param floatDataRecord
* the floatDataRecord to set
*/
public void setFloatDataRecord(FloatDataRecord floatDataRecord) {
this.floatDataRecord = floatDataRecord;
}
/**
* @return the gridGeometry
*/
public GridGeometry2D getGridGeometry() {
return gridGeometry;
}
/**
* @param gridGeometry
* the gridGeometry to set
*/
public void setGridGeometry(GridGeometry2D gridGeometry) {
this.gridGeometry = gridGeometry;
}
}