use of org.geotoolkit.coverage.grid.GridGeometryIterator in project geotoolkit by Geomatys.
the class Categorize method execute.
@Override
protected void execute() throws ProcessException {
final GridCoverageResource source = getSource();
final WritableGridCoverageResource destination = getDestination();
try {
final GridGeometry inputGG = source.getGridGeometry();
final GridGeometry readGeom;
Envelope env = getEnvelope();
if (env == null) {
env = inputGG.getEnvelope();
readGeom = inputGG;
} else {
MathTransform gridToCRS = inputGG.getGridToCRS(PixelInCell.CELL_CORNER);
GeographicBoundingBox bbox = null;
try {
bbox = ReferencingUtilities.findGeographicBBox(source).orElse(null);
} catch (DataStoreException e) {
/* This error is not directly related to data. It could be
* caused by malformed metadata. In which case, we just
* ignore it.
*/
LOGGER.log(Level.FINE, "Cannot deduce geographic extent from metadata.", e);
}
if (env.getCoordinateReferenceSystem() != null) {
final CoordinateOperation op = CRS.findOperation(inputGG.getCoordinateReferenceSystem(), env.getCoordinateReferenceSystem(), bbox);
gridToCRS = MathTransforms.concatenate(gridToCRS, op.getMathTransform());
// Crop area of interest on source coverage area
final GeneralEnvelope sourceEnv;
try {
sourceEnv = Envelopes.transform(op, inputGG.getEnvelope());
} catch (TransformException ex) {
throw new ProcessException("Cannot check input envelope validity against source coverage.", this, ex);
}
sourceEnv.intersect(env);
env = sourceEnv;
} else {
final GeneralEnvelope tmpEnv = new GeneralEnvelope(env);
tmpEnv.setCoordinateReferenceSystem(inputGG.getCoordinateReferenceSystem());
// Crop area of interest on source coverage area
tmpEnv.intersect(inputGG.getEnvelope());
env = tmpEnv;
}
readGeom = new GridGeometry(PixelInCell.CELL_CORNER, gridToCRS, env, GridRoundingMode.ENCLOSING);
}
final GridGeometryIterator it = new GridGeometryIterator(readGeom);
while (it.hasNext()) {
final GridGeometry sliceGeom = it.next();
final GeneralEnvelope expectedSliceEnvelope = GeneralEnvelope.castOrCopy(sliceGeom.getEnvelope());
GridCoverage sourceCvg = source.read(sliceGeom);
if (sourceCvg instanceof GridCoverageStack) {
// Try to unravel expected slice
final Optional<GridCoverage> slice = extractSlice((GridCoverageStack) sourceCvg, sliceGeom.getEnvelope());
if (slice.isPresent()) {
sourceCvg = slice.get();
}
}
// If the reader has not returned a coverage fitting queried
// geometry, we have to resample input ourselves.
GridCoverage source2D = sourceCvg;
source2D = source2D.forConvertedValues(true);
final boolean compliantCrs = Utilities.equalsApproximately(expectedSliceEnvelope.getCoordinateReferenceSystem(), source2D.getCoordinateReferenceSystem());
final boolean compliantEnvelope = expectedSliceEnvelope.contains(source2D.getGridGeometry().getEnvelope(), true);
if (!(compliantCrs && compliantEnvelope)) {
source2D = resample(source2D, sliceGeom);
}
final RenderedImage slice = categorize(source2D.render(null));
final GridCoverageBuilder builder = new GridCoverageBuilder();
builder.setDomain(source2D.getGridGeometry());
builder.setValues(slice);
final GridCoverage resultCoverage = builder.build();
destination.write(resultCoverage);
}
} catch (TransformException ex) {
throw new ProcessException("Cannot adapt input geometry", this, ex);
} catch (FactoryException ex) {
throw new ProcessException("Failure on EPSG database use", this, ex);
} catch (DataStoreException ex) {
throw new ProcessException("Cannot access either input or output data source", this, ex);
} catch (CancellationException ex) {
throw new DismissProcessException("Process cancelled", this, ex);
}
}
use of org.geotoolkit.coverage.grid.GridGeometryIterator in project geotoolkit by Geomatys.
the class TileMatrixSetBuilder method build.
/**
* Create multi dimension template from grid geometry and parameters.
* If scales are defined they will be used otherwise scales will be computed
* using the interation method defined.
*
* @return created tile matrix set
* @throws IllegalArgumentException if template could not be
* created because grid geometry or parameters doesn't have enough information.
*/
public DefiningTileMatrixSet build() {
ArgumentChecks.ensureNonNull("gridGeom", gridGeometry);
final CoordinateReferenceSystem crs = gridGeometry.getCoordinateReferenceSystem();
final DefiningTileMatrixSet pyramid = new DefiningTileMatrixSet(crs);
// loop on all dimensions
try {
final GridGeometryIterator ite = new GridGeometryIterator(gridGeometry);
while (ite.hasNext()) {
final GridGeometry slice = ite.next();
final Envelope envelope = slice.getEnvelope();
final DirectPosition upperLeft = new GeneralDirectPosition(crs);
// -- We found the second horizontale axis dimension.
final int horizontalOrdinate = CRSUtilities.firstHorizontalAxis(crs);
for (int d = 0; d < crs.getCoordinateSystem().getDimension(); d++) {
final double v = (d == horizontalOrdinate + 1) ? envelope.getMaximum(d) : envelope.getMinimum(d);
upperLeft.setOrdinate(d, v);
}
final double spanX = envelope.getSpan(horizontalOrdinate);
final double spanY = envelope.getSpan(horizontalOrdinate + 1);
if (scales != null) {
int idinc = 0;
for (double scale : scales) {
final String name = isSlice ? "" + idinc++ : UUID.randomUUID().toString();
pyramid.createTileMatrix(createTileMatrix(name, upperLeft, scale, spanX, spanY));
}
} else {
final double[] allRes;
try {
allRes = slice.getResolution(true);
} catch (IncompleteGridGeometryException ex) {
throw new IllegalArgumentException("TileMatrix resolution could not be computed");
}
if (Double.isNaN(allRes[horizontalOrdinate])) {
throw new IllegalArgumentException("Horizontal resolution is undefined on axis " + horizontalOrdinate);
}
if (Double.isNaN(allRes[horizontalOrdinate + 1])) {
throw new IllegalArgumentException("Horizontal resolution is undefined on axis " + (horizontalOrdinate + 1));
}
final double resolution = Double.min(allRes[horizontalOrdinate], allRes[horizontalOrdinate + 1]);
switch(iteration) {
case BOTTOM_TO_TOP:
{
double res = resolution;
DefiningTileMatrix m = createTileMatrix(UUID.randomUUID().toString(), upperLeft, res, spanX, spanY);
Dimension gridSize = m.getGridSize();
pyramid.createTileMatrix(m);
// multiply resolution by given ratio until we reach one or two tiles.
while (gridSize.width * gridSize.height > nbTileThreshold) {
res *= scaleFactor;
m = createTileMatrix(UUID.randomUUID().toString(), upperLeft, res, spanX, spanY);
gridSize = m.getGridSize();
pyramid.createTileMatrix(m);
}
}
break;
case TOP_TO_BOTTOM_STRICT:
buildTopToBottom(pyramid, upperLeft, spanX, spanY, resolution);
break;
case TOP_TO_BOTTOM_LASTEXACT:
{
final Entry<Double, Integer> last = buildTopToBottom(pyramid, upperLeft, spanX, spanY, resolution);
if (last.getKey() > resolution) {
// add a tile matrix with exact resolution
final String name = isSlice ? "" + (last.getValue() + 1) : UUID.randomUUID().toString();
pyramid.createTileMatrix(createTileMatrix("" + name, upperLeft, resolution, spanX, spanY));
}
}
break;
case TOP_TO_BOTTOM_EXTRAPOLATE:
{
final Entry<Double, Integer> last = buildTopToBottom(pyramid, upperLeft, spanX, spanY, resolution);
if (last.getKey() != resolution) {
// add a tile matrix with next resolution
final String name = isSlice ? "" + (last.getValue() + 1) : UUID.randomUUID().toString();
pyramid.createTileMatrix(createTileMatrix("" + name, upperLeft, last.getKey() / scaleFactor, spanX, spanY));
}
}
break;
default:
throw new IllegalArgumentException("Unsupported iteration mode : " + iteration);
}
}
}
return pyramid;
} catch (IncompleteGridGeometryException ex) {
throw new IllegalArgumentException(ex);
}
}
use of org.geotoolkit.coverage.grid.GridGeometryIterator in project geotoolkit by Geomatys.
the class BandCombineProcess method execute.
@Override
protected void execute() throws ProcessException {
ArgumentChecks.ensureNonNull("inputParameter", inputParameters);
// PARAMETERS CHECK ////////////////////////////////////////////////////
final GridCoverage[] inputCoverage = inputParameters.getValue(IN_COVERAGES);
if (inputCoverage.length == 0) {
throw new ProcessException("No coverage to combine", this, null);
} else if (inputCoverage.length == 1) {
// nothing to do
outputParameters.getOrCreate(OUT_COVERAGE).setValue(inputCoverage[0]);
return;
}
// TODO: better logic
GridGeometry outputGeom = null;
// CALL IMAGE BAND COMBINE /////////////////////////////////////////////
final RenderedImage[] images = new RenderedImage[inputCoverage.length];
final List<SampleDimension> sds = new ArrayList<>();
for (int i = 0; i < inputCoverage.length; i++) {
final GridCoverage gridCoverage2D = inputCoverage[i];
final List<SampleDimension> covSds = gridCoverage2D.getSampleDimensions();
if (covSds.isEmpty())
throw new ProcessException("Cannot extract sample dimension from input coverage " + i, this);
sds.addAll(covSds);
final GridGeometry gg = gridCoverage2D.getGridGeometry();
if (gg.getDimension() <= 2) {
images[i] = gridCoverage2D.render(null);
if (outputGeom == null)
outputGeom = gridCoverage2D.getGridGeometry();
} else {
final GridGeometryIterator sliceIt = new GridGeometryIterator(gg);
if (!sliceIt.hasNext())
throw new ProcessException("Input coverage [at index " + i + "] is empty", this);
final GridGeometry nextGeom = sliceIt.next();
if (outputGeom == null)
outputGeom = nextGeom;
images[i] = gridCoverage2D.render(nextGeom.getExtent());
}
}
final ProcessDescriptor imageCombineDesc = org.geotoolkit.processing.image.bandcombine.BandCombineDescriptor.INSTANCE;
final Parameters params = Parameters.castOrWrap(imageCombineDesc.getInputDescriptor().createValue());
params.parameter("images").setValue(images);
final Process process = imageCombineDesc.createProcess(params);
RenderedImage resultImage = (RenderedImage) process.call().parameter("result").getValue();
// REBUILD COVERAGE ////////////////////////////////////////////////////
final GridCoverageBuilder gcb = new GridCoverageBuilder();
gcb.setValues(resultImage);
gcb.setDomain(outputGeom);
gcb.setRanges(sds);
final GridCoverage resultCoverage = gcb.build();
outputParameters.getOrCreate(OUT_COVERAGE).setValue(resultCoverage);
}
Aggregations