Search in sources :

Example 16 with CoordinateSystemAxis

use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.

the class AbstractEnvelope method getMaximum.

/**
 * Returns the maximal ordinate value for the specified dimension. In the typical case
 * of non-empty envelopes <em>not</em> spanning the anti-meridian, this method returns the
 * {@link #getUpper(int)} value verbatim. In the case of envelope spanning the anti-meridian,
 * this method returns the {@linkplain CoordinateSystemAxis#getMaximumValue() axis maximum value}.
 * If the range in the given dimension is invalid, then this method returns {@code NaN}.
 *
 * @param  dimension  the dimension for which to obtain the ordinate value.
 * @return the maximal ordinate value at the given dimension.
 * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
 *         than the {@linkplain #getDimension() envelope dimension}.
 */
@Override
public double getMaximum(final int dimension) throws IndexOutOfBoundsException {
    double upper = getUpper(dimension);
    if (isNegative(upper - getLower(dimension))) {
        // Special handling for -0.0
        final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
        upper = isWrapAround(axis) ? axis.getMaximumValue() : Double.NaN;
    }
    return upper;
}
Also used : CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis)

Example 17 with CoordinateSystemAxis

use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.

the class AbstractEnvelope method toSimpleEnvelopes.

/**
 * Returns this envelope as an array of simple (without wraparound) envelopes.
 * The length of the returned array depends on the number of dimensions where a
 * {@linkplain org.opengis.referencing.cs.RangeMeaning#WRAPAROUND wraparound} range is found.
 * Typically, wraparound occurs only in the range of longitude values, when the range crosses
 * the anti-meridian (a.k.a. date line). However this implementation will take in account any
 * axis having wraparound {@linkplain CoordinateSystemAxis#getRangeMeaning() range meaning}.
 *
 * <p>Special cases:</p>
 *
 * <ul>
 *   <li>If this envelope {@linkplain #isEmpty() is empty}, then this method returns an empty array.</li>
 *   <li>If this envelope does not have any wraparound behavior, then this method returns {@code this}
 *       in an array of length 1. This envelope is <strong>not</strong> cloned.</li>
 *   <li>If this envelope crosses the <cite>anti-meridian</cite> (a.k.a. <cite>date line</cite>)
 *       then this method represents this envelope as two separated simple envelopes.
 *   <li>While uncommon, the envelope could theoretically crosses the limit of other axis having
 *       wraparound range meaning. If wraparound occur along <var>n</var> axes, then this method
 *       represents this envelope as 2ⁿ separated simple envelopes.
 * </ul>
 *
 * @return a representation of this envelope as an array of non-empty envelope.
 *
 * @see Envelope2D#toRectangles()
 * @see GeneralEnvelope#simplify()
 *
 * @since 0.4
 */
@SuppressWarnings("ReturnOfCollectionOrArrayField")
public Envelope[] toSimpleEnvelopes() {
    // A bitmask of the dimensions having a "wrap around" behavior.
    long isWrapAround = 0;
    CoordinateReferenceSystem crs = null;
    final int dimension = getDimension();
    for (int i = 0; i != dimension; i++) {
        // Do not use getSpan(i).
        final double span = getUpper(i) - getLower(i);
        if (!(span > 0)) {
            // Use '!' for catching NaN.
            if (!isNegative(span)) {
                // Span is positive zero.
                return EMPTY;
            }
            if (crs == null) {
                crs = getCoordinateReferenceSystem();
            }
            if (!isWrapAround(crs, i)) {
                return EMPTY;
            }
            if (i >= Long.SIZE) {
                // a CRS is unusual enough for not being worth to make the distinction in the error message.
                throw new IllegalStateException(Errors.format(Errors.Keys.ExcessiveListSize_2, "axis", dimension));
            }
            isWrapAround |= (1L << i);
        }
    }
    /*
         * The number of simple envelopes is 2ⁿ where n is the number of wraparound found. In most
         * cases, isWrapAround == 0 so we have an array of length 1 containing only this envelope.
         */
    final int bitCount = Long.bitCount(isWrapAround);
    if (bitCount >= Integer.SIZE - 1) {
        // Should be very unusual, but let be paranoiac.
        throw new IllegalStateException(Errors.format(Errors.Keys.ExcessiveListSize_2, "wraparound", bitCount));
    }
    final Envelope[] envelopes = new Envelope[1 << bitCount];
    if (envelopes.length == 1) {
        envelopes[0] = this;
    } else {
        /*
             * Need to create at least 2 envelopes. Instantiate now all envelopes with ordinate values
             * initialized to a copy of this envelope. We will write directly in their internal arrays later.
             */
        double[] c = new double[dimension * 2];
        for (int i = 0; i < dimension; i++) {
            c[i] = getLower(i);
            c[i + dimension] = getUpper(i);
        }
        final double[][] ordinates = new double[envelopes.length][];
        for (int i = 0; i < envelopes.length; i++) {
            final GeneralEnvelope envelope = new GeneralEnvelope(i == 0 ? c : c.clone());
            envelope.crs = crs;
            envelopes[i] = envelope;
            ordinates[i] = envelope.ordinates;
        }
        /*
             * Assign the minimum and maximum ordinate values in the dimension where a wraparound has been found.
             * The 'for' loop below iterates only over the 'i' values for which the 'isWrapAround' bit is set to 1.
             */
        // For identifying whether we need to set the lower or the upper ordinate.
        int mask = 1;
        @SuppressWarnings("null") final CoordinateSystem // Should not be null at this point.
        cs = crs.getCoordinateSystem();
        for (int i; (i = Long.numberOfTrailingZeros(isWrapAround)) != Long.SIZE; isWrapAround &= ~(1L << i)) {
            final CoordinateSystemAxis axis = cs.getAxis(i);
            final double min = axis.getMinimumValue();
            final double max = axis.getMaximumValue();
            for (int j = 0; j < ordinates.length; j++) {
                c = ordinates[j];
                if ((j & mask) == 0) {
                    c[i + dimension] = max;
                } else {
                    c[i] = min;
                }
            }
            mask <<= 1;
        }
    }
    return envelopes;
}
Also used : CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) Envelope(org.opengis.geometry.Envelope) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Example 18 with CoordinateSystemAxis

use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.

the class AbstractEnvelope method getMinimum.

/**
 * Returns the minimal ordinate value for the specified dimension. In the typical case
 * of non-empty envelopes <em>not</em> spanning the anti-meridian, this method returns the
 * {@link #getLower(int)} value verbatim. In the case of envelope spanning the anti-meridian,
 * this method returns the {@linkplain CoordinateSystemAxis#getMinimumValue() axis minimum value}.
 * If the range in the given dimension is invalid, then this method returns {@code NaN}.
 *
 * @param  dimension  the dimension for which to obtain the ordinate value.
 * @return the minimal ordinate value at the given dimension.
 * @throws IndexOutOfBoundsException if the given index is negative or is equals or greater
 *         than the {@linkplain #getDimension() envelope dimension}.
 */
@Override
public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
    double lower = getLower(dimension);
    if (isNegative(getUpper(dimension) - lower)) {
        // Special handling for -0.0
        final CoordinateSystemAxis axis = getAxis(getCoordinateReferenceSystem(), dimension);
        lower = isWrapAround(axis) ? axis.getMinimumValue() : Double.NaN;
    }
    return lower;
}
Also used : CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis)

Example 19 with CoordinateSystemAxis

use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.

the class Envelope2D method toRectangles.

/**
 * Returns this envelope as non-empty Java2D rectangle objects. This method returns an array of length 0, 1,
 * 2 or 4 depending on whether the envelope crosses the anti-meridian or the limit of any other axis having
 * {@linkplain org.opengis.referencing.cs.RangeMeaning#WRAPAROUND wraparound} range meaning.
 * More specifically:
 *
 * <ul>
 *   <li>If this envelope {@linkplain #isEmpty() is empty}, then this method returns an empty array.</li>
 *   <li>If this envelope does not have any wraparound behavior, then this method returns a copy
 *       of this envelope as an instance of {@code Rectangle2D.Double} in an array of length 1.</li>
 *   <li>If this envelope crosses the <cite>anti-meridian</cite> (a.k.a. <cite>date line</cite>)
 *       then this method represents this envelope as two separated rectangles.
 *   <li>While uncommon, the envelope could theoretically crosses the limit of other axis having
 *       wraparound range meaning. If wraparound occur along the two axes, then this method
 *       represents this envelope as four separated rectangles.
 * </ul>
 *
 * <div class="note"><b>API note:</b>
 * The return type is the {@code Rectangle2D.Double} implementation class rather than the {@code Rectangle2D}
 * abstract class because the {@code Envelope2D} class hierarchy already exposes this implementation choice.</div>
 *
 * @return a representation of this envelope as an array of non-empty Java2D rectangles.
 *         The array never contains {@code this}.
 *
 * @see GeneralEnvelope#toSimpleEnvelopes()
 *
 * @since 0.4
 */
@SuppressWarnings("ReturnOfCollectionOrArrayField")
public Rectangle2D.Double[] toRectangles() {
    // A bitmask of the dimensions having a "wrap around" behavior.
    int isWrapAround = 0;
    for (int i = 0; i != DIMENSION; i++) {
        final double span = (i == 0) ? width : height;
        if (!(span > 0)) {
            // Use '!' for catching NaN.
            if (!isNegative(span) || !isWrapAround(crs, i)) {
                return EMPTY;
            }
            isWrapAround |= (1 << i);
        }
    }
    /*
         * The number of rectangles is 2ⁿ where n is the number of wraparound found.
         */
    final Rectangle2D.Double[] rect = new Rectangle2D.Double[1 << Integer.bitCount(isWrapAround)];
    for (int i = 0; i < rect.length; i++) {
        rect[i] = new Rectangle2D.Double(x, y, width, height);
    }
    if ((isWrapAround & 1) != 0) {
        /*
             *  (x+width)   (x)
             *          ↓   ↓
             *    ──────┐   ┌───────
             *    …next │   │ start…
             *    ──────┘   └───────
             */
        final CoordinateSystemAxis axis = getAxis(crs, 0);
        final Rectangle2D.Double start = rect[0];
        final Rectangle2D.Double next = rect[1];
        start.width = axis.getMaximumValue() - x;
        next.x = axis.getMinimumValue();
        next.width += x - next.x;
    }
    if ((isWrapAround & 2) != 0) {
        /*
             *              │   ⋮   │
             *              │ start │
             * (y)        → └───────┘
             * (y+height) → ┌───────┐
             *              │ next  │
             *              │   ⋮   │
             */
        final CoordinateSystemAxis axis = getAxis(crs, 1);
        final Rectangle2D.Double start = rect[0];
        // == 1 if y is the only wraparound axis, or 2 otherwise.
        final Rectangle2D.Double next = rect[isWrapAround - 1];
        start.height = axis.getMaximumValue() - y;
        next.y = axis.getMinimumValue();
        next.height += y - next.y;
    }
    if (isWrapAround == 3) {
        /*
             * If there is a wraparound along both axes, copy the values.
             * The (x) and (y) labels indicate which values to copy.
             *
             *      (y) R1 │   │ R0
             *    ─────────┘   └─────────
             *    ─────────┐   ┌─────────
             *    (x,y) R3 │   │ R2 (x)
             */
        rect[1].height = rect[0].height;
        rect[2].width = rect[0].width;
        rect[3].x = rect[1].x;
        rect[3].width = rect[1].width;
        rect[3].y = rect[2].y;
        rect[3].height = rect[2].height;
    }
    return rect;
}
Also used : Rectangle2D(java.awt.geom.Rectangle2D) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis)

Example 20 with CoordinateSystemAxis

use of org.opengis.referencing.cs.CoordinateSystemAxis in project sis by apache.

the class Envelope2D method getMinimum.

/**
 * Returns the minimal ordinate along the specified dimension. This method handles
 * anti-meridian spanning as documented in the {@link AbstractEnvelope#getMinimum(int)}
 * method.
 *
 * @param  dimension  the dimension to query.
 * @return the minimal ordinate value along the given dimension.
 * @throws IndexOutOfBoundsException if the given index is out of bounds.
 */
@Override
public double getMinimum(final int dimension) throws IndexOutOfBoundsException {
    final double value, span;
    switch(dimension) {
        case 0:
            value = x;
            span = width;
            break;
        case 1:
            value = y;
            span = height;
            break;
        default:
            throw indexOutOfBounds(dimension);
    }
    if (isNegative(span)) {
        // Special handling for -0.0
        final CoordinateSystemAxis axis = getAxis(crs, dimension);
        return isWrapAround(axis) ? axis.getMinimumValue() : NaN;
    }
    return value;
}
Also used : CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis)

Aggregations

CoordinateSystemAxis (org.opengis.referencing.cs.CoordinateSystemAxis)50 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)15 Test (org.junit.Test)14 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)9 EllipsoidalCS (org.opengis.referencing.cs.EllipsoidalCS)5 Unit (javax.measure.Unit)4 VerticalCRS (org.opengis.referencing.crs.VerticalCRS)4 AxisDirection (org.opengis.referencing.cs.AxisDirection)4 FactoryException (org.opengis.util.FactoryException)4 IdentifiedObject (org.opengis.referencing.IdentifiedObject)3 VerticalCS (org.opengis.referencing.cs.VerticalCS)3 InternationalString (org.opengis.util.InternationalString)3 DefaultVerticalCRS (org.apache.sis.referencing.crs.DefaultVerticalCRS)2 DefaultCoordinateSystemAxis (org.apache.sis.referencing.cs.DefaultCoordinateSystemAxis)2 DefaultVerticalCS (org.apache.sis.referencing.cs.DefaultVerticalCS)2 AbstractCoordinateOperation (org.apache.sis.referencing.operation.AbstractCoordinateOperation)2 DependsOnMethod (org.apache.sis.test.DependsOnMethod)2 Identifier (org.opengis.metadata.Identifier)2 VerticalExtent (org.opengis.metadata.extent.VerticalExtent)2 GeodeticCRS (org.opengis.referencing.crs.GeodeticCRS)2