Search in sources :

Example 66 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class Geographic3Dto2DTest method createDatumShiftForGeographic2D.

/**
 * Creates a "Geographic 2D to 3D → Geocentric → Affine → Geographic → Geographic 3D to 2D" chain.
 * This method is used for integration tests.
 *
 * @param  factory  the math transform factory to use for creating and concatenating the transform.
 * @param  affine   the math transform for the operation in geocentric Cartesian domain.
 * @param  pv       the parameters for the operation in geographic coordinates.
 * @return the chain of transforms.
 * @throws FactoryException if an error occurred while creating a transform.
 *
 * @see GeocentricTranslationTest#createDatumShiftForGeographic2D(MathTransformFactory)
 */
static MathTransform createDatumShiftForGeographic2D(final MathTransformFactory factory, final MathTransform affine, final Parameters pv) throws FactoryException {
    assertEquals("sourceDimensions", 3, affine.getSourceDimensions());
    assertEquals("targetDimensions", 3, affine.getTargetDimensions());
    /*
         * Create a "Geographic to Geocentric" conversion with ellipsoid axis length units converted to metres
         * (the unit implied by SRC_SEMI_MAJOR) because it is the unit of Bursa-Wolf parameters that we created above.
         */
    Parameters step = Parameters.castOrWrap(factory.getDefaultParameters(GeographicToGeocentric.NAME));
    step.getOrCreate(MapProjection.SEMI_MAJOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.SRC_SEMI_MAJOR));
    step.getOrCreate(MapProjection.SEMI_MINOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.SRC_SEMI_MINOR));
    MathTransform toGeocentric = factory.createParameterizedTransform(step);
    assertEquals("sourceDimensions", 3, toGeocentric.getSourceDimensions());
    assertEquals("targetDimensions", 3, toGeocentric.getTargetDimensions());
    final MathTransform reduce = factory.createParameterizedTransform(factory.getDefaultParameters("Geographic3D to 2D conversion"));
    assertEquals("sourceDimensions", 3, reduce.getSourceDimensions());
    assertEquals("targetDimensions", 2, reduce.getTargetDimensions());
    try {
        toGeocentric = factory.createConcatenatedTransform(reduce.inverse(), toGeocentric);
    } catch (NoninvertibleTransformException e) {
        throw new FactoryException(e);
    }
    assertEquals("sourceDimensions", 2, toGeocentric.getSourceDimensions());
    assertEquals("targetDimensions", 3, toGeocentric.getTargetDimensions());
    /*
         * Create a "Geocentric to Geographic" conversion with ellipsoid axis length units converted to metres
         * because this is the unit of the Geocentric CRS used above.
         */
    step = Parameters.castOrWrap(factory.getDefaultParameters(GeocentricToGeographic.NAME));
    step.getOrCreate(MapProjection.SEMI_MAJOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.TGT_SEMI_MAJOR));
    step.getOrCreate(MapProjection.SEMI_MINOR).setValue(pv.doubleValue(GeocentricAffineBetweenGeographic.TGT_SEMI_MINOR));
    MathTransform toGeographic = factory.createParameterizedTransform(step);
    assertEquals("sourceDimensions", 3, toGeographic.getSourceDimensions());
    assertEquals("targetDimensions", 3, toGeographic.getTargetDimensions());
    toGeographic = factory.createConcatenatedTransform(toGeographic, reduce);
    assertEquals("sourceDimensions", 3, toGeographic.getSourceDimensions());
    assertEquals("targetDimensions", 2, toGeographic.getTargetDimensions());
    /*
         * The  Geocentric → Affine → Geographic  chain.
         */
    return factory.createConcatenatedTransform(toGeocentric, factory.createConcatenatedTransform(affine, toGeographic));
}
Also used : NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) Parameters(org.apache.sis.parameter.Parameters) MathTransform(org.opengis.referencing.operation.MathTransform) FactoryException(org.opengis.util.FactoryException)

Example 67 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class TransformSeparator method filterSourceDimensions.

/**
 * Creates a transform for the same mathematic than the given {@code step}
 * but expecting only the given dimensions as inputs.
 * This method is invoked by {@link #separate()} when user-specified source dimensions need to be taken in account.
 * The given {@code step} and {@code dimensions} are typically the values of
 * {@link #transform} and {@link #sourceDimensions} fields respectively, but not necessarily.
 * In particular those arguments will differ when this method is invoked recursively for processing
 * concatenated or {@linkplain PassThroughTransform#getSubTransform() sub-transforms}.
 *
 * <p>Subclasses can override this method if they need to handle some {@code MathTransform} implementations
 * in a special way. However all implementations of this method shall obey to the following contract:</p>
 * <ul class="verbose">
 *   <li>{@link #sourceDimensions} and {@link #targetDimensions} should not be assumed accurate
 *       since they may be temporarily outdated or modified during recursive calls to this method.</li>
 *   <li>{@link #sourceDimensions} should not be modified by this method.</li>
 *   <li>{@link #targetDimensions} <strong>must</strong> be <em>overwritten</em> (not updated) by this method to the
 *       sequence of all target dimensions of {@code step} that are also target dimensions of the returned transform.
 *       The indices shall be in strictly increasing order from 0 inclusive to
 *       {@code step.getTargetDimensions()} exclusive.</li>
 * </ul>
 *
 * @param  step        the transform for which to retain only a subset of the source dimensions.
 * @param  dimensions  indices of the source dimensions of {@code step} to retain.
 * @return a transform expecting only the given source dimensions.
 * @throws FactoryException if the given transform is not separable.
 */
@SuppressWarnings("AssignmentToCollectionOrArrayFieldFromParameter")
protected MathTransform filterSourceDimensions(final MathTransform step, final int[] dimensions) throws FactoryException {
    if (dimensions.length == 0) {
        return IdentityTransform.create(0);
    }
    final int numSrc = step.getSourceDimensions();
    final int numTgt = step.getTargetDimensions();
    final int lower = dimensions[0];
    final int upper = dimensions[dimensions.length - 1] + 1;
    if (lower == 0 && upper == numSrc && dimensions.length == numSrc) {
        targetDimensions = series(0, numTgt);
        return step;
    }
    if (step.isIdentity()) {
        targetDimensions = dimensions;
        return IdentityTransform.create(dimensions.length);
    }
    if (step instanceof ConcatenatedTransform) {
        final ConcatenatedTransform ctr = (ConcatenatedTransform) step;
        final MathTransform step1 = filterSourceDimensions(ctr.transform1, dimensions);
        final MathTransform step2 = filterSourceDimensions(ctr.transform2, targetDimensions);
        return factory.createConcatenatedTransform(step1, step2);
    // Keep the 'targetDimensions' computed by the last step.
    }
    /*
         * Special case for the passthrough transform: if at least one input dimension belong to the pass-
         * through sub-transform, then invoke this method recursively for the sub-transform dimensions.
         */
    if (step instanceof PassThroughTransform) {
        final PassThroughTransform passThrough = (PassThroughTransform) step;
        final int numSubSrc = passThrough.subTransform.getSourceDimensions();
        final int numNewDim = passThrough.subTransform.getTargetDimensions() - numSubSrc;
        final int subLower = passThrough.firstAffectedOrdinate;
        final int subUpper = subLower + numSubSrc;
        int[] subDimensions = new int[dimensions.length];
        targetDimensions = null;
        int n = 0;
        for (int dim : dimensions) {
            if (dim >= subLower) {
                if (dim < subUpper) {
                    // Dimension n belong to the subtransform.
                    subDimensions[n++] = dim - subLower;
                    continue;
                }
                dim += numNewDim;
            }
            /*
                 * Dimension n belong to heading or trailing dimensions.
                 * Passthrough, after adjustment for trailing dimensions.
                 */
            targetDimensions = insert(targetDimensions, dim);
        }
        subDimensions = ArraysExt.resize(subDimensions, n);
        /*
             * If no source dimension belong to the sub-transform, then all source dimensions are heading or
             * trailing dimensions. A passthrough transform without its sub-transform is an identity transform.
             */
        if (n == 0) {
            return IdentityTransform.create(dimensions.length);
        }
        /*
             * There is at least one dimension to separate in the sub-transform. Perform this separation and get
             * the list of target dimensions. We need to offset the target dimensions by the amount of leading
             * dimensions once the separation is done, in order to translate from the sub-transform's dimension
             * numbering to the transform's numbering.
             */
        int[] target = targetDimensions;
        final MathTransform subTransform = filterSourceDimensions(passThrough.subTransform, subDimensions);
        for (final int dim : targetDimensions) {
            target = insert(target, dim + subLower);
        }
        targetDimensions = target;
        /*
             * If all source dimensions not in the sub-transform are consecutive numbers, we can use our passthrough
             * transform implementation. The "consecutive numbers" requirement (expressed in the 'if' statement below)
             * is a consequence of a limitation in our current implementation: our current passthrough transform does
             * not accept arbitrary index for modified ordinates.
             */
        if (containsAll(dimensions, lower, subLower) && containsAll(dimensions, subUpper, upper)) {
            return factory.createPassThroughTransform(subLower - lower, subTransform, Math.max(0, upper - subUpper));
        }
    }
    /*
         * If the transform is affine (or at least projective), express the transform as a matrix. Then, select
         * target dimensions that depend only on specified source dimensions. If a target dimension depends on
         * at least one discarded source dimension, then that output dimension will be discarded as well.
         */
    final Matrix matrix = MathTransforms.getMatrix(step);
    if (matrix != null) {
        targetDimensions = null;
        int startOfRow = 0;
        boolean isLastRowAccepted = false;
        final int numFilteredColumns = (dimensions.length + 1);
        double[] elements = new double[(numTgt + 1) * numFilteredColumns];
        reduce: for (int j = 0; j <= numTgt; j++) {
            /*
                 * For each target dimension (i.e. a matrix row), find the matrix elements (excluding translation
                 * terms in the last column) for each source dimension to be kept. If a dependancy to at least one
                 * discarded input dimension is found, then the whole output dimension is discarded.
                 */
            int filteredColumn = 0;
            for (int i = 0; i < numSrc; i++) {
                final double element = matrix.getElement(j, i);
                if (filteredColumn < dimensions.length && dimensions[filteredColumn] == i) {
                    elements[startOfRow + filteredColumn++] = element;
                } else if (element != 0) {
                    /*
                         * Output dimension 'j' depends on one of discarded input dimension 'i'.
                         * The whole row will be discarded.
                         */
                    continue reduce;
                }
            }
            // Copy the translation term.
            elements[startOfRow + filteredColumn++] = matrix.getElement(j, numSrc);
            // We should have used all values in the 'dimensions' array.
            assert filteredColumn == numFilteredColumns : filteredColumn;
            startOfRow += numFilteredColumns;
            if (j == numTgt) {
                /*
                     * In an affine transform, the last row is usually [0 0 0 … 1].
                     * This is not a real dimension, but nevertheless mandatory.
                     */
                isLastRowAccepted = true;
            } else {
                targetDimensions = insert(targetDimensions, j);
            }
        }
        if (isLastRowAccepted) {
            elements = ArraysExt.resize(elements, startOfRow);
            return factory.createAffineTransform(Matrices.create(startOfRow / numFilteredColumns, numFilteredColumns, elements));
        }
    /*
             * In an affine transform, the last row is not supposed to have dependency to any source dimension.
             * But if we reach this point, our matrix has such dependencies.
             */
    }
    throw new FactoryException(Resources.format(Resources.Keys.NotAnAffineTransform));
}
Also used : Matrix(org.opengis.referencing.operation.Matrix) MathTransform(org.opengis.referencing.operation.MathTransform) FactoryException(org.opengis.util.FactoryException)

Example 68 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class EPSGFactoryTest method testDeprecatedCoordinateSystems.

/**
 * Tests creation of deprecated coordinate systems.
 *
 * @throws FactoryException if an error occurred while querying the factory.
 */
@Test
public void testDeprecatedCoordinateSystems() throws FactoryException {
    final EPSGFactory factory = TestFactorySource.factory;
    assumeNotNull(factory);
    for (final Map.Entry<Integer, Integer> entry : EPSGDataAccess.deprecatedCS().entrySet()) {
        final CoordinateSystem expected = factory.createEllipsoidalCS(entry.getValue().toString());
        loggings.assertNoUnexpectedLog();
        final String code = entry.getKey().toString();
        final CoordinateSystem deprecated;
        try {
            deprecated = factory.createEllipsoidalCS(code);
        } catch (FactoryException e) {
            final String m = e.getMessage();
            if (m.contains("9115") || m.contains("9116") || m.contains("9117") || m.contains("9118") || m.contains("9119") || m.contains("9120")) {
                // Unit "9116" to "9120" are known to be unsupported.
                continue;
            }
            throw e;
        }
        loggings.assertNextLogContains(code);
        final int dimension = expected.getDimension();
        assertEquals("dimension", dimension, deprecated.getDimension());
        for (int i = 0; i < dimension; i++) {
            final CoordinateSystemAxis ref = expected.getAxis(i);
            final CoordinateSystemAxis axis = deprecated.getAxis(i);
            assertEquals("name", ref.getName(), axis.getName());
            assertEquals("alias", ref.getAlias(), axis.getAlias());
            assertEquals("direction", ref.getDirection(), axis.getDirection());
            assertEquals("rangeMeaning", ref.getRangeMeaning(), axis.getRangeMeaning());
            assertEquals("unit", ref.getUnit().getSystemUnit(), axis.getUnit().getSystemUnit());
        }
    }
}
Also used : FactoryException(org.opengis.util.FactoryException) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) Map(java.util.Map) Test(org.junit.Test)

Example 69 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class DefaultVerticalExtent method intersect.

/**
 * Sets this vertical extent to the intersection of this extent with the specified one.
 * The {@linkplain org.apache.sis.referencing.crs.DefaultVerticalCRS#getDatum() vertical datum}
 * must be the same (ignoring metadata) for both extents; this method does not perform datum shift.
 * However this method can perform unit conversions.
 *
 * <p>If there is no intersection between the two extents, then this method sets both minimum and
 * maximum values to {@linkplain Double#NaN}. If either this extent or the specified extent has NaN
 * bounds, then the corresponding bounds of the intersection result will also be NaN.</p>
 *
 * @param  other  the vertical extent to intersect with this extent.
 * @throws IllegalArgumentException if the two extents do not use the same datum, ignoring metadata.
 *
 * @see Extents#intersection(VerticalExtent, VerticalExtent)
 * @see org.apache.sis.geometry.GeneralEnvelope#intersect(Envelope)
 *
 * @since 0.8
 */
public void intersect(final VerticalExtent other) throws IllegalArgumentException {
    checkWritePermission();
    ArgumentChecks.ensureNonNull("other", other);
    Double min = other.getMinimumValue();
    Double max = other.getMaximumValue();
    try {
        final MathTransform1D cv = getConversionFrom(other.getVerticalCRS());
        if (isReversing(cv, min, max)) {
            Double tmp = min;
            min = max;
            max = tmp;
        }
        /*
             * If minimumValue is NaN, keep it unchanged (because x > minimumValue is false)
             * in order to preserve the NilReason. Conversely if min is NaN, then we want to
             * take it without conversion for preserving its NilReason.
             */
        if (min != null) {
            if (minimumValue == null || min.isNaN() || (min = convert(cv, min)) > minimumValue) {
                minimumValue = min;
            }
        }
        if (max != null) {
            if (maximumValue == null || max.isNaN() || (max = convert(cv, max)) < maximumValue) {
                maximumValue = max;
            }
        }
    } catch (UnsupportedOperationException | FactoryException | ClassCastException | TransformException e) {
        throw new IllegalArgumentException(Errors.format(Errors.Keys.IncompatiblePropertyValue_1, "verticalCRS"), e);
    }
    if (minimumValue != null && maximumValue != null && minimumValue > maximumValue) {
        minimumValue = maximumValue = NilReason.MISSING.createNilObject(Double.class);
    }
}
Also used : FactoryException(org.opengis.util.FactoryException) TransformException(org.opengis.referencing.operation.TransformException) MathTransform1D(org.opengis.referencing.operation.MathTransform1D)

Example 70 with FactoryException

use of org.opengis.util.FactoryException in project sis by apache.

the class CoordinateSystemTransform method create.

/**
 * Implementation of {@link DefaultMathTransformFactory#createCoordinateSystemChange(CoordinateSystem,
 * CoordinateSystem, Ellipsoid)}, defined here for reducing the {@code DefaultMathTransformFactory}
 * weight in the common case where the conversions handled by this class are not needed.
 */
static MathTransform create(final MathTransformFactory factory, final CoordinateSystem source, final CoordinateSystem target) throws FactoryException {
    int passthrough = 0;
    CoordinateSystemTransform kernel = null;
    if (source instanceof CartesianCS) {
        if (target instanceof SphericalCS) {
            kernel = CartesianToSpherical.INSTANCE;
        } else if (target instanceof PolarCS) {
            kernel = CartesianToPolar.INSTANCE;
        } else if (target instanceof CylindricalCS) {
            kernel = CartesianToPolar.INSTANCE;
            passthrough = 1;
        }
    } else if (target instanceof CartesianCS) {
        if (source instanceof SphericalCS) {
            kernel = SphericalToCartesian.INSTANCE;
        } else if (source instanceof PolarCS) {
            kernel = PolarToCartesian.INSTANCE;
        } else if (source instanceof CylindricalCS) {
            kernel = PolarToCartesian.INSTANCE;
            passthrough = 1;
        }
    }
    Exception cause = null;
    try {
        if (kernel == null) {
            return factory.createAffineTransform(CoordinateSystems.swapAndScaleAxes(source, target));
        } else if (source.getDimension() == kernel.getSourceDimensions() + passthrough && target.getDimension() == kernel.getTargetDimensions() + passthrough) {
            final MathTransform tr = (passthrough == 0) ? kernel.completeTransform(factory) : kernel.passthrough(factory);
            final MathTransform before = factory.createAffineTransform(CoordinateSystems.swapAndScaleAxes(source, CoordinateSystems.replaceAxes(source, AxesConvention.NORMALIZED)));
            final MathTransform after = factory.createAffineTransform(CoordinateSystems.swapAndScaleAxes(CoordinateSystems.replaceAxes(target, AxesConvention.NORMALIZED), target));
            return factory.createConcatenatedTransform(before, factory.createConcatenatedTransform(tr, after));
        }
    } catch (IllegalArgumentException | IncommensurableException e) {
        cause = e;
    }
    throw new OperationNotFoundException(Resources.format(Resources.Keys.CoordinateOperationNotFound_2, WKTUtilities.toType(CoordinateSystem.class, source.getClass()), WKTUtilities.toType(CoordinateSystem.class, target.getClass())), cause);
}
Also used : CartesianCS(org.opengis.referencing.cs.CartesianCS) SphericalCS(org.opengis.referencing.cs.SphericalCS) PolarCS(org.opengis.referencing.cs.PolarCS) CylindricalCS(org.opengis.referencing.cs.CylindricalCS) OperationNotFoundException(org.opengis.referencing.operation.OperationNotFoundException) MathTransform(org.opengis.referencing.operation.MathTransform) IncommensurableException(javax.measure.IncommensurableException) OperationNotFoundException(org.opengis.referencing.operation.OperationNotFoundException) IncommensurableException(javax.measure.IncommensurableException) FactoryException(org.opengis.util.FactoryException)

Aggregations

FactoryException (org.opengis.util.FactoryException)84 TransformException (org.opengis.referencing.operation.TransformException)27 GeometryWrapper (org.apache.jena.geosparql.implementation.GeometryWrapper)21 MismatchedDimensionException (org.opengis.geometry.MismatchedDimensionException)19 ExprEvalException (org.apache.jena.sparql.expr.ExprEvalException)17 MathTransform (org.opengis.referencing.operation.MathTransform)15 DatatypeFormatException (org.apache.jena.datatypes.DatatypeFormatException)12 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)10 IdentifiedObject (org.opengis.referencing.IdentifiedObject)8 Envelope (org.locationtech.jts.geom.Envelope)7 ArrayList (java.util.ArrayList)6 ParameterValueGroup (org.opengis.parameter.ParameterValueGroup)6 NoninvertibleTransformException (org.opengis.referencing.operation.NoninvertibleTransformException)6 Literal (org.apache.jena.rdf.model.Literal)5 UnavailableFactoryException (org.apache.sis.referencing.factory.UnavailableFactoryException)5 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)5 ParseException (java.text.ParseException)4 AbstractIdentifiedObject (org.apache.sis.referencing.AbstractIdentifiedObject)4 BackingStoreException (org.apache.sis.util.collection.BackingStoreException)4 Test (org.junit.Test)4