Search in sources :

Example 1 with DimensionNameType

use of org.opengis.metadata.spatial.DimensionNameType in project sis by apache.

the class GridExtent method validateAxisTypes.

/**
 * Verifies that the given array (if non-null) contains no duplicated values, then returns a copy of that array.
 * The returned copy may be shared by many {@code GridExtent} instances. Consequently it shall not be modified.
 *
 * @throws IllegalArgumentException if the given array contains duplicated elements.
 */
@SuppressWarnings("ReturnOfCollectionOrArrayField")
private static DimensionNameType[] validateAxisTypes(DimensionNameType[] types) throws IllegalArgumentException {
    if (types == null) {
        return null;
    }
    if (Arrays.equals(DEFAULT_TYPES, types)) {
        // Common case verified before POOL synchronized lock.
        return DEFAULT_TYPES;
    }
    DimensionNameType[] shared = POOL.get(types);
    if (shared == null) {
        /*
             * Verify the array only if it was not found in the pool. Arrays in the pool were already validated,
             * so do not need to be verified again. The check performed here is inefficient (nested loop), but it
             * should be okay since the arrays are usually small (less than 5 elements) and the checks should not
             * be done often (because of the pool).
             */
        types = types.clone();
        for (int i = 1; i < types.length; i++) {
            final DimensionNameType t = types[i];
            if (t != null) {
                for (int j = i; --j >= 0; ) {
                    if (t.equals(types[j])) {
                        throw new IllegalArgumentException(Errors.format(Errors.Keys.DuplicatedElement_1, t));
                    }
                }
            }
        }
        shared = POOL.putIfAbsent(types, types);
        if (shared == null) {
            return types;
        }
    }
    return shared;
}
Also used : DimensionNameType(org.opengis.metadata.spatial.DimensionNameType)

Example 2 with DimensionNameType

use of org.opengis.metadata.spatial.DimensionNameType in project sis by apache.

the class CanvasExtent method suggestAxisTypes.

/**
 * Suggests axis types for supplemental dimensions not managed by the {@link Canvas}.
 * Those types are only a help for debugging purpose, by providing more information
 * to the developers. They should not be used for any "real" work.
 *
 * @param  crs  the coordinate reference system to use for inferring axis types.
 * @param  displayDimension  number of dimensions managed by the {@link Canvas}.
 * @return suggested axis types. Never null, but contains null elements.
 *
 * @see Canvas#axisTypes
 */
static DimensionNameType[] suggestAxisTypes(final CoordinateReferenceSystem crs, final int displayDimension) {
    if (crs != null) {
        final CoordinateSystem cs = crs.getCoordinateSystem();
        if (cs != null) {
            // Should never be null, but we are paranoiac.
            int i = cs.getDimension();
            final DimensionNameType[] axisTypes = new DimensionNameType[i];
            while (--i >= displayDimension) {
                final AxisDirection dir = AxisDirections.absolute(cs.getAxis(i).getDirection());
                if (AxisDirection.FUTURE.equals(dir)) {
                    axisTypes[i] = DimensionNameType.TIME;
                } else if (AxisDirection.UP.equals(dir)) {
                    axisTypes[i] = DimensionNameType.VERTICAL;
                }
            }
            return axisTypes;
        }
    }
    return new DimensionNameType[displayDimension];
}
Also used : CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) AxisDirection(org.opengis.referencing.cs.AxisDirection) DimensionNameType(org.opengis.metadata.spatial.DimensionNameType)

Example 3 with DimensionNameType

use of org.opengis.metadata.spatial.DimensionNameType in project sis by apache.

the class GridExtentCRS method build.

/**
 * Builds a coordinate reference system for the given axis types. The CRS type is always engineering.
 * We can not create temporal CRS because we do not know the temporal datum origin.
 *
 * @param  gridToCRS  matrix of the transform used for converting grid cell indices to envelope coordinates.
 *         It does not matter whether it maps pixel center or corner (translation coefficients are ignored).
 * @param  types   the value of {@link GridExtent#types} or a default value (shall not be {@code null}).
 * @param  locale  locale to use for axis names, or {@code null} for default.
 * @return CRS for the grid, or {@code null}.
 *
 * @see GridExtent#typeFromAxes(CoordinateReferenceSystem, int)
 */
static EngineeringCRS build(final Matrix gridToCRS, final DimensionNameType[] types, final Locale locale) throws FactoryException {
    final int tgtDim = gridToCRS.getNumRow() - 1;
    final int srcDim = Math.min(gridToCRS.getNumCol() - 1, types.length);
    final CoordinateSystemAxis[] axes = new CoordinateSystemAxis[tgtDim];
    final CSFactory csFactory = DefaultFactories.forBuildin(CSFactory.class);
    boolean hasVertical = false;
    boolean hasTime = false;
    boolean hasOther = false;
    for (int i = 0; i < srcDim; i++) {
        final DimensionNameType type = types[i];
        if (type != null) {
            /*
                 * Try to locate the CRS dimension corresponding to grid dimension j.
                 * We expect a one-to-one matching; if it is not the case, return null.
                 * Current version does not accept scale factors, but we could revisit
                 * in a future version if there is a need for it.
                 */
            int target = -1;
            double scale = 0;
            for (int j = 0; j < tgtDim; j++) {
                final double m = gridToCRS.getElement(j, i);
                if (m != 0) {
                    if (target >= 0 || axes[j] != null || Math.abs(m) != 1) {
                        return null;
                    }
                    target = j;
                    scale = m;
                }
            }
            if (target < 0) {
                return null;
            }
            /*
                 * This hard-coded set of axis directions is the converse of
                 * GridExtent.AXIS_DIRECTIONS map.
                 */
            String abbreviation;
            AxisDirection direction;
            if (type == DimensionNameType.COLUMN || type == DimensionNameType.SAMPLE) {
                abbreviation = "x";
                direction = AxisDirection.COLUMN_POSITIVE;
            } else if (type == DimensionNameType.ROW || type == DimensionNameType.LINE) {
                abbreviation = "y";
                direction = AxisDirection.ROW_POSITIVE;
            } else if (type == DimensionNameType.VERTICAL) {
                abbreviation = "z";
                direction = AxisDirection.UP;
                hasVertical = true;
            } else if (type == DimensionNameType.TIME) {
                abbreviation = "t";
                direction = AxisDirection.FUTURE;
                hasTime = true;
            } else {
                abbreviation = abbreviation(target);
                direction = AxisDirection.OTHER;
                hasOther = true;
            }
            /*
                 * Verify that no other axis has the same direction and abbreviation. If duplicated
                 * values are found, keep only the first occurrence in grid axis order (may not be
                 * the CRS axis order).
                 */
            for (int k = tgtDim; --k >= 0; ) {
                final CoordinateSystemAxis previous = axes[k];
                if (previous != null) {
                    if (direction.equals(AxisDirections.absolute(previous.getDirection()))) {
                        direction = AxisDirection.OTHER;
                        hasOther = true;
                    }
                    if (abbreviation.equals(previous.getAbbreviation())) {
                        abbreviation = abbreviation(target);
                    }
                }
            }
            if (scale < 0) {
                direction = AxisDirections.opposite(direction);
            }
            final String name = Types.toString(Types.getCodeTitle(type), locale);
            axes[target] = axis(csFactory, name, abbreviation, direction);
        }
    }
    /*
         * Search for axes that have not been created in above loop.
         * It happens when some axes have no associated `DimensionNameType` code.
         */
    for (int j = 0; j < tgtDim; j++) {
        if (axes[j] == null) {
            final String name = Vocabulary.getResources(locale).getString(Vocabulary.Keys.Dimension_1, j);
            final String abbreviation = abbreviation(j);
            axes[j] = axis(csFactory, name, abbreviation, AxisDirection.OTHER);
        }
    }
    /*
         * Create a coordinate system of affine type if all axes seem spatial.
         * If no specialized type seems to fit, use an unspecified ("abstract")
         * coordinate system type in last resort.
         */
    final Map<String, ?> properties = properties("Grid extent");
    final CoordinateSystem cs;
    if (hasOther || (tgtDim > (hasTime ? 1 : 3))) {
        cs = new AbstractCS(properties, axes);
    } else
        switch(tgtDim) {
            case 1:
                {
                    final CoordinateSystemAxis axis = axes[0];
                    if (hasVertical) {
                        cs = csFactory.createVerticalCS(properties, axis);
                    } else if (hasTime) {
                        cs = csFactory.createTimeCS(properties, axis);
                    } else {
                        cs = csFactory.createLinearCS(properties, axis);
                    }
                    break;
                }
            case 2:
                cs = csFactory.createAffineCS(properties, axes[0], axes[1]);
                break;
            case 3:
                cs = csFactory.createAffineCS(properties, axes[0], axes[1], axes[2]);
                break;
            default:
                return null;
        }
    return DefaultFactories.forBuildin(CRSFactory.class).createEngineeringCRS(properties(cs.getName()), CommonCRS.Engineering.GRID.datum(), cs);
}
Also used : CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) CRSFactory(org.opengis.referencing.crs.CRSFactory) AbstractCS(org.apache.sis.referencing.cs.AbstractCS) CSFactory(org.opengis.referencing.cs.CSFactory) AxisDirection(org.opengis.referencing.cs.AxisDirection) DimensionNameType(org.opengis.metadata.spatial.DimensionNameType)

Example 4 with DimensionNameType

use of org.opengis.metadata.spatial.DimensionNameType 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 5 with DimensionNameType

use of org.opengis.metadata.spatial.DimensionNameType 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)

Aggregations

DimensionNameType (org.opengis.metadata.spatial.DimensionNameType)5 GridExtent (org.apache.sis.coverage.grid.GridExtent)2 AxisDirection (org.opengis.referencing.cs.AxisDirection)2 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)2 NoSuchElementException (java.util.NoSuchElementException)1 GridGeometry (org.apache.sis.coverage.grid.GridGeometry)1 GeneralEnvelope (org.apache.sis.geometry.GeneralEnvelope)1 AbstractCS (org.apache.sis.referencing.cs.AbstractCS)1 ParameterNotFoundException (org.opengis.parameter.ParameterNotFoundException)1 NoSuchAuthorityCodeException (org.opengis.referencing.NoSuchAuthorityCodeException)1 CRSFactory (org.opengis.referencing.crs.CRSFactory)1 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)1 CSFactory (org.opengis.referencing.cs.CSFactory)1 CoordinateSystemAxis (org.opengis.referencing.cs.CoordinateSystemAxis)1 MathTransform (org.opengis.referencing.operation.MathTransform)1 MathTransformFactory (org.opengis.referencing.operation.MathTransformFactory)1 TransformException (org.opengis.referencing.operation.TransformException)1 NoSuchIdentifierException (org.opengis.util.NoSuchIdentifierException)1