-
Notifications
You must be signed in to change notification settings - Fork 179
Stereographic projection lat/lon bbox #504
Comments
The calculation for that lat-lon bounding box is done by ProjectionImpl.projToLatLonBB(ProjectionRect). It incorrectly assumes that you can calculate the lat-lon bounding box from the projection bounding box. I've got some code that demonstrates the problem: public static void main(String[] args) {
// These projection parameters and values are from "Best GFS Northern Hemisphere 381km Time Series":
// http:https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/GFS/N_Hemisphere_381km/Best.html
Stereographic stereo = new Stereographic(90, 255, 0.9330127018922193);
double[] x = new double[] {-12192.129, -11811.129, -11430.129, -11049.129, -10668.129, -10287.129, -9906.129,
-9525.129, -9144.129, -8763.129, -8382.129, -8001.129, -7620.129, -7239.129, -6858.129, -6477.129,
-6096.129, -5715.129, -5334.129, -4953.129, -4572.129, -4191.129, -3810.129, -3429.129, -3048.129,
-2667.129, -2286.129, -1905.129, -1524.129, -1143.129, -762.129, -381.12903, -0.12901638, 380.87097,
761.871, 1142.871, 1523.871, 1904.871, 2285.871, 2666.871, 3047.871, 3428.871, 3809.871, 4190.871,
4571.871, 4952.871, 5333.871, 5714.871, 6095.871, 6476.871, 6857.871, 7238.871, 7619.871, 8000.871,
8381.871, 8762.871, 9143.871, 9524.871, 9905.871, 10286.871, 10667.871, 11048.871, 11429.871, 11810.871,
12191.871};
double[] y = new double[] {-12192.129, -11811.129, -11430.129, -11049.129, -10668.129, -10287.129, -9906.129,
-9525.129, -9144.129, -8763.129, -8382.129, -8001.129, -7620.129, -7239.129, -6858.129, -6477.129,
-6096.129, -5715.129, -5334.129, -4953.129, -4572.129, -4191.129, -3810.129, -3429.129, -3048.129,
-2667.129, -2286.129, -1905.129, -1524.129, -1143.129, -762.129, -381.12903, -0.12901638, 380.87097,
761.871, 1142.871, 1523.871, 1904.871, 2285.871, 2666.871, 3047.871, 3428.871, 3809.871, 4190.871,
4571.871, 4952.871, 5333.871, 5714.871, 6095.871, 6476.871, 6857.871, 7238.871, 7619.871, 8000.871,
8381.871, 8762.871, 9143.871, 9524.871, 9905.871, 10286.871, 10667.871, 11048.871, 11429.871, 11810.871,
12191.871};
double minX = Double.MAX_VALUE;
double minY = Double.MAX_VALUE;
double maxX = -Double.MAX_VALUE;
double maxY = -Double.MAX_VALUE;
double minLon = Double.MAX_VALUE;
double minLat = Double.MAX_VALUE;
double maxLon = -Double.MAX_VALUE;
double maxLat = -Double.MAX_VALUE;
for (int i = 0; i < x.length; ++i) {
minX = Math.min(minX, x[i]);
minY = Math.min(minY, y[i]);
maxX = Math.max(maxX, x[i]);
maxY = Math.max(maxY, y[i]);
ProjectionPoint projPoint = new ProjectionPointImpl(x[i], y[i]);
LatLonPoint latLonPoint = stereo.projToLatLon(projPoint);
System.out.printf("latLonPoint %s: %s%n", i + 1, latLonPoint);
minLon = Math.min(minLon, latLonPoint.getLongitude());
minLat = Math.min(minLat, latLonPoint.getLatitude());
maxLon = Math.max(maxLon, latLonPoint.getLongitude());
maxLat = Math.max(maxLat, latLonPoint.getLatitude());
}
ProjectionRect actualProjBB = new ProjectionRect(minX, minY, maxX, maxY);
System.out.println("actualProjBB: " + actualProjBB);
LatLonPoint minLatLon = new LatLonPointImpl(minLat, minLon);
LatLonPoint maxLatLon = new LatLonPointImpl(maxLat, maxLon);
LatLonRect actualLatLonBB = new LatLonRect(minLatLon, maxLatLon);
System.out.println("actualLatLonBB: " + actualLatLonBB);
LatLonRect wrongLatLonBB = stereo.projToLatLonBB(actualProjBB);
System.out.println("wrongLatLonBB: " + wrongLatLonBB);
} The result:
I'll turn this into a failing unit test. Thanks for the report, Yuan! |
This dataset covers the entire Northern Hemisphere (plus some). All four corners of the grid are at 20.8S latitude with longitudes of 120E, 30E, 60W, and 150W. The real problem is that a Latitude-Longitude Bounding Box just doesn't make sense when you are dealing with an area that includes one of the poles. |
Depends how you define "bounding box". To me that doesn't mean looking only at corners--that means looking at min/max extent. So if a pole is included, fine 90N is one of the ends. But by definition of bounds, unless that domain is actually a line in lon/lat space, you have a different value for the other end. |
My first code sample was wrong: you must include the lat/lon values of all grid cells in the bounding box calculation (the outer product of x and y). New code: public static void main(String[] args) {
// These projection parameters and values are from "Best GFS Northern Hemisphere 381km Time Series":
// http:https://thredds.ucar.edu/thredds/dodsC/grib/NCEP/GFS/N_Hemisphere_381km/Best.html
Stereographic stereo = new Stereographic(90, 255, 0.9330127018922193);
double[] x = new double[] {-12192.129, -11811.129, -11430.129, -11049.129, -10668.129, -10287.129, -9906.129,
-9525.129, -9144.129, -8763.129, -8382.129, -8001.129, -7620.129, -7239.129, -6858.129, -6477.129,
-6096.129, -5715.129, -5334.129, -4953.129, -4572.129, -4191.129, -3810.129, -3429.129, -3048.129,
-2667.129, -2286.129, -1905.129, -1524.129, -1143.129, -762.129, -381.12903, -0.12901638, 380.87097,
761.871, 1142.871, 1523.871, 1904.871, 2285.871, 2666.871, 3047.871, 3428.871, 3809.871, 4190.871,
4571.871, 4952.871, 5333.871, 5714.871, 6095.871, 6476.871, 6857.871, 7238.871, 7619.871, 8000.871,
8381.871, 8762.871, 9143.871, 9524.871, 9905.871, 10286.871, 10667.871, 11048.871, 11429.871, 11810.871,
12191.871};
double[] y = new double[] {-12192.129, -11811.129, -11430.129, -11049.129, -10668.129, -10287.129, -9906.129,
-9525.129, -9144.129, -8763.129, -8382.129, -8001.129, -7620.129, -7239.129, -6858.129, -6477.129,
-6096.129, -5715.129, -5334.129, -4953.129, -4572.129, -4191.129, -3810.129, -3429.129, -3048.129,
-2667.129, -2286.129, -1905.129, -1524.129, -1143.129, -762.129, -381.12903, -0.12901638, 380.87097,
761.871, 1142.871, 1523.871, 1904.871, 2285.871, 2666.871, 3047.871, 3428.871, 3809.871, 4190.871,
4571.871, 4952.871, 5333.871, 5714.871, 6095.871, 6476.871, 6857.871, 7238.871, 7619.871, 8000.871,
8381.871, 8762.871, 9143.871, 9524.871, 9905.871, 10286.871, 10667.871, 11048.871, 11429.871, 11810.871,
12191.871};
double minLon = Double.MAX_VALUE;
double minLat = Double.MAX_VALUE;
double maxLon = -Double.MAX_VALUE;
double maxLat = -Double.MAX_VALUE;
for (int i = 0; i < x.length; ++i) {
for (int j = 0; j < y.length; ++j) {
ProjectionPoint projPoint = new ProjectionPointImpl(x[i], y[j]);
LatLonPoint latLonPoint = stereo.projToLatLon(projPoint);
minLon = Math.min(minLon, latLonPoint.getLongitude());
minLat = Math.min(minLat, latLonPoint.getLatitude());
maxLon = Math.max(maxLon, latLonPoint.getLongitude());
maxLat = Math.max(maxLat, latLonPoint.getLatitude());
}
}
ProjectionRect actualProjBB = new ProjectionRect(Doubles.min(x), Doubles.min(y), Doubles.max(x), Doubles.max(y));
System.out.println("actualProjBB: " + actualProjBB);
LatLonPoint minLatLon = new LatLonPointImpl(minLat, minLon);
LatLonPoint maxLatLon = new LatLonPointImpl(maxLat, maxLon);
LatLonRect actualLatLonBB = new LatLonRect(minLatLon, maxLatLon);
System.out.println("actualLatLonBB: " + actualLatLonBB);
LatLonRect wrongLatLonBB = stereo.projToLatLonBB(actualProjBB);
System.out.println("wrongLatLonBB: " + wrongLatLonBB);
}
|
For the record, I think you are supposed to override ProjectionImpl.projToLatLonBB(ProjectionRect) to handle this. Note this is taking the projection coords, which should make sense, to latlon box, which as ethan says, may not. The likely answer is you must subset in projection space, not latlon space. |
In the GFS N Hemisphere dataset, the dataset bbox is ll: 21.65S 150.0W+ ur: 21.65S 30.00E which may not be wrong, but how can a client do any subset based on this value?
The text was updated successfully, but these errors were encountered: