Merge "Issue #189 fix contour subgridding for worldwide grids" into development
Former-commit-id:340f8e1fa8
[formerly 553b56aa362b452110a7f5a4f76aec9640d13599] Former-commit-id:5055164f55
This commit is contained in:
commit
ee7daccb2c
1 changed files with 114 additions and 43 deletions
|
@ -31,8 +31,12 @@ import org.apache.commons.collections.map.LRUMap;
|
|||
import org.eclipse.swt.graphics.RGB;
|
||||
import org.geotools.coverage.grid.GeneralGridEnvelope;
|
||||
import org.geotools.coverage.grid.GeneralGridGeometry;
|
||||
import org.geotools.coverage.grid.GridEnvelope2D;
|
||||
import org.geotools.coverage.grid.GridGeometry2D;
|
||||
import org.geotools.geometry.DirectPosition2D;
|
||||
import org.geotools.geometry.Envelope2D;
|
||||
import org.geotools.geometry.GeneralEnvelope;
|
||||
import org.geotools.geometry.jts.ReferencedEnvelope;
|
||||
import org.geotools.referencing.operation.DefaultMathTransformFactory;
|
||||
import org.opengis.referencing.crs.CoordinateReferenceSystem;
|
||||
import org.opengis.referencing.datum.PixelInCell;
|
||||
|
@ -46,6 +50,7 @@ import com.raytheon.uf.common.datastorage.records.FloatDataRecord;
|
|||
import com.raytheon.uf.common.datastorage.records.IDataRecord;
|
||||
import com.raytheon.uf.common.geospatial.CRSCache;
|
||||
import com.raytheon.uf.common.geospatial.MapUtil;
|
||||
import com.raytheon.uf.common.geospatial.TransformFactory;
|
||||
import com.raytheon.uf.common.geospatial.util.WorldWrapChecker;
|
||||
import com.raytheon.uf.common.status.IUFStatusHandler;
|
||||
import com.raytheon.uf.common.status.UFStatus;
|
||||
|
@ -632,47 +637,112 @@ public class ContourSupport {
|
|||
public static GeneralEnvelope calculateSubGrid(IExtent workingExtent,
|
||||
GeneralGridGeometry mapGridGeometry,
|
||||
GeneralGridGeometry imageGridGeometry) throws VizException {
|
||||
GeneralEnvelope env = null;
|
||||
GeneralEnvelope env = new GeneralEnvelope(2);
|
||||
try {
|
||||
// transform screen extent to map crs
|
||||
double[] screen = new double[] { workingExtent.getMinX(),
|
||||
workingExtent.getMinY(), workingExtent.getMaxX(),
|
||||
workingExtent.getMaxY() };
|
||||
double[] map = new double[4];
|
||||
|
||||
long t0 = System.currentTimeMillis();
|
||||
mapGridGeometry.getGridToCRS(PixelInCell.CELL_CORNER).transform(
|
||||
screen, 0, map, 0, 2);
|
||||
long t1 = System.currentTimeMillis();
|
||||
System.out.println("subgrid transform grid to CRS time: "
|
||||
+ (t1 - t0));
|
||||
|
||||
// TODO: Construct screen Grid Geometry
|
||||
GeneralGridEnvelope gge = new GeneralGridEnvelope(new int[] {
|
||||
(int) Math.floor(screen[0]), (int) Math.floor(screen[1]) },
|
||||
new int[] { (int) Math.ceil(screen[2]),
|
||||
(int) Math.ceil(screen[3]) }, false);
|
||||
GridGeometry2D screenGeometry = new GridGeometry2D(gge,
|
||||
mapGridGeometry.getGridToCRS(),
|
||||
mapGridGeometry.getCoordinateReferenceSystem());
|
||||
GridGeometry2D imageGeometry = new GridGeometry2D(imageGridGeometry);
|
||||
|
||||
t0 = System.currentTimeMillis();
|
||||
org.opengis.geometry.Envelope[] envs = MapUtil.computeEnvelopes(
|
||||
screenGeometry, imageGeometry);
|
||||
t1 = System.currentTimeMillis();
|
||||
System.out.println("subgrid compute envelopes time: " + (t1 - t0));
|
||||
|
||||
double[] grid = new double[4];
|
||||
grid[0] = envs[0].getMinimum(0);
|
||||
grid[1] = envs[0].getMinimum(1);
|
||||
grid[2] = envs[0].getMaximum(0);
|
||||
grid[3] = envs[0].getMaximum(1);
|
||||
env = new GeneralEnvelope(2);
|
||||
env.setRange(0, Math.min(grid[0], grid[2]),
|
||||
Math.max(grid[0], grid[2]));
|
||||
env.setRange(1, Math.min(grid[1], grid[3]),
|
||||
Math.max(grid[1], grid[3]));
|
||||
GridGeometry2D mapGeometry2D = GridGeometry2D.wrap(mapGridGeometry);
|
||||
GridGeometry2D imageGeometry2D = GridGeometry2D
|
||||
.wrap(imageGridGeometry);
|
||||
// Start with a grid envelope in screen space0
|
||||
GridEnvelope2D screenGridEnvelope = new GridEnvelope2D(
|
||||
(int) Math.floor(workingExtent.getMinX()),
|
||||
(int) Math.floor(workingExtent.getMinY()),
|
||||
(int) Math.ceil(workingExtent.getWidth()),
|
||||
(int) Math.ceil(workingExtent.getHeight()));
|
||||
// intersect with mapGeometry so we only have points on the actual
|
||||
// display
|
||||
screenGridEnvelope = new GridEnvelope2D(
|
||||
screenGridEnvelope.intersection(mapGeometry2D
|
||||
.getGridRange2D()));
|
||||
// convert from screen grid space to screen crs space.
|
||||
Envelope2D screenCRSEnvelope = mapGeometry2D
|
||||
.gridToWorld(screenGridEnvelope);
|
||||
// Use referenced envelope to go from screen crs into image crs.
|
||||
ReferencedEnvelope screenRefEnvelope = new ReferencedEnvelope(
|
||||
screenCRSEnvelope);
|
||||
screenRefEnvelope = screenRefEnvelope
|
||||
.transform(
|
||||
imageGridGeometry.getCoordinateReferenceSystem(),
|
||||
true, 200);
|
||||
// Convert from image crs to image grid space.
|
||||
GridEnvelope2D screenImageGridEnvelope = imageGeometry2D
|
||||
.worldToGrid(new Envelope2D(screenRefEnvelope));
|
||||
// intersection to limit to grid cells within the image.
|
||||
screenImageGridEnvelope = new GridEnvelope2D(
|
||||
screenImageGridEnvelope.intersection(imageGeometry2D
|
||||
.getGridRange2D()));
|
||||
// Referenced envelope does an almost perfect transformation.
|
||||
// Unfortunately, it has been observed that when the screen is polar
|
||||
// stereographic and the image is equidistant cylindrical that the
|
||||
// referenced envelope algorithm can miss several rows of data near
|
||||
// the pole. An envelope expansion has been added here to
|
||||
// check every edge of the subgrid to see if the next image cell is
|
||||
// on the screen, if it is then additional rows or columns are
|
||||
// added.
|
||||
MathTransform transform = TransformFactory.gridCellToGridCell(
|
||||
imageGridGeometry, PixelInCell.CELL_CENTER,
|
||||
mapGridGeometry, PixelInCell.CELL_CENTER);
|
||||
DirectPosition2D center = new DirectPosition2D(
|
||||
screenImageGridEnvelope.getCenterX(),
|
||||
screenImageGridEnvelope.getCenterY());
|
||||
// this loop checks first in the x direction then in the y direction
|
||||
for (int ordinate : new int[] { 0, 1 }) {
|
||||
// loop over every row or column on the top or left and check
|
||||
// the center point, if it can be transformed to screen space
|
||||
// and is on the screen then add the whole row or column and try
|
||||
// the next one. Choosing just the center point is arbitrary,
|
||||
// but it catches all known cases.
|
||||
for (int i = screenImageGridEnvelope.getLow(ordinate); i > imageGeometry2D
|
||||
.getGridRange2D().getLow(ordinate); i -= 1) {
|
||||
DirectPosition2D imageCell = center.clone();
|
||||
imageCell.setOrdinate(ordinate, i);
|
||||
DirectPosition2D screenCell = new DirectPosition2D();
|
||||
try {
|
||||
transform.transform(imageCell, screenCell);
|
||||
} catch (TransformException e) {
|
||||
// exception probably means we are outside valid range.
|
||||
break;
|
||||
}
|
||||
if (workingExtent.contains(screenCell.getCoordinate())) {
|
||||
screenImageGridEnvelope.add(imageCell);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// same thing only this time on the bottom and right.
|
||||
for (int i = screenImageGridEnvelope.getHigh(ordinate); i > imageGeometry2D
|
||||
.getGridRange2D().getHigh(ordinate); i -= 1) {
|
||||
DirectPosition2D imageCell = center.clone();
|
||||
imageCell.setOrdinate(ordinate, i);
|
||||
DirectPosition2D screenCell = new DirectPosition2D();
|
||||
try {
|
||||
transform.transform(imageCell, screenCell);
|
||||
} catch (TransformException e) {
|
||||
// exception probably means we are outside valid range.
|
||||
break;
|
||||
}
|
||||
if (workingExtent.contains(screenCell.getCoordinate())) {
|
||||
screenImageGridEnvelope.add(imageCell);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add a 1 pixel border since worldToGrid is only guaranteed to
|
||||
// include a cell if the cell center is in the envelope but we want
|
||||
// to include the data in the subgrid if even a tiny bit of the edge
|
||||
// overlaps.
|
||||
screenImageGridEnvelope.grow(1, 1);
|
||||
// intersection to limit to grid cells within the image.
|
||||
screenImageGridEnvelope = new GridEnvelope2D(
|
||||
screenImageGridEnvelope.intersection(imageGeometry2D
|
||||
.getGridRange2D()));
|
||||
if (!screenImageGridEnvelope.isEmpty()) {
|
||||
// Convert GridEnvelope to general envelope.
|
||||
env.setRange(0, screenImageGridEnvelope.getLow(0),
|
||||
screenImageGridEnvelope.getHigh(0));
|
||||
env.setRange(1, screenImageGridEnvelope.getLow(1),
|
||||
screenImageGridEnvelope.getHigh(1));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new VizException("Error transforming extent", e);
|
||||
}
|
||||
|
@ -1128,9 +1198,10 @@ public class ContourSupport {
|
|||
double gridPixelSize = offCenter[0] - center[0];
|
||||
double gridPixelMax = 2000.;
|
||||
|
||||
// If gridPixelSize is large, arrows on streamline will be too small, so adjust here
|
||||
if(gridPixelSize > gridPixelMax) {
|
||||
gridPixelSize = gridPixelSize/5;
|
||||
// If gridPixelSize is large, arrows on streamline will be too small, so
|
||||
// adjust here
|
||||
if (gridPixelSize > gridPixelMax) {
|
||||
gridPixelSize = gridPixelSize / 5;
|
||||
}
|
||||
float arrowSize = (float) (currentMagnification * 5 / zoom / gridPixelSize);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue