Skip to content

Commit

Permalink
GEOS-8159: Better harmonize ROI computations and management
Browse files Browse the repository at this point in the history
  • Loading branch information
dromagnoli committed Jun 6, 2017
1 parent 19ac699 commit bfa5603
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 21 deletions.
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;


import org.geotools.referencing.CRS;
import org.geotools.util.logging.Logging; import org.geotools.util.logging.Logging;
import org.opengis.referencing.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;


import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.Geometry;


Expand All @@ -25,7 +28,7 @@ final class ROIManager {
private static final Logger LOGGER = Logging.getLogger(ROIManager.class); private static final Logger LOGGER = Logging.getLogger(ROIManager.class);


/** Input Geometry */ /** Input Geometry */
final Geometry roi; final Geometry originalRoi;


/** ROI reprojected in the input ROI CRS */ /** ROI reprojected in the input ROI CRS */
Geometry roiInNativeCRS; Geometry roiInNativeCRS;
Expand All @@ -51,6 +54,9 @@ final class ROIManager {
/** Boolean indicating if the ROI is a BBOX */ /** Boolean indicating if the ROI is a BBOX */
final boolean isROIBBOX; final boolean isROIBBOX;


/** Boolean indicating if the roiCRS equals the targetCRS */
boolean roiCrsEqualsTargetCrs = true;

/** /**
* Constructor. * Constructor.
* *
Expand All @@ -59,7 +65,7 @@ final class ROIManager {
* roi * roi
*/ */
public ROIManager(Geometry roi, CoordinateReferenceSystem roiCRS) { public ROIManager(Geometry roi, CoordinateReferenceSystem roiCRS) {
this.roi = roi; this.originalRoi = roi;
DownloadUtilities.checkPolygonROI(roi); DownloadUtilities.checkPolygonROI(roi);
// Check ROI CRS // Check ROI CRS
if (roiCRS == null) { if (roiCRS == null) {
Expand All @@ -85,7 +91,7 @@ public void useNativeCRS(final CoordinateReferenceSystem nativeCRS) throws IOExc
if (nativeCRS == null) { if (nativeCRS == null) {
throw new IllegalArgumentException("The provided nativeCRS is null"); throw new IllegalArgumentException("The provided nativeCRS is null");
} }
roiInNativeCRS = DownloadUtilities.transformGeometry(roi, nativeCRS); roiInNativeCRS = DownloadUtilities.transformGeometry(originalRoi, nativeCRS);
DownloadUtilities.checkPolygonROI(roiInNativeCRS); DownloadUtilities.checkPolygonROI(roiInNativeCRS);
if (isROIBBOX) { if (isROIBBOX) {
if (LOGGER.isLoggable(Level.FINE)) { if (LOGGER.isLoggable(Level.FINE)) {
Expand All @@ -111,22 +117,35 @@ public void useNativeCRS(final CoordinateReferenceSystem nativeCRS) throws IOExc
* *
* @param targetCRS a valid instance of {@link CoordinateReferenceSystem} * @param targetCRS a valid instance of {@link CoordinateReferenceSystem}
* @throws IOException in case something bad happens. * @throws IOException in case something bad happens.
* @throws FactoryException
*/ */
public void useTargetCRS(final CoordinateReferenceSystem targetCRS) throws IOException { public void useTargetCRS(final CoordinateReferenceSystem targetCRS) throws IOException, FactoryException {
if (targetCRS == null) { if (targetCRS == null) {
throw new IllegalArgumentException("The provided targetCRS is null"); throw new IllegalArgumentException("The provided targetCRS is null");
} }
if (roiInNativeCRS == null) { if (roiInNativeCRS == null) {
throw new IllegalStateException("It looks like useNativeCRS has not been called yet"); throw new IllegalStateException("It looks like useNativeCRS has not been called yet");
} }
this.targetCRS = targetCRS; this.targetCRS = targetCRS;
if (!CRS.equalsIgnoreMetadata(roiCRS, targetCRS)) {

MathTransform reprojectionTrasform = CRS.findMathTransform(roiCRS, targetCRS, true);
if (!reprojectionTrasform.isIdentity()) {
// avoid doing the transform if this is the identity
roiCrsEqualsTargetCrs = false;
}
}

if (isROIBBOX) { if (isROIBBOX) {
// we need to use a larger bbox in native CRS // we need to use a larger bbox in native CRS
roiInTargetCRS = DownloadUtilities.transformGeometry(safeRoiInNativeCRS, targetCRS); roiInTargetCRS = DownloadUtilities.transformGeometry(safeRoiInNativeCRS, targetCRS);
DownloadUtilities.checkPolygonROI(roiInTargetCRS); DownloadUtilities.checkPolygonROI(roiInTargetCRS);
safeRoiInTargetCRS = roiInTargetCRS.getEnvelope(); safeRoiInTargetCRS = roiInTargetCRS.getEnvelope();
safeRoiInTargetCRS.setUserData(targetCRS); safeRoiInTargetCRS.setUserData(targetCRS);


// Back to the minimal roiInTargetCrs for future clipping if needed.
roiInTargetCRS = roiCrsEqualsTargetCrs ? originalRoi : DownloadUtilities.transformGeometry(originalRoi, targetCRS);

// touch safeRoiInNativeCRS // touch safeRoiInNativeCRS
safeRoiInNativeCRS = DownloadUtilities.transformGeometry(safeRoiInTargetCRS, nativeCRS); safeRoiInNativeCRS = DownloadUtilities.transformGeometry(safeRoiInTargetCRS, nativeCRS);
DownloadUtilities.checkPolygonROI(safeRoiInNativeCRS); DownloadUtilities.checkPolygonROI(safeRoiInNativeCRS);
Expand All @@ -149,8 +168,8 @@ public boolean isROIBBOX() {
/** /**
* @return the roi * @return the roi
*/ */
public Geometry getRoi() { public Geometry getOriginalRoi() {
return roi; return originalRoi;
} }


/** /**
Expand Down Expand Up @@ -195,4 +214,18 @@ public CoordinateReferenceSystem getTargetCRS() {
return targetCRS; return targetCRS;
} }


public boolean isRoiCrsEqualsTargetCrs() {
return roiCrsEqualsTargetCrs;
}

public Geometry getTargetRoi(boolean clip) {
if (clip) {
// clipping means carefully following the ROI shape
return isRoiCrsEqualsTargetCrs() ? originalRoi : getRoiInTargetCRS();
} else {
// use envelope of the ROI to simply crop and not clip the raster. This is important since when
// reprojecting we might read a bit more than needed!
return isRoiCrsEqualsTargetCrs() ? originalRoi.getEnvelope() : getSafeRoiInTargetCRS().getEnvelope();
}
}
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import javax.imageio.stream.ImageOutputStream; import javax.imageio.stream.ImageOutputStream;
import javax.media.jai.Interpolation; import javax.media.jai.Interpolation;


import org.apache.commons.lang.ArrayUtils;
import org.geoserver.catalog.CoverageInfo; import org.geoserver.catalog.CoverageInfo;
import org.geoserver.data.util.CoverageUtils; import org.geoserver.data.util.CoverageUtils;
import org.geoserver.platform.resource.Resource; import org.geoserver.platform.resource.Resource;
Expand All @@ -35,7 +34,6 @@
import org.geotools.process.raster.BandSelectProcess; import org.geotools.process.raster.BandSelectProcess;
import org.geotools.process.raster.CropCoverage; import org.geotools.process.raster.CropCoverage;
import org.geotools.referencing.CRS; import org.geotools.referencing.CRS;
import org.geotools.resources.coverage.CoverageUtilities;
import org.geotools.resources.coverage.FeatureUtilities; import org.geotools.resources.coverage.FeatureUtilities;
import org.geotools.util.logging.Logging; import org.geotools.util.logging.Logging;
import org.opengis.filter.Filter; import org.opengis.filter.Filter;
Expand Down Expand Up @@ -236,7 +234,7 @@ public Resource execute(String mimeType, final ProgressListener progressListener


// --> READ // --> READ
originalGridCoverage = reader.read(readParameters); originalGridCoverage = reader.read(readParameters);

// check, the reader might have returned a null coverage // check, the reader might have returned a null coverage
if(originalGridCoverage == null) { if(originalGridCoverage == null) {
throw new WPSException("The reader did not return any data for current input " throw new WPSException("The reader did not return any data for current input "
Expand Down Expand Up @@ -294,18 +292,13 @@ public Resource execute(String mimeType, final ProgressListener progressListener
} }
// Crop or Clip // Crop or Clip
final CropCoverage cropCoverage = new CropCoverage(); // TODO avoid creation final CropCoverage cropCoverage = new CropCoverage(); // TODO avoid creation
if (clip) {
// clipping means carefully following the ROI shape
clippedGridCoverage = cropCoverage.execute(reprojectedGridCoverage, // Get the proper ROI (depending on clip parameter and CRS)
roiManager.getRoiInTargetCRS(), progressListener); Geometry croppingRoi = roiManager.getTargetRoi(clip);
} else { clippedGridCoverage = cropCoverage.execute(reprojectedGridCoverage, croppingRoi, progressListener);
// use envelope of the ROI to simply crop and not clip the raster. This is important since when
// reprojecting we might read a bit more than needed! if (clippedGridCoverage == null) {
clippedGridCoverage = cropCoverage.execute(reprojectedGridCoverage,
roiManager.getSafeRoiInTargetCRS().getEnvelope(), progressListener);
}

if(clippedGridCoverage == null) {
throw new WPSException("No data left after applying the ROI. This means there " throw new WPSException("No data left after applying the ROI. This means there "
+ "is source data, but none matching the requested ROI"); + "is source data, but none matching the requested ROI");
} }
Expand Down

0 comments on commit bfa5603

Please sign in to comment.