Skip to content

Commit 7128226

Browse files
committed
Allow center longitude to be set without normalization
Some GRIB GDS parameters result in longitudes outside of -180 - 180, or even greater than 360. This change allows for the center longitude of the lat lon projection to be set without normalization, such that it can accuratly represent the longitude range computed from the GDS. While it would probably be better to shift the longitude values to fit within -180 - 180, this change maintains the current behavior. Addresses #1519
1 parent ac95229 commit 7128226

3 files changed

Lines changed: 48 additions & 14 deletions

File tree

cdm/core/src/main/java/ucar/unidata/geoloc/projection/LatLonProjection.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
/*
2-
* Copyright (c) 1998-2018 University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
5+
56
package ucar.unidata.geoloc.projection;
67

78
import ucar.nc2.constants.CF;
@@ -248,23 +249,59 @@ public double[][] latLonToProj(double[][] from, double[][] to, int latIndex, int
248249

249250

250251
/**
251-
* Set the center of the Longitude range. It is normalized to +/- 180.
252+
* Set the center longitude of this projection, normalizing it into the range [-180, 180].
253+
*
254+
* <p>
252255
* The cylinder is cut at the "seam" = centerLon +- 180.
253256
* Use this to keep the Longitude values kept in the range [centerLon +-180], which
254257
* makes seam handling easier.
258+
* {@link #latLonToProj} returns longitudes in the range
259+
* [{@code centerLon} - 180, {@code centerLon} + 180], so the center longitude controls where the
260+
* seam falls and therefore which longitude values are produced.
261+
*
262+
* <p>
263+
* This method always normalizes the supplied value to [-180, 180], which discards information
264+
* about grids whose longitude coordinates legitimately lie outside that range. To preserve
265+
* such information, use
266+
* {@link #setCenterLon(double, boolean)} with {@code normalize = false}.
255267
*
256-
* @param centerLon the center of the Longitude range.
257-
* @return centerLon normalized to +/- 180.
268+
* @param centerLon the center of the longitude range, in degrees east.
269+
* @return centerLon normalized to [-180, 180].
270+
* @deprecated use {@link #setCenterLon(double, boolean)} with {@code normalize = true}
258271
*/
272+
@Deprecated
259273
public double setCenterLon(double centerLon) {
260-
this.centerLon = LatLonPoints.lonNormal(centerLon);
274+
return setCenterLon(centerLon, true);
275+
}
276+
277+
/**
278+
* Set the center longitude of this projection, optionally normalizing it into the range [-180, 180].
279+
*
280+
* <p>
281+
* The center longitude controls the location of the projection "seam" (at {@code centerLon} +/- 180).
282+
* This also means it controls the range of longitudes returned by the projection. When {@code normalize}
283+
* is {@code false}, the supplied value is stored as given. This allows the projection to
284+
* reproduce grid longitudes that lie outside [-180, 180].
285+
*
286+
* @param centerLon the center of the longitude range, in degrees east.
287+
* @param normalize if {@code true}, normalize {@code centerLon} into [-180, 180]; if {@code false},
288+
* store it unchanged.
289+
* @return the center longitude that was stored.
290+
*/
291+
public double setCenterLon(double centerLon, boolean normalize) {
292+
this.centerLon = normalize ? LatLonPoints.lonNormal(centerLon) : centerLon;
261293
return this.centerLon;
262294
}
263295

264296
/**
265-
* Get the center of the Longitude range. It is normalized to +/- 180.
297+
* Get the center longitude of this projection, in degrees east.
298+
*
299+
* <p>
300+
* Note that this value is normalized to [-180, 180] only if it was set via
301+
* {@link #setCenterLon(double)} (or {@link #setCenterLon(double, boolean)} with
302+
* {@code normalize = true}).
266303
*
267-
* @return the center longitude
304+
* @return the center longitude.
268305
*/
269306
public double getCenterLon() {
270307
return centerLon;

grib/src/main/java/ucar/nc2/grib/grib1/Grib1Gds.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2025 John Caron and University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 John Caron and University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
55

@@ -557,9 +557,7 @@ public String toString() {
557557
public GdsHorizCoordSys makeHorizCoordSys() {
558558
LatLonProjection proj = new LatLonProjection(getEarth());
559559
double centerLon = ((int) ((lo2 - lo1 + deltaLon) / 2 / scale3)) * scale3;
560-
proj.setCenterLon(centerLon);
561-
562-
// ProjectionPoint startP = proj.latLonToProj(LatLonPoint.create(la1, lo1));
560+
proj.setCenterLon(centerLon, false);
563561
double startx = lo1; // startP.getX();
564562
double starty = la1; // startP.getY();
565563
return new GdsHorizCoordSys(getNameShort(), template, 0, scanMode, proj, startx, getDx(), starty, getDy(),

grib/src/main/java/ucar/nc2/grib/grib2/Grib2Gds.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1998-2025 John Caron and University Corporation for Atmospheric Research/Unidata
2+
* Copyright (c) 1998-2026 John Caron and University Corporation for Atmospheric Research/Unidata
33
* See LICENSE for license information.
44
*/
55

@@ -519,8 +519,7 @@ public int[] getOptionalPoints() {
519519
public GdsHorizCoordSys makeHorizCoordSys() {
520520
LatLonProjection proj = new LatLonProjection(getEarth());
521521
double centerLon = ((int) ((lo2 - lo1 + deltaLon) / 2 / getScale())) * getScale();
522-
proj.setCenterLon(centerLon);
523-
// ProjectionPoint startP = proj.latLonToProj(LatLonPoint.create(la1, lo1));
522+
proj.setCenterLon(centerLon, false);
524523
double startx = lo1; // startP.getX();
525524
double starty = la1; // startP.getY();
526525
return new GdsHorizCoordSys(getNameShort(), template, numberOfDataPoints, scanMode, proj, startx, deltaLon,

0 commit comments

Comments
 (0)