Search in sources :

Example 1 with QuantitativeResult

use of org.opengis.metadata.quality.QuantitativeResult in project sis by apache.

the class PositionalAccuracyConstant method getLinearAccuracy.

/**
 * Convenience method returning the accuracy in meters for the specified operation.
 * This method tries each of the following procedures and returns the first successful one:
 *
 * <ul>
 *   <li>If at least one {@link QuantitativeResult} is found with a linear unit, then the largest
 *       accuracy estimate is converted to {@linkplain Units#METRE metres} and returned.</li>
 *   <li>Otherwise, if the operation is a {@link Conversion}, then returns 0 since a conversion
 *       is by definition accurate up to rounding errors.</li>
 *   <li>Otherwise, if the operation is a {@link Transformation}, then checks if the datum shift
 *       were applied with the help of Bursa-Wolf parameters. This procedure looks for SIS-specific
 *       {@link #DATUM_SHIFT_APPLIED} and {@link #DATUM_SHIFT_OMITTED DATUM_SHIFT_OMITTED} constants.</li>
 *   <li>Otherwise, if the operation is a {@link ConcatenatedOperation}, returns the sum of the accuracy
 *       of all components. This is a conservative scenario where we assume that errors cumulate linearly.
 *       Note that this is not necessarily the "worst case" scenario since the accuracy could be worst
 *       if the math transforms are highly non-linear.</li>
 * </ul>
 *
 * If the above is modified, please update {@code AbstractCoordinateOperation.getLinearAccuracy()} javadoc.
 *
 * @param  operation  the operation to inspect for accuracy.
 * @return the accuracy estimate (always in meters), or NaN if unknown.
 *
 * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation#getLinearAccuracy()
 */
public static double getLinearAccuracy(final CoordinateOperation operation) {
    double accuracy = Double.NaN;
    final Collection<PositionalAccuracy> accuracies = operation.getCoordinateOperationAccuracy();
    for (final PositionalAccuracy metadata : accuracies) {
        for (final Result result : metadata.getResults()) {
            if (result instanceof QuantitativeResult) {
                final QuantitativeResult quantity = (QuantitativeResult) result;
                final Collection<? extends Record> records = quantity.getValues();
                if (records != null) {
                    final Unit<?> unit = quantity.getValueUnit();
                    if (Units.isLinear(unit)) {
                        final Unit<Length> unitOfLength = unit.asType(Length.class);
                        for (final Record record : records) {
                            for (final Object value : record.getAttributes().values()) {
                                if (value instanceof Number) {
                                    double v = ((Number) value).doubleValue();
                                    v = unitOfLength.getConverterTo(Units.METRE).convert(v);
                                    if (v >= 0 && !(v <= accuracy)) {
                                        // '!' is for replacing the NaN value.
                                        accuracy = v;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    if (Double.isNaN(accuracy)) {
        /*
             * No quantitative (linear) accuracy were found. If the coordinate operation is actually
             * a conversion, the accuracy is up to rounding error (i.e. conceptually 0) by definition.
             */
        if (operation instanceof Conversion) {
            return 0;
        }
        /*
             * If the coordinate operation is actually a transformation, checks if Bursa-Wolf parameters
             * were available for the datum shift. This is SIS-specific. See field javadoc for a rational
             * about the return values chosen.
             */
        if (operation instanceof Transformation) {
            if (accuracies.contains(DATUM_SHIFT_APPLIED)) {
                return DATUM_SHIFT_ACCURACY;
            }
            if (accuracies.contains(DATUM_SHIFT_OMITTED)) {
                return UNKNOWN_ACCURACY;
            }
        }
        /*
             * If the coordinate operation is a compound of other coordinate operations, returns the sum of their accuracy,
             * skipping unknown ones. Making the sum is a conservative approach (not exactly the "worst case" scenario,
             * since it could be worst if the transforms are highly non-linear).
             */
        if (operation instanceof ConcatenatedOperation) {
            for (final CoordinateOperation op : ((ConcatenatedOperation) operation).getOperations()) {
                final double candidate = Math.abs(getLinearAccuracy(op));
                if (!Double.isNaN(candidate)) {
                    if (Double.isNaN(accuracy)) {
                        accuracy = candidate;
                    } else {
                        accuracy += candidate;
                    }
                }
            }
        }
    }
    return accuracy;
}
Also used : Transformation(org.opengis.referencing.operation.Transformation) PositionalAccuracy(org.opengis.metadata.quality.PositionalAccuracy) DefaultAbsoluteExternalPositionalAccuracy(org.apache.sis.metadata.iso.quality.DefaultAbsoluteExternalPositionalAccuracy) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) Conversion(org.opengis.referencing.operation.Conversion) Result(org.opengis.metadata.quality.Result) QuantitativeResult(org.opengis.metadata.quality.QuantitativeResult) DefaultConformanceResult(org.apache.sis.metadata.iso.quality.DefaultConformanceResult) QuantitativeResult(org.opengis.metadata.quality.QuantitativeResult) Length(javax.measure.quantity.Length) Record(org.opengis.util.Record) ConcatenatedOperation(org.opengis.referencing.operation.ConcatenatedOperation)

Example 2 with QuantitativeResult

use of org.opengis.metadata.quality.QuantitativeResult in project sis by apache.

the class FeatureTestCase method testCustomAttribute.

/**
 * Tests the possibility to plugin custom attributes via {@code AbstractFeature.setProperty(Property)}.
 */
@Test
@DependsOnMethod({ "testSimpleValues", "testSimpleProperties" })
public void testCustomAttribute() {
    feature = createFeature(DefaultFeatureTypeTest.city());
    final AbstractAttribute<String> wrong = SingletonAttributeTest.parliament();
    final CustomAttribute<String> city = new CustomAttribute<>(Features.cast((DefaultAttributeType<?>) feature.getType().getProperty("city"), String.class));
    feature.setProperty(city);
    setAttributeValue("city", "Utopia", "Atlantide");
    try {
        feature.setProperty(wrong);
        fail("Shall not be allowed to set a property of the wrong type.");
    } catch (IllegalArgumentException e) {
        final String message = e.getMessage();
        assertTrue(message, message.contains("parliament"));
        assertTrue(message, message.contains("City"));
    }
    if (assertSameProperty("city", city, true)) {
        /*
             * The quality report is expected to contains a custom element.
             */
        int numOccurrences = 0;
        final DataQuality quality = verifyQualityReports("population");
        for (final Element report : quality.getReports()) {
            final String identifier = report.getMeasureIdentification().toString();
            if (identifier.equals("city")) {
                numOccurrences++;
                final Result result = TestUtilities.getSingleton(report.getResults());
                assertInstanceOf("result", QuantitativeResult.class, result);
                assertEquals("quality.report.result.errorStatistic", CustomAttribute.ADDITIONAL_QUALITY_INFO, String.valueOf(((QuantitativeResult) result).getErrorStatistic()));
            }
        }
        assertEquals("Number of reports.", 1, numOccurrences);
    }
}
Also used : QuantitativeResult(org.opengis.metadata.quality.QuantitativeResult) DataQuality(org.opengis.metadata.quality.DataQuality) Element(org.opengis.metadata.quality.Element) SimpleInternationalString(org.apache.sis.util.iso.SimpleInternationalString) Result(org.opengis.metadata.quality.Result) QuantitativeResult(org.opengis.metadata.quality.QuantitativeResult) ConformanceResult(org.opengis.metadata.quality.ConformanceResult) Test(org.junit.Test) DependsOnMethod(org.apache.sis.test.DependsOnMethod)

Aggregations

QuantitativeResult (org.opengis.metadata.quality.QuantitativeResult)2 Result (org.opengis.metadata.quality.Result)2 Length (javax.measure.quantity.Length)1 DefaultAbsoluteExternalPositionalAccuracy (org.apache.sis.metadata.iso.quality.DefaultAbsoluteExternalPositionalAccuracy)1 DefaultConformanceResult (org.apache.sis.metadata.iso.quality.DefaultConformanceResult)1 DependsOnMethod (org.apache.sis.test.DependsOnMethod)1 SimpleInternationalString (org.apache.sis.util.iso.SimpleInternationalString)1 Test (org.junit.Test)1 ConformanceResult (org.opengis.metadata.quality.ConformanceResult)1 DataQuality (org.opengis.metadata.quality.DataQuality)1 Element (org.opengis.metadata.quality.Element)1 PositionalAccuracy (org.opengis.metadata.quality.PositionalAccuracy)1 ConcatenatedOperation (org.opengis.referencing.operation.ConcatenatedOperation)1 Conversion (org.opengis.referencing.operation.Conversion)1 CoordinateOperation (org.opengis.referencing.operation.CoordinateOperation)1 Transformation (org.opengis.referencing.operation.Transformation)1 Record (org.opengis.util.Record)1