Search in sources :

Example 6 with OperationMethod

use of org.opengis.referencing.operation.OperationMethod in project sis by apache.

the class OperationMethodSetTest method testMixedCases.

/**
 * Tests a non-empty set.
 */
@Test
@DependsOnMethod("testEmpty")
public void testMixedCases() {
    final DefaultOperationMethod merA = createMethod(CylindricalProjection.class, "Mercator (variant A)");
    final DefaultOperationMethod merB = createMethod(CylindricalProjection.class, "Mercator (variant B)");
    final DefaultOperationMethod merC = createMethod(CylindricalProjection.class, "Mercator (variant C)");
    final DefaultOperationMethod dup = createMethod(CylindricalProjection.class, "Mercator (variant B)");
    final DefaultOperationMethod lamb = createMethod(ConicProjection.class, "Lambert");
    final DefaultOperationMethod[] methods = new DefaultOperationMethod[] { merA, merB, merC, dup, lamb };
    final OperationMethodSet mercators = create(CylindricalProjection.class, methods);
    final OperationMethodSet lambert = create(ConicProjection.class, methods);
    final OperationMethodSet all = create(Projection.class, methods);
    /*
         * Mercator case.
         *   - Intentionally start the iteration without checking 'hasNext()' - the iterator shall be robust to that.
         *   - Intentionally start an other iteration (indirectly) in the middle of the first one.
         */
    final Iterator<OperationMethod> iterator = mercators.iterator();
    assertSame(merA, iterator.next());
    assertSame(merB, iterator.next());
    assertArrayEquals("toArray", new DefaultOperationMethod[] { merA, merB, merC }, mercators.toArray());
    assertSame(merC, iterator.next());
    assertFalse(iterator.hasNext());
    assertFalse("isEmpty", mercators.isEmpty());
    assertEquals("size", 3, mercators.size());
    /*
         * Lambert case. Test twice since the two excecutions will take different code paths.
         */
    assertEquals(Collections.singleton(lamb), lambert);
    assertEquals(Collections.singleton(lamb), lambert);
    /*
         * Test filtering: the test should not contain any conic projection.
         */
    assertEmpty(create(PlanarProjection.class, methods));
    /*
         * Opportunist tests.
         */
    assertFalse(lambert.containsAll(all));
    assertTrue(all.containsAll(lambert));
    assertTrue(all.containsAll(mercators));
}
Also used : PlanarProjection(org.opengis.referencing.operation.PlanarProjection) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Example 7 with OperationMethod

use of org.opengis.referencing.operation.OperationMethod in project sis by apache.

the class DefaultMathTransformFactory method getOperationMethod.

/**
 * Returns the operation method for the specified name or identifier. The given argument shall be either
 * a method {@linkplain DefaultOperationMethod#getName() name} (e.g. <cite>"Transverse Mercator"</cite>)
 * or one of its {@linkplain DefaultOperationMethod#getIdentifiers() identifiers} (e.g. {@code "EPSG:9807"}).
 *
 * <p>The search is case-insensitive. Comparisons against method names can be
 * {@linkplain DefaultOperationMethod#isHeuristicMatchForName(String) heuristic}.</p>
 *
 * <p>If more than one method match the given identifier, then the first (according iteration order)
 * non-{@linkplain org.apache.sis.util.Deprecable#isDeprecated() deprecated} matching method is returned.
 * If all matching methods are deprecated, the first one is returned.</p>
 *
 * @param  identifier  the name or identifier of the operation method to search.
 * @return the coordinate operation method for the given name or identifier.
 * @throws NoSuchIdentifierException if there is no operation method registered for the specified identifier.
 *
 * @see org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory#getOperationMethod(String)
 */
public OperationMethod getOperationMethod(String identifier) throws NoSuchIdentifierException {
    identifier = CharSequences.trimWhitespaces(identifier);
    ArgumentChecks.ensureNonEmpty("identifier", identifier);
    OperationMethod method = methodsByName.get(identifier);
    if (method == null) {
        final ReferencingServices services = ReferencingServices.getInstance();
        synchronized (methods) {
            method = services.getOperationMethod(methods, identifier);
        }
        if (method == null) {
            throw new NoSuchIdentifierException(Resources.format(Resources.Keys.NoSuchOperationMethod_1, identifier), identifier);
        }
        /*
             * Remember the method we just found, for faster check next time.
             */
        final OperationMethod previous = methodsByName.putIfAbsent(identifier.intern(), method);
        if (previous != null) {
            method = previous;
        }
    }
    return method;
}
Also used : ReferencingServices(org.apache.sis.internal.metadata.ReferencingServices) NoSuchIdentifierException(org.opengis.util.NoSuchIdentifierException) DefaultOperationMethod(org.apache.sis.referencing.operation.DefaultOperationMethod) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Example 8 with OperationMethod

use of org.opengis.referencing.operation.OperationMethod in project sis by apache.

the class Formatter method appendComplement.

/**
 * Appends the optional complementary attributes common to many {@link IdentifiedObject} subtypes.
 * Those attributes are {@code ANCHOR}, {@code SCOPE}, {@code AREA}, {@code BBOX}, {@code VERTICALEXTENT},
 * {@code TIMEEXTENT}, {@code ID} (previously known as {@code AUTHORITY}) and {@code REMARKS},
 * and have a special treatment: they are written by {@link #append(FormattableObject)}
 * after the {@code formatTo(Formatter)} method returned.
 *
 * <p>The {@code ID[<name>,<code>,…]} element is normally written only for the root element
 * (unless the convention is {@code INTERNAL}), but there is various exceptions to this rule.
 * If formatted, the {@code ID} element will be by default on the same line than the enclosing
 * element (e.g. {@code SPHEROID["Clarke 1866", …, ID["EPSG", 7008]]}). Other example:</p>
 *
 * {@preformat text
 *   PROJCS["NAD27 / Idaho Central",
 *     GEOGCS[...etc...],
 *     ...etc...
 *     ID["EPSG", 26769]]
 * }
 *
 * For non-internal conventions, all elements other than {@code ID[…]} are formatted
 * only for {@link CoordinateOperation} and root {@link ReferenceSystem} instances,
 * with an exception for remarks of {@code ReferenceSystem} embedded inside {@code CoordinateOperation}.
 * Those restrictions are our interpretation of the following ISO 19162 requirement:
 *
 * <blockquote>(…snip…) {@code <scope extent identifier remark>} is a collection of four optional attributes
 * which may be applied to a coordinate reference system, a coordinate operation or a boundCRS. (…snip…)
 * Identifier (…snip…) may also be utilised for components of these objects although this is not recommended
 * except for coordinate operation methods (including map projections) and parameters. (…snip…)
 * A {@code <remark>} can be included within the descriptions of source and target CRS embedded within
 * a coordinate transformation as well as within the coordinate transformation itself.</blockquote>
 */
@SuppressWarnings("null")
private void appendComplement(final IdentifiedObject object, final FormattableObject parent, final FormattableObject gp) {
    isComplement = true;
    // Whether to format ID[…] elements.
    final boolean showIDs;
    // Whether we shall limit to a single ID[…] element.
    final boolean filterID;
    // Whether to format any element other than ID[…] and Remarks[…].
    final boolean showOthers;
    // Whether to format Remarks[…].
    final boolean showRemarks;
    if (convention == Convention.INTERNAL) {
        showIDs = true;
        filterID = false;
        showOthers = true;
        showRemarks = true;
    } else {
        /*
             * Except for the special cases of OperationMethod and Parameters, ISO 19162 recommends to format the
             * ID only for the root element.  But Apache SIS adds an other exception to this rule by handling the
             * components of CompoundCRS as if they were root elements. The reason is that users often create their
             * own CompoundCRS from standard components, for example by adding a time axis to some standard CRS like
             * "WGS84". The resulting CompoundCRS usually have no identifier. Then the users often need to extract a
             * particular component of a CompoundCRS, most often the horizontal part, and will need its identifier
             * for example in a Web Map Service (WMS). Those ID are lost if we do not format them here.
             */
        if (parent == null || parent instanceof CompoundCRS) {
            showIDs = true;
        } else if (gp instanceof CoordinateOperation && !(parent instanceof IdentifiedObject)) {
            // "SourceCRS[…]" and "TargetCRS[…]" sub-elements in CoordinateOperation.
            showIDs = true;
        } else if (convention == Convention.WKT2_SIMPLIFIED) {
            showIDs = false;
        } else {
            showIDs = (object instanceof OperationMethod) || (object instanceof GeneralParameterDescriptor);
        }
        if (convention.majorVersion() == 1) {
            filterID = true;
            showOthers = false;
            showRemarks = false;
        } else {
            filterID = (parent != null);
            if (object instanceof CoordinateOperation) {
                showOthers = !(parent instanceof ConcatenatedOperation);
                showRemarks = showOthers;
            } else if (object instanceof ReferenceSystem) {
                showOthers = (parent == null);
                showRemarks = (parent == null) || (gp instanceof CoordinateOperation);
            } else {
                // Mandated by ISO 19162.
                showOthers = false;
                showRemarks = false;
            }
        }
    }
    if (showOthers) {
        appendForSubtypes(object);
    }
    if (showIDs) {
        Collection<ReferenceIdentifier> identifiers = object.getIdentifiers();
        if (identifiers != null) {
            // Paranoiac check
            if (filterID) {
                for (final ReferenceIdentifier id : identifiers) {
                    if (Citations.identifierMatches(authority, id.getAuthority())) {
                        identifiers = Collections.singleton(id);
                        break;
                    }
                }
            }
            for (ReferenceIdentifier id : identifiers) {
                if (!(id instanceof FormattableObject)) {
                    id = ImmutableIdentifier.castOrCopy(id);
                }
                append((FormattableObject) id);
                if (filterID)
                    break;
            }
        }
    }
    if (showRemarks) {
        appendOnNewLine(WKTKeywords.Remark, object.getRemarks(), ElementKind.REMARKS);
    }
    isComplement = false;
}
Also used : ReferenceIdentifier(org.opengis.referencing.ReferenceIdentifier) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) GeneralParameterDescriptor(org.opengis.parameter.GeneralParameterDescriptor) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) ConcatenatedOperation(org.opengis.referencing.operation.ConcatenatedOperation) IdentifiedObject(org.opengis.referencing.IdentifiedObject) ReferenceSystem(org.opengis.referencing.ReferenceSystem) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Example 9 with OperationMethod

use of org.opengis.referencing.operation.OperationMethod in project sis by apache.

the class CRSBuilder method verify.

/**
 * Verifies if the user-defined conversion created from GeoTIFF values
 * matches the given conversion created from the EPSG geodetic dataset.
 * This method does not verify the EPSG code of the given conversion.
 *
 * @param  projection  the conversion created from the EPSG geodetic dataset.
 */
private void verify(final Conversion projection, final Unit<Angle> angularUnit, final Unit<Length> linearUnit) throws FactoryException {
    final Unit<Angle> azimuthUnit = createUnit(GeoKeys.AzimuthUnits, (short) 0, Angle.class, Units.DEGREE);
    final String type = getAsString(GeoKeys.CoordTrans);
    if (type != null) {
        /*
             * Compare the name of the map projection declared in the GeoTIFF file with the name
             * of the projection used by the EPSG geodetic dataset.
             */
        final OperationMethod method = projection.getMethod();
        if (!IdentifiedObjects.isHeuristicMatchForName(method, type)) {
            Identifier expected = IdentifiedObjects.getIdentifier(method, Citations.GEOTIFF);
            if (expected == null) {
                expected = IdentifiedObjects.getIdentifier(method, null);
            }
            warning(Resources.Keys.NotTheEpsgValue_5, IdentifiedObjects.getIdentifierOrName(projection), expected.getCode(), GeoKeys.name(GeoKeys.CoordTrans), type, "");
        }
        /*
             * Compare the parameter values with the ones declared in the EPSG geodetic dataset.
             */
        final ParameterValueGroup parameters = projection.getParameterValues();
        for (final short key : remainingKeys()) {
            final Unit<?> unit;
            switch(GeoKeys.unitOf(key)) {
                case GeoKeys.RATIO:
                    unit = Units.UNITY;
                    break;
                case GeoKeys.LINEAR:
                    unit = linearUnit;
                    break;
                case GeoKeys.ANGULAR:
                    unit = angularUnit;
                    break;
                case GeoKeys.AZIMUTH:
                    unit = azimuthUnit;
                    break;
                default:
                    continue;
            }
            try {
                verify(projection, parameters.parameter("GeoTIFF:" + key).doubleValue(unit), key, unit);
            } catch (ParameterNotFoundException e) {
                warning(Resources.Keys.UnexpectedParameter_2, type, GeoKeys.name(key));
            }
        }
    }
}
Also used : Identifier(org.opengis.metadata.Identifier) Angle(javax.measure.quantity.Angle) ParameterValueGroup(org.opengis.parameter.ParameterValueGroup) ParameterNotFoundException(org.opengis.parameter.ParameterNotFoundException) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Example 10 with OperationMethod

use of org.opengis.referencing.operation.OperationMethod in project sis by apache.

the class GeoKeysTest method verifyProjectionNames.

/**
 * Verifies that GeoTIFF projection aliases registered in the {@link org.apache.sis.internal.referencing.provider}
 * package match the name of fields listed in {@link GeoIdentifiers} and that GeoTIFF numerical codes correspond.
 * This method verifies only projection names and identifiers, not parameter names.
 */
@Test
@DependsOnMethod("testName")
public void verifyProjectionNames() {
    final MathTransformFactory factory = DefaultFactories.forBuildin(MathTransformFactory.class);
    for (final OperationMethod method : factory.getAvailableMethods(SingleOperation.class)) {
        final Identifier identifier = IdentifiedObjects.getIdentifier(method, Citations.GEOTIFF);
        final Set<String> names = IdentifiedObjects.getNames(method, Citations.GEOTIFF);
        /*
             * If there is no GeoTIFF identifiers, we should have no GeoTIFF name neither.
             * However we may have more than one name, since GeoTIFF defines also aliases.
             */
        assertEquals(method.getName().getCode(), identifier == null, names.isEmpty());
        if (identifier != null) {
            final int code = Short.parseShort(identifier.getCode());
            for (final String name : names) {
                assertEquals(name, code, GeoIdentifiers.code(name));
            }
        }
    }
}
Also used : Identifier(org.opengis.metadata.Identifier) MathTransformFactory(org.opengis.referencing.operation.MathTransformFactory) OperationMethod(org.opengis.referencing.operation.OperationMethod) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Aggregations

OperationMethod (org.opengis.referencing.operation.OperationMethod)29 Test (org.junit.Test)17 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)11 DependsOnMethod (org.apache.sis.test.DependsOnMethod)8 DefaultOperationMethod (org.apache.sis.referencing.operation.DefaultOperationMethod)6 Identifier (org.opengis.metadata.Identifier)5 HashMap (java.util.HashMap)4 GeneralParameterDescriptor (org.opengis.parameter.GeneralParameterDescriptor)4 CC_OperationParameterGroupTest (org.apache.sis.internal.jaxb.referencing.CC_OperationParameterGroupTest)3 GeneralParameterValue (org.opengis.parameter.GeneralParameterValue)3 ParameterDescriptorGroup (org.opengis.parameter.ParameterDescriptorGroup)3 IdentifiedObject (org.opengis.referencing.IdentifiedObject)3 MathTransform (org.opengis.referencing.operation.MathTransform)3 MathTransformFactory (org.opengis.referencing.operation.MathTransformFactory)3 NoSuchIdentifierException (org.opengis.util.NoSuchIdentifierException)3 IdentityHashMap (java.util.IdentityHashMap)2 DefaultProjectedCRS (org.apache.sis.referencing.crs.DefaultProjectedCRS)2 InvalidGeodeticParameterException (org.apache.sis.referencing.factory.InvalidGeodeticParameterException)2 DefaultConversion (org.apache.sis.referencing.operation.DefaultConversion)2 ParameterDescriptor (org.opengis.parameter.ParameterDescriptor)2