in common/src/main/java/org/apache/sedona/common/raster/RasterBandEditors.java [282:404]
public static GridCoverage2D clip(
GridCoverage2D raster,
int band,
Geometry geometry,
boolean allTouched,
double noDataValue,
boolean crop,
boolean lenient)
throws FactoryException, TransformException {
// Selecting the band from original raster
RasterUtils.ensureBand(raster, band);
GridCoverage2D singleBandRaster = RasterBandAccessors.getBand(raster, new int[] {band});
Pair<GridCoverage2D, Geometry> pair =
RasterUtils.setDefaultCRSAndTransform(singleBandRaster, geometry);
singleBandRaster = pair.getLeft();
geometry = pair.getRight();
// Crop the raster
// this will shrink the extent of the raster to the geometry
Crop cropObject = new Crop();
ParameterValueGroup parameters = cropObject.getParameters();
parameters.parameter("Source").setValue(singleBandRaster);
parameters.parameter(Crop.PARAMNAME_DEST_NODATA).setValue(new double[] {noDataValue});
parameters.parameter(Crop.PARAMNAME_ROI).setValue(geometry);
GridCoverage2D newRaster;
try {
newRaster = (GridCoverage2D) cropObject.doOperation(parameters, null);
} catch (CannotCropException e) {
if (lenient) {
return null;
} else {
throw e;
}
}
if (!crop) {
double[] metadataOriginal = RasterAccessors.metadata(raster);
int widthOriginalRaster = (int) metadataOriginal[2],
heightOriginalRaster = (int) metadataOriginal[3];
Raster rasterData = RasterUtils.getRaster(raster.getRenderedImage());
// create a new raster and set a default value that's the no-data value
String bandType = RasterBandAccessors.getBandType(raster, 1);
int dataTypeCode = RasterUtils.getDataTypeCode(RasterBandAccessors.getBandType(raster, 1));
boolean isDataTypeIntegral = RasterUtils.isDataTypeIntegral(dataTypeCode);
WritableRaster resultRaster =
RasterFactory.createBandedRaster(
dataTypeCode, widthOriginalRaster, heightOriginalRaster, 1, null);
int sizeOfArray = widthOriginalRaster * heightOriginalRaster;
if (isDataTypeIntegral) {
int[] array =
ArrayUtils.toPrimitive(
Collections.nCopies(sizeOfArray, (int) noDataValue)
.toArray(new Integer[sizeOfArray]));
resultRaster.setSamples(0, 0, widthOriginalRaster, heightOriginalRaster, 0, array);
} else {
double[] array =
ArrayUtils.toPrimitive(
Collections.nCopies(sizeOfArray, noDataValue).toArray(new Double[sizeOfArray]));
resultRaster.setSamples(0, 0, widthOriginalRaster, heightOriginalRaster, 0, array);
}
// rasterize the geometry to iterate over the clipped raster
GridCoverage2D rasterized =
RasterConstructors.asRaster(geometry, raster, bandType, allTouched, 150);
Raster rasterizedData = RasterUtils.getRaster(rasterized.getRenderedImage());
double[] metadataRasterized = RasterAccessors.metadata(rasterized);
int widthRasterized = (int) metadataRasterized[2],
heightRasterized = (int) metadataRasterized[3];
for (int j = 0; j < heightRasterized; j++) {
for (int i = 0; i < widthRasterized; i++) {
Point2D point = RasterUtils.getWorldCornerCoordinates(rasterized, i, j);
int[] rasterCoord =
RasterUtils.getGridCoordinatesFromWorld(raster, point.getX(), point.getY());
int x = Math.abs(rasterCoord[0]), y = Math.abs(rasterCoord[1]);
if (rasterizedData.getPixel(i, j, (int[]) null)[0] == 0) {
continue;
}
if (isDataTypeIntegral) {
int[] pixelValue = rasterData.getPixel(x, y, (int[]) null);
resultRaster.setPixel(x, y, new int[] {pixelValue[band - 1]});
} else {
double[] pixelValue = rasterData.getPixel(x, y, (double[]) null);
resultRaster.setPixel(x, y, new double[] {pixelValue[band - 1]});
}
}
}
newRaster =
RasterUtils.clone(
resultRaster,
raster.getGridGeometry(),
newRaster.getSampleDimensions(),
newRaster,
noDataValue,
true);
} else {
RenderedImage image = newRaster.getRenderedImage();
int minX = image.getMinX();
int minY = image.getMinY();
if (minX != 0 || minY != 0) {
newRaster = RasterUtils.shiftRasterToZeroOrigin(newRaster, noDataValue);
} else {
newRaster =
RasterUtils.clone(
newRaster.getRenderedImage(),
newRaster.getGridGeometry(),
newRaster.getSampleDimensions(),
newRaster,
noDataValue,
true);
}
}
return newRaster;
}