Issue #3030 Avoid GeoTools Resampler2D infinite recursion.
Change-Id: Ie2dc0a66e8f15648b1a76a0d54efb36795223345 Former-commit-id:76c5bb67a5
[formerly76c5bb67a5
[formerly 123ddd451854e93063f518b0ece746b1109df9d1]] Former-commit-id:d7e6ab67d6
Former-commit-id:8583e0fb64
This commit is contained in:
parent
db4bb7b6c6
commit
281ffc1ecc
3 changed files with 73 additions and 194 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue