Skip to content

Commit

Permalink
GetCoverage support for scaling, interpolation, crs, range subsetting
Browse files Browse the repository at this point in the history
  • Loading branch information
Simone Giannecchini authored and aaime committed Dec 17, 2012
1 parent 149b2f3 commit a2a6e00
Show file tree
Hide file tree
Showing 37 changed files with 1,991 additions and 448 deletions.
2 changes: 1 addition & 1 deletion src/community/wcs2_0/src/main/java/applicationContext.xml
Expand Up @@ -114,7 +114,7 @@
</bean>

<!-- Envelope dimensions mapper util class-->
<bean id="envelopeDimensionsMapper" class="org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper"/>
<bean id="envelopeDimensionsMapper" class="org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper"/>


<bean id="GMLCoverageResponseDelegate" class="org.geoserver.wcs2_0.response.GMLCoverageResponseDelegate">
Expand Down
Expand Up @@ -18,7 +18,7 @@
import org.geoserver.wcs.responses.CoverageResponseDelegateFinder;
import org.geoserver.wcs2_0.exception.WCS20Exception;
import org.geoserver.wcs2_0.response.WCS20DescribeCoverageTransformer;
import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geotools.util.logging.Logging;
import org.geotools.xml.transform.TransformerBase;
import org.opengis.coverage.grid.GridCoverage;
Expand All @@ -39,13 +39,13 @@ public class DefaultWebCoverageService20 implements WebCoverageService20 {
private CoverageResponseDelegateFinder responseFactory;

/** Utility class to map envelope dimension*/
private EnvelopeDimensionsMapper envelopeDimensionsMapper;
private EnvelopeAxesLabelsMapper envelopeAxesMapper;

public DefaultWebCoverageService20(GeoServer geoServer, CoverageResponseDelegateFinder responseFactory, EnvelopeDimensionsMapper envelopeDimensionsMapper) {
public DefaultWebCoverageService20(GeoServer geoServer, CoverageResponseDelegateFinder responseFactory, EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.geoServer = geoServer;
this.catalog = geoServer.getCatalog();
this.responseFactory = responseFactory;
this.envelopeDimensionsMapper=envelopeDimensionsMapper;
this.envelopeAxesMapper=envelopeDimensionsMapper;
}

@Override
Expand All @@ -67,12 +67,12 @@ public WCS20DescribeCoverageTransformer describeCoverage(DescribeCoverageType re
checkVersion(request.getVersion());

if( request.getCoverageId() == null || request.getCoverageId().isEmpty() ) {
throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCSExceptionCode.EmptyCoverageIdList, "coverageId");
throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCS20ExceptionCode.EmptyCoverageIdList, "coverageId");
}

WCSInfo wcs = getServiceInfo();

WCS20DescribeCoverageTransformer describeTransformer = new WCS20DescribeCoverageTransformer(wcs, catalog, responseFactory,envelopeDimensionsMapper);
WCS20DescribeCoverageTransformer describeTransformer = new WCS20DescribeCoverageTransformer(wcs, catalog, responseFactory,envelopeAxesMapper);
describeTransformer.setEncoding(Charset.forName(wcs.getGeoServer().getSettings().getCharset()));
return describeTransformer;
}
Expand All @@ -83,10 +83,10 @@ public GridCoverage getCoverage(GetCoverageType request) {
checkVersion(request.getVersion());

if( request.getCoverageId() == null || "".equals(request.getCoverageId()) ) {
throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCSExceptionCode.EmptyCoverageIdList, "coverageId");
throw new OWS20Exception("Required parameter coverageId missing", WCS20Exception.WCS20ExceptionCode.EmptyCoverageIdList, "coverageId");
}

return new GetCoverage(getServiceInfo(), catalog,envelopeDimensionsMapper).run(request);
return new GetCoverage(getServiceInfo(), catalog,envelopeAxesMapper).run(request);
}

private void checkVersion(String version) {
Expand Down
758 changes: 621 additions & 137 deletions src/community/wcs2_0/src/main/java/org/geoserver/wcs2_0/GetCoverage.java

Large diffs are not rendered by default.

Expand Up @@ -21,16 +21,34 @@ public class WCS20Exception extends OWS20Exception {
*/
private static final long serialVersionUID = -6110652531274829497L;

public static class WCSExceptionCode extends OWS20Exception.OWSExceptionCode {
public static class WCS20ExceptionCode extends OWS20Exception.OWSExceptionCode {

public final static OWSExceptionCode NoSuchCoverage = new WCSExceptionCode("NoSuchCoverage", 404);
public final static OWSExceptionCode EmptyCoverageIdList = new WCSExceptionCode("emptyCoverageIdList", 404);
public final static OWSExceptionCode InvalidEncodingSyntax = new WCSExceptionCode("InvalidEncodingSyntax", 400);
public final static OWSExceptionCode InvalidScaleFactor = new WCSExceptionCode("InvalidScaleFactor", 404);
public final static OWSExceptionCode InvalidExtent = new WCSExceptionCode("InvalidExtent", 404);
public final static OWSExceptionCode ScalingAxisUndefined = new WCSExceptionCode("ScalingAxisUndefined", 404);
public final static WCS20ExceptionCode EmptyCoverageIdList = new WCS20ExceptionCode("emptyCoverageIdList", 404);
public final static WCS20ExceptionCode InvalidEncodingSyntax = new WCS20ExceptionCode("InvalidEncodingSyntax", 400);

// Scaling Extension
public final static WCS20ExceptionCode InvalidScaleFactor = new WCS20ExceptionCode("InvalidScaleFactor", 404);
public final static WCS20ExceptionCode InvalidExtent = new WCS20ExceptionCode("InvalidExtent", 404);
public final static WCS20ExceptionCode ScaleAxisUndefined = new WCS20ExceptionCode("ScaleAxisUndefined", 404);


// Interpolation Extension
public final static WCS20ExceptionCode NoSuchAxis = new WCS20ExceptionCode("ScalingAxisUndefined", 404);
public final static WCS20ExceptionCode InterpolationMethodNotSupported = new WCS20ExceptionCode("InterpolationMethodNotSupported", 404);

// CRS Extension
public final static WCS20ExceptionCode NotACrs = new WCS20ExceptionCode("NotACrs", 404);
public final static WCS20ExceptionCode SubsettingCrsNotSupported = new WCS20ExceptionCode("SubsettingCrs-NotSupported", 404);
public final static WCS20ExceptionCode OutputCrsNotSupported = new WCS20ExceptionCode("OutputCrs-NotSupported", 404);


protected WCSExceptionCode(String exceptionCode, Integer httpCode) {
// CORE
public final static WCS20ExceptionCode NoSuchCoverage = new WCS20ExceptionCode("NoSuchCoverage", 404);
public final static WCS20ExceptionCode InvalidSubsetting = new WCS20ExceptionCode("InvalidSubsetting", 404);
public final static WCS20ExceptionCode InvalidAxisLabel = new WCS20ExceptionCode("InvalidAxisLabel", 404);


protected WCS20ExceptionCode(String exceptionCode, Integer httpCode) {
super(exceptionCode, httpCode);
}
}
Expand Down
Expand Up @@ -11,7 +11,7 @@

import org.geoserver.ows.KvpParser;
import org.geoserver.platform.OWS20Exception;
import org.geoserver.wcs2_0.exception.WCS20Exception.WCSExceptionCode;
import org.geoserver.wcs2_0.exception.WCS20Exception.WCS20ExceptionCode;

/**
* Parses the WCS 2.0 subset key
Expand Down Expand Up @@ -44,7 +44,7 @@ public Object parse(String value) throws Exception {

if (openIdx == -1 || closeIdx == -1 || closeIdx < value.length() - 1) {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected",
WCSExceptionCode.InvalidEncodingSyntax, "subset");
WCS20ExceptionCode.InvalidEncodingSyntax, "subset");

}

Expand All @@ -61,7 +61,7 @@ public Object parse(String value) throws Exception {
crs = dcElements[1];
} else {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected",
WCSExceptionCode.InvalidEncodingSyntax, "subset");
WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}

// parse the second part, intervalOrPoint
Expand Down Expand Up @@ -89,7 +89,7 @@ public Object parse(String value) throws Exception {
} else {
throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) "
+ "where interval or point has either 1 or two elements",
WCSExceptionCode.InvalidEncodingSyntax, "subset");
WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
}

Expand All @@ -102,7 +102,7 @@ private String parsePoint(String point, boolean allowStar) {
} else {
throw new OWS20Exception(
"Invalid usage of *, it can be used only when specifying an interval",
WCSExceptionCode.InvalidEncodingSyntax, "subset");
WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
} else if (point.startsWith("\"") && point.endsWith("\"")) {
point = point.substring(1, point.length() - 1);
Expand All @@ -113,7 +113,7 @@ private String parsePoint(String point, boolean allowStar) {
} catch (NumberFormatException e) {
throw new OWS20Exception("Invalid point value " + point
+ ", it is not a number and it's not between double quotes",
WCSExceptionCode.InvalidEncodingSyntax, "subset");
WCS20ExceptionCode.InvalidEncodingSyntax, "subset");
}
}

Expand Down
Expand Up @@ -16,6 +16,8 @@
*/
package org.geoserver.wcs2_0.response;

import java.awt.image.DataBuffer;
import java.awt.image.RenderedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
Expand All @@ -25,11 +27,14 @@

import javax.measure.unit.Unit;
import javax.measure.unit.UnitFormat;
import javax.media.jai.PlanarImage;
import javax.media.jai.iterator.RectIter;
import javax.media.jai.iterator.RectIterFactory;
import javax.xml.transform.TransformerException;

import org.geoserver.platform.ServiceException;
import org.geoserver.wcs.responses.CoverageResponseDelegate;
import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geotools.coverage.GridSampleDimension;
import org.geotools.coverage.TypeMap;
import org.geotools.coverage.grid.GridCoverage2D;
Expand Down Expand Up @@ -82,9 +87,9 @@ public class GMLCoverageResponseDelegate implements CoverageResponseDelegate {
*/
private static class GMLTransformer extends TransformerBase{

private EnvelopeDimensionsMapper envelopeDimensionsMapper;
private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;

public GMLTransformer(EnvelopeDimensionsMapper envelopeDimensionsMapper ) {
public GMLTransformer(EnvelopeAxesLabelsMapper envelopeDimensionsMapper ) {
this.envelopeDimensionsMapper=envelopeDimensionsMapper;
}

Expand Down Expand Up @@ -321,7 +326,7 @@ private void handleRange(GridCoverage2D gc2d) {
end("gml:rangeParameters");

start("tupleList");
// // walk through the coverage and spit it out!
// walk through the coverage and spit it out!
// final RenderedImage raster= gc2d.getRenderedImage();
// final int numBands=raster.getSampleModel().getNumBands();
// final int dataType=raster.getSampleModel().getDataType();
Expand Down Expand Up @@ -411,10 +416,11 @@ private void handleRangeType(GridCoverage2D gc2d) {
// get bands
final SampleDimension[] bands= gc2d.getSampleDimensions();


// handle bands
int i=1;
for(SampleDimension sd:bands){
final AttributesImpl fieldAttr = new AttributesImpl();
fieldAttr.addAttribute("", "name", "name", "", sd.getDescription().toString()); // TODO NCNAME?
fieldAttr.addAttribute("", "name", "name", "", "band"+i++);//sd.getDescription().toString()); // TODO NCNAME?
start("swe:field",fieldAttr);

start("swe:Quantity");
Expand Down Expand Up @@ -619,11 +625,11 @@ public Translator createTranslator(ContentHandler handler) {
}

/** Can be used to map dimensions name to indexes*/
private EnvelopeDimensionsMapper envelopeDimensionsMapper;
private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;



public GMLCoverageResponseDelegate(EnvelopeDimensionsMapper envelopeDimensionsMapper) {
public GMLCoverageResponseDelegate(EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.envelopeDimensionsMapper=envelopeDimensionsMapper;

}
Expand Down
Expand Up @@ -17,7 +17,7 @@
import org.geoserver.wcs.responses.CoverageResponseDelegateFinder;
import org.geoserver.wcs2_0.WCS20Const;
import org.geoserver.wcs2_0.exception.WCS20Exception;
import org.geoserver.wcs2_0.util.EnvelopeDimensionsMapper;
import org.geoserver.wcs2_0.util.EnvelopeAxesLabelsMapper;
import org.geoserver.wcs2_0.util.NCNameResourceCodec;
import org.geoserver.wcs2_0.util.StringUtils;
import org.geotools.geometry.jts.ReferencedEnvelope;
Expand Down Expand Up @@ -46,12 +46,12 @@ public class WCS20DescribeCoverageTransformer extends TransformerBase {
private CoverageResponseDelegateFinder responseFactory;

/** Utility class to map envelope dimension*/
private EnvelopeDimensionsMapper envelopeDimensionsMapper;
private EnvelopeAxesLabelsMapper envelopeDimensionsMapper;

/**
* Creates a new WFSCapsTransformer object.
*/
public WCS20DescribeCoverageTransformer(WCSInfo wcs, Catalog catalog, CoverageResponseDelegateFinder responseFactory,EnvelopeDimensionsMapper envelopeDimensionsMapper) {
public WCS20DescribeCoverageTransformer(WCSInfo wcs, Catalog catalog, CoverageResponseDelegateFinder responseFactory,EnvelopeAxesLabelsMapper envelopeDimensionsMapper) {
this.wcs = wcs;
this.catalog = catalog;
this.responseFactory = responseFactory;
Expand Down Expand Up @@ -105,7 +105,7 @@ public void encode(Object o) throws IllegalArgumentException {
if( ! badCoverageIds.isEmpty() ) {
String mergedIds = StringUtils.merge(badCoverageIds);
throw new WCS20Exception("Could not find the requested coverage(s): " + mergedIds
, WCS20Exception.WCSExceptionCode.NoSuchCoverage, mergedIds);
, WCS20Exception.WCS20ExceptionCode.NoSuchCoverage, mergedIds);
}

// ok: build the response
Expand Down
Expand Up @@ -28,6 +28,7 @@
import org.geotools.util.logging.Logging;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;

Expand All @@ -38,17 +39,17 @@
* TODO caching depending on CRS?
* TODO handle composite CRS
*/
public class EnvelopeDimensionsMapper {
public class EnvelopeAxesLabelsMapper {

/** Logger for this class*/
private final static Logger LOGGER= Logging.getLogger(EnvelopeDimensionsMapper.class);
private final static Logger LOGGER= Logging.getLogger(EnvelopeAxesLabelsMapper.class);

public List<String> getAxesNames(Envelope envelope, boolean swapAxes){
Utilities.ensureNonNull("envelope", envelope);
final CoordinateReferenceSystem crs= envelope.getCoordinateReferenceSystem();

// handle axes switch for geographic crs
final boolean axesSwitch= CRS.getAxisOrder(crs)==AxisOrder.EAST_NORTH&&swapAxes;
final boolean axesSwitch= crs instanceof GeographicCRS &&swapAxes;

// additional fields for CRS
final CoordinateSystem cs=crs.getCoordinateSystem();
Expand Down

0 comments on commit a2a6e00

Please sign in to comment.