Issue #1279 change GridCoverage to choose more reasonable longitude ranges, use a 0 central meridian for huge grids to avoid normalization in geotools, fix intersections in GridGeometryProjections to work for unnormalized areas, fix data wrapper world wrap detection to work for any crs which doesn't normalize.

Former-commit-id: 9bef14fdb1 [formerly aac3144f51] [formerly 2f7a04f8ef] [formerly e3cc30e8a8 [formerly 2f7a04f8ef [formerly 908b9ec666e5dfb50ef4fe3899bf2288bf4cecc5]]]
Former-commit-id: e3cc30e8a8
Former-commit-id: f7f14001910f26e749c9069418cd703088ba92a9 [formerly a67d5e2b6c]
Former-commit-id: 6748ebb4ec
This commit is contained in:
Ben Steffensmeier 2012-10-18 12:39:01 -05:00
parent 2244937369
commit b7f3492c1a
4 changed files with 50 additions and 11 deletions

View file

@ -595,6 +595,20 @@ public abstract class GridCoverage extends PersistableDataObject implements
maxLon -= 1.0E-12;
minLon += 1.0E-12;
}
// Normalize the range by shifting 360 degrees to bring the range
// within +/-360 degree as much as possible. For example the
// Canadian-NH model gets calculated as 179.7 to 540.3 but it
// works better to use -180.3 to 180.3.
while (minLon > 0 && maxLon > 360) {
minLon -= 360;
maxLon -= 360;
}
// Normalize the low end.
while (minLon < -360 && maxLon < 0) {
minLon += 360;
maxLon += 360;
}
try {
geometry = MapUtil.createGeometry(minLat, minLon, maxLat,
maxLon);
@ -743,7 +757,8 @@ public abstract class GridCoverage extends PersistableDataObject implements
if (isSubGridded()) {
String subGridName = getName();
int index = subGridName.lastIndexOf(SUBGRID_TOKEN);
if (index >= 0 && index + SUBGRID_TOKEN.length() < subGridName.length()) {
if (index >= 0
&& index + SUBGRID_TOKEN.length() < subGridName.length()) {
model = subGridName.substring(index + SUBGRID_TOKEN.length());
}
}

View file

@ -97,7 +97,16 @@ public class LatLonGridCoverage extends GridCoverage {
double maxLon = minLon + dx * nx;
double centralMeridian = (minLon + maxLon) / 2.0;
if (dx * nx <= 360) {
centralMeridian = MapUtil.correctLon(centralMeridian);
} else {
// For almost all map projections geotools will clip all math
// transforms to be within +-180 of the central meridian. For grids
// that wrap around the world more than once this is a problem. When
// the central Meridian is 0.0 then geotools does not do this
// clipping, which works much better.
centralMeridian = 0.0;
}
crs = MapUtil.constructEquidistantCylindrical(
MapUtil.AWIPS_EARTH_RADIUS, MapUtil.AWIPS_EARTH_RADIUS,
centralMeridian, 0);

View file

@ -385,11 +385,28 @@ public class MapUtil {
LATLON_PROJECTION, false);
ReferencedEnvelope newTargetREnv = targetREnv.transform(
LATLON_PROJECTION, false);
com.vividsolutions.jts.geom.Envelope intersection = newTargetREnv
.intersection(newSourceEnv);
// Its possible to get two envelopes that don't intersect in a common
// space, for example one could have longitude from -200 to -160 and
// another could have longitude from 160 to 200. Even though these are
// the same range, they don't intersect. These two loops will shift the
// data 360 degrees in the x direction until all intersections are
// found.
while (newSourceEnv.getMaxX() > newTargetREnv.getMinX()) {
newSourceEnv.translate(-360, 0);
intersection.expandToInclude(newTargetREnv
.intersection(newSourceEnv));
}
while (newSourceEnv.getMinX() < newTargetREnv.getMaxX()) {
newSourceEnv.translate(360, 0);
intersection.expandToInclude(newTargetREnv
.intersection(newSourceEnv));
}
// Get the newEnvelope
ReferencedEnvelope newEnv = new ReferencedEnvelope(JTS.getEnvelope2D(
newTargetREnv.intersection(newSourceEnv), LATLON_PROJECTION),
LATLON_PROJECTION);
intersection, LATLON_PROJECTION), LATLON_PROJECTION);
newEnv = newEnv.transform(targetCRS, false, 500);
// Calculate nx and ny, start with the number of original grid
// points in the intersection and then adjust to the new aspect

View file

@ -27,8 +27,6 @@ import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.datum.PixelInCell;
import org.opengis.referencing.operation.MathTransform;
import com.raytheon.uf.common.geospatial.MapUtil;
/**
*
* Abstract class for any data implementation that can act as both a source and
@ -138,8 +136,8 @@ public abstract class AbstractDataWrapper implements DataSource,
grid2crs.transform(corner2, corner2);
crs2LatLon.transform(corner1, corner1);
crs2LatLon.transform(corner2, corner2);
corner1.x = MapUtil.correctLon(corner1.x);
corner2.x = MapUtil.correctLon(corner2.x);
corner1.x = corner1.x - 360;
corner2.x = corner2.x - 360;
crs2LatLon.inverse().transform(corner1, corner1);
crs2LatLon.inverse().transform(corner2, corner2);
grid2crs.inverse().transform(corner1, corner1);