Search in sources :

Example 16 with GridExtent

use of org.apache.sis.coverage.grid.GridExtent in project sis by apache.

the class RenderingData method setCoverageSpace.

/**
 * Sets the input space (domain) and output space (ranges) of the coverage to be rendered.
 * It should be followed by a call to {@link #ensureImageLoaded(GridCoverage, GridExtent)}.
 *
 * @param  domain  the two-dimensional grid geometry, or {@code null} if there is no data.
 * @param  ranges  descriptions of bands, or {@code null} if there is no data.
 *
 * @see #isEmpty()
 */
@SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
public final void setCoverageSpace(final GridGeometry domain, final List<SampleDimension> ranges) {
    processor.setFillValues(SampleDimensions.backgrounds(ranges));
    // Not cloned because already an unmodifiable list.
    dataRanges = ranges;
    dataGeometry = domain;
    /*
         * If the grid geometry does not define a "grid to CRS" transform, set it to an identity transform.
         * We do that because this class needs a complete `GridGeometry` as much as possible.
         */
    if (domain != null && !domain.isDefined(GridGeometry.GRID_TO_CRS) && domain.isDefined(GridGeometry.EXTENT)) {
        CoordinateReferenceSystem crs = null;
        if (domain.isDefined(GridGeometry.CRS)) {
            crs = domain.getCoordinateReferenceSystem();
        }
        final GridExtent extent = domain.getExtent();
        dataGeometry = new GridGeometry(extent, PixelInCell.CELL_CENTER, MathTransforms.identity(extent.getDimension()), crs);
    }
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Example 17 with GridExtent

use of org.apache.sis.coverage.grid.GridExtent in project sis by apache.

the class GridGeometryBuilder method build.

/**
 * Creates the grid geometry and collect related metadata.
 * This method shall be invoked exactly once after {@link #validateMandatoryTags()}.
 * After this method call (if successful), the returned value is guaranteed non-null
 * and can be used as a flag for determining that the build has been completed.
 *
 * @param  width   the image width in pixels.
 * @param  height  the image height in pixels.
 * @return the grid geometry, guaranteed non-null.
 * @throws FactoryException if an error occurred while creating a CRS or a transform.
 */
@SuppressWarnings("fallthrough")
public GridGeometry build(final Reader reader, final long width, final long height) throws FactoryException {
    CoordinateReferenceSystem crs = null;
    if (keyDirectory != null) {
        final CRSBuilder helper = new CRSBuilder(reader);
        try {
            crs = helper.build(this);
            description = helper.description;
            cellGeometry = helper.cellGeometry;
        } catch (NoSuchIdentifierException | ParameterNotFoundException e) {
            short key = Resources.Keys.UnsupportedProjectionMethod_1;
            if (e instanceof NoSuchAuthorityCodeException) {
                key = Resources.Keys.UnknownCRS_1;
            }
            reader.store.warning(reader.resources().getString(key, reader.store.getDisplayName()), e);
        } catch (IllegalArgumentException | NoSuchElementException | ClassCastException e) {
            if (!helper.alreadyReported) {
                canNotCreate(reader, e);
            }
        }
    }
    /*
         * If the CRS is non-null, then it is either two- or three-dimensional.
         * The `affine` matrix may be for a greater number of dimensions, so it
         * may need to be reduced.
         */
    int n = (crs != null) ? crs.getCoordinateSystem().getDimension() : 2;
    final DimensionNameType[] axisTypes = new DimensionNameType[n];
    final long[] high = new long[n];
    switch(n) {
        // Fallthrough everywhere.
        default:
            axisTypes[2] = DimensionNameType.VERTICAL;
        case 2:
            axisTypes[1] = DimensionNameType.ROW;
            high[1] = height - 1;
        case 1:
            axisTypes[0] = DimensionNameType.COLUMN;
            high[0] = width - 1;
        case 0:
            break;
    }
    final GridExtent extent = new GridExtent(axisTypes, null, high, true);
    boolean pixelIsPoint = CellGeometry.POINT.equals(cellGeometry);
    final MathTransformFactory factory = DefaultFactories.forBuildin(MathTransformFactory.class);
    GridGeometry gridGeometry;
    try {
        MathTransform gridToCRS;
        if (affine != null) {
            gridToCRS = factory.createAffineTransform(Matrices.resizeAffine(affine, ++n, n));
        } else {
            pixelIsPoint = true;
            gridToCRS = Localization.nonLinear(modelTiePoints);
            gridToCRS = factory.createPassThroughTransform(0, gridToCRS, n - 2);
        }
        gridGeometry = new GridGeometry(extent, pixelIsPoint ? PixelInCell.CELL_CENTER : PixelInCell.CELL_CORNER, gridToCRS, crs);
    } catch (TransformException e) {
        GeneralEnvelope envelope = null;
        if (crs != null) {
            envelope = new GeneralEnvelope(crs);
            envelope.setToNaN();
        }
        gridGeometry = new GridGeometry(extent, envelope, GridOrientation.HOMOTHETY);
        canNotCreate(reader, e);
    /*
             * Note: we catch TransformExceptions because they may be caused by erroneous data in the GeoTIFF file,
             * but let FactoryExceptions propagate because they are more likely to be a SIS configuration problem.
             */
    }
    // Not needed anymore, so let GC do its work.
    keyDirectory = null;
    numericParameters = null;
    asciiParameters = null;
    modelTiePoints = null;
    affine = null;
    return gridGeometry;
}
Also used : NoSuchAuthorityCodeException(org.opengis.referencing.NoSuchAuthorityCodeException) GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) MathTransform(org.opengis.referencing.operation.MathTransform) MathTransformFactory(org.opengis.referencing.operation.MathTransformFactory) TransformException(org.opengis.referencing.operation.TransformException) NoSuchIdentifierException(org.opengis.util.NoSuchIdentifierException) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) ParameterNotFoundException(org.opengis.parameter.ParameterNotFoundException) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) DimensionNameType(org.opengis.metadata.spatial.DimensionNameType) NoSuchElementException(java.util.NoSuchElementException)

Example 18 with GridExtent

use of org.apache.sis.coverage.grid.GridExtent in project sis by apache.

the class Grid method getExtent.

/**
 * Builds the grid extent if the shape is available. The shape may not be available
 * if a dimension has unlimited length. The dimension names are informative only.
 *
 * @param  axes  value of {@link #getAxes(Decoder)}. Element order does not matter for this method.
 * @return the extent, or {@code null} if not available.
 */
@SuppressWarnings("fallthrough")
private GridExtent getExtent(final Axis[] axes) {
    final List<Dimension> dimensions = getDimensions();
    final int n = dimensions.size();
    final long[] high = new long[n];
    for (int i = 0; i < n; i++) {
        final long length = dimensions.get(i).length();
        if (length <= 0)
            return null;
        high[(n - 1) - i] = length;
    }
    final DimensionNameType[] names = new DimensionNameType[n];
    switch(n) {
        // Fall through
        default:
            names[1] = DimensionNameType.ROW;
        // Fall through
        case 1:
            names[0] = DimensionNameType.COLUMN;
        case 0:
            break;
    }
    for (final Axis axis : axes) {
        if (axis.getNumDimensions() == 1) {
            final DimensionNameType name;
            if (AxisDirections.isVertical(axis.direction)) {
                name = DimensionNameType.VERTICAL;
            } else if (AxisDirections.isTemporal(axis.direction)) {
                name = DimensionNameType.TIME;
            } else {
                continue;
            }
            int dim = axis.gridDimensionIndices[0];
            // Convert netCDF order to "natural" order.
            dim = names.length - 1 - dim;
            if (dim >= 0)
                names[dim] = name;
        }
    }
    return new GridExtent(names, null, high, false);
}
Also used : GridExtent(org.apache.sis.coverage.grid.GridExtent) DimensionNameType(org.opengis.metadata.spatial.DimensionNameType)

Example 19 with GridExtent

use of org.apache.sis.coverage.grid.GridExtent in project sis by apache.

the class MetadataBuilder method addSpatialRepresentation.

/**
 * Adds and populates a "spatial representation info" node using the given grid geometry.
 * This method invokes implicitly {@link #newGridRepresentation(GridType)}, unless this
 * method returns {@code false} in which case nothing has been done.
 * Storage locations are:
 *
 * <ul>
 *   <li>{@code metadata/spatialRepresentationInfo/transformationDimensionDescription}</li>
 *   <li>{@code metadata/spatialRepresentationInfo/transformationParameterAvailability}</li>
 *   <li>{@code metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionName}</li>
 *   <li>{@code metadata/spatialRepresentationInfo/axisDimensionProperties/dimensionSize}</li>
 *   <li>{@code metadata/spatialRepresentationInfo/axisDimensionProperties/resolution}</li>
 *   <li>{@code metadata/identificationInfo/spatialRepresentationType}</li>
 *   <li>{@code metadata/referenceSystemInfo}</li>
 * </ul>
 *
 * This method does not add the envelope provided by {@link GridGeometry#getEnvelope()}.
 * That envelope appears in a separated node, which can be added by {@link #addExtent(Envelope)}.
 * This separation is required by {@link AbstractGridResource} for instance.
 *
 * @param  description    a general description of the "grid to CRS" transformation, or {@code null} if none.
 *                        Can also be specified later by a call to {@link #setGridToCRS(CharSequence)}.
 * @param  grid           the grid extent, "grid to CRS" transform and target CRS, or {@code null} if none.
 * @param  addResolution  whether to declare the resolutions. Callers should set this argument to {@code false} if they intend
 *                        to provide the resolution themselves, or if grid axes are not in the same order than CRS axes.
 * @return whether a "spatial representation info" node has been added.
 */
public final boolean addSpatialRepresentation(final String description, final GridGeometry grid, final boolean addResolution) {
    final GridType type;
    if (grid == null) {
        if (description == null) {
            return false;
        }
        type = GridType.UNSPECIFIED;
    } else {
        type = grid.isConversionLinear(0, 1) ? GridType.GEORECTIFIED : GridType.GEOREFERENCEABLE;
    }
    addSpatialRepresentation(SpatialRepresentationType.GRID);
    newGridRepresentation(type);
    setGridToCRS(description);
    if (grid != null) {
        setGeoreferencingAvailability(grid.isDefined(GridGeometry.GRID_TO_CRS), false, false);
        CoordinateSystem cs = null;
        if (grid.isDefined(GridGeometry.CRS)) {
            final CoordinateReferenceSystem crs = grid.getCoordinateReferenceSystem();
            cs = crs.getCoordinateSystem();
            addReferenceSystem(crs);
        }
        if (grid.isDefined(GridGeometry.EXTENT)) {
            final GridExtent extent = grid.getExtent();
            final int dimension = extent.getDimension();
            for (int i = 0; i < dimension; i++) {
                final Optional<DimensionNameType> axisType = extent.getAxisType(i);
                if (axisType.isPresent()) {
                    setAxisName(i, axisType.get());
                }
                setAxisSize(i, extent.getSize(i));
            }
        }
        if (addResolution && grid.isDefined(GridGeometry.RESOLUTION)) {
            final double[] resolution = grid.getResolution(false);
            for (int i = 0; i < resolution.length; i++) {
                setAxisResolution(i, resolution[i], (cs != null) ? cs.getAxis(i).getUnit() : null);
            }
        }
    }
    return true;
}
Also used : GridExtent(org.apache.sis.coverage.grid.GridExtent) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) org.apache.sis.metadata.iso.constraint(org.apache.sis.metadata.iso.constraint) org.opengis.metadata.constraint(org.opengis.metadata.constraint)

Example 20 with GridExtent

use of org.apache.sis.coverage.grid.GridExtent in project sis by apache.

the class TiledGridCoverage method render.

/**
 * Returns a two-dimensional slice of grid data as a rendered image.
 *
 * @param  sliceExtent  a subspace of this grid coverage extent, or {@code null} for the whole image.
 * @return the grid slice as a rendered image. Image location is relative to {@code sliceExtent}.
 */
@Override
public RenderedImage render(GridExtent sliceExtent) {
    final GridExtent available = getGridGeometry().getExtent();
    final int dimension = available.getDimension();
    if (sliceExtent == null) {
        sliceExtent = available;
    } else {
        final int sd = sliceExtent.getDimension();
        if (sd != dimension) {
            throw new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_3, "sliceExtent", dimension, sd));
        }
    }
    final int[] selectedDimensions = sliceExtent.getSubspaceDimensions(BIDIMENSIONAL);
    if (selectedDimensions[1] != 1) {
        // TODO
        throw new UnsupportedOperationException("Non-horizontal slices not yet implemented.");
    }
    final RenderedImage image;
    try {
        // Indices of first tile to read, inclusive.
        final int[] tileLower = new int[dimension];
        // Indices of last tile to read, exclusive.
        final int[] tileUpper = new int[dimension];
        // Pixel offset compared to Area Of Interest.
        final int[] offsetAOI = new int[dimension];
        // Subsampled image size.
        final int[] imageSize = new int[dimension];
        for (int i = 0; i < dimension; i++) {
            // Lowest valid coordinate in subsampled image.
            final long min = available.getLow(i);
            // Highest valid coordinate, inclusive.
            final long max = available.getHigh(i);
            // Requested coordinate in subsampled image.
            final long aoiMin = sliceExtent.getLow(i);
            final long aoiMax = sliceExtent.getHigh(i);
            final long tileUp = incrementExact(toTileMatrixCoordinate(Math.min(aoiMax, max), i));
            final long tileLo = toTileMatrixCoordinate(Math.max(aoiMin, min), i);
            if (tileUp <= tileLo) {
                final String message = Errors.getResources(getLocale()).getString(Errors.Keys.IllegalRange_2, aoiMin, aoiMax);
                if (aoiMin > aoiMax) {
                    throw new IllegalArgumentException(message);
                } else {
                    throw new DisjointExtentException(message);
                }
            }
            // Lower and upper coordinates in subsampled image, rounded to integer number of tiles and clipped to available data.
            final long lower = /* inclusive */
            Math.max(toSubsampledPixel(/* inclusive */
            multiplyExact(tileLo, tileSize[i]), i), min);
            final long upper = incrementExact(Math.min(toSubsampledPixel(decrementExact(multiplyExact(tileUp, tileSize[i])), i), max));
            imageSize[i] = toIntExact(subtractExact(upper, lower));
            offsetAOI[i] = toIntExact(subtractExact(lower, aoiMin));
            tileLower[i] = toIntExact(subtractExact(tileLo, tmcOfFirstTile[i]));
            tileUpper[i] = toIntExact(subtractExact(tileUp, tmcOfFirstTile[i]));
        }
        /*
             * Prepare an iterator over all tiles to read, together with the following properties:
             *    - Two-dimensional conversion from pixel coordinates to "real world" coordinates.
             */
        final AOI iterator = new AOI(tileLower, tileUpper, offsetAOI, dimension);
        final Map<String, Object> properties = DeferredProperty.forGridGeometry(getGridGeometry(), selectedDimensions);
        if (deferredTileReading) {
            image = new TiledDeferredImage(imageSize, tileLower, properties, iterator);
        } else {
            /*
                 * If the loading strategy is not `RasterLoadingStrategy.AT_GET_TILE_TIME`, get all tiles
                 * in the area of interest now. I/O operations, if needed, happen in `readTiles(…)` call.
                 */
            final Raster[] result = readTiles(iterator);
            image = new TiledImage(properties, colors, imageSize[X_DIMENSION], imageSize[Y_DIMENSION], tileLower[X_DIMENSION], tileLower[Y_DIMENSION], result);
        }
    } catch (Exception e) {
        // Too many exception types for listing them all.
        throw new CannotEvaluateException(Resources.forLocale(getLocale()).getString(Resources.Keys.CanNotRenderImage_1, getDisplayName()), e);
    }
    return image;
}
Also used : DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) GridExtent(org.apache.sis.coverage.grid.GridExtent) Raster(java.awt.image.Raster) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) Point(java.awt.Point) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) DataStoreException(org.apache.sis.storage.DataStoreException) IOException(java.io.IOException) CannotEvaluateException(org.apache.sis.coverage.CannotEvaluateException) DisjointExtentException(org.apache.sis.coverage.grid.DisjointExtentException) RenderedImage(java.awt.image.RenderedImage) TiledImage(org.apache.sis.internal.coverage.j2d.TiledImage) CannotEvaluateException(org.apache.sis.coverage.CannotEvaluateException)

Aggregations

GridExtent (org.apache.sis.coverage.grid.GridExtent)22 GridGeometry (org.apache.sis.coverage.grid.GridGeometry)10 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)6 Point (java.awt.Point)4 RenderedImage (java.awt.image.RenderedImage)3 IOException (java.io.IOException)3 SampleDimension (org.apache.sis.coverage.SampleDimension)3 GridCoverage (org.apache.sis.coverage.grid.GridCoverage)3 TransformException (org.opengis.referencing.operation.TransformException)3 Rectangle (java.awt.Rectangle)2 BufferedImage (java.awt.image.BufferedImage)2 GridCoverage2D (org.apache.sis.coverage.grid.GridCoverage2D)2 GridDerivation (org.apache.sis.coverage.grid.GridDerivation)2 RenderException (org.apache.sis.portrayal.RenderException)2 DimensionNameType (org.opengis.metadata.spatial.DimensionNameType)2 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)2 MathTransform (org.opengis.referencing.operation.MathTransform)2 AffineTransform (java.awt.geom.AffineTransform)1 NoninvertibleTransformException (java.awt.geom.NoninvertibleTransformException)1 Rectangle2D (java.awt.geom.Rectangle2D)1