Issue #2309 Request subgrids of grib data whenever possible.
Former-commit-id:38fc89ffaa
[formerly c9e8e6a8d6550f41039e2208b50bd053bfef94b8] Former-commit-id:990964ca40
This commit is contained in:
parent
99d1e66925
commit
f061cc71c8
1 changed files with 122 additions and 32 deletions
|
@ -25,9 +25,11 @@ import java.util.Map;
|
||||||
import javax.measure.unit.Unit;
|
import javax.measure.unit.Unit;
|
||||||
|
|
||||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||||
|
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||||
import org.geotools.coverage.grid.GridGeometry2D;
|
import org.geotools.coverage.grid.GridGeometry2D;
|
||||||
import org.geotools.coverage.grid.InvalidGridGeometryException;
|
import org.geotools.coverage.grid.InvalidGridGeometryException;
|
||||||
import org.geotools.geometry.DirectPosition2D;
|
import org.geotools.geometry.DirectPosition2D;
|
||||||
|
import org.geotools.geometry.Envelope2D;
|
||||||
import org.opengis.referencing.FactoryException;
|
import org.opengis.referencing.FactoryException;
|
||||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||||
import org.opengis.referencing.operation.MathTransform;
|
import org.opengis.referencing.operation.MathTransform;
|
||||||
|
@ -37,12 +39,14 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject;
|
||||||
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
|
import com.raytheon.uf.common.dataplugin.grid.GridRecord;
|
||||||
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo;
|
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfo;
|
||||||
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup;
|
import com.raytheon.uf.common.dataplugin.grid.dataset.DatasetInfoLookup;
|
||||||
|
import com.raytheon.uf.common.datastorage.Request;
|
||||||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||||
import com.raytheon.uf.common.geospatial.interpolation.BilinearInterpolation;
|
import com.raytheon.uf.common.geospatial.interpolation.BilinearInterpolation;
|
||||||
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
|
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
|
||||||
import com.raytheon.uf.common.geospatial.interpolation.NearestNeighborInterpolation;
|
import com.raytheon.uf.common.geospatial.interpolation.NearestNeighborInterpolation;
|
||||||
|
import com.raytheon.uf.common.geospatial.util.EnvelopeIntersection;
|
||||||
import com.raytheon.uf.common.gridcoverage.GridCoverage;
|
import com.raytheon.uf.common.gridcoverage.GridCoverage;
|
||||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||||
import com.raytheon.uf.common.status.UFStatus;
|
import com.raytheon.uf.common.status.UFStatus;
|
||||||
|
@ -63,6 +67,8 @@ import com.raytheon.viz.grid.rsc.GridResourceData;
|
||||||
import com.raytheon.viz.grid.util.ConformalityUtil;
|
import com.raytheon.viz.grid.util.ConformalityUtil;
|
||||||
import com.raytheon.viz.grid.xml.FieldDisplayTypesFactory;
|
import com.raytheon.viz.grid.xml.FieldDisplayTypesFactory;
|
||||||
import com.vividsolutions.jts.geom.Coordinate;
|
import com.vividsolutions.jts.geom.Coordinate;
|
||||||
|
import com.vividsolutions.jts.geom.Envelope;
|
||||||
|
import com.vividsolutions.jts.geom.Geometry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -72,15 +78,16 @@ import com.vividsolutions.jts.geom.Coordinate;
|
||||||
*
|
*
|
||||||
* SOFTWARE HISTORY
|
* SOFTWARE HISTORY
|
||||||
*
|
*
|
||||||
* Date Ticket# Engineer Description
|
* Date Ticket# Engineer Description
|
||||||
* ------------ ---------- ----------- --------------------------
|
* ------------- -------- ----------- --------------------------
|
||||||
* Mar 09, 2011 bsteffen Initial creation
|
* Mar 09, 2011 bsteffen Initial creation
|
||||||
* Feb 25, 2013 1659 bsteffen Add PDOs to D2DGridResource in
|
* Feb 25, 2013 1659 bsteffen Add PDOs to D2DGridResource in
|
||||||
* constructor to avoid duplicate data
|
* constructor to avoid duplicate data
|
||||||
* requests.
|
* requests.
|
||||||
* Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows.
|
* Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows.
|
||||||
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error
|
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error
|
||||||
* in Maputil.rotation
|
* in Maputil.rotation
|
||||||
|
* Sep 12, 2013 2309 bsteffen Request subgrids whenever possible.
|
||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
@ -92,7 +99,14 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
||||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||||
.getHandler(D2DGridResource.class);
|
.getHandler(D2DGridResource.class);
|
||||||
|
|
||||||
private boolean reprojectedData = false;
|
/*
|
||||||
|
* Flag indicating if the resource is displaying the full unaltered data or
|
||||||
|
* if some of the data has been modified for the descriptor(such as
|
||||||
|
* reprojection or subgridding). A value of false indicates no
|
||||||
|
* modification. If modification has occured than a reproject will require
|
||||||
|
* requesting the data again so it can be reformatted for the new display.
|
||||||
|
*/
|
||||||
|
private boolean dataModified = false;
|
||||||
|
|
||||||
public D2DGridResource(GridResourceData resourceData,
|
public D2DGridResource(GridResourceData resourceData,
|
||||||
LoadProperties loadProperties) {
|
LoadProperties loadProperties) {
|
||||||
|
@ -134,48 +148,76 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
||||||
protected GeneralGridData getData(GridRecord gridRecord)
|
protected GeneralGridData getData(GridRecord gridRecord)
|
||||||
throws VizException {
|
throws VizException {
|
||||||
Unit<?> dataUnit = gridRecord.getParameter().getUnit();
|
Unit<?> dataUnit = gridRecord.getParameter().getUnit();
|
||||||
// Reqest data for tilts if this is Std Env sampling.
|
GridCoverage location = gridRecord.getLocation();
|
||||||
|
GridGeometry2D gridGeometry = location.getGridGeometry();
|
||||||
|
|
||||||
|
/* Request data for tilts if this is Std Env sampling. */
|
||||||
IDataRecord[] dataRecs = GridResourceData.getDataRecordsForTilt(
|
IDataRecord[] dataRecs = GridResourceData.getDataRecordsForTilt(
|
||||||
gridRecord, descriptor);
|
gridRecord, descriptor);
|
||||||
if (dataRecs == null) {
|
if (dataRecs == null) {
|
||||||
dataRecs = DataCubeContainer.getDataRecord(gridRecord);
|
GridGeometry2D subGridGeometry = calculateSubgrid(gridGeometry);
|
||||||
|
if (subGridGeometry.equals(gridGeometry)) {
|
||||||
|
dataRecs = DataCubeContainer.getDataRecord(gridRecord);
|
||||||
|
} else if (subGridGeometry != null) {
|
||||||
|
/* transform subgrid envelope into a slab request. */
|
||||||
|
GridEnvelope2D subGridRange = subGridGeometry.getGridRange2D();
|
||||||
|
int[] min = { subGridRange.getLow(0), subGridRange.getLow(1) };
|
||||||
|
int[] max = { subGridRange.getHigh(0) + 1,
|
||||||
|
subGridRange.getHigh(1) + 1 };
|
||||||
|
Request request = Request.buildSlab(min, max);
|
||||||
|
dataRecs = DataCubeContainer.getDataRecord(gridRecord, request,
|
||||||
|
null);
|
||||||
|
/*
|
||||||
|
* gridGeometries used in renderables are expected to have min
|
||||||
|
* x,y be 0.
|
||||||
|
*/
|
||||||
|
subGridRange.x = 0;
|
||||||
|
subGridRange.y = 0;
|
||||||
|
gridGeometry = new GridGeometry2D(subGridRange,
|
||||||
|
subGridGeometry.getEnvelope());
|
||||||
|
dataModified = true;
|
||||||
|
}
|
||||||
if (dataRecs == null) {
|
if (dataRecs == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For world wide lat lon grids we reproject, this is done to match A1,
|
|
||||||
// but it also makes the wind barbs look more evenly spaced near the
|
GeneralGridData data = getData(dataRecs, gridGeometry, dataUnit);
|
||||||
// pole.
|
/*
|
||||||
GridCoverage location = gridRecord.getLocation();
|
* For world wide lat lon grids we reproject, this is done to match A1,
|
||||||
GeneralGridData data = getData(dataRecs, location.getGridGeometry(),
|
* but it also makes the wind barbs look more evenly spaced near the
|
||||||
dataUnit);
|
* pole.
|
||||||
|
*/
|
||||||
if (location != null && location.getSpacingUnit().equals("degree")) {
|
if (location != null && location.getSpacingUnit().equals("degree")) {
|
||||||
if (!ConformalityUtil.testConformality(location.getGridGeometry(),
|
if (!ConformalityUtil.testConformality(gridGeometry,
|
||||||
descriptor.getGridGeometry())) {
|
descriptor.getGridGeometry())) {
|
||||||
data = reprojectData(data);
|
data = reprojectData(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Wind Direction(and possibly others) can be set so that we rotate the
|
/*
|
||||||
// direction to be relative to the north pole instead of grid relative.
|
* Wind Direction(and possibly others) can be set so that we rotate the
|
||||||
|
* direction to be relative to the north pole instead of grid relative.
|
||||||
|
*/
|
||||||
if (stylePreferences != null
|
if (stylePreferences != null
|
||||||
&& stylePreferences.getDisplayFlags()
|
&& stylePreferences.getDisplayFlags()
|
||||||
.hasFlag("RotateVectorDir")) {
|
.hasFlag("RotateVectorDir")) {
|
||||||
GridGeometry2D geom = GridGeometry2D.wrap(location
|
GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
|
||||||
.getGridGeometry());
|
MathTransform grid2crs = gridGeometry.getGridToCRS();
|
||||||
MathTransform grid2crs = geom.getGridToCRS();
|
|
||||||
try {
|
try {
|
||||||
MathTransform crs2ll = MapUtil.getTransformToLatLon(geom
|
MathTransform crs2ll = MapUtil
|
||||||
.getCoordinateReferenceSystem());
|
.getTransformToLatLon(gridGeometry
|
||||||
for (int i = 0; i < geom.getGridRange2D().width; i++) {
|
.getCoordinateReferenceSystem());
|
||||||
for (int j = 0; j < geom.getGridRange2D().height; j++) {
|
for (int i = 0; i < gridRange.width; i++) {
|
||||||
int index = i + j * geom.getGridRange2D().width;
|
for (int j = 0; j < gridRange.height; j++) {
|
||||||
|
int index = i + j * gridRange.width;
|
||||||
float dir = data.getScalarData().get(index);
|
float dir = data.getScalarData().get(index);
|
||||||
if (dir > -9999) {
|
if (dir > -9999) {
|
||||||
DirectPosition2D dp = new DirectPosition2D(i, j);
|
DirectPosition2D dp = new DirectPosition2D(i, j);
|
||||||
grid2crs.transform(dp, dp);
|
grid2crs.transform(dp, dp);
|
||||||
crs2ll.transform(dp, dp);
|
crs2ll.transform(dp, dp);
|
||||||
Coordinate ll = new Coordinate(dp.x, dp.y);
|
Coordinate ll = new Coordinate(dp.x, dp.y);
|
||||||
float rot = (float) MapUtil.rotation(ll, geom);
|
float rot = (float) MapUtil.rotation(ll,
|
||||||
|
gridGeometry);
|
||||||
dir = (dir + rot) % 360;
|
dir = (dir + rot) % 360;
|
||||||
data.getScalarData().put(index, dir);
|
data.getScalarData().put(index, dir);
|
||||||
}
|
}
|
||||||
|
@ -192,6 +234,53 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected GridGeometry2D calculateSubgrid(GridGeometry2D dataGeometry) {
|
||||||
|
try {
|
||||||
|
CoordinateReferenceSystem dataCRS = dataGeometry
|
||||||
|
.getCoordinateReferenceSystem();
|
||||||
|
org.opengis.geometry.Envelope descEnv = descriptor
|
||||||
|
.getGridGeometry().getEnvelope();
|
||||||
|
Envelope2D dataEnv = dataGeometry.getEnvelope2D();
|
||||||
|
int dataWidth = dataGeometry.getGridRange2D().width;
|
||||||
|
int dataHeight = dataGeometry.getGridRange2D().height;
|
||||||
|
/*
|
||||||
|
* Use grid spacing to determine a threshold for
|
||||||
|
* EnvelopeIntersection. This guarantees the result is within one
|
||||||
|
* grid cell.
|
||||||
|
*/
|
||||||
|
double dx = dataEnv.width / dataWidth;
|
||||||
|
double dy = dataEnv.height / dataHeight;
|
||||||
|
double threshold = Math.max(dx, dy);
|
||||||
|
Geometry geom = EnvelopeIntersection.createEnvelopeIntersection(
|
||||||
|
descEnv, dataEnv, threshold, dataWidth, dataHeight);
|
||||||
|
/* Convert from jts envelope to geotools envelope. */
|
||||||
|
Envelope env = geom.getEnvelopeInternal();
|
||||||
|
Envelope2D subEnv = new Envelope2D(dataCRS, env.getMinX(),
|
||||||
|
env.getMinY(), env.getWidth(), env.getHeight());
|
||||||
|
GridEnvelope2D subRange = dataGeometry.worldToGrid(subEnv);
|
||||||
|
/* Add a 1 pixel border so interpolation near the edges is nice */
|
||||||
|
subRange.grow(1, 1);
|
||||||
|
/* Make sure not to grow bigger than original grid. */
|
||||||
|
subRange = new GridEnvelope2D(subRange.intersection(dataGeometry
|
||||||
|
.getGridRange2D()));
|
||||||
|
if (subRange.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new GridGeometry2D(subRange, dataGeometry.getGridToCRS(),
|
||||||
|
dataCRS);
|
||||||
|
} catch (FactoryException e) {
|
||||||
|
/* Not a big deal, just request all data. */
|
||||||
|
statusHandler.handle(Priority.DEBUG, "Unable to request subgrid.",
|
||||||
|
e);
|
||||||
|
} catch (TransformException e) {
|
||||||
|
/* Not a big deal, just request all data. */
|
||||||
|
/* Java 7 multiple exception catches are going to be amazing! */
|
||||||
|
statusHandler.handle(Priority.DEBUG, "Unable to request subgrid.",
|
||||||
|
e);
|
||||||
|
}
|
||||||
|
return dataGeometry;
|
||||||
|
}
|
||||||
|
|
||||||
public GeneralGridData reprojectData(GeneralGridData data) {
|
public GeneralGridData reprojectData(GeneralGridData data) {
|
||||||
if (descriptor == null) {
|
if (descriptor == null) {
|
||||||
return data;
|
return data;
|
||||||
|
@ -200,7 +289,7 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
||||||
GeneralGridGeometry targetGeometry = MapUtil.reprojectGeometry(data
|
GeneralGridGeometry targetGeometry = MapUtil.reprojectGeometry(data
|
||||||
.getGridGeometry(), descriptor.getGridGeometry()
|
.getGridGeometry(), descriptor.getGridGeometry()
|
||||||
.getEnvelope(), true, 2);
|
.getEnvelope(), true, 2);
|
||||||
reprojectedData = true;
|
dataModified = true;
|
||||||
Interpolation interpolation = null;
|
Interpolation interpolation = null;
|
||||||
if (this.hasCapability(ImagingCapability.class)
|
if (this.hasCapability(ImagingCapability.class)
|
||||||
&& !this.getCapability(ImagingCapability.class)
|
&& !this.getCapability(ImagingCapability.class)
|
||||||
|
@ -312,8 +401,9 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||||
if (reprojectedData) {
|
if (dataModified) {
|
||||||
clearRequestedData();
|
clearRequestedData();
|
||||||
|
dataModified = false;
|
||||||
}
|
}
|
||||||
super.project(crs);
|
super.project(crs);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue