Java Code Examples for org.opengis.geometry.Envelope#getDimension()

The following examples show how to use org.opengis.geometry.Envelope#getDimension() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ArrayEnvelope.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Constructs a new envelope with the same data than the specified envelope.
 *
 * @param envelope  the envelope to copy.
 */
public ArrayEnvelope(final Envelope envelope) {
    ensureNonNull("envelope", envelope);
    /*
     * Do not optimize with `if (envelope instanceof ArrayEnvelope)` because subclasses may change the semantic.
     * In particular the SubEnvelope subclass uses only a subrange of this array. If we still want to optimize,
     * we would have to test for specific classes. It is probably not worth at this stage.
     */
    crs = envelope.getCoordinateReferenceSystem();
    final int dimension = envelope.getDimension();
    coordinates = new double[dimension * 2];
    final DirectPosition lowerCorner = envelope.getLowerCorner();
    final DirectPosition upperCorner = envelope.getUpperCorner();
    for (int i=0; i<dimension; i++) {
        coordinates[i]           = lowerCorner.getOrdinate(i);
        coordinates[i+dimension] = upperCorner.getOrdinate(i);
    }
    verifyRanges(crs, coordinates);
}
 
Example 2
Source File: ServicesForMetadata.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Sets a geographic bounding box from the specified envelope.
 * If the envelope has no CRS, then (<var>longitude</var>, <var>latitude</var>) axis order is assumed.
 * If the envelope CRS is not geographic, then the envelope will be transformed to a geographic CRS.
 * If {@code findOpCaller} is {@code true}, then some failures will cause this method to return {@code null}
 * instead than throwing an exception, and warning may be logged with assumption that caller is the named
 * method from {@link Envelopes} — typically {@link Envelopes#findOperation(Envelope, Envelope)}.
 *
 * @param  envelope      the source envelope.
 * @param  target        the target bounding box, or {@code null} for creating it automatically.
 * @param  findOpCaller  non-null for replacing some (not all) exceptions by {@code null} return value.
 * @return the bounding box or {@code null} on failure. Never {@code null} if {@code findOpCaller} argument is {@code null}.
 * @throws TransformException if the given envelope can not be transformed.
 */
@Override
public DefaultGeographicBoundingBox setBounds(final Envelope envelope, final DefaultGeographicBoundingBox target,
        final String findOpCaller) throws TransformException
{
    final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
    GeographicCRS normalizedCRS = ReferencingUtilities.toNormalizedGeographicCRS(crs, false, false);
    if (normalizedCRS == null) {
        if (crs != null) {
            normalizedCRS = CommonCRS.defaultGeographic();
        } else if (envelope.getDimension() != 2) {
            if (findOpCaller != null) return null;
            throw new TransformException(dimensionNotFound(Resources.Keys.MissingHorizontalDimension_1, crs));
        }
    }
    return setGeographicExtent(envelope, target, crs, normalizedCRS, findOpCaller);
}
 
Example 3
Source File: ReferencingAssert.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Asserts that two envelopes have the same minimum and maximum coordinates.
 * This method ignores the envelope type (i.e. the implementation class) and the CRS.
 *
 * @param expected    the expected envelope.
 * @param actual      the envelope to compare with the expected one.
 * @param tolerances  the tolerance threshold on location along each axis. If this array length is shorter
 *                    than the number of dimensions, then the last tolerance is reused for all remaining axes.
 *                    If this array is empty, then the tolerance threshold is zero.
 *
 * @since 0.7
 */
public static void assertEnvelopeEquals(final Envelope expected, final Envelope actual, final double... tolerances) {
    final int dimension = expected.getDimension();
    assertEquals("dimension", dimension, actual.getDimension());
    final DirectPosition expectedLower = expected.getLowerCorner();
    final DirectPosition expectedUpper = expected.getUpperCorner();
    final DirectPosition actualLower   = actual  .getLowerCorner();
    final DirectPosition actualUpper   = actual  .getUpperCorner();
    double tolerance = 0;
    for (int i=0; i<dimension; i++) {
        if (i < tolerances.length) {
            tolerance = tolerances[i];
        }
        if (abs(expectedLower.getOrdinate(i) - actualLower.getOrdinate(i)) > tolerance ||
            abs(expectedUpper.getOrdinate(i) - actualUpper.getOrdinate(i)) > tolerance)
        {
            fail("Envelopes are not equal in dimension " + i + ":\n"
                    + "expected " + Envelopes.toString(expected) + "\n"
                    + " but got " + Envelopes.toString(actual));
        }
    }
}
 
Example 4
Source File: ReferencingAssert.java    From sis with Apache License 2.0 6 votes vote down vote up
/**
 * Tests if the given {@code outer} envelope contains the given {@code inner} envelope.
 * This method will also verify class consistency by invoking the {@code intersects}
 * method, and by interchanging the arguments.
 *
 * @param outer  the envelope which is expected to contains the given inner envelope.
 * @param inner  the envelope which should be contained by the outer envelope.
 */
public static void assertContains(final AbstractEnvelope outer, final Envelope inner) {
    assertTrue("outer.contains(inner)",   outer.contains  (inner, true));
    assertTrue("outer.contains(inner)",   outer.contains  (inner, false));
    assertTrue("outer.intersects(inner)", outer.intersects(inner, true));
    assertTrue("outer.intersects(inner)", outer.intersects(inner, false));
    if (inner instanceof AbstractEnvelope) {
        final AbstractEnvelope ai = (AbstractEnvelope) inner;
        assertTrue ("inner.intersects(outer)", ai.intersects(outer, true));
        assertTrue ("inner.intersects(outer)", ai.intersects(outer, false));
        assertFalse("inner.contains(outer)",   ai.contains  (outer, true));
        assertFalse("inner.contains(outer)",   ai.contains  (outer, false));
    }
    final GeneralDirectPosition median = new GeneralDirectPosition(inner.getDimension());
    for (int i=median.getDimension(); --i>=0;) {
        median.setOrdinate(i, inner.getMedian(i));
    }
    assertTrue("outer.contains(median)", outer.contains(median));
}
 
Example 5
Source File: Envelopes.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Formats the given envelope as a {@code POLYGON} element in the <cite>Well Known Text</cite>
 * (WKT) format. {@code POLYGON} can be used as an alternative to {@code BOX} when the element
 * needs to be considered as a standard WKT geometry.
 *
 * <p>The string returned by this method can be {@linkplain GeneralEnvelope#GeneralEnvelope(CharSequence)
 * parsed} by the {@code GeneralEnvelope} constructor.</p>
 *
 * @param  envelope  the envelope to format.
 * @return the envelope as a {@code POLYGON} in WKT format.
 * @throws IllegalArgumentException if the given envelope can not be formatted.
 *
 * @see org.apache.sis.io.wkt
 */
public static String toPolygonWKT(final Envelope envelope) throws IllegalArgumentException {
    /*
     * Get the dimension, ignoring the trailing ones which have infinite values.
     */
    int dimension = envelope.getDimension();
    while (dimension != 0) {
        final double length = envelope.getSpan(dimension - 1);
        if (Double.isFinite(length)) {
            break;
        }
        dimension--;
    }
    if (dimension < 2) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.EmptyEnvelope2D));
    }
    final StringBuilder buffer = new StringBuilder("POLYGON(");
    String separator = "(";
    for (int corner = 0; corner < CORNERS.length; corner += 2) {
        for (int i=0; i<dimension; i++) {
            final double value;
            switch (i) {
                case  0: // Fall through
                case  1: value = CORNERS[corner+i] ? envelope.getMaximum(i) : envelope.getMinimum(i); break;
                default: value = envelope.getMedian(i); break;
            }
            trimFractionalPart(buffer.append(separator).append(value));
            separator = " ";
        }
        separator = ", ";
    }
    return buffer.append("))").toString();
}
 
Example 6
Source File: AbstractEnvelope.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Implementation of the public {@link #toString()} and {@link Envelopes#toString(Envelope)}
 * methods for formatting a {@code BOX} element from an envelope.
 *
 * @param  envelope           the envelope to format.
 * @param  isSinglePrecision  {@code true} if every lower and upper corner values can be casted to {@code float}.
 * @return this envelope as a {@code BOX} or {@code BOX3D} (most typical dimensions) element.
 *
 * @see GeneralEnvelope#GeneralEnvelope(CharSequence)
 * @see CoordinateFormat
 * @see org.apache.sis.io.wkt
 */
static String toString(final Envelope envelope, final boolean isSinglePrecision) {
    final int dimension = envelope.getDimension();
    final StringBuilder buffer = new StringBuilder(64).append("BOX");
    if (dimension != 2) {
        buffer.append(dimension).append('D');
    }
    if (dimension == 0) {
        buffer.append("()");
    } else {
        final DirectPosition lowerCorner = envelope.getLowerCorner();
        final DirectPosition upperCorner = envelope.getUpperCorner();
        boolean isUpper = false;
        do {                                                        // Executed exactly twice.
            for (int i=0; i<dimension; i++) {
                buffer.append(i == 0 && !isUpper ? '(' : ' ');
                final double coordinate = (isUpper ? upperCorner : lowerCorner).getOrdinate(i);
                if (isSinglePrecision) {
                    buffer.append((float) coordinate);
                } else {
                    buffer.append(coordinate);
                }
                trimFractionalPart(buffer);
            }
            buffer.append(isUpper ? ')' : ',');
        } while ((isUpper = !isUpper) == true);
    }
    return buffer.toString();
}
 
Example 7
Source File: ServicesForMetadata.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Sets a vertical extent with the value inferred from the given envelope.
 * Only the vertical coordinates are extracted; all other coordinates are ignored.
 *
 * @param  envelope  the source envelope.
 * @param  target    the target vertical extent where to store envelope information.
 * @throws TransformException if no vertical component can be extracted from the given envelope.
 */
@Override
public void setBounds(final Envelope envelope, final DefaultVerticalExtent target) throws TransformException {
    final CoordinateReferenceSystem crs = envelope.getCoordinateReferenceSystem();
    final VerticalCRS verticalCRS = CRS.getVerticalComponent(crs, true);
    if (verticalCRS == null && envelope.getDimension() != 1) {
        throw new TransformException(dimensionNotFound(Resources.Keys.MissingVerticalDimension_1, crs));
    }
    setVerticalExtent(envelope, target, crs, verticalCRS);
}
 
Example 8
Source File: GridExtent.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Creates an affine transform from the coordinates of this grid to the coordinates of the given envelope.
 * This method assumes that all axes are in the same order (no axis swapping) and there is no flipping of
 * axis direction. The transform maps cell corners.
 *
 * <p>This method is not yet public because we have not decided what could be an API for controlling axis
 * swapping and flipping, if desired.</p>
 *
 * @param  env  the target envelope. Despite this method name, the envelope CRS is ignored.
 * @return an affine transform from this grid extent to the given envelope, expressed as a matrix.
 */
final MatrixSIS cornerToCRS(final Envelope env) {
    final int          srcDim = getDimension();
    final int          tgtDim = env.getDimension();
    final MatrixSIS    affine = Matrices.create(tgtDim + 1, srcDim + 1, ExtendedPrecisionMatrix.ZERO);
    final DoubleDouble scale  = new DoubleDouble();
    final DoubleDouble offset = new DoubleDouble();
    for (int j=0; j<tgtDim; j++) {
        if (j < srcDim) {
            offset.set(coordinates[j]);
            scale.set(coordinates[j + srcDim]);
            scale.subtract(offset);
            scale.add(1);
            scale.inverseDivideGuessError(env.getSpan(j));
            if (!offset.isZero()) {                     // Use `if` for keeping the value if scale is NaN.
                offset.multiply(scale);
                offset.negate();
            }
            offset.addGuessError(env.getMinimum(j));
            affine.setNumber(j, srcDim, offset);
        } else {
            scale.value = Double.NaN;
            scale.error = Double.NaN;
        }
        affine.setNumber(j, j, scale);
    }
    affine.setElement(tgtDim, srcDim, 1);
    return affine;
}
 
Example 9
Source File: AbstractLocation.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Returns coordinates of a representative point for the location instance.
 * This is typically (but not necessarily) the centroid of the location instance.
 *
 * <p>The default implementation returns the {@linkplain #getEnvelope()} median position.</p>
 *
 * @return coordinates of a representative point for the location instance, or {@code null} if none.
 */
public Position getPosition() {
    final Envelope envelope = getEnvelope();
    if (envelope == null) {
        return null;
    }
    final int dimension = envelope.getDimension();
    final GeneralDirectPosition pos = new GeneralDirectPosition(dimension);
    pos.setCoordinateReferenceSystem(envelope.getCoordinateReferenceSystem());
    for (int i=0; i<dimension; i++) {
        pos.setOrdinate(i, envelope.getMedian(i));
    }
    return pos;
}
 
Example 10
Source File: ArgumentChecks.java    From sis with Apache License 2.0 5 votes vote down vote up
/**
 * Ensures that the given envelope, if non-null, has the expected number of dimensions.
 * This method does nothing if the given envelope is null.
 *
 * @param  name      the name of the argument to be checked. Used only if an exception is thrown.
 * @param  expected  the expected number of dimensions.
 * @param  envelope  the envelope to check for its dimension, or {@code null}.
 * @throws MismatchedDimensionException if the given envelope is non-null and does
 *         not have the expected number of dimensions.
 */
public static void ensureDimensionMatches(final String name, final int expected, final Envelope envelope)
        throws MismatchedDimensionException
{
    if (envelope != null) {
        final int dimension = envelope.getDimension();
        if (dimension != expected) {
            throw new MismatchedDimensionException(Errors.format(
                    Errors.Keys.MismatchedDimension_3, name, expected, dimension));
        }
    }
}
 
Example 11
Source File: Matrices.java    From sis with Apache License 2.0 3 votes vote down vote up
/**
 * Creates a transform matrix mapping the given source envelope to the given destination envelope.
 * The given envelopes can have any dimensions, which are handled as below:
 *
 * <ul>
 *   <li>If the two envelopes have the same {@linkplain Envelope#getDimension() dimension},
 *       then the transform is {@linkplain #isAffine(Matrix) affine}.</li>
 *   <li>If the destination envelope has less dimensions than the source envelope,
 *       then trailing dimensions are silently dropped.</li>
 *   <li>If the target envelope has more dimensions than the source envelope,
 *       then the transform will append trailing coordinates with the 0 value.</li>
 * </ul>
 *
 * This method ignores the {@linkplain Envelope#getCoordinateReferenceSystem() envelope CRS}, which may be null.
 * Actually this method is used more often for grid envelopes
 * (which have no CRS) than geodetic envelopes.
 *
 * <h4>Spanning the anti-meridian of a Geographic CRS</h4>
 * If the given envelopes cross the date line, then this method requires their {@code getSpan(int)} method
 * to behave as documented in the {@link org.apache.sis.geometry.AbstractEnvelope#getSpan(int)} javadoc.
 * Furthermore the matrix created by this method will produce expected results only for source or destination
 * points before the date line, since the wrap around operation can not be represented by an affine transform.
 *
 * <h4>Example</h4>
 * Given a source envelope of size 100 × 200 (the units do not matter for this method) and a destination
 * envelope of size 300 × 500, and given {@linkplain Envelope#getLowerCorner() lower corner} translation
 * from (-20, -40) to (-10, -25), then the following method call:
 *
 * {@preformat java
 *   matrix = Matrices.createTransform(
 *           new Envelope2D(null, -20, -40, 100, 200),
 *           new Envelope2D(null, -10, -25, 300, 500));
 * }
 *
 * will return the following square matrix. The transform of the lower corner is given as an example:
 *
 * {@preformat math
 *   ┌     ┐   ┌              ┐   ┌     ┐
 *   │ -10 │   │ 3.0  0    50 │   │ -20 │       // 3.0 is the scale factor from width of 100 to 300
 *   │ -25 │ = │ 0    2.5  75 │ × │ -40 │       // 2.5 is the scale factor from height of 200 to 500
 *   │   1 │   │ 0    0     1 │   │   1 │
 *   └     ┘   └              ┘   └     ┘
 * }
 *
 * @param  srcEnvelope  the source envelope.
 * @param  dstEnvelope  the destination envelope.
 * @return the transform from the given source envelope to target envelope.
 *
 * @see #createTransform(AxisDirection[], AxisDirection[])
 * @see #createTransform(Envelope, AxisDirection[], Envelope, AxisDirection[])
 * @see org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes(CoordinateSystem, CoordinateSystem)
 */
public static MatrixSIS createTransform(final Envelope srcEnvelope, final Envelope dstEnvelope) {
    ArgumentChecks.ensureNonNull("srcEnvelope", srcEnvelope);
    ArgumentChecks.ensureNonNull("dstEnvelope", dstEnvelope);
    /*
     * Following code is a simplified version of above createTransform(Envelope, AxisDirection[], ...) method.
     * We need to make sure that those two methods are consistent and compute the matrix values in the same way.
     */
    final int srcDim = srcEnvelope.getDimension();
    final int dstDim = dstEnvelope.getDimension();
    final DirectPosition srcCorner = srcEnvelope.getLowerCorner();
    final DirectPosition dstCorner = dstEnvelope.getLowerCorner();
    final MatrixSIS matrix = createZero(dstDim+1, srcDim+1);
    for (int i = Math.min(srcDim, dstDim); --i >= 0;) {
        /*
         * Note on envelope spanning over the anti-meridian: the GeoAPI javadoc does not mandate the
         * precise behavior of getSpan(int) in such situation.  In the particular case of Apache SIS
         * implementations, the envelope will compute the span correctly (taking in account the wrap
         * around behavior). For non-SIS implementations, we can not know.
         *
         * For the translation term, we really need the lower corner, NOT envelope.getMinimum(i),
         * because we need the starting point, which is not the minimal value when spanning over
         * the anti-meridian.
         */
        final double scale     = dstEnvelope.getSpan(i)   / srcEnvelope.getSpan(i);
        final double translate = dstCorner.getOrdinate(i) - srcCorner.getOrdinate(i)*scale;
        matrix.setElement(i, i,      scale);
        matrix.setElement(i, srcDim, translate);
    }
    matrix.setElement(dstDim, srcDim, 1);
    return matrix;
}
 
Example 12
Source File: LocalizationGridBuilder.java    From sis with Apache License 2.0 3 votes vote down vote up
/**
 * Returns the envelope of source coordinates. The {@code fullArea} argument control whether
 * the returned envelope shall encompass full surface of every cells or only their centers:
 * <ul>
 *   <li>If {@code true}, then the returned envelope encompasses full cell surfaces,
 *       from lower border to upper border. In other words, the returned envelope encompasses all
 *       {@linkplain org.opengis.referencing.datum.PixelInCell#CELL_CORNER cell corners}.</li>
 *   <li>If {@code false}, then the returned envelope encompasses only
 *       {@linkplain org.opengis.referencing.datum.PixelInCell#CELL_CENTER cell centers}, inclusive.</li>
 * </ul>
 *
 * This is the envelope of the grid domain (i.e. the ranges of valid {@code gridX} and {@code gridY} argument
 * values in calls to {@code get/setControlPoint(…)} methods) transformed as below:
 * <ol>
 *   <li>expanded by ½ cell on each side if {@code fullArea} is {@code true}</li>
 *   <li>transformed by the inverse of {@linkplain #getSourceToGrid() source to grid} transform.</li>
 * </ol>
 *
 * @param  fullArea  whether the the envelope shall encompass the full cell surfaces instead than only their centers.
 * @return the envelope of grid points, from lower corner to upper corner.
 * @throws IllegalStateException if the grid points are not yet known.
 * @throws TransformException if the envelope can not be calculated.
 *
 * @see LinearTransformBuilder#getSourceEnvelope()
 *
 * @since 1.0
 */
public Envelope getSourceEnvelope(final boolean fullArea) throws TransformException {
    Envelope envelope = linear.getSourceEnvelope();
    if (fullArea) {
        for (int i = envelope.getDimension(); --i >= 0;) {
            final GeneralEnvelope ge = GeneralEnvelope.castOrCopy(envelope);
            ge.setRange(i, ge.getLower(i) - 0.5,
                           ge.getUpper(i) + 0.5);
            envelope = ge;
        }
    }
    return Envelopes.transform(sourceToGrid.inverse(), envelope);
}
 
Example 13
Source File: AbstractEnvelope.java    From sis with Apache License 2.0 3 votes vote down vote up
/**
 * Compares to the specified envelope for equality up to the specified tolerance value.
 * The tolerance value {@code eps} can be either relative to the {@linkplain #getSpan(int)
 * envelope span} along each dimension or can be an absolute value (as for example some
 * ground resolution of a {@linkplain org.apache.sis.coverage.grid.GridCoverage grid coverage}).
 *
 * <ul>
 *   <li>If {@code epsIsRelative} is set to {@code true}, the actual tolerance value for a
 *       given dimension <var>i</var> is {@code eps} × {@code span} where {@code span}
 *       is the maximum of {@linkplain #getSpan(int) this envelope span} and the specified
 *       envelope span along dimension <var>i</var>.</li>
 *   <li>If {@code epsIsRelative} is set to {@code false}, the actual tolerance value for a
 *       given dimension <var>i</var> is {@code eps}.</li>
 * </ul>
 *
 * <div class="note"><b>Note:</b>
 * Relative tolerance values (as opposed to absolute tolerance values) help to workaround the
 * fact that tolerance value are CRS dependent. For example the tolerance value need to be
 * smaller for geographic CRS than for UTM projections, because the former typically has a
 * [-180…180]° range while the later can have a range of thousands of meters.</div>
 *
 * <h4>Coordinate Reference System</h4>
 * To be considered equal, the two envelopes must have the same {@linkplain #getDimension() dimension}
 * and their CRS must be {@linkplain org.apache.sis.util.Utilities#equalsIgnoreMetadata equals,
 * ignoring metadata}. If at least one envelope has a null CRS, then the CRS are ignored and the
 * coordinate values are compared as if the CRS were equal.
 *
 * @param  other          the envelope to compare with.
 * @param  eps            the tolerance value to use for numerical comparisons.
 * @param  epsIsRelative  {@code true} if the tolerance value should be relative to axis length,
 *                        or {@code false} if it is an absolute value.
 * @return {@code true} if the given object is equal to this envelope up to the given tolerance value.
 *
 * @see #contains(Envelope)
 * @see #intersects(Envelope)
 */
public boolean equals(final Envelope other, final double eps, final boolean epsIsRelative) {
    ensureNonNull("other", other);
    final int dimension = getDimension();
    if (other.getDimension() != dimension || !equalsIgnoreMetadata(
            getCoordinateReferenceSystem(), other.getCoordinateReferenceSystem(), false))
    {
        return false;
    }
    final DirectPosition lowerCorner = other.getLowerCorner();
    final DirectPosition upperCorner = other.getUpperCorner();
    for (int i=0; i<dimension; i++) {
        double ε = eps;
        if (epsIsRelative) {
            final double span = Math.max(getSpan(i), other.getSpan(i));
            if (span > 0 && span < Double.POSITIVE_INFINITY) {
                ε *= span;
            }
        }
        if (!epsilonEqual(getLower(i), lowerCorner.getOrdinate(i), ε) ||
            !epsilonEqual(getUpper(i), upperCorner.getOrdinate(i), ε))
        {
            return false;
        }
    }
    return true;
}