Merge "Issue #3030 Avoid GeoTools Resampler2D infinite recursion." into development
Former-commit-id:8f3b8c9bdf
[formerlydd362ec359
] [formerlyc2a1533ff8
] [formerly8f3b8c9bdf
[formerlydd362ec359
] [formerlyc2a1533ff8
] [formerly536ec2790a
[formerlyc2a1533ff8
[formerly a74c24200e9911ff4f2023d9fb1be77516b4c09a]]]] Former-commit-id:536ec2790a
Former-commit-id:91a90d44e0
[formerly4ac5fd90f4
] [formerly c6dab31639d3dfc9ab7163fe5b8b72ec9ca0af2a [formerlyd34a8c9753
]] Former-commit-id: 39503eb1283387f8ca31dae05fbc0c70830cc1a6 [formerlyc0f6a951c4
] Former-commit-id:c7378e6125
This commit is contained in:
commit
bcc66dc18e
3 changed files with 73 additions and 194 deletions
|
@ -19,21 +19,28 @@
|
||||||
**/
|
**/
|
||||||
package com.raytheon.viz.grid.data;
|
package com.raytheon.viz.grid.data;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
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.Request;
|
||||||
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
|
import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
|
||||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
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.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.common.time.DataTime;
|
||||||
import com.raytheon.uf.viz.core.exception.VizException;
|
import com.raytheon.uf.viz.core.exception.VizException;
|
||||||
import com.raytheon.viz.grid.util.CoverageUtils;
|
|
||||||
import com.raytheon.viz.grid.util.SliceUtil;
|
import com.raytheon.viz.grid.util.SliceUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,6 +76,7 @@ public class ImportRequestableData extends AliasRequestableData {
|
||||||
this.dataTime = dataTime;
|
this.dataTime = dataTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public Object getDataValue(Object arg) throws DataCubeException {
|
public Object getDataValue(Object arg) throws DataCubeException {
|
||||||
Request req = Request.ALL;
|
Request req = Request.ALL;
|
||||||
if (arg instanceof Request) {
|
if (arg instanceof Request) {
|
||||||
|
@ -87,26 +95,26 @@ public class ImportRequestableData extends AliasRequestableData {
|
||||||
float w2 = (millis2 - dataTime.getValidTime().getTimeInMillis())
|
float w2 = (millis2 - dataTime.getValidTime().getTimeInMillis())
|
||||||
/ w1;
|
/ w1;
|
||||||
w1 = 1 - w2;
|
w1 = 1 - w2;
|
||||||
if (rval instanceof FloatDataRecord
|
if ((rval instanceof FloatDataRecord)
|
||||||
&& interp2 instanceof FloatDataRecord) {
|
&& (interp2 instanceof FloatDataRecord)) {
|
||||||
// multiply in place so rval will hold correct value after
|
// multiply in place so rval will hold correct value after
|
||||||
// calculation
|
// calculation
|
||||||
interpolate(((FloatDataRecord) rval).getFloatData(),
|
interpolate(((FloatDataRecord) rval).getFloatData(),
|
||||||
((FloatDataRecord) interp2).getFloatData(), w2, w1);
|
((FloatDataRecord) interp2).getFloatData(), w2, w1);
|
||||||
} else if (rval instanceof FloatDataRecord[]
|
} else if ((rval instanceof FloatDataRecord[])
|
||||||
&& interp2 instanceof FloatDataRecord) {
|
&& (interp2 instanceof FloatDataRecord)) {
|
||||||
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
|
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
|
||||||
FloatDataRecord[] recs2 = (FloatDataRecord[]) interp2;
|
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(),
|
interpolate(recs[i].getFloatData(),
|
||||||
recs2[i].getFloatData(), w2, w1);
|
recs2[i].getFloatData(), w2, w1);
|
||||||
}
|
}
|
||||||
} else if (rval instanceof IDataRecord[]) {
|
} else if (rval instanceof IDataRecord[]) {
|
||||||
IDataRecord[] recs = (IDataRecord[]) rval;
|
IDataRecord[] recs = (IDataRecord[]) rval;
|
||||||
IDataRecord[] recs2 = (IDataRecord[]) interp2;
|
IDataRecord[] recs2 = (IDataRecord[]) interp2;
|
||||||
for (int i = 0; i < recs.length && i < recs2.length; i++) {
|
for (int i = 0; (i < recs.length) && (i < recs2.length); i++) {
|
||||||
if (recs[i] instanceof FloatDataRecord
|
if ((recs[i] instanceof FloatDataRecord)
|
||||||
&& recs2[i] instanceof FloatDataRecord) {
|
&& (recs2[i] instanceof FloatDataRecord)) {
|
||||||
interpolate(((FloatDataRecord) recs[i]).getFloatData(),
|
interpolate(((FloatDataRecord) recs[i]).getFloatData(),
|
||||||
((FloatDataRecord) recs2[i]).getFloatData(),
|
((FloatDataRecord) recs2[i]).getFloatData(),
|
||||||
w2, w1);
|
w2, w1);
|
||||||
|
@ -115,32 +123,27 @@ public class ImportRequestableData extends AliasRequestableData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CoverageUtils covUtil = CoverageUtils.getInstance();
|
|
||||||
GridCoverage sourceGrid = (GridCoverage) sourceRecord.getSpace();
|
GridCoverage sourceGrid = (GridCoverage) sourceRecord.getSpace();
|
||||||
GridCoverage destGrid = (GridCoverage) getSpace();
|
GridCoverage destGrid = (GridCoverage) getSpace();
|
||||||
Interpolation interpolation = Interpolation
|
Interpolation interpolation = new BicubicInterpolation();
|
||||||
.getInstance(Interpolation.INTERP_BICUBIC);
|
|
||||||
try {
|
try {
|
||||||
if (rval instanceof FloatDataRecord) {
|
if (rval instanceof FloatDataRecord) {
|
||||||
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid, destGrid,
|
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
|
||||||
(FloatDataRecord) rval, interpolation)
|
(FloatDataRecord) rval, interpolation);
|
||||||
.getFloatDataRecord();
|
|
||||||
rval = SliceUtil.slice(fdr, req);
|
rval = SliceUtil.slice(fdr, req);
|
||||||
} else if (rval instanceof FloatDataRecord[]) {
|
} else if (rval instanceof FloatDataRecord[]) {
|
||||||
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
|
FloatDataRecord[] recs = (FloatDataRecord[]) rval;
|
||||||
for (int i = 0; i < recs.length; i++) {
|
for (int i = 0; i < recs.length; i++) {
|
||||||
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid,
|
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
|
||||||
destGrid, recs[i], interpolation)
|
recs[i], interpolation);
|
||||||
.getFloatDataRecord();
|
|
||||||
recs[i] = SliceUtil.slice(fdr, req);
|
recs[i] = SliceUtil.slice(fdr, req);
|
||||||
}
|
}
|
||||||
} else if (rval instanceof IDataRecord[]) {
|
} else if (rval instanceof IDataRecord[]) {
|
||||||
IDataRecord[] recs = (IDataRecord[]) rval;
|
IDataRecord[] recs = (IDataRecord[]) rval;
|
||||||
for (int i = 0; i < recs.length; i++) {
|
for (int i = 0; i < recs.length; i++) {
|
||||||
if (recs[i] instanceof FloatDataRecord) {
|
if (recs[i] instanceof FloatDataRecord) {
|
||||||
FloatDataRecord fdr = covUtil.remapGrid(sourceGrid,
|
FloatDataRecord fdr = remapGrid(sourceGrid, destGrid,
|
||||||
destGrid, (FloatDataRecord) recs[i],
|
(FloatDataRecord) recs[i], interpolation);
|
||||||
interpolation).getFloatDataRecord();
|
|
||||||
recs[i] = SliceUtil.slice(fdr, req);
|
recs[i] = SliceUtil.slice(fdr, req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,6 +155,50 @@ public class ImportRequestableData extends AliasRequestableData {
|
||||||
return rval;
|
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 *
|
* Performs the following calc in place at arr1: arr1 = arr1 * val1 + arr2 *
|
||||||
* val2
|
* val2
|
||||||
|
@ -165,7 +212,7 @@ public class ImportRequestableData extends AliasRequestableData {
|
||||||
float val2) {
|
float val2) {
|
||||||
if (arr1.length == arr2.length) {
|
if (arr1.length == arr2.length) {
|
||||||
for (int i = 0; i < arr1.length; i++) {
|
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 {
|
} else {
|
||||||
// world implodes
|
// 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
|
* 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