Merge "Issue #2309 Request subgrids of grib data whenever possible." into development
Former-commit-id:7245c8674d
[formerly e7f1c0a4f67bf2f440c27c4e77e8d8ae0145186a] Former-commit-id:caf2e69a87
This commit is contained in:
commit
0da96389cf
1 changed files with 122 additions and 32 deletions
|
@ -25,9 +25,11 @@ import java.util.Map;
|
|||
import javax.measure.unit.Unit;
|
||||
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.coverage.grid.InvalidGridGeometryException;
|
||||
import org.geotools.geometry.DirectPosition2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.opengis.referencing.FactoryException;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
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.dataset.DatasetInfo;
|
||||
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.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.ReferencedCoordinate;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.BilinearInterpolation;
|
||||
import com.raytheon.uf.common.geospatial.interpolation.Interpolation;
|
||||
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.status.IUFStatusHandler;
|
||||
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.xml.FieldDisplayTypesFactory;
|
||||
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
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Mar 09, 2011 bsteffen Initial creation
|
||||
* Feb 25, 2013 1659 bsteffen Add PDOs to D2DGridResource in
|
||||
* constructor to avoid duplicate data
|
||||
* requests.
|
||||
* Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows.
|
||||
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error
|
||||
* in Maputil.rotation
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Mar 09, 2011 bsteffen Initial creation
|
||||
* Feb 25, 2013 1659 bsteffen Add PDOs to D2DGridResource in
|
||||
* constructor to avoid duplicate data
|
||||
* requests.
|
||||
* Jul 15, 2013 2107 bsteffen Fix sampling of grid vector arrows.
|
||||
* Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error
|
||||
* in Maputil.rotation
|
||||
* Sep 12, 2013 2309 bsteffen Request subgrids whenever possible.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -92,7 +99,14 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
|||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.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,
|
||||
LoadProperties loadProperties) {
|
||||
|
@ -134,48 +148,76 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
|||
protected GeneralGridData getData(GridRecord gridRecord)
|
||||
throws VizException {
|
||||
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(
|
||||
gridRecord, descriptor);
|
||||
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) {
|
||||
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
|
||||
// pole.
|
||||
GridCoverage location = gridRecord.getLocation();
|
||||
GeneralGridData data = getData(dataRecs, location.getGridGeometry(),
|
||||
dataUnit);
|
||||
|
||||
GeneralGridData data = getData(dataRecs, gridGeometry, dataUnit);
|
||||
/*
|
||||
* 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
|
||||
* pole.
|
||||
*/
|
||||
if (location != null && location.getSpacingUnit().equals("degree")) {
|
||||
if (!ConformalityUtil.testConformality(location.getGridGeometry(),
|
||||
if (!ConformalityUtil.testConformality(gridGeometry,
|
||||
descriptor.getGridGeometry())) {
|
||||
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
|
||||
&& stylePreferences.getDisplayFlags()
|
||||
.hasFlag("RotateVectorDir")) {
|
||||
GridGeometry2D geom = GridGeometry2D.wrap(location
|
||||
.getGridGeometry());
|
||||
MathTransform grid2crs = geom.getGridToCRS();
|
||||
GridEnvelope2D gridRange = gridGeometry.getGridRange2D();
|
||||
MathTransform grid2crs = gridGeometry.getGridToCRS();
|
||||
try {
|
||||
MathTransform crs2ll = MapUtil.getTransformToLatLon(geom
|
||||
.getCoordinateReferenceSystem());
|
||||
for (int i = 0; i < geom.getGridRange2D().width; i++) {
|
||||
for (int j = 0; j < geom.getGridRange2D().height; j++) {
|
||||
int index = i + j * geom.getGridRange2D().width;
|
||||
MathTransform crs2ll = MapUtil
|
||||
.getTransformToLatLon(gridGeometry
|
||||
.getCoordinateReferenceSystem());
|
||||
for (int i = 0; i < gridRange.width; i++) {
|
||||
for (int j = 0; j < gridRange.height; j++) {
|
||||
int index = i + j * gridRange.width;
|
||||
float dir = data.getScalarData().get(index);
|
||||
if (dir > -9999) {
|
||||
DirectPosition2D dp = new DirectPosition2D(i, j);
|
||||
grid2crs.transform(dp, dp);
|
||||
crs2ll.transform(dp, dp);
|
||||
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;
|
||||
data.getScalarData().put(index, dir);
|
||||
}
|
||||
|
@ -192,6 +234,53 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
|||
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) {
|
||||
if (descriptor == null) {
|
||||
return data;
|
||||
|
@ -200,7 +289,7 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
|||
GeneralGridGeometry targetGeometry = MapUtil.reprojectGeometry(data
|
||||
.getGridGeometry(), descriptor.getGridGeometry()
|
||||
.getEnvelope(), true, 2);
|
||||
reprojectedData = true;
|
||||
dataModified = true;
|
||||
Interpolation interpolation = null;
|
||||
if (this.hasCapability(ImagingCapability.class)
|
||||
&& !this.getCapability(ImagingCapability.class)
|
||||
|
@ -312,8 +401,9 @@ public class D2DGridResource extends GridResource<GridResourceData> implements
|
|||
|
||||
@Override
|
||||
public void project(CoordinateReferenceSystem crs) throws VizException {
|
||||
if (reprojectedData) {
|
||||
if (dataModified) {
|
||||
clearRequestedData();
|
||||
dataModified = false;
|
||||
}
|
||||
super.project(crs);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue