Search in sources :

Example 1 with GridExtent

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

the class StatusBar method apply.

/**
 * Implementation of {@link #applyCanvasGeometry(GridGeometry)} without changing {@link #position} visibility state.
 * Invoking this method usually invalidate the coordinates shown in this status bar. The new coordinates can not be
 * easily recomputed because the {@link #lastX} and {@link #lastY} values may not be valid anymore, as a result of
 * possible changes in JavaFX local coordinate system. Consequently the coordinates should be temporarily hidden
 * until a new {@link MouseEvent} gives us the new local coordinates, unless this method is invoked in a context
 * where we know that the "real world" coordinates should be the same even if local coordinates changed.
 *
 * @param  geometry  geometry of the coverage shown in {@link MapCanvas}, or {@code null}.
 */
private void apply(final GridGeometry geometry) {
    /*
         * Compute values in local variables without modifying `StatusBar` fields for now.
         * The fields will be updated only after we know that this operation is successful.
         */
    MathTransform localToCRS = null;
    CoordinateReferenceSystem crs = null;
    double resolution = 1;
    double[] inflate = null;
    Unit<?> unit = Units.PIXEL;
    if (geometry != null) {
        if (geometry.isDefined(GridGeometry.CRS)) {
            crs = geometry.getCoordinateReferenceSystem();
        }
        if (geometry.isDefined(GridGeometry.GRID_TO_CRS)) {
            localToCRS = geometry.getGridToCRS(PixelInCell.CELL_CENTER);
        }
        /*
             * Compute the precision of coordinates to format. We use the finest resolution,
             * looking only at axes having the same units of measurement than the first axis.
             * This will be used as a fallback if we can not compute the precision specific
             * to a coordinate, for example if we can not compute the derivative.
             */
        if (geometry.isDefined(GridGeometry.RESOLUTION)) {
            double[] resolutions = geometry.getResolution(true);
            if (crs != null && resolutions.length != 0) {
                final CoordinateSystem cs = crs.getCoordinateSystem();
                unit = cs.getAxis(0).getUnit();
                for (int i = 0; i < resolutions.length; i++) {
                    if (unit.equals(cs.getAxis(i).getUnit())) {
                        final double r = resolutions[i];
                        if (r < resolution)
                            resolution = r;
                    }
                }
            }
        }
        /*
             * Add a tolerance factor of ½ pixel when computing the number of significant
             * fraction digits to show in coordinates.
             */
        if (geometry.isDefined(GridGeometry.EXTENT)) {
            final GridExtent extent = geometry.getExtent();
            final int n = extent.getDimension();
            inflate = new double[n];
            for (int i = 0; i < n; i++) {
                inflate[i] = (0.5 / extent.getSize(i)) + 1;
            }
        }
    }
    final boolean sameCRS = Utilities.equalsIgnoreMetadata(objectiveCRS, crs);
    if (localToCRS == null) {
        localToCRS = MathTransforms.identity(BIDIMENSIONAL);
    }
    final int srcDim = Math.max(localToCRS.getSourceDimensions(), BIDIMENSIONAL);
    final int tgtDim = localToCRS.getTargetDimensions();
    /*
         * Remaining code should not fail, so we can start modifying the `StatusBar` fields.
         * The buffers for source and target coordinates are recreated because the number of
         * dimensions may have changed. The `lastX` and `lastY` coordinates are local to the
         * JavaFX view and considered invalid  because they depend on the transforms applied
         * on JavaFX node, which may have changed together with `localToObjectiveCRS` change.
         * So we can not use those values for updating the coordinates shown in status bar.
         * Instead we will wait for the next mouse event to provide new local coordinates.
         */
    ((LocalToObjective) localToObjectiveCRS).setNoCheck(localToCRS);
    targetCoordinates = new GeneralDirectPosition(tgtDim);
    sourceCoordinates = (srcDim == tgtDim) ? targetCoordinates.coordinates : new double[srcDim];
    objectiveCRS = crs;
    // May be updated again below.
    localToPositionCRS = localToCRS;
    inflatePrecisions = inflate;
    precisions = null;
    // Not valid anymove — see above block comment.
    lastX = lastY = Double.NaN;
    if (sameCRS) {
        updateLocalToPositionCRS();
        // Keep the format CRS unchanged since we made `localToPositionCRS` consistent with its value.
        if (fullOperationSearchRequired != null && fullOperationSearchRequired.test(canvas)) {
            setPositionCRS(format.getDefaultCRS());
        }
    } else {
        objectiveToPositionCRS = null;
        // Should be invoked before to set precision.
        setFormatCRS(crs, null);
        crs = OperationFinder.toGeospatial(crs, canvas);
        // May invoke setFormatCRS(…) after background work.
        crs = setReplaceablePositionCRS(crs);
    }
    format.setGroundPrecision(Quantities.create(resolution, unit));
    /*
         * If the CRS changed, we may need to update the selected menu item. It happens when this method
         * is invoked because new data have been loaded, as opposed to this method being invoked after a
         * gesture event (zoom, pan, rotation).
         */
    if (!sameCRS && selectedSystem != null) {
        selectedSystem.set(crs);
    }
}
Also used : GridExtent(org.apache.sis.coverage.grid.GridExtent) GeneralDirectPosition(org.apache.sis.geometry.GeneralDirectPosition) MathTransform(org.opengis.referencing.operation.MathTransform) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Example 2 with GridExtent

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

the class CoverageCanvas method toString.

/**
 * Returns a string representation for debugging purposes.
 * The string content may change in any future version.
 */
@Override
public String toString() {
    if (!Platform.isFxApplicationThread()) {
        return super.toString();
    }
    final String lineSeparator = System.lineSeparator();
    final StringBuilder buffer = new StringBuilder(1000);
    final TableAppender table = new TableAppender(buffer);
    table.setMultiLinesCells(true);
    try {
        table.nextLine('═');
        getGridGeometry().getGeographicExtent().ifPresent((bbox) -> {
            table.append(String.format("Canvas geographic bounding box (λ,ɸ):%n" + "Max: % 10.5f°  % 10.5f°%n" + "Min: % 10.5f°  % 10.5f°", bbox.getEastBoundLongitude(), bbox.getNorthBoundLatitude(), bbox.getWestBoundLongitude(), bbox.getSouthBoundLatitude())).appendHorizontalSeparator();
        });
        final Rectangle2D aoi = getAreaOfInterest();
        final DirectPosition poi = getPointOfInterest(true);
        if (aoi != null && poi != null) {
            table.append(String.format("A/P of interest in objective CRS (x,y):%n" + "Max: %, 16.4f  %, 16.4f%n" + "POI: %, 16.4f  %, 16.4f%n" + "Min: %, 16.4f  %, 16.4f%n", aoi.getMaxX(), aoi.getMaxY(), poi.getOrdinate(0), poi.getOrdinate(1), aoi.getMinX(), aoi.getMinY())).appendHorizontalSeparator();
        }
        final Rectangle source = data.objectiveToData(aoi);
        if (source != null) {
            table.append("Extent in source coverage:").append(lineSeparator).append(String.valueOf(new GridExtent(source))).append(lineSeparator).nextLine();
        }
        table.nextLine('═');
        table.flush();
    } catch (RenderException | TransformException | IOException e) {
        buffer.append(e).append(lineSeparator);
    }
    return buffer.toString();
}
Also used : DirectPosition(org.opengis.geometry.DirectPosition) GridExtent(org.apache.sis.coverage.grid.GridExtent) RenderException(org.apache.sis.portrayal.RenderException) TableAppender(org.apache.sis.io.TableAppender) Rectangle2D(java.awt.geom.Rectangle2D) Rectangle(java.awt.Rectangle) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) TransformException(org.opengis.referencing.operation.TransformException) IOException(java.io.IOException)

Example 3 with GridExtent

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

the class ImageRequest method load.

/**
 * Loads the image. If the coverage has more than {@value #BIDIMENSIONAL} dimensions,
 * only two of them are taken for the image; for all other dimensions, only the values
 * at lowest index will be read.
 *
 * <p>If the {@link #coverage} field was null, it will be initialized as a side-effect.
 * No other fields will be modified.</p>
 *
 * <h4>Thread safety</h4>
 * This class does not need to be thread-safe because it should be used only once in a well-defined life cycle.
 * We nevertheless synchronize as a safety (e.g. user could give the same {@code ImageRequest} to two different
 * {@link CoverageExplorer} instances). In such case the {@link GridCoverage} will be loaded only once,
 * but no caching is done for the {@link RenderedImage} (because usually not needed).
 *
 * @param  task  the task invoking this method (for checking for cancellation).
 * @return the image loaded from the source given at construction time, or {@code null}
 *         if the task has been cancelled.
 * @throws DataStoreException if an error occurred while loading the grid coverage.
 */
final synchronized RenderedImage load(final FutureTask<?> task) throws DataStoreException {
    GridCoverage cv = coverage;
    final Long id = LogHandler.loadingStart(resource);
    try {
        if (cv == null) {
            cv = MultiResolutionImageLoader.getInstance(resource, null).getOrLoad(domain, range);
        }
        coverage = cv = cv.forConvertedValues(true);
        if (task.isCancelled()) {
            return null;
        }
        GridExtent ex = sliceExtent;
        if (ex == null) {
            final GridGeometry gg = cv.getGridGeometry();
            if (gg.getDimension() > MultiResolutionImageLoader.BIDIMENSIONAL) {
                ex = MultiResolutionImageLoader.slice(gg.derive(), gg.getExtent()).getIntersection();
            }
        }
        return cv.render(ex);
    } finally {
        LogHandler.loadingStop(id);
    }
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) GridCoverage(org.apache.sis.coverage.grid.GridCoverage)

Example 4 with GridExtent

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

the class RasterReader method readAsCoverage.

/**
 * Parses a raster from the given input stream and returns as a coverage.
 *
 * @param  input  source of bytes to read.
 * @return the raster as a coverage, or {@code null} if the raster is empty.
 * @throws Exception in an error occurred while reading from the given input or creating the coverage.
 *         Exception type may be I/O, SQL, factory, data store, arithmetic, raster format, <i>etc.</i>,
 *         too numerous for enumerating them all.
 */
public GridCoverage readAsCoverage(final ChannelDataInput input) throws Exception {
    final BufferedImage image = readAsImage(input);
    if (image == null) {
        return null;
    }
    CoordinateReferenceSystem crs = null;
    final int srid = getSRID();
    if (spatialRefSys != null) {
        crs = spatialRefSys.fetchCRS(srid);
    } else if (srid > 0) {
        crs = CRS.forCode(Constants.EPSG + ':' + srid);
    }
    if (crs == null) {
        crs = defaultCRS;
    }
    final GridExtent extent = new GridExtent(image.getWidth(), image.getHeight());
    final GridGeometry domain = new GridGeometry(extent, ANCHOR, getGridToCRS(), crs);
    /*
         * Create pseudo-categories with a transfer function if we need to specify "no data" value,
         * or the sign of stored data do not match the sign of expected values.
         */
    List<SampleDimension> range = null;
    if (needsTransferFunction()) {
        final SampleDimension[] sd = new SampleDimension[bands.length];
        final SampleDimension.Builder builder = new SampleDimension.Builder();
        for (int b = 0; b < sd.length; b++) {
            final Band band = bands[b];
            if ((band.getDataBufferType() & OPPOSITE_SIGN) != 0) {
                // See `Band.OPPOSITE_SIGN` javadoc for more information on this limitation.
                throw new RasterFormatException("Data type not yet supported.");
            }
            sd[b] = builder.setName(b + 1).setBackground(band.noDataValue).build();
            builder.clear();
        }
        range = Arrays.asList(sd);
    }
    return new GridCoverage2D(domain, range, image);
}
Also used : GridGeometry(org.apache.sis.coverage.grid.GridGeometry) GridExtent(org.apache.sis.coverage.grid.GridExtent) GridCoverage2D(org.apache.sis.coverage.grid.GridCoverage2D) SampleDimension(org.apache.sis.coverage.SampleDimension) BufferedImage(java.awt.image.BufferedImage) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) RasterFormatException(java.awt.image.RasterFormatException)

Example 5 with GridExtent

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

the class AbstractGridResource method logReadOperation.

/**
 * Logs the execution of a {@link #read(GridGeometry, int...)} operation.
 * The log level will be {@link Level#FINE} if the operation was quick enough,
 * or {@link PerformanceLevel#SLOW} or higher level otherwise.
 *
 * @param  file        the file that was opened, or {@code null} for {@link #getSourceName()}.
 * @param  domain      domain of the created grid coverage.
 * @param  startTime   value of {@link System#nanoTime()} when the loading process started.
 */
protected final void logReadOperation(final Object file, final GridGeometry domain, final long startTime) {
    final Logger logger = getLogger();
    final long nanos = System.nanoTime() - startTime;
    final Level level = PerformanceLevel.forDuration(nanos, TimeUnit.NANOSECONDS);
    if (logger.isLoggable(level)) {
        final Locale locale = getLocale();
        final Object[] parameters = new Object[6];
        parameters[0] = IOUtilities.filename(file != null ? file : getSourceName());
        parameters[5] = nanos / (double) StandardDateFormat.NANOS_PER_SECOND;
        JDK9.ifPresentOrElse(domain.getGeographicExtent(), (box) -> {
            final AngleFormat f = new AngleFormat(locale);
            double min = box.getSouthBoundLatitude();
            double max = box.getNorthBoundLatitude();
            f.setPrecision(max - min, true);
            f.setRoundingMode(RoundingMode.FLOOR);
            parameters[1] = f.format(new Latitude(min));
            f.setRoundingMode(RoundingMode.CEILING);
            parameters[2] = f.format(new Latitude(max));
            min = box.getWestBoundLongitude();
            max = box.getEastBoundLongitude();
            f.setPrecision(max - min, true);
            f.setRoundingMode(RoundingMode.FLOOR);
            parameters[3] = f.format(new Longitude(min));
            f.setRoundingMode(RoundingMode.CEILING);
            parameters[4] = f.format(new Longitude(max));
        }, () -> {
            // If no geographic coordinates, fallback on the 2 first dimensions.
            if (domain.isDefined(GridGeometry.ENVELOPE)) {
                final Envelope box = domain.getEnvelope();
                final int dimension = Math.min(box.getDimension(), 2);
                for (int t = 1, i = 0; i < dimension; i++) {
                    parameters[t++] = box.getMinimum(i);
                    parameters[t++] = box.getMaximum(i);
                }
            } else if (domain.isDefined(GridGeometry.EXTENT)) {
                final GridExtent box = domain.getExtent();
                final int dimension = Math.min(box.getDimension(), 2);
                for (int t = 1, i = 0; i < dimension; i++) {
                    parameters[t++] = box.getLow(i);
                    parameters[t++] = box.getHigh(i);
                }
            }
        });
        final LogRecord record = Resources.forLocale(locale).getLogRecord(level, Resources.Keys.LoadedGridCoverage_6, parameters);
        record.setSourceClassName(GridCoverageResource.class.getName());
        record.setSourceMethodName("read");
        record.setLoggerName(logger.getName());
        logger.log(record);
    }
}
Also used : Locale(java.util.Locale) GridExtent(org.apache.sis.coverage.grid.GridExtent) Latitude(org.apache.sis.measure.Latitude) AngleFormat(org.apache.sis.measure.AngleFormat) Logger(java.util.logging.Logger) Envelope(org.opengis.geometry.Envelope) Longitude(org.apache.sis.measure.Longitude) LogRecord(java.util.logging.LogRecord) GridCoverageResource(org.apache.sis.storage.GridCoverageResource) Level(java.util.logging.Level) PerformanceLevel(org.apache.sis.util.logging.PerformanceLevel)

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