Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,22 @@
import java.util.Collections;
import java.util.List;

import java.util.Objects;
import org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox;
import org.ehcache.Cache;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.opengis.metadata.extent.GeographicBoundingBox;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

import ucar.nc2.dataset.CoordinateAxis1D;
import ucar.nc2.dt.GridCoordSystem;
import ucar.unidata.geoloc.LatLonPoint;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.geoloc.Projection;
import ucar.unidata.geoloc.ProjectionImpl;
import ucar.unidata.geoloc.ProjectionPoint;
import ucar.unidata.geoloc.projection.RotatedPole;
import uk.ac.rdg.resc.edal.cache.EdalCache;
import uk.ac.rdg.resc.edal.domain.Extent;
import uk.ac.rdg.resc.edal.geometry.BoundingBox;
import uk.ac.rdg.resc.edal.geometry.BoundingBoxImpl;
Expand All @@ -68,6 +72,11 @@
*/
public class CdmTransformedGrid extends AbstractTransformedGrid {
private static final long serialVersionUID = 1L;

private static final int MAX_HEAP_ENTRIES = 50;
private static final String CACHE_NAME = "BBOX_CACHE";
private static final Cache<Integer, BoundingBox> bboxCache;

private final ProjectionImpl proj;
private final ReferenceableAxis<Double> xAxis;

Expand All @@ -76,6 +85,19 @@ public class CdmTransformedGrid extends AbstractTransformedGrid {

private transient Array2D<GridCell2D> domainObjs = null;

static {
Cache<Integer, BoundingBox> existing = EdalCache.cacheManager
.getCache("BBOX_CACHE", Integer.class, BoundingBox.class);
if (existing == null) {
bboxCache = EdalCache.cacheManager.createCache(CACHE_NAME,
CacheConfigurationBuilder.newCacheConfigurationBuilder(Integer.class,
BoundingBox.class,
ResourcePoolsBuilder.heap(MAX_HEAP_ENTRIES)));
} else {
bboxCache = existing;
}
}

/**
* Create a new {@link CdmTransformedGrid} from a defined
* {@link ProjectionImpl} and a pair of axes
Expand Down Expand Up @@ -133,44 +155,50 @@ public CdmTransformedGrid(GridCoordSystem coordSys) {
xAxis = CdmUtils.createReferenceableAxis((CoordinateAxis1D) coordSys.getXHorizAxis(),
xAxisIsLongitude);
yAxis = CdmUtils.createReferenceableAxis((CoordinateAxis1D) coordSys.getYHorizAxis());

List<HorizontalPosition> gridPoints = new ArrayList<>();
for(Double x : xAxis.getCoordinateValues()) {
for(Double y : yAxis.getCoordinateValues() ) {
LatLonPoint ll = proj.projToLatLon(x, y);
gridPoints.add(new HorizontalPosition(ll.getLongitude(), ll.getLatitude()));
// create the key for the bbox cache
final int hcsHash = Objects.hash(xAxis, yAxis);
if (!bboxCache.containsKey(hcsHash)) {
// compute the bounding box (can be expensive for large grids)
System.out.println("Computing bounding box for grid with hash " + hcsHash);
double latMin = Double.MAX_VALUE;
double lonMin = Double.MAX_VALUE;
double latMax = Double.MIN_VALUE;
double lonMax = Double.MIN_VALUE;

for (Double x : xAxis.getCoordinateValues()) {
for (Double y : yAxis.getCoordinateValues()) {
LatLonPoint ll = proj.projToLatLon(x, y);
lonMin = Math.min(lonMin, ll.getLongitude());
lonMax = Math.max(lonMax, ll.getLongitude());
latMin = Math.min(latMin, ll.getLatitude());
latMax = Math.max(latMax, ll.getLatitude());
}
}
}

BoundingBox latLonBoundingBox = GISUtils.getBoundingBox(gridPoints);
/*
* Some projections do not have a well-defined lat-lon bounding box and
* return NaNs. In these cases, we fall back to using global limits
*/
double lonMin = latLonBoundingBox.getMinX();
double lonMax = latLonBoundingBox.getMaxX();
double latMin = latLonBoundingBox.getMinY();
double latMax = latLonBoundingBox.getMaxY();
if (Double.isNaN(lonMin)) {
/*
* Some projections do not have a well-defined lat-lon bounding box and
* return NaNs. In these cases, we fall back to using global limits
*/
if (Double.isNaN(lonMin)) {
lonMin = -180.0;
}
if (Double.isNaN(lonMax)) {
}
if (Double.isNaN(lonMax)) {
lonMax = 180.0;
}
if (Double.isNaN(latMin) || Math.abs(latMin + 90) < 1) {
}
if (Double.isNaN(latMin) || Math.abs(latMin + 90) < 1) {
latMin = -90.0;
}
if (Double.isNaN(latMax) || Math.abs(latMax - 90) < 1) {
}
if (Double.isNaN(latMax) || Math.abs(latMax - 90) < 1) {
latMax = 90.0;
}
}

if (latMin != latMax && lonMin != lonMax) {
if (latMin != latMax && lonMin != lonMax) {
/*
* The normal situation - use the bounds to create the bounding box
*/
bbox = new BoundingBoxImpl(lonMin, latMin, lonMax, latMax,
GISUtils.defaultGeographicCRS());
} else {
GISUtils.defaultGeographicCRS());
} else {
/*
* Some projections (MSGnavigation as returned by GRIB is the only
* one I've actually found so far) end up returning a bounding box
Expand All @@ -180,6 +208,11 @@ public CdmTransformedGrid(GridCoordSystem coordSys) {
* It seems to be the case that the projection just doesn't work.
*/
bbox = BoundingBoxImpl.global();
}
bboxCache.put(hcsHash, bbox);
} else {
System.out.println("Obtain bounding box for grid with hash " + hcsHash + " from cache");
bbox = bboxCache.get(hcsHash);
}
}

Expand Down
Loading