Issue #2309 Request subgrids of grib data whenever possible.

Former-commit-id: 38fc89ffaa [formerly c9e8e6a8d6550f41039e2208b50bd053bfef94b8]
Former-commit-id: 990964ca40
This commit is contained in:
Ben Steffensmeier 2013-09-16 10:52:14 -05:00
parent 99d1e66925
commit f061cc71c8

View file

@ -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);
} }