Search in sources :

Example 6 with GeneralEnvelope

use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.

the class Java2D method tryGetEnvelope.

/**
 * If the given object is a Java2D geometry and its envelope is non-empty, returns
 * that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
 *
 * @param  geometry  the geometry from which to get the envelope, or {@code null}.
 * @return the envelope of the given object, or {@code null} if the object is not
 *         a recognized geometry or its envelope is empty.
 */
@Override
final GeneralEnvelope tryGetEnvelope(final Object geometry) {
    if (geometry instanceof Shape) {
        final Rectangle2D bounds = ((Shape) geometry).getBounds2D();
        if (!bounds.isEmpty()) {
            // Test if there is NaN values.
            final GeneralEnvelope env = new GeneralEnvelope(2);
            env.setRange(0, bounds.getMinX(), bounds.getMaxX());
            env.setRange(1, bounds.getMinY(), bounds.getMaxY());
            return env;
        }
    }
    return null;
}
Also used : Shape(java.awt.Shape) Rectangle2D(java.awt.geom.Rectangle2D) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Example 7 with GeneralEnvelope

use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.

the class EnvelopeOperationTest method run.

/**
 * Implementation of the test methods.
 */
private static void run(final AbstractFeature feature) {
    assertNull("Before a geometry is set", feature.getPropertyValue("bounds"));
    GeneralEnvelope expected;
    // Set one geometry
    Polygon classes = new Polygon();
    classes.startPath(10, 20);
    classes.lineTo(10, 30);
    classes.lineTo(15, 30);
    classes.lineTo(15, 20);
    feature.setPropertyValue("classes", classes);
    expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
    expected.setRange(0, 10, 15);
    expected.setRange(1, 20, 30);
    assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
    // Set second geometry
    Point wall = new Point(18, 40);
    feature.setPropertyValue("climbing wall", wall);
    expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
    expected.setRange(0, 10, 18);
    expected.setRange(1, 20, 40);
    assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
    // Set third geometry. This geometry has CRS axis order reversed.
    Polygon gymnasium = new Polygon();
    gymnasium.startPath(-5, -30);
    gymnasium.lineTo(-6, -30);
    gymnasium.lineTo(-6, -31);
    gymnasium.lineTo(-5, -31);
    feature.setPropertyValue("gymnasium", gymnasium);
    expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
    expected.setRange(0, -31, 18);
    expected.setRange(1, -6, 40);
    assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
}
Also used : Point(com.esri.core.geometry.Point) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) Polygon(com.esri.core.geometry.Polygon)

Example 8 with GeneralEnvelope

use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.

the class LinearTransformBuilder method getSourceEnvelope.

/**
 * Returns the envelope of source points. The lower and upper values are inclusive.
 *
 * @return the envelope of source points.
 * @throws IllegalStateException if the source points are not yet known.
 *
 * @since 1.0
 */
public Envelope getSourceEnvelope() {
    if (gridSize != null) {
        final int dim = gridSize.length;
        final GeneralEnvelope envelope = new GeneralEnvelope(dim);
        for (int i = 0; i < dim; i++) {
            envelope.setRange(i, 0, gridSize[i] - 1);
        }
        return envelope;
    } else {
        return envelope(sources);
    }
}
Also used : GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Example 9 with GeneralEnvelope

use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.

the class Store method parseEnvelope.

/**
 * Parses the envelope described by the header line starting with {@code @stboundedby}.
 * The envelope returned by this method will be stored in the {@link #envelope} field.
 *
 * <p>Example:</p>
 * {@preformat text
 *   &#64;stboundedby, urn:ogc:def:crs:CRS:1.3:84, 2D, 50.23 9.23, 50.31 9.27, 2012-01-17T12:33:41Z, 2012-01-17T12:37:00Z, sec
 * }
 *
 * This method sets {@link #timeEncoding} and {@link #spatialDimensionCount} as a side-effect.
 *
 * @param  elements  the line elements. The first elements should be {@code "@stboundedby"}.
 * @return the envelope, or {@code null} if the given list does not contain enough elements.
 */
@SuppressWarnings("fallthrough")
private GeneralEnvelope parseEnvelope(final List<String> elements) throws DataStoreException, FactoryException {
    CoordinateReferenceSystem crs = null;
    int spatialDimensionCount = 2;
    boolean isDimExplicit = false;
    double[] lowerCorner = ArraysExt.EMPTY_DOUBLE;
    double[] upperCorner = ArraysExt.EMPTY_DOUBLE;
    Instant startTime = null;
    Instant endTime = null;
    Unit<Time> timeUnit = Units.SECOND;
    boolean isTimeAbsolute = false;
    int ordinal = -1;
    for (final String element : elements) {
        ordinal++;
        if (!element.isEmpty()) {
            switch(ordinal) {
                // The "@stboundedby" header.
                case 0:
                    continue;
                case 1:
                    crs = CRS.forCode(element);
                    continue;
                case 2:
                    if (element.length() == 2 && Character.toUpperCase(element.charAt(1)) == 'D') {
                        isDimExplicit = true;
                        spatialDimensionCount = element.charAt(0) - '0';
                        if (spatialDimensionCount < 1 || spatialDimensionCount > 3) {
                            throw new DataStoreReferencingException(errors().getString(Errors.Keys.IllegalCoordinateSystem_1, element));
                        }
                        continue;
                    }
                    /*
                             * According the Moving Feature specification, the [dim] element is optional.
                             * If we did not recognized the dimension, assume that we have the next element
                             * (i.e. the lower corner). Fall-through so we can process it.
                             */
                    // Fall through
                    ordinal++;
                case 3:
                    lowerCorner = CharSequences.parseDoubles(element, ORDINATE_SEPARATOR);
                    continue;
                case 4:
                    upperCorner = CharSequences.parseDoubles(element, ORDINATE_SEPARATOR);
                    continue;
                case 5:
                    startTime = Instant.parse(element);
                    continue;
                case 6:
                    endTime = Instant.parse(element);
                    continue;
                case 7:
                    switch(element.toLowerCase(Locale.US)) {
                        case "sec":
                        case "second":
                            /* Already SECOND. */
                            continue;
                        case "minute":
                            timeUnit = Units.MINUTE;
                            continue;
                        case "hour":
                            timeUnit = Units.HOUR;
                            continue;
                        case "day":
                            timeUnit = Units.DAY;
                            continue;
                        case "absolute":
                            isTimeAbsolute = true;
                            continue;
                        default:
                            throw new DataStoreReferencingException(errors().getString(Errors.Keys.UnknownUnit_1, element));
                    }
            }
            // If we reach this point, there is some remaining unknown elements. Ignore them.
            break;
        }
    }
    /*
         * Complete the CRS by adding a vertical component if needed, then a temporal component.
         * Only after the CRS has been completed we can create the envelope.
         *
         * Vertical component:
         *   Ideally, should be part of the CRS created from the authority code. But if the authority
         *   code is only for a two-dimensional CRS, we default to an arbitrary height component.
         *
         * Temporal component:
         *   Assumed never part of the authority code. We need to build the temporal component ourselves
         *   in order to set the origin to the start time.
         */
    final GeneralEnvelope envelope;
    if (crs != null) {
        int count = 0;
        final CoordinateReferenceSystem[] components = new CoordinateReferenceSystem[3];
        components[count++] = crs;
        /*
             * If the coordinates are three-dimensional but the CRS is 2D, add a vertical axis.
             * The vertical axis shall be the third one, however we do not enforce that rule
             * since Apache SIS should work correctly even if the vertical axis is elsewhere.
             */
        int dimension = crs.getCoordinateSystem().getDimension();
        if (isDimExplicit) {
            if (spatialDimensionCount > dimension) {
                components[count++] = CommonCRS.Vertical.MEAN_SEA_LEVEL.crs();
                dimension++;
            }
            if (dimension != spatialDimensionCount) {
                throw new DataStoreReferencingException(errors().getString(Errors.Keys.MismatchedDimension_3, "@stboundedby(CRS)", spatialDimensionCount, dimension));
            }
        }
        if (dimension > Short.MAX_VALUE) {
            throw new DataStoreReferencingException(errors().getString(Errors.Keys.ExcessiveNumberOfDimensions_1, dimension));
        }
        spatialDimensionCount = dimension;
        /*
             * Add a temporal axis if we have a start time (no need for end time).
             * This block presumes that the CRS does not already have a time axis.
             * If a time axis was already present, an exception will be thrown at
             * builder.createCompoundCRS(…) invocation time.
             */
        final GeodeticObjectBuilder builder = new GeodeticObjectBuilder();
        String name = crs.getName().getCode();
        if (startTime != null) {
            final TemporalCRS temporal;
            if (isTimeAbsolute) {
                temporal = TimeEncoding.DEFAULT.crs();
                timeEncoding = TimeEncoding.ABSOLUTE;
            } else {
                temporal = builder.createTemporalCRS(Date.from(startTime), timeUnit);
                timeEncoding = new TimeEncoding(temporal.getDatum(), timeUnit);
            }
            components[count++] = temporal;
            name = name + " + " + temporal.getName().getCode();
        }
        crs = builder.addName(name).createCompoundCRS(ArraysExt.resize(components, count));
        envelope = new GeneralEnvelope(crs);
    } else {
        /*
             * While illegal in principle, Apache SIS accepts missing CRS.
             * In such case, use only the number of dimensions.
             */
        int dim = spatialDimensionCount;
        // Same criterion than in above block.
        if (startTime != null)
            dim++;
        envelope = new GeneralEnvelope(dim);
    }
    /*
         * At this point we got the three- or four-dimensional spatio-temporal CRS.
         * We can now set the envelope coordinate values, including temporal values.
         */
    int dim;
    if ((dim = lowerCorner.length) != spatialDimensionCount || (dim = upperCorner.length) != spatialDimensionCount) {
        throw new DataStoreReferencingException(errors().getString(Errors.Keys.MismatchedDimension_3, "@stboundedby(BBOX)", spatialDimensionCount, dim));
    }
    for (int i = 0; i < spatialDimensionCount; i++) {
        envelope.setRange(i, lowerCorner[i], upperCorner[i]);
    }
    if (startTime != null) {
        envelope.setRange(spatialDimensionCount, timeEncoding.toCRS(startTime.toEpochMilli()), (endTime == null) ? Double.NaN : timeEncoding.toCRS(endTime.toEpochMilli()));
    }
    this.spatialDimensionCount = (short) spatialDimensionCount;
    return envelope;
}
Also used : Instant(java.time.Instant) Time(javax.measure.quantity.Time) TemporalCRS(org.opengis.referencing.crs.TemporalCRS) DataStoreReferencingException(org.apache.sis.storage.DataStoreReferencingException) GeodeticObjectBuilder(org.apache.sis.internal.referencing.GeodeticObjectBuilder) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope)

Example 10 with GeneralEnvelope

use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.

the class ESRI method tryGetEnvelope.

/**
 * If the given object is an ESRI geometry and its envelope is non-empty, returns
 * that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
 *
 * @param  geometry  the geometry from which to get the envelope, or {@code null}.
 * @return the envelope of the given object, or {@code null} if the object is not
 *         a recognized geometry or its envelope is empty.
 */
@Override
final GeneralEnvelope tryGetEnvelope(final Object geometry) {
    if (geometry instanceof Geometry) {
        final Envelope2D bounds = new Envelope2D();
        ((Geometry) geometry).queryEnvelope2D(bounds);
        if (!bounds.isEmpty()) {
            // Test if there is NaN values.
            final GeneralEnvelope env = new GeneralEnvelope(2);
            env.setRange(0, bounds.xmin, bounds.xmax);
            env.setRange(1, bounds.ymin, bounds.ymax);
            return env;
        }
    }
    return null;
}
Also used : Geometry(com.esri.core.geometry.Geometry) GeneralEnvelope(org.apache.sis.geometry.GeneralEnvelope) Envelope2D(com.esri.core.geometry.Envelope2D)

Aggregations

GeneralEnvelope (org.apache.sis.geometry.GeneralEnvelope)14 Envelope2D (org.apache.sis.geometry.Envelope2D)3 Test (org.junit.Test)3 Envelope (org.opengis.geometry.Envelope)3 DependsOnMethod (org.apache.sis.test.DependsOnMethod)2 Envelope2D (com.esri.core.geometry.Envelope2D)1 Geometry (com.esri.core.geometry.Geometry)1 Point (com.esri.core.geometry.Point)1 Polygon (com.esri.core.geometry.Polygon)1 Shape (java.awt.Shape)1 Rectangle2D (java.awt.geom.Rectangle2D)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Instant (java.time.Instant)1 Time (javax.measure.quantity.Time)1 GeodeticObjectBuilder (org.apache.sis.internal.referencing.GeodeticObjectBuilder)1 DefaultGeographicBoundingBox (org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox)1 DefaultGeographicCRS (org.apache.sis.referencing.crs.DefaultGeographicCRS)1 DataStoreReferencingException (org.apache.sis.storage.DataStoreReferencingException)1 GeographicBoundingBox (org.opengis.metadata.extent.GeographicBoundingBox)1 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)1