Search in sources :

Example 31 with FactoryException

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

the class GridGeometry method localizationGrid.

/**
 * Builds a localization grid from the given GeoTIFF tie points.
 * This method may invoke itself recursively.
 *
 * @param  modelTiePoints  the model tie points read from GeoTIFF file.
 * @param  addTo           if non-null, add the transform result to this map.
 */
private static MathTransform localizationGrid(final Vector modelTiePoints, final Map<Envelope, MathTransform> addTo) throws FactoryException, TransformException {
    final int size = modelTiePoints.size();
    final int n = size / RECORD_LENGTH;
    if (n == 0)
        return null;
    final Vector x = modelTiePoints.subSampling(0, RECORD_LENGTH, n);
    final Vector y = modelTiePoints.subSampling(1, RECORD_LENGTH, n);
    try {
        final LocalizationGridBuilder grid = new LocalizationGridBuilder(x, y);
        final LinearTransform sourceToGrid = grid.getSourceToGrid();
        final double[] ordinates = new double[2];
        for (int i = 0; i < size; i += RECORD_LENGTH) {
            ordinates[0] = modelTiePoints.doubleValue(i);
            ordinates[1] = modelTiePoints.doubleValue(i + 1);
            sourceToGrid.transform(ordinates, 0, ordinates, 0, 1);
            grid.setControlPoint(Math.toIntExact(Math.round(ordinates[0])), Math.toIntExact(Math.round(ordinates[1])), modelTiePoints.doubleValue(i + 3), modelTiePoints.doubleValue(i + 4));
        }
        grid.setDesiredPrecision(PRECISION);
        final MathTransform tr = grid.create(null);
        if (addTo != null && addTo.put(grid.getSourceEnvelope(), tr) != null) {
            // Should never happen. If it does, we have a bug in our algorithm.
            throw new FactoryException();
        }
        return tr;
    } catch (ArithmeticException | FactoryException e) {
        /*
             * May happen when the model tie points are not distributed on a regular grid.
             * For example Sentinel 1 images may have tie points spaced by 1320 pixels on the X axis,
             * except the very last point which is only 1302 pixels after the previous one. We try to
             * handle such grids by splitting them in two parts: one grid for the columns where points
             * are spaced by 1320 pixels and one grid for the last column. Such splitting needs to be
             * done horizontally and vertically, which result in four grids:
             *
             *    ┌──────────────────┬───┐
             *    │                  │   │
             *    │         0        │ 1 │
             *    │                  │   │
             *    ├──────────────────┼───┤ splitY
             *    │         2        │ 3 │
             *    └──────────────────┴───┘
             *                    splitX
             */
        final Set<Double> uniques = new HashSet<>(100);
        final double splitX = threshold(x, uniques);
        final double splitY = threshold(y, uniques);
        if (Double.isNaN(splitX) && Double.isNaN(splitY)) {
            // Can not do better. Report the failure.
            throw e;
        }
        final int[][] indices = new int[4][size];
        final int[] lengths = new int[4];
        for (int i = 0; i < size; ) {
            final double px = modelTiePoints.doubleValue(i);
            final double py = modelTiePoints.doubleValue(i + 1);
            // Number of the part where to add current point.
            int part = 0;
            // Point will be added to part #1 or #3.
            if (px > splitX)
                part = 1;
            // Point will be added to part #2 or #3.
            if (py > splitY)
                part |= 2;
            // Bitmask of the parts where to add the point.
            int parts = 1 << part;
            // Add also the point to part #1 or #3.
            if (px == splitX)
                parts |= 1 << (part | 1);
            // Add also the point to part #2 or #3.
            if (py == splitY)
                parts |= 1 << (part | 2);
            if (parts == 0b0111) {
                // Add also the point to part #3.
                parts = 0b1111;
                assert px == splitX && py == splitY;
            }
            final int upper = i + RECORD_LENGTH;
            do {
                part = Integer.numberOfTrailingZeros(parts);
                @SuppressWarnings("MismatchedReadAndWriteOfArray") final int[] tileIndices = indices[part];
                int k = lengths[part];
                for (int j = i; j < upper; j++) {
                    tileIndices[k++] = j;
                }
                lengths[part] = k;
            } while (// Clear the bit of the part we processed.
            (parts &= ~(1 << part)) != 0);
            i = upper;
        }
        /*
             * At this point, we finished to collect indices of the points to use for parts #0, 1, 2 and 3.
             * Verify that each part has less points than the initial vector (otherwise it would be a bug),
             * and identify which part is the biggest one. This is usually part #0.
             */
        int maxLength = 0;
        int largestPart = 0;
        for (int i = 0; i < indices.length; i++) {
            final int length = lengths[i];
            // Safety against infinite recursivity.
            if (length >= size)
                throw e;
            indices[i] = Arrays.copyOf(indices[i], length);
            if (length > maxLength) {
                maxLength = length;
                largestPart = i;
            }
        }
        /*
             * The biggest part will define the global transform. All other parts will define a specialization
             * valid only in a sub-area. Put those information in a map for MathTransforms.specialize(…).
             */
        MathTransform global = null;
        final Map<Envelope, MathTransform> specialization = new LinkedHashMap<>(4);
        for (int i = 0; i < indices.length; i++) {
            final Vector sub = modelTiePoints.pick(indices[i]);
            if (i == largestPart) {
                global = localizationGrid(sub, null);
            } else {
                localizationGrid(sub, specialization);
            }
        }
        return MathTransforms.specialize(global, specialization);
    }
}
Also used : Set(java.util.Set) HashSet(java.util.HashSet) MathTransform(org.opengis.referencing.operation.MathTransform) FactoryException(org.opengis.util.FactoryException) LinearTransform(org.apache.sis.referencing.operation.transform.LinearTransform) LocalizationGridBuilder(org.apache.sis.referencing.operation.builder.LocalizationGridBuilder) Vector(org.apache.sis.math.Vector) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 32 with FactoryException

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

the class TransformCommand method run.

/**
 * Transforms coordinates from the files given in argument or from the standard input stream.
 *
 * @return 0 on success, or an exit code if the command failed for a reason other than an uncaught Java exception.
 */
@Override
public int run() throws Exception {
    final CoordinateReferenceSystem sourceCRS = fetchCRS(Option.SOURCE_CRS);
    final CoordinateReferenceSystem targetCRS = fetchCRS(Option.TARGET_CRS);
    /*
         * Read all coordinates, so we can compute the area of interest.
         * This will be used when searching for a coordinate operation.
         */
    GeographicBoundingBox areaOfInterest = null;
    List<double[]> points = Collections.emptyList();
    final boolean useStandardInput = useStandardInput();
    if (useStandardInput || !files.isEmpty()) {
        if (useStandardInput) {
            try (LineNumberReader in = new LineNumberReader(new InputStreamReader(System.in, encoding))) {
                points = readCoordinates(in, "stdin");
            }
        } else {
            for (final String file : files) {
                try (LineNumberReader in = new LineNumberReader(new InputStreamReader(new FileInputStream(file), encoding))) {
                    points = readCoordinates(in, file);
                }
            }
        }
        try {
            final GeographicCRS domainOfValidityCRS = ReferencingUtilities.toNormalizedGeographicCRS(sourceCRS);
            if (domainOfValidityCRS != null) {
                toDomainOfValidity = CRS.findOperation(sourceCRS, domainOfValidityCRS, null).getMathTransform();
                areaOfInterest = computeAreaOfInterest(points);
            }
        } catch (FactoryException e) {
            warning(e);
        }
    }
    operation = CRS.findOperation(sourceCRS, targetCRS, areaOfInterest);
    /*
         * Prints the header: source CRS, target CRS, operation steps and positional accuracy.
         */
    outHeader = new TableAppender(new LineAppender(out), " ");
    outHeader.setMultiLinesCells(true);
    printHeader(Vocabulary.Keys.Source);
    printNameAndIdentifier(operation.getSourceCRS(), false);
    printHeader(Vocabulary.Keys.Destination);
    printNameAndIdentifier(operation.getTargetCRS(), false);
    printHeader(Vocabulary.Keys.Operations);
    printOperations(operation, false);
    outHeader.nextLine();
    printDomainOfValidity(operation.getDomainOfValidity());
    printAccuracy(CRS.getLinearAccuracy(operation));
    if (options.containsKey(Option.VERBOSE)) {
        printDetails();
    }
    outHeader.flush();
    outHeader = null;
    /*
         * At this point we finished to write the header. If there is at least one input file,
         * compute the number of digits to format and perform the actual coordinate operations.
         */
    if (!points.isEmpty()) {
        // Must be set before computeNumFractionDigits(…).
        ordinateWidth = 15;
        coordinateFormat = NumberFormat.getInstance(Locale.US);
        coordinateFormat.setGroupingUsed(false);
        computeNumFractionDigits(operation.getTargetCRS().getCoordinateSystem());
        out.println();
        printAxes(operation.getTargetCRS().getCoordinateSystem());
        out.println();
        transform(points);
        if (errorMessage != null) {
            error(errorMessage, errorCause);
        }
    }
    return 0;
}
Also used : InputStreamReader(java.io.InputStreamReader) FactoryException(org.opengis.util.FactoryException) TableAppender(org.apache.sis.io.TableAppender) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) DefaultGeographicBoundingBox(org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox) InternationalString(org.opengis.util.InternationalString) GeographicCRS(org.opengis.referencing.crs.GeographicCRS) LineAppender(org.apache.sis.io.LineAppender) FileInputStream(java.io.FileInputStream) LineNumberReader(java.io.LineNumberReader)

Example 33 with FactoryException

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

the class CRS method findOperations.

/**
 * Finds mathematical operations that transform or convert coordinates from the given source to the
 * given target coordinate reference system. If at least one operation exists, they are returned in
 * preference order: the operation having the widest intersection between its
 * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}
 * and the given area of interest are returned first.
 *
 * @param  sourceCRS       the CRS of source coordinates.
 * @param  targetCRS       the CRS of target coordinates.
 * @param  areaOfInterest  the area of interest, or {@code null} if none.
 * @return mathematical operations from {@code sourceCRS} to {@code targetCRS}.
 * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
 * @throws FactoryException if the operation can not be created for another reason.
 *
 * @see DefaultCoordinateOperationFactory#createOperations(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
 *
 * @since 1.0
 */
public static List<CoordinateOperation> findOperations(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS, final GeographicBoundingBox areaOfInterest) throws FactoryException {
    ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
    ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
    final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
    final DefaultCoordinateOperationFactory factory = CoordinateOperations.factory();
    try {
        return factory.createOperations(sourceCRS, targetCRS, context);
    } catch (UnavailableFactoryException e) {
        if (AuthorityFactories.failure(e)) {
            throw e;
        } else
            try {
                return Collections.singletonList(factory.createOperation(sourceCRS, targetCRS, context));
            } catch (FactoryException ex) {
                ex.addSuppressed(e);
                throw ex;
            }
    }
}
Also used : FactoryException(org.opengis.util.FactoryException) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) DefaultCoordinateOperationFactory(org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) CoordinateOperationContext(org.apache.sis.referencing.operation.CoordinateOperationContext)

Example 34 with FactoryException

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

the class CRS method findOperation.

/**
 * Finds a mathematical operation that transforms or converts coordinates from the given source to the
 * given target coordinate reference system. If an estimation of the geographic area containing the points
 * to transform is known, it can be specified for helping this method to find a better suited operation.
 * If no area of interest is specified, then the current default is the widest
 * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}.
 * A future Apache SIS version may also take the country of current locale in account.
 *
 * <div class="note"><b>Note:</b>
 * the area of interest is just one aspect that may affect the coordinate operation.
 * Other aspects are the time of interest (because some coordinate operations take in account the
 * plate tectonics movement) or the desired accuracy. For more control on the coordinate operation
 * to create, see {@link CoordinateOperationContext}.</div>
 *
 * After the caller received a {@code CoordinateOperation} instance, the following methods can be invoked
 * for checking if the operation suits the caller's needs:
 *
 * <ul>
 *   <li>{@link #getGeographicBoundingBox(CoordinateOperation)}
 *       for checking if the operation is valid in the caller's area of interest.</li>
 *   <li>{@link #getLinearAccuracy(CoordinateOperation)}
 *       for checking if the operation has sufficient accuracy for caller's purpose.</li>
 * </ul>
 *
 * If the source and target CRS are equivalent, then this method returns an operation backed by an
 * {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform#isIdentity() identity}
 * transform. If there is no known operation between the given pair of CRS, then this method throws an
 * {@link OperationNotFoundException}.
 *
 * @param  sourceCRS       the CRS of source coordinates.
 * @param  targetCRS       the CRS of target coordinates.
 * @param  areaOfInterest  the area of interest, or {@code null} if none.
 * @return the mathematical operation from {@code sourceCRS} to {@code targetCRS}.
 * @throws OperationNotFoundException if no operation was found between the given pair of CRS.
 * @throws FactoryException if the operation can not be created for another reason.
 *
 * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, CoordinateOperationContext)
 *
 * @since 0.7
 */
public static CoordinateOperation findOperation(final CoordinateReferenceSystem sourceCRS, final CoordinateReferenceSystem targetCRS, final GeographicBoundingBox areaOfInterest) throws FactoryException {
    ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
    ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
    final CoordinateOperationContext context = CoordinateOperationContext.fromBoundingBox(areaOfInterest);
    /*
         * In principle we should just delegate to factory.createOperation(…). However this operation may fail
         * if a connection to the EPSG database has been found, but the EPSG tables do not yet exist in that
         * database and
         */
    final DefaultCoordinateOperationFactory factory = CoordinateOperations.factory();
    try {
        return factory.createOperation(sourceCRS, targetCRS, context);
    } catch (UnavailableFactoryException e) {
        if (AuthorityFactories.failure(e)) {
            throw e;
        } else
            try {
                // Above method call replaced the EPSG factory by a fallback. Try again.
                return factory.createOperation(sourceCRS, targetCRS, context);
            } catch (FactoryException ex) {
                ex.addSuppressed(e);
                throw ex;
            }
    }
}
Also used : FactoryException(org.opengis.util.FactoryException) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) DefaultCoordinateOperationFactory(org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory) UnavailableFactoryException(org.apache.sis.referencing.factory.UnavailableFactoryException) CoordinateOperationContext(org.apache.sis.referencing.operation.CoordinateOperationContext)

Example 35 with FactoryException

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

the class GenericCardinalGeomPropertyFunction method checkSecondFilter.

@Override
protected boolean checkSecondFilter(SpatialArguments spatialArguments, GeometryWrapper targetGeometryWrapper) {
    // Test Geometry against the Geometry from Object to see if it is a success.
    // Used when checking against bound Subjects.
    // Cardinal functions only check against the search envelope.
    SearchEnvelope searchEnvelope = spatialArguments.getSearchEnvelope();
    try {
        GeometryWrapper srs = targetGeometryWrapper.convertSRS(searchEnvelope.getSrsURI());
        Envelope targetEnvelope = srs.getEnvelope();
        boolean result = searchEnvelope.check(targetEnvelope);
        return result;
    } catch (FactoryException | MismatchedDimensionException | TransformException ex) {
        throw new ExprEvalException(ex.getMessage() + ": " + targetGeometryWrapper.asLiteral(), ex);
    }
}
Also used : FactoryException(org.opengis.util.FactoryException) GeometryWrapper(org.apache.jena.geosparql.implementation.GeometryWrapper) TransformException(org.opengis.referencing.operation.TransformException) SearchEnvelope(org.apache.jena.geosparql.spatial.SearchEnvelope) SearchEnvelope(org.apache.jena.geosparql.spatial.SearchEnvelope) Envelope(org.locationtech.jts.geom.Envelope) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) ExprEvalException(org.apache.jena.sparql.expr.ExprEvalException)

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