if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.finest(new StringBuffer("execute CoverageRequest response. Called request is: ")
.append(request).toString());
}
CoverageInfo meta = null;
GridCoverage2D coverage = null;
try {
meta = catalog.getCoverageByName(request.getIdentifier().getValue());
// first let's run some sanity checks on the inputs
checkDomainSubset(meta, request.getDomainSubset());
checkRangeSubset(meta, request.getRangeSubset());
checkOutput(meta, request.getOutput());
// grab the format, the reader using the default params,
final Format format = meta.getStore().getFormat();
final AbstractGridCoverage2DReader reader = (AbstractGridCoverage2DReader) meta
.getGridCoverageReader(null, HINTS);
final ParameterValueGroup params = reader.getFormat().getReadParameters();
// handle spatial domain subset, if needed
final GeneralEnvelope originalEnvelope = reader.getOriginalEnvelope();
final BoundingBoxType bbox = request.getDomainSubset().getBoundingBox();
final CoordinateReferenceSystem nativeCRS = originalEnvelope
.getCoordinateReferenceSystem();
final GeneralEnvelope destinationEnvelopeInSourceCRS;
final GeneralEnvelope destinationEnvelope;
if (bbox != null) {
// first off, parse the envelope corners
double[] lowerCorner = new double[bbox.getLowerCorner().size()];
double[] upperCorner = new double[bbox.getUpperCorner().size()];
for (int i = 0; i < lowerCorner.length; i++) {
lowerCorner[i] = (Double) bbox.getLowerCorner().get(i);
upperCorner[i] = (Double) bbox.getUpperCorner().get(i);
}
destinationEnvelope = new GeneralEnvelope(lowerCorner, upperCorner);
// grab the native crs
// if no crs has beens specified, the native one is assumed
if (bbox.getCrs() == null) {
destinationEnvelope.setCoordinateReferenceSystem(nativeCRS);
destinationEnvelopeInSourceCRS = destinationEnvelope;
} else {
// otherwise we need to transform
final CoordinateReferenceSystem bboxCRS = CRS.decode(bbox.getCrs());
destinationEnvelope.setCoordinateReferenceSystem(bboxCRS);
final MathTransform bboxToNativeTx = CRS.findMathTransform(bboxCRS, nativeCRS,
true);
destinationEnvelopeInSourceCRS = CRS.transform(bboxToNativeTx,
destinationEnvelope);
destinationEnvelopeInSourceCRS.setCoordinateReferenceSystem(nativeCRS);
}
} else {
destinationEnvelopeInSourceCRS = reader.getOriginalEnvelope();
destinationEnvelope = destinationEnvelopeInSourceCRS;
}
final GridCrsType gridCRS = request.getOutput().getGridCRS();
// TODO: handle time domain subset...
// Compute the target crs, the crs that the final coverage will be
// served into
final CoordinateReferenceSystem targetCRS;
if (gridCRS == null)
targetCRS = reader.getOriginalEnvelope().getCoordinateReferenceSystem();
else
targetCRS = CRS.decode(gridCRS.getGridBaseCRS());
// grab the grid to world transformation
MathTransform gridToCRS = reader.getOriginalGridToWorld(PixelInCell.CELL_CORNER);
if (gridCRS != null) {
Double[] origin = (Double[]) gridCRS.getGridOrigin();
Double[] offsets = (Double[]) gridCRS.getGridOffsets();
// from the specification if grid origin is omitted and the crs
// is 2d the default it's 0,0
if (origin == null) {
origin = new Double[] { 0.0, 0.0 };
}
// if no offsets has been specified we try to default on the
// native ones
if (offsets == null) {
if (!(gridToCRS instanceof AffineTransform2D)
&& !(gridToCRS instanceof IdentityTransform))
throw new WcsException(
"Internal error, the coverage we're playing with does not have an affine transform...");
if (gridToCRS instanceof IdentityTransform) {
if (gridCRS.getGridType().equals(GridType.GT2dSimpleGrid))
offsets = new Double[] { 1.0, 1.0 };
else
offsets = new Double[] { 1.0, 0.0, 0.0, 1.0 };
} else {
AffineTransform2D affine = (AffineTransform2D) gridToCRS;
if (gridCRS.getGridType().equals(GridType.GT2dSimpleGrid))
offsets = new Double[] { affine.getScaleX(), affine.getScaleY() };
else
offsets = new Double[] { affine.getScaleX(), affine.getShearX(),
affine.getShearY(), affine.getScaleY() };
}
}
// building the actual transform for the resulting grid geometry
AffineTransform tx;
if (gridCRS.getGridType().equals(GridType.GT2dSimpleGrid.getXmlConstant())) {
tx = new AffineTransform(offsets[0], 0, 0, offsets[1], origin[0], origin[1]);
} else {
tx = new AffineTransform(offsets[0], offsets[2], offsets[1], offsets[3],
origin[0], origin[1]);
}
gridToCRS = new AffineTransform2D(tx);
}
// now we have enough info to read the coverage, grab the parameters
// and add the grid geometry info
final Map parameters = CoverageUtils.getParametersKVP(reader.getFormat()
.getReadParameters());
final GeneralEnvelope intersected = new GeneralEnvelope(destinationEnvelopeInSourceCRS);
intersected.intersect(originalEnvelope);
final GridGeometry2D destinationGridGeometry =new GridGeometry2D(PixelInCell.CELL_CENTER, gridToCRS, intersected, null);
parameters.put(AbstractGridFormat.READ_GRIDGEOMETRY2D.getName().toString(),
destinationGridGeometry);
coverage = (GridCoverage2D) reader.read(CoverageUtils.getParameters(reader.getFormat()
.getReadParameters(), parameters, true));
if ((coverage == null) || !(coverage instanceof GridCoverage2D)) {
throw new IOException("The requested coverage could not be found.");
}
/**
* Band Select (works on just one field)
*/
GridCoverage2D bandSelectedCoverage = coverage;
String interpolationType = null;
if (request.getRangeSubset() != null) {
if (request.getRangeSubset().getFieldSubset().size() > 1) {
throw new WcsException("Multi field coverages are not supported yet");
}
FieldSubsetType field = (FieldSubsetType) request.getRangeSubset().getFieldSubset()
.get(0);
interpolationType = field.getInterpolationType();
// handle axis subset
if (field.getAxisSubset().size() > 1) {
throw new WcsException("Multi axis coverages are not supported yet");
}
if (field.getAxisSubset().size() == 1) {
// prepare a support structure to quickly get the band index
// of a
// key
List<CoverageDimensionInfo> dimensions = meta.getDimensions();
Map<String, Integer> dimensionMap = new HashMap<String, Integer>();
for (int i = 0; i < dimensions.size(); i++) {
String keyName = dimensions.get(i).getName().replace(' ', '_');
dimensionMap.put(keyName, i);
}