package ucar.nc2.ft.cover.impl;
import ucar.ma2.Array;
import ucar.ma2.InvalidRangeException;
import ucar.nc2.Dimension;
import ucar.nc2.constants.AxisType;
import ucar.nc2.dataset.*;
import ucar.nc2.ft.cover.CoverageCS;
import ucar.nc2.time.CalendarDateRange;
import ucar.unidata.geoloc.LatLonRect;
import ucar.unidata.geoloc.ProjectionImpl;
import ucar.unidata.geoloc.ProjectionRect;
import ucar.unidata.geoloc.vertical.VerticalTransform;
import java.io.IOException;
import java.util.*;
/**
* Coverage Coordinate System implementation.
*
* @author John
* @since 12/25/12
*/
public class CoverageCSImpl implements CoverageCS {
protected NetcdfDataset ds;
protected CoordinateSystem cs;
protected CoverageCSFactory fac;
protected ProjectionImpl projection;
protected ProjectionRect mapArea;
protected CoverageCSImpl(NetcdfDataset ds, CoordinateSystem cs, CoverageCSFactory fac) {
this.ds = ds;
this.cs = cs;
this.fac = fac;
// set canonical area
ProjectionImpl projOrig = cs.getProjection();
if (projOrig != null) {
projection = projOrig.constructCopy();
projection.setDefaultMapArea(getBoundingBox()); // LOOK too expensive for 2D
}
}
@Override
public String getName() {
return cs.getName();
}
@Override
public List<Dimension> getDomain() {
return cs.getDomain();
}
@Override
public List<CoordinateAxis> getCoordinateAxes() {
return fac.standardAxes;
}
@Override
public List<CoordinateAxis> getOtherCoordinateAxes() {
return fac.otherAxes;
}
@Override
public boolean isProductSet() {
return cs.isProductSet();
}
@Override
public List<CoordinateTransform> getCoordinateTransforms() {
return cs.getCoordinateTransforms();
}
@Override
public CoordinateAxis getXHorizAxis() {
return cs.isLatLon() ? cs.getLonAxis() : cs.getXaxis();
}
@Override
public CoordinateAxis getYHorizAxis() {
return cs.isLatLon() ? cs.getLatAxis() : cs.getYaxis();
}
@Override
public boolean isLatLon() {
return cs.isLatLon();
}
@Override
public LatLonRect getLatLonBoundingBox() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public ProjectionRect getBoundingBox() {
if (mapArea == null) makeBoundingBox();
return mapArea;
}
private void makeBoundingBox() {
// x,y may be 2D
if (!(getXHorizAxis() instanceof CoordinateAxis1D) || !(getYHorizAxis() instanceof CoordinateAxis1D)) {
CoordinateAxis xaxis = getXHorizAxis();
CoordinateAxis yaxis = getYHorizAxis();
/* could try to optimize this - just get cord=ners or something
CoordinateAxis2D xaxis2 = (CoordinateAxis2D) horizXaxis;
CoordinateAxis2D yaxis2 = (CoordinateAxis2D) horizYaxis;
MAMath.MinMax
*/
mapArea = new ProjectionRect(xaxis.getMinValue(), yaxis.getMinValue(),
xaxis.getMaxValue(), yaxis.getMaxValue());
} else {
CoordinateAxis1D xaxis1 = (CoordinateAxis1D) getXHorizAxis();
CoordinateAxis1D yaxis1 = (CoordinateAxis1D) getYHorizAxis();
/* add one percent on each side if its a projection. WHY?
double dx = 0.0, dy = 0.0;
if (!isLatLon()) {
dx = .01 * (xaxis1.getCoordEdge((int) xaxis1.getSize()) - xaxis1.getCoordEdge(0));
dy = .01 * (yaxis1.getCoordEdge((int) yaxis1.getSize()) - yaxis1.getCoordEdge(0));
}
mapArea = new ProjectionRect(xaxis1.getCoordEdge(0) - dx, yaxis1.getCoordEdge(0) - dy,
xaxis1.getCoordEdge((int) xaxis1.getSize()) + dx,
yaxis1.getCoordEdge((int) yaxis1.getSize()) + dy); */
mapArea = new ProjectionRect(xaxis1.getCoordEdge(0), yaxis1.getCoordEdge(0),
xaxis1.getCoordEdge((int) xaxis1.getSize()),
yaxis1.getCoordEdge((int) yaxis1.getSize()));
}
}
@Override
public ProjectionImpl getProjection() {
return projection;
}
@Override
public CoordinateAxis getVerticalAxis() {
return fac.vertAxis;
}
@Override
public boolean isZPositive() {
CoordinateAxis vertZaxis = getVerticalAxis();
if (vertZaxis == null) return false;
if (vertZaxis.getPositive() != null) {
return vertZaxis.getPositive().equalsIgnoreCase(ucar.nc2.constants.CF.POSITIVE_UP);
}
if (vertZaxis.getAxisType() == AxisType.Height) return true;
if (vertZaxis.getAxisType() == AxisType.Pressure) return false;
return true; // default
}
@Override
public VerticalCT getVerticalCT() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public VerticalTransform getVerticalTransform() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public boolean hasTimeAxis() {
return getTimeAxis() != null;
}
@Override
public CoordinateAxis getTimeAxis() {
return fac.timeAxis;
}
@Override
public CalendarDateRange getCalendarDateRange() {
if (!hasTimeAxis()) return null;
CoordinateAxis timeAxis = getTimeAxis();
if (timeAxis instanceof CoordinateAxis1DTime)
return ((CoordinateAxis1DTime) timeAxis).getCalendarDateRange();
// bail out for now
return null;
}
@Override
public String toString() {
return fac.toString();
}
@Override
public void show(Formatter f, boolean showCoords) {
f.format("Coordinate System (%s)%n%n", getName());
}
///////////////////
@Override
public Subset makeSubsetFromLatLonRect(LatLonRect llbb) throws InvalidRangeException {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Subset getSubset() {
return new SubsetImpl();
}
static class SubsetImpl implements Subset {
int level = -1;
int time = -1;
@Override
public void setLevel(int idx) {
this.level = idx;
}
@Override
public void setTime(int idx) {
this.time = idx;
}
// kludge
Array readData(VariableEnhanced ve) throws IOException, InvalidRangeException {
int n = ve.getRank();
int[] origin = new int[n];
int[] shape = new int[n];
System.arraycopy(ve.getShape(), 0, shape, 0, n);
// assume canonical ordering
if (level >= 0) {
}
Array result = ve.read(origin, shape);
return result.reduce();
}
}
}