*/
private WCSEnvelope extractSubsettingEnvelope() {
//default envelope in subsettingCRS
final CoordinateReferenceSystem sourceCRS = reader.getCoordinateReferenceSystem();
WCSEnvelope sourceEnvelopeInSubsettingCRS = new WCSEnvelope(reader.getOriginalEnvelope());
if (!(subsettingCRS == null || CRS.equalsIgnoreMetadata(subsettingCRS, sourceCRS))) {
// reproject source envelope to subsetting crs for initialization
try {
sourceEnvelopeInSubsettingCRS = new WCSEnvelope(CRS.transform(
reader.getOriginalEnvelope(), subsettingCRS));
} catch (Exception e) {
try {
// see if we can get a valid restricted area using the projection handlers
ProjectionHandler handler = ProjectionHandlerFinder.getHandler(
new ReferencedEnvelope(0, 1, 0, 1, subsettingCRS), sourceCRS, false);
if (handler != null) {
ReferencedEnvelope validArea = handler.getValidAreaBounds();
Envelope intersection = validArea.intersection(ReferencedEnvelope
.reference(reader.getOriginalEnvelope()));
ReferencedEnvelope re = new ReferencedEnvelope(intersection, sourceCRS);
sourceEnvelopeInSubsettingCRS = new WCSEnvelope(re.transform(subsettingCRS,
true));
} else {
throw new WCS20Exception("Unable to initialize subsetting envelope",
WCS20Exception.WCS20ExceptionCode.SubsettingCrsNotSupported,
subsettingCRS.toWKT(), e); // TODO extract code
}
} catch (Exception e2) {
throw new WCS20Exception("Unable to initialize subsetting envelope",
WCS20Exception.WCS20ExceptionCode.SubsettingCrsNotSupported,
subsettingCRS.toWKT(), e2); // TODO extract code
}
}
}
// check if we have to subset, if not let's send back the basic coverage
final EList<DimensionSubsetType> requestedDimensions = request.getDimensionSubset();
if(requestedDimensions==null||requestedDimensions.size()<=0){
return sourceEnvelopeInSubsettingCRS;
}
int maxDimensions = 2 + enabledDimensions.size();
if(requestedDimensions.size() > maxDimensions){
throw new WCS20Exception(
"Invalid number of dimensions",
WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,Integer.toString(requestedDimensions.size()));
}
// put aside the dimensions that we have for double checking
final List<String> axesNames = envelopeDimensionsMapper.getAxesNames(sourceEnvelopeInSubsettingCRS, true);
final List<String> foundDimensions= new ArrayList<String>();
// === parse dimensions
// the subsetting envelope is initialized with the source envelope in subsetting CRS
WCSEnvelope subsettingEnvelope = new WCSEnvelope(sourceEnvelopeInSubsettingCRS);
Set<String> dimensionKeys = enabledDimensions.keySet();
for (DimensionSubsetType dim : requestedDimensions){
String dimension = WCSDimensionsSubsetHelper.getDimensionName(dim);
// skip time support
if (WCSDimensionsSubsetHelper.TIME_NAMES.contains(dimension.toLowerCase())) {
if (dimensionKeys.contains(ResourceInfo.TIME)) {
// fine, we'll parse it later
continue;
} else {
throw new WCS20Exception("Invalid axis label provided: " + dimension,
WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel, null);
}
}
if (WCSDimensionsSubsetHelper.ELEVATION_NAMES.contains(dimension.toLowerCase())) {
if (dimensionKeys.contains(ResourceInfo.ELEVATION)) {
// fine, we'll parse it later
continue;
} else {
throw new WCS20Exception("Invalid axis label provided: " + dimension,
WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel, null);
}
}
boolean isCustomDimension = false;
for (String dimensionKey : dimensionKeys){
if (dimensionKey.equalsIgnoreCase(dimension)) {
isCustomDimension = true;
break;
}
}
if (isCustomDimension) {
continue;
}
if(!axesNames.contains(dimension)) {
throw new WCS20Exception("Invalid axis label provided: " + dimension,
WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,
dimension == null ? "Null" : dimension);
}
// did we already do something with this dimension?
if(foundDimensions.contains(dimension)){
throw new WCS20Exception("Axis label already used during subsetting",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
}
foundDimensions.add(dimension);
// now decide what to do
// final String CRS= dim.getCRS();// TODO HOW DO WE USE THIS???
if(dim instanceof DimensionTrimType){
// TRIMMING
final DimensionTrimType trim = (DimensionTrimType) dim;
final double low = Double.parseDouble(trim.getTrimLow());
final double high = Double.parseDouble(trim.getTrimHigh());
final int axisIndex = envelopeDimensionsMapper.getAxisIndex(sourceEnvelopeInSubsettingCRS, dimension);
if (axisIndex < 0) {
throw new WCS20Exception("Invalid axis provided",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
}
// low > high && not dateline wrapping?
if (low > high && !subsettingEnvelope.isLongitude(axisIndex)) {
throw new WCS20Exception("Low greater than High",
WCS20Exception.WCS20ExceptionCode.InvalidSubsetting, trim.getTrimLow());
}
// notice how we choose the order of the axes
subsettingEnvelope.setRange(axisIndex, low, high);
} else if (dim instanceof DimensionSliceType) {
// SLICING
final DimensionSliceType slicing= (DimensionSliceType) dim;
final String slicePointS = slicing.getSlicePoint();
final double slicePoint=Double.parseDouble(slicePointS);
final int axisIndex=envelopeDimensionsMapper.getAxisIndex(sourceEnvelopeInSubsettingCRS, dimension);
if (axisIndex < 0) {
throw new WCS20Exception("Invalid axis provided",WCS20Exception.WCS20ExceptionCode.InvalidAxisLabel,dimension);
}
// notice how we choose the order of the axes
AffineTransform affineTransform = RequestUtils.getAffineTransform(reader.getOriginalGridToWorld(PixelInCell.CELL_CENTER));
final double scale = axisIndex == 0 ? affineTransform.getScaleX() : -affineTransform.getScaleY();
subsettingEnvelope.setRange(axisIndex, slicePoint, slicePoint + scale);
// slice point outside coverage
if (sourceEnvelopeInSubsettingCRS.getMinimum(axisIndex) > slicePoint || slicePoint > sourceEnvelopeInSubsettingCRS.getMaximum(axisIndex)){
throw new WCS20Exception(
"SlicePoint outside coverage envelope",
WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,
slicePointS);
}
} else {
throw new WCS20Exception(
"Invalid element found while attempting to parse dimension subsetting request",
WCS20Exception.WCS20ExceptionCode.InvalidSubsetting,
dim.getClass().toString());
}
}
// make sure we have not been requested to subset outside of the source CRS
requestedEnvelope = new WCSEnvelope(subsettingEnvelope);
subsettingEnvelope.intersect(new GeneralEnvelope(sourceEnvelopeInSubsettingCRS));
if (subsettingEnvelope.isEmpty()) {
throw new WCS20Exception("Empty intersection after subsetting",
WCS20Exception.WCS20ExceptionCode.InvalidSubsetting, "");// TODO spit our
// envelope trimmed
}