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;
}
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);
}
}
Aggregations