Search in sources :

Example 16 with GeographicBoundingBox

use of org.opengis.metadata.extent.GeographicBoundingBox in project sis by apache.

the class CoordinateOperationFinder method createOperations.

/**
 * Infers operations for conversions or transformations between two coordinate reference systems.
 * If a non-null authority factory – the <cite>registry</cite> – has been specified at construction time,
 * then this method will first query that factory (<cite>late-binding</cite> approach – see class javadoc).
 * If no operation has been found in the registry or if no registry has been specified to the constructor,
 * this method inspects the given CRS and delegates the work to one or many {@code createOperationStep(…)}
 * methods (<cite>early-binding</cite> approach).
 *
 * <p>At first, this method is invoked with the {@code sourceCRS} and {@code targetCRS} arguments given to the
 * {@link DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem,
 * CoordinateOperationContext) CoordinateOperationFactory.createOperation(…)} method. But then, this method may
 * be invoked recursively by some {@code createOperationStep(…)} methods with different source or target CRS,
 * for example in order to process the {@linkplain org.apache.sis.referencing.crs.DefaultProjectedCRS#getBaseCRS()
 * base geographic CRS} of a projected CRS.</p>
 *
 * <p>Coordinate operations are returned in preference order: best operations for the area of interest should be first.
 * The returned list is modifiable: callers can add, remove or set elements without impact on this
 * {@code CoordinateOperationFinder} instance.</p>
 *
 * @param  sourceCRS  input coordinate reference system.
 * @param  targetCRS  output coordinate reference system.
 * @return coordinate operations from {@code sourceCRS} to {@code targetCRS}.
 * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
 * @throws FactoryException if the operation creation failed for some other reason.
 *
 * @since 1.0
 */
@Override
public List<CoordinateOperation> createOperations(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS) throws FactoryException {
    ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
    ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
    if (equalsIgnoreMetadata(sourceCRS, targetCRS))
        try {
            return asList(createFromAffineTransform(AXIS_CHANGES, sourceCRS, targetCRS, CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(), targetCRS.getCoordinateSystem())));
        } catch (IllegalArgumentException | IncommensurableException e) {
            throw new FactoryException(Resources.format(Resources.Keys.CanNotInstantiateGeodeticObject_1, new CRSPair(sourceCRS, targetCRS)), e);
        }
    /*
         * If this method is invoked recursively, verify if the requested operation is already in the cache.
         * We do not perform this verification on the first invocation because it was already verified by
         * DefaultCoordinateOperationFactory.createOperation(…). We do not block if the operation is in
         * process of being computed in another thread because of the risk of deadlock. If the operation
         * is not in the cache, store the key in our internal map for preventing infinite recursivity.
         */
    final CRSPair key = new CRSPair(sourceCRS, targetCRS);
    if (useCache && stopAtFirst && !previousSearches.isEmpty()) {
        final CoordinateOperation op = factorySIS.cache.peek(key);
        // Must be a modifiable list as per this method contract.
        if (op != null)
            return asList(op);
    }
    if (previousSearches.put(key, Boolean.TRUE) != null) {
        throw new FactoryException(Resources.format(Resources.Keys.RecursiveCreateCallForCode_2, CoordinateOperation.class, key));
    }
    /*
         * If the user did not specified an area of interest, use the domain of validity of the CRS.
         */
    GeographicBoundingBox bbox = Extents.getGeographicBoundingBox(areaOfInterest);
    if (bbox == null) {
        bbox = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS), CRS.getGeographicBoundingBox(targetCRS));
        areaOfInterest = CoordinateOperationContext.setGeographicBoundingBox(areaOfInterest, bbox);
    }
    /*
         * Verify if some extension module handles this pair of CRS in a special way. For example it may
         * be the "sis-gdal" module checking if the given CRS are wrappers around Proj.4 data structure.
         */
    {
        // For keeping 'operations' list locale.
        final List<CoordinateOperation> operations = new ArrayList<>();
        for (final SpecializedOperationFactory sp : factorySIS.getSpecializedFactories()) {
            for (final CoordinateOperation op : sp.findOperations(sourceCRS, targetCRS)) {
                if (filter(op)) {
                    operations.add(op);
                }
            }
        }
        if (!operations.isEmpty()) {
            CoordinateOperationSorter.sort(operations, bbox);
            return operations;
        }
    }
    /*
         * Verify in the EPSG dataset if the operation is explicitely defined by an authority.
         */
    if (registry != null) {
        final List<CoordinateOperation> authoritatives = super.createOperations(sourceCRS, targetCRS);
        if (!authoritatives.isEmpty())
            return authoritatives;
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof GeneralDerivedCRS) {
        final GeneralDerivedCRS source = (GeneralDerivedCRS) sourceCRS;
        if (targetCRS instanceof GeneralDerivedCRS) {
            return createOperationStep(source, (GeneralDerivedCRS) targetCRS);
        }
        if (targetCRS instanceof SingleCRS) {
            return createOperationStep(source, (SingleCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (targetCRS instanceof GeneralDerivedCRS) {
        final GeneralDerivedCRS target = (GeneralDerivedCRS) targetCRS;
        if (sourceCRS instanceof SingleCRS) {
            return createOperationStep((SingleCRS) sourceCRS, target);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof GeodeticCRS) {
        final GeodeticCRS source = (GeodeticCRS) sourceCRS;
        if (targetCRS instanceof GeodeticCRS) {
            return createOperationStep(source, (GeodeticCRS) targetCRS);
        }
        if (targetCRS instanceof VerticalCRS) {
            return createOperationStep(source, (VerticalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof VerticalCRS) {
        final VerticalCRS source = (VerticalCRS) sourceCRS;
        if (targetCRS instanceof VerticalCRS) {
            return createOperationStep(source, (VerticalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof TemporalCRS) {
        final TemporalCRS source = (TemporalCRS) sourceCRS;
        if (targetCRS instanceof TemporalCRS) {
            return createOperationStep(source, (TemporalCRS) targetCRS);
        }
    }
    // //////////////////////////////////////////////////////////////////////////////
    if (sourceCRS instanceof CompoundCRS || targetCRS instanceof CompoundCRS) {
        return createOperationStep(sourceCRS, CRS.getSingleComponents(sourceCRS), targetCRS, CRS.getSingleComponents(targetCRS));
    }
    throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS));
}
Also used : FactoryException(org.opengis.util.FactoryException) SpecializedOperationFactory(org.apache.sis.internal.referencing.SpecializedOperationFactory) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) ArrayList(java.util.ArrayList) List(java.util.List)

Example 17 with GeographicBoundingBox

use of org.opengis.metadata.extent.GeographicBoundingBox in project sis by apache.

the class StoreTest method testGetMetadata.

/**
 * Tests {@link Store#getMetadata()}.
 *
 * @throws DataStoreException if an error occurred while parsing the data.
 */
@Test
public void testGetMetadata() throws DataStoreException {
    final Metadata metadata;
    try (Store store = open()) {
        metadata = store.getMetadata();
    }
    final Extent extent = getSingleton(((AbstractIdentification) getSingleton(metadata.getIdentificationInfo())).getExtents());
    final GeographicBoundingBox bbox = (GeographicBoundingBox) getSingleton(extent.getGeographicElements());
    assertEquals("westBoundLongitude", 50.23, bbox.getWestBoundLongitude(), STRICT);
    assertEquals("eastBoundLongitude", 50.31, bbox.getEastBoundLongitude(), STRICT);
    assertEquals("southBoundLatitude", 9.23, bbox.getSouthBoundLatitude(), STRICT);
    assertEquals("northBoundLatitude", 9.27, bbox.getNorthBoundLatitude(), STRICT);
    assertTrue("Should not have a vertical extent.", extent.getVerticalElements().isEmpty());
}
Also used : Extent(org.opengis.metadata.extent.Extent) Metadata(org.opengis.metadata.Metadata) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) Test(org.junit.Test)

Example 18 with GeographicBoundingBox

use of org.opengis.metadata.extent.GeographicBoundingBox in project sis by apache.

the class SingleOperationMarshallingTest method testConversionUnmarshalling.

/**
 * Tests unmarshalling of a defining conversion.
 *
 * @throws JAXBException if an error occurred during marshalling or unmarshalling.
 */
@Test
@DependsOnMethod("testOperationMethod")
public void testConversionUnmarshalling() throws JAXBException {
    final DefaultConversion c = unmarshalFile(DefaultConversion.class, "Conversion.xml");
    assertEquals("name", "World Mercator", c.getName().getCode());
    assertEquals("identifier", "3395", getSingleton(c.getIdentifiers()).getCode());
    assertEquals("scope", "Very small scale mapping.", String.valueOf(c.getScope()));
    assertNull("operationVersion", c.getOperationVersion());
    final GeographicBoundingBox e = (GeographicBoundingBox) getSingleton(c.getDomainOfValidity().getGeographicElements());
    assertEquals("eastBoundLongitude", +180, e.getEastBoundLongitude(), STRICT);
    assertEquals("westBoundLongitude", -180, e.getWestBoundLongitude(), STRICT);
    assertEquals("northBoundLatitude", 84, e.getNorthBoundLatitude(), STRICT);
    assertEquals("southBoundLatitude", -80, e.getSouthBoundLatitude(), STRICT);
    // This is a defining conversion, so we do not expect CRS.
    assertNull("sourceCRS", c.getSourceCRS());
    assertNull("targetCRS", c.getTargetCRS());
    assertNull("interpolationCRS", c.getInterpolationCRS());
    assertNull("mathTransform", c.getMathTransform());
    // The most difficult part.
    final OperationMethod method = c.getMethod();
    assertNotNull("method", method);
    verifyMethod(method);
    final ParameterValueGroup parameters = c.getParameterValues();
    assertNotNull("parameters", parameters);
    final Iterator<GeneralParameterValue> it = parameters.values().iterator();
    verifyParameter(method, parameters, -0.0, (ParameterValue<?>) it.next());
    verifyParameter(method, parameters, -90.0, (ParameterValue<?>) it.next());
    assertFalse("Unexpected parameter.", it.hasNext());
    Validators.validate(c);
}
Also used : GeneralParameterValue(org.opengis.parameter.GeneralParameterValue) ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) OperationMethod(org.opengis.referencing.operation.OperationMethod) CC_OperationParameterGroupTest(org.apache.sis.internal.jaxb.referencing.CC_OperationParameterGroupTest) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 19 with GeographicBoundingBox

use of org.opengis.metadata.extent.GeographicBoundingBox in project sis by apache.

the class Extents method getGeographicBoundingBox.

/**
 * Returns a single geographic bounding box from the specified extent.
 * This method tries to find the bounding box in the cheapest way
 * before to fallback on more expansive computations:
 *
 * <ol>
 *   <li>First, this method searches geographic elements that are instance of {@link GeographicBoundingBox}.<ul>
 *     <li>If exactly one such instance is found, then this method returns that instance directly (no copy).</li>
 *     <li>If more than one instance is found, then this method computes and returns the
 *         {@linkplain DefaultGeographicBoundingBox#add union} of all bounding boxes.</li>
 *   </ul></li>
 *   <li>If above step found no {@code GeographicBoundingBox}, then this method inspects geographic elements
 *       that are instance of {@link BoundingPolygon}, taking in account only the envelopes associated to a
 *       coordinate reference system of kind {@link GeographicCRS}. If such envelopes are found, then this
 *       method computes and returns their union.</li>
 *   <li>If above step found no polygon's envelope associated to a geographic CRS, then in last resort this
 *       method uses all polygon's envelopes regardless their coordinate reference system (provided that the
 *       CRS is not null), applying coordinate transformations if needed.</li>
 *   <li>If above step found no polygon's envelope, then this method returns {@code null}.</li>
 * </ol>
 *
 * @param  extent  the extent to convert to a geographic bounding box, or {@code null}.
 * @return a geographic bounding box extracted from the given extent, or {@code null} if none.
 *
 * @see org.apache.sis.referencing.CRS#getDomainOfValidity(CoordinateReferenceSystem)
 */
public static GeographicBoundingBox getGeographicBoundingBox(final Extent extent) {
    GeographicBoundingBox bounds = null;
    if (extent != null) {
        DefaultGeographicBoundingBox modifiable = null;
        final List<Envelope> fallbacks = new ArrayList<>();
        for (final GeographicExtent element : extent.getGeographicElements()) {
            /*
                 * If a geographic bounding box can be obtained, add it to the previous boxes (if any).
                 * All exclusion boxes before the first inclusion box are ignored.
                 */
            if (element instanceof GeographicBoundingBox) {
                final GeographicBoundingBox item = (GeographicBoundingBox) element;
                if (bounds == null) {
                    /*
                         * We use DefaultGeographicBoundingBox.getInclusion(Boolean) below because
                         * add(…) method that we use cares about the case where inclusion is false.
                         */
                    if (DefaultGeographicBoundingBox.getInclusion(item.getInclusion())) {
                        bounds = item;
                    }
                } else {
                    if (modifiable == null) {
                        bounds = modifiable = new DefaultGeographicBoundingBox(bounds);
                    }
                    modifiable.add(item);
                }
            }
        }
        /*
             * If we found not explicit GeographicBoundingBox element, use the information that we
             * collected in BoundingPolygon elements. This may involve coordinate transformations.
             */
        if (bounds == null)
            try {
                for (final Envelope envelope : fallbacks) {
                    final DefaultGeographicBoundingBox item = new DefaultGeographicBoundingBox();
                    item.setBounds(envelope);
                    if (bounds == null) {
                        bounds = item;
                    } else {
                        if (modifiable == null) {
                            bounds = modifiable = new DefaultGeographicBoundingBox(bounds);
                        }
                        modifiable.add(item);
                    }
                }
            } catch (TransformException e) {
                throw new InvalidMetadataException(Errors.format(Errors.Keys.CanNotTransformEnvelope), e);
            }
    }
    return bounds;
}
Also used : InvalidMetadataException(org.apache.sis.metadata.InvalidMetadataException) ArrayList(java.util.ArrayList) TransformException(org.opengis.referencing.operation.TransformException) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) Envelope(org.opengis.geometry.Envelope) GeographicExtent(org.opengis.metadata.extent.GeographicExtent)

Aggregations

GeographicBoundingBox (org.opengis.metadata.extent.GeographicBoundingBox)19 Test (org.junit.Test)8 DefaultGeographicBoundingBox (org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox)6 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)5 TransformException (org.opengis.referencing.operation.TransformException)5 FactoryException (org.opengis.util.FactoryException)5 Extent (org.opengis.metadata.extent.Extent)4 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)4 DependsOnMethod (org.apache.sis.test.DependsOnMethod)3 Envelope (org.opengis.geometry.Envelope)3 GeographicExtent (org.opengis.metadata.extent.GeographicExtent)3 ArrayList (java.util.ArrayList)2 TableAppender (org.apache.sis.io.TableAppender)2 VerticalExtent (org.opengis.metadata.extent.VerticalExtent)2 GeneralDerivedCRS (org.opengis.referencing.crs.GeneralDerivedCRS)2 SingleCRS (org.opengis.referencing.crs.SingleCRS)2 VerticalCRS (org.opengis.referencing.crs.VerticalCRS)2 InternationalString (org.opengis.util.InternationalString)2 IllegalArgumentException (com.sun.star.lang.IllegalArgumentException)1 FileInputStream (java.io.FileInputStream)1