Search in sources :

Example 1 with MismatchedDimensionException

use of org.opengis.geometry.MismatchedDimensionException in project sis by apache.

the class Envelopes method transform.

/**
 * Implementation of {@link #transform(MathTransform, Envelope)} with the opportunity to
 * save the projected center coordinate.
 *
 * @param  targetPt  after this method call, the center of the source envelope projected to the target CRS.
 *                   The length of this array must be the number of target dimensions.
 *                   May be {@code null} if this information is not needed.
 */
@SuppressWarnings("null")
private static GeneralEnvelope transform(final MathTransform transform, final Envelope envelope, final double[] targetPt) throws TransformException {
    if (transform.isIdentity()) {
        /*
             * Slight optimization: Just copy the envelope. Note that we need to set the CRS
             * to null because we don't know what the target CRS was supposed to be. Even if
             * an identity transform often imply that the target CRS is the same one than the
             * source CRS, it is not always the case. The metadata may be differents, or the
             * transform may be a datum shift without Bursa-Wolf parameters, etc.
             */
        final GeneralEnvelope transformed = new GeneralEnvelope(envelope);
        transformed.setCoordinateReferenceSystem(null);
        if (targetPt != null) {
            for (int i = envelope.getDimension(); --i >= 0; ) {
                targetPt[i] = transformed.getMedian(i);
            }
        }
        return transformed;
    }
    /*
         * Checks argument validity: envelope and math transform dimensions must be consistent.
         */
    final int sourceDim = transform.getSourceDimensions();
    final int targetDim = transform.getTargetDimensions();
    if (envelope.getDimension() != sourceDim) {
        throw new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimension_2, sourceDim, envelope.getDimension()));
    }
    /*
         * Allocates all needed objects. The value '3' below is because the following 'while'
         * loop uses a 'pointIndex' to be interpreted as a number in base 3 (see the comment
         * inside the loop).  The coordinate to transform must be initialized to the minimal
         * ordinate values. This coordinate will be updated in the 'switch' statement inside
         * the 'while' loop.
         */
    if (sourceDim >= 20) {
        // Maximal value supported by Formulas.pow3(int) is 19.
        throw new IllegalArgumentException(Errors.format(Errors.Keys.ExcessiveNumberOfDimensions_1));
    }
    int pointIndex = 0;
    boolean isDerivativeSupported = true;
    GeneralEnvelope transformed = null;
    final Matrix[] derivatives = new Matrix[Formulas.pow3(sourceDim)];
    final double[] ordinates = new double[derivatives.length * targetDim];
    final double[] sourcePt = new double[sourceDim];
    for (int i = sourceDim; --i >= 0; ) {
        sourcePt[i] = envelope.getMinimum(i);
    }
    // A window over a single coordinate in the 'ordinates' array.
    final DirectPositionView ordinatesView = new DirectPositionView.Double(ordinates, 0, targetDim);
    /*
         * Iterates over every minimal, maximal and median ordinate values (3 points) along each
         * dimension. The total number of iterations is 3 ^ (number of source dimensions).
         */
    transformPoint: while (true) {
        /*
             * Compute the derivative (optional operation). If this operation fails, we will
             * set a flag to 'false' so we don't try again for all remaining points. We try
             * to compute the derivative and the transformed point in a single operation if
             * we can. If we can not, we will compute those two information separately.
             *
             * Note that the very last point to be projected must be the envelope center.
             * There is usually no need to calculate the derivative for that last point,
             * but we let it does anyway for safety.
             */
        final int offset = pointIndex * targetDim;
        try {
            derivatives[pointIndex] = derivativeAndTransform(transform, sourcePt, ordinates, offset, isDerivativeSupported);
        } catch (TransformException e) {
            if (!isDerivativeSupported) {
                // Derivative were already disabled, so something went wrong.
                throw e;
            }
            isDerivativeSupported = false;
            transform.transform(sourcePt, 0, ordinates, offset, 1);
            // Log only if the above call was successful.
            recoverableException(Envelopes.class, e);
        }
        /*
             * The transformed point has been saved for future reuse after the enclosing
             * 'while' loop. Now add the transformed point to the destination envelope.
             */
        if (transformed == null) {
            transformed = new GeneralEnvelope(targetDim);
            for (int i = 0; i < targetDim; i++) {
                final double value = ordinates[offset + i];
                transformed.setRange(i, value, value);
            }
        } else {
            ordinatesView.offset = offset;
            transformed.add(ordinatesView);
        }
        /*
             * Get the next point coordinate. The 'coordinateIndex' variable is an index in base 3
             * having a number of digits equals to the number of source dimensions.  For example a
             * 4-D space have indexes ranging from "0000" to "2222" (numbers in base 3). The digits
             * are then mapped to minimal (0), maximal (1) or central (2) ordinates. The outer loop
             * stops when the counter roll back to "0000". Note that 'targetPt' must keep the value
             * of the last projected point, which must be the envelope center identified by "2222"
             * in the 4-D case.
             */
        int indexBase3 = ++pointIndex;
        for (int dim = sourceDim; --dim >= 0; indexBase3 /= 3) {
            switch(indexBase3 % 3) {
                // Continue the loop.
                case 0:
                    sourcePt[dim] = envelope.getMinimum(dim);
                    break;
                case 1:
                    sourcePt[dim] = envelope.getMaximum(dim);
                    continue transformPoint;
                case 2:
                    sourcePt[dim] = envelope.getMedian(dim);
                    continue transformPoint;
                // Should never happen
                default:
                    throw new AssertionError(indexBase3);
            }
        }
        break;
    }
    assert pointIndex == derivatives.length : pointIndex;
    /*
         * At this point we finished to build an envelope from all sampled positions. Now iterate
         * over all points. For each point, iterate over all line segments from that point to a
         * neighbor median point.  Use the derivate information for approximating the transform
         * behavior in that area by a cubic curve. We can then find analytically the curve extremum.
         *
         * The same technic is applied in transform(MathTransform, Rectangle2D), except that in
         * the Rectangle2D case the calculation was bundled right inside the main loop in order
         * to avoid the need for storage.
         */
    DirectPosition temporary = null;
    final DirectPositionView sourceView = new DirectPositionView.Double(sourcePt, 0, sourceDim);
    final CurveExtremum extremum = new CurveExtremum();
    for (pointIndex = 0; pointIndex < derivatives.length; pointIndex++) {
        final Matrix D1 = derivatives[pointIndex];
        if (D1 != null) {
            int indexBase3 = pointIndex, power3 = 1;
            for (int i = sourceDim; --i >= 0; indexBase3 /= 3, power3 *= 3) {
                final int digitBase3 = indexBase3 % 3;
                if (digitBase3 != 2) {
                    // Process only if we are not already located on the median along the dimension i.
                    final int medianIndex = pointIndex + power3 * (2 - digitBase3);
                    final Matrix D2 = derivatives[medianIndex];
                    if (D2 != null) {
                        final double xmin = envelope.getMinimum(i);
                        final double xmax = envelope.getMaximum(i);
                        final double x2 = envelope.getMedian(i);
                        final double x1 = (digitBase3 == 0) ? xmin : xmax;
                        final int offset1 = targetDim * pointIndex;
                        final int offset2 = targetDim * medianIndex;
                        for (int j = 0; j < targetDim; j++) {
                            extremum.resolve(x1, ordinates[offset1 + j], D1.getElement(j, i), x2, ordinates[offset2 + j], D2.getElement(j, i));
                            boolean isP2 = false;
                            do {
                                // Executed exactly twice, one for each extremum point.
                                final double x = isP2 ? extremum.ex2 : extremum.ex1;
                                if (x > xmin && x < xmax) {
                                    final double y = isP2 ? extremum.ey2 : extremum.ey1;
                                    if (y < transformed.getMinimum(j) || y > transformed.getMaximum(j)) {
                                        /*
                                             * At this point, we have determined that adding the extremum point
                                             * would expand the envelope. However we will not add that point
                                             * directly because its position may not be quite right (since we
                                             * used a cubic curve approximation). Instead, we project the point
                                             * on the envelope border which is located vis-à-vis the extremum.
                                             */
                                        for (int ib3 = pointIndex, dim = sourceDim; --dim >= 0; ib3 /= 3) {
                                            final double ordinate;
                                            if (dim == i) {
                                                // Position of the extremum.
                                                ordinate = x;
                                            } else
                                                switch(ib3 % 3) {
                                                    case 0:
                                                        ordinate = envelope.getMinimum(dim);
                                                        break;
                                                    case 1:
                                                        ordinate = envelope.getMaximum(dim);
                                                        break;
                                                    case 2:
                                                        ordinate = envelope.getMedian(dim);
                                                        break;
                                                    // Should never happen
                                                    default:
                                                        throw new AssertionError(ib3);
                                                }
                                            sourcePt[dim] = ordinate;
                                        }
                                        temporary = transform.transform(sourceView, temporary);
                                        transformed.add(temporary);
                                    }
                                }
                            } while ((isP2 = !isP2) == true);
                        }
                    }
                }
            }
            // Let GC do its job earlier.
            derivatives[pointIndex] = null;
        }
    }
    if (targetPt != null) {
        // Copy the coordinate of the center point.
        System.arraycopy(ordinates, ordinates.length - targetDim, targetPt, 0, targetDim);
    }
    return transformed;
}
Also used : DirectPosition(org.opengis.geometry.DirectPosition) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) TransformException(org.opengis.referencing.operation.TransformException) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) Matrix(org.opengis.referencing.operation.Matrix) DirectPositionView(org.apache.sis.internal.referencing.DirectPositionView)

Example 2 with MismatchedDimensionException

use of org.opengis.geometry.MismatchedDimensionException in project sis by apache.

the class Shapes2D method transform.

/**
 * Transforms a rectangular envelope using the given coordinate operation.
 * The transformation is only approximative: the returned envelope may be bigger
 * than the smallest possible bounding box, but should not be smaller in most cases.
 *
 * <p>This method can handle the case where the rectangle contains the North or South pole,
 * or when it cross the ±180° longitude.</p>
 *
 * @param  operation    the operation to use. Source and target dimension must be 2.
 * @param  envelope     the rectangle to transform (may be {@code null}).
 * @param  destination  the destination rectangle (may be {@code envelope}).
 *         If {@code null}, a new rectangle will be created and returned.
 * @return {@code destination}, or a new rectangle if {@code destination} was non-null and {@code envelope} was null.
 * @throws TransformException if a transform failed.
 *
 * @see #transform(MathTransform2D, Rectangle2D, Rectangle2D)
 * @see Envelopes#transform(CoordinateOperation, Envelope)
 */
@SuppressWarnings("null")
public static Rectangle2D transform(final CoordinateOperation operation, final Rectangle2D envelope, Rectangle2D destination) throws TransformException {
    ArgumentChecks.ensureNonNull("operation", operation);
    if (envelope == null) {
        return null;
    }
    final MathTransform transform = operation.getMathTransform();
    if (!(transform instanceof MathTransform2D)) {
        throw new MismatchedDimensionException(Errors.format(Errors.Keys.IllegalPropertyValueClass_3, "transform", MathTransform2D.class, MathTransform.class));
    }
    MathTransform2D mt = (MathTransform2D) transform;
    final double[] center = new double[2];
    destination = transform(mt, envelope, destination, center);
    /*
         * If the source envelope crosses the expected range of valid coordinates, also projects
         * the range bounds as a safety. See the comments in transform(Envelope, ...).
         */
    final CoordinateReferenceSystem sourceCRS = operation.getSourceCRS();
    if (sourceCRS != null) {
        final CoordinateSystem cs = sourceCRS.getCoordinateSystem();
        if (cs != null && cs.getDimension() == 2) {
            // Paranoiac check.
            CoordinateSystemAxis axis = cs.getAxis(0);
            double min = envelope.getMinX();
            double max = envelope.getMaxX();
            Point2D.Double pt = null;
            for (int i = 0; i < 4; i++) {
                if (i == 2) {
                    axis = cs.getAxis(1);
                    min = envelope.getMinY();
                    max = envelope.getMaxY();
                }
                final double v = (i & 1) == 0 ? axis.getMinimumValue() : axis.getMaximumValue();
                if (!(v > min && v < max)) {
                    continue;
                }
                if (pt == null) {
                    pt = new Point2D.Double();
                }
                if ((i & 2) == 0) {
                    pt.x = v;
                    pt.y = envelope.getCenterY();
                } else {
                    pt.x = envelope.getCenterX();
                    pt.y = v;
                }
                destination.add(mt.transform(pt, pt));
            }
        }
    }
    /*
         * Now take the target CRS in account.
         */
    final CoordinateReferenceSystem targetCRS = operation.getTargetCRS();
    if (targetCRS == null) {
        return destination;
    }
    final CoordinateSystem targetCS = targetCRS.getCoordinateSystem();
    if (targetCS == null || targetCS.getDimension() != 2) {
        // It should be an error, but we keep this method tolerant.
        return destination;
    }
    /*
         * Checks for singularity points. See the Envelopes.transform(CoordinateOperation, Envelope)
         * method for comments about the algorithm. The code below is the same algorithm adapted for
         * the 2D case and the related objects (Point2D, Rectangle2D, etc.).
         *
         * The 'border' variable in the loop below is used in order to compress 2 dimensions
         * and 2 extremums in a single loop, in this order: (xmin, xmax, ymin, ymax).
         */
    TransformException warning = null;
    Point2D sourcePt = null;
    Point2D targetPt = null;
    // A bitmask for each (dimension, extremum) pairs.
    int includedBoundsValue = 0;
    for (int border = 0; border < 4; border++) {
        // 2 dimensions and 2 extremums compacted in a flag.
        // The dimension index being examined.
        final int dimension = border >>> 1;
        final CoordinateSystemAxis axis = targetCS.getAxis(dimension);
        if (axis == null) {
            // Should never be null, but check as a paranoiac safety.
            continue;
        }
        final double extremum = (border & 1) == 0 ? axis.getMinimumValue() : axis.getMaximumValue();
        if (Double.isInfinite(extremum) || Double.isNaN(extremum)) {
            continue;
        }
        if (targetPt == null) {
            try {
                mt = mt.inverse();
            } catch (NoninvertibleTransformException exception) {
                Envelopes.recoverableException(Shapes2D.class, exception);
                return destination;
            }
            targetPt = new Point2D.Double();
        }
        switch(dimension) {
            case 0:
                targetPt.setLocation(extremum, center[1]);
                break;
            case 1:
                targetPt.setLocation(center[0], extremum);
                break;
            default:
                throw new AssertionError(border);
        }
        try {
            sourcePt = mt.transform(targetPt, sourcePt);
        } catch (TransformException exception) {
            if (warning == null) {
                warning = exception;
            } else {
                warning.addSuppressed(exception);
            }
            continue;
        }
        if (envelope.contains(sourcePt)) {
            destination.add(targetPt);
            includedBoundsValue |= (1 << border);
        }
    }
    /*
         * Iterate over all dimensions of type "WRAPAROUND" for which minimal or maximal axis
         * values have not yet been included in the envelope. We could inline this check inside
         * the above loop, but we don't in order to have a chance to exclude the dimensions for
         * which the point have already been added.
         *
         * See transform(CoordinateOperation, Envelope) for more comments about the algorithm.
         */
    if (includedBoundsValue != 0) {
        /*
             * Bits mask transformation:
             *   1) Swaps the two dimensions               (YyXx  →  XxYy)
             *   2) Insert a space between each bits       (XxYy  →  X.x.Y.y.)
             *   3) Fill the space with duplicated values  (X.x.Y.y.  →  XXxxYYyy)
             *
             * In terms of bit positions 1,2,4,8 (not bit values), we have:
             *
             *   8421  →  22881144
             *   i.e. (ymax, ymin, xmax, xmin)  →  (xmax², ymax², xmin², ymin²)
             *
             * Now look at the last part: (xmin², ymin²). The next step is to perform a bitwise
             * AND operation in order to have only both of the following conditions:
             *
             *   Borders not yet added to the envelope: ~(ymax, ymin, xmax, xmin)
             *   Borders in which a singularity exists:  (xmin, xmin, ymin, ymin)
             *
             * The same operation is repeated on the next 4 bits for (xmax, xmax, ymax, ymax).
             */
        int toTest = ((includedBoundsValue & 1) << 3) | ((includedBoundsValue & 4) >>> 1) | ((includedBoundsValue & 2) << 6) | ((includedBoundsValue & 8) << 2);
        // Duplicate the bit values.
        toTest |= (toTest >>> 1);
        toTest &= ~(includedBoundsValue | (includedBoundsValue << 4));
        /*
             * Forget any axes that are not of kind "WRAPAROUND". Then get the final
             * bit pattern indicating which points to test. Iterate over that bits.
             */
        if ((toTest & 0x33333333) != 0 && !CoordinateOperations.isWrapAround(targetCS.getAxis(0)))
            toTest &= 0xCCCCCCCC;
        if ((toTest & 0xCCCCCCCC) != 0 && !CoordinateOperations.isWrapAround(targetCS.getAxis(1)))
            toTest &= 0x33333333;
        while (toTest != 0) {
            final int border = Integer.numberOfTrailingZeros(toTest);
            final int bitMask = 1 << border;
            // Clear now the bit, for the next iteration.
            toTest &= ~bitMask;
            final int dimensionToAdd = (border >>> 1) & 1;
            final CoordinateSystemAxis toAdd = targetCS.getAxis(dimensionToAdd);
            final CoordinateSystemAxis added = targetCS.getAxis(dimensionToAdd ^ 1);
            double x = (border & 1) == 0 ? toAdd.getMinimumValue() : toAdd.getMaximumValue();
            double y = (border & 4) == 0 ? added.getMinimumValue() : added.getMaximumValue();
            if (dimensionToAdd != 0) {
                final double t = x;
                x = y;
                y = t;
            }
            targetPt.setLocation(x, y);
            try {
                sourcePt = mt.transform(targetPt, sourcePt);
            } catch (TransformException exception) {
                if (warning == null) {
                    warning = exception;
                } else {
                    warning.addSuppressed(exception);
                }
                continue;
            }
            if (envelope.contains(sourcePt)) {
                destination.add(targetPt);
            }
        }
    }
    /*
         * At this point we finished envelope transformation. Verify if some ordinates need to be "wrapped around"
         * as a result of the coordinate operation.   This is usually the longitude axis where the source CRS uses
         * the [-180 … +180]° range and the target CRS uses the [0 … 360]° range, or the converse. In such case we
         * set the rectangle to the full range (we do not use the mechanism documented in Envelope2D) because most
         * Rectangle2D implementations do not support spanning the anti-meridian. This results in larger rectangle
         * than what would be possible with GeneralEnvelope or Envelope2D, but we try to limit the situation where
         * this expansion is applied.
         */
    final Set<Integer> wrapAroundChanges;
    if (operation instanceof AbstractCoordinateOperation) {
        wrapAroundChanges = ((AbstractCoordinateOperation) operation).getWrapAroundChanges();
    } else {
        wrapAroundChanges = CoordinateOperations.wrapAroundChanges(sourceCRS, targetCS);
    }
    for (int dim : wrapAroundChanges) {
        // Empty in the vast majority of cases.
        final CoordinateSystemAxis axis = targetCS.getAxis(dim);
        final double minimum = axis.getMinimumValue();
        final double maximum = axis.getMaximumValue();
        final double o1, o2;
        if (dim == 0) {
            o1 = destination.getMinX();
            o2 = destination.getMaxX();
        } else {
            o1 = destination.getMinY();
            o2 = destination.getMaxY();
        }
        if (o1 < minimum || o2 > maximum) {
            final double span = maximum - minimum;
            if (dim == 0) {
                destination.setRect(minimum, destination.getY(), span, destination.getHeight());
            } else {
                destination.setRect(destination.getX(), minimum, destination.getWidth(), span);
            }
        }
    }
    if (warning != null) {
        Envelopes.recoverableException(Shapes2D.class, warning);
    }
    return destination;
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) TransformException(org.opengis.referencing.operation.TransformException) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) Point2D(java.awt.geom.Point2D) MathTransform2D(org.opengis.referencing.operation.MathTransform2D) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) AbstractCoordinateOperation(org.apache.sis.referencing.operation.AbstractCoordinateOperation)

Example 3 with MismatchedDimensionException

use of org.opengis.geometry.MismatchedDimensionException in project sis by apache.

the class LinearTransformBuilder method setControlPoints.

/**
 * Sets all matching control point pairs, overwriting any previous setting. The source positions are the keys in
 * the given map, and the target positions are the associated values in the map. The map should not contain two
 * entries with the same source position. Coordinate reference systems are ignored.
 * Null positions are silently ignored.
 *
 * <p>All source positions shall have the same number of dimensions (the <cite>source dimension</cite>),
 * and all target positions shall have the same number of dimensions (the <cite>target dimension</cite>).
 * However the source dimension does not need to be the same the target dimension.
 * Apache SIS currently supports only one- or two-dimensional source positions,
 * together with arbitrary target dimension.</p>
 *
 * <p>If this builder has been created with the {@link #LinearTransformBuilder(int...)} constructor,
 * then the ordinate values of all source positions shall be integers in the [0 … {@code gridSize[0]}-1]
 * range for the first dimension (typically column indices), in the [0 … {@code gridSize[1]}-1] range for
 * the second dimension (typically row indices), <i>etc</i>. This constraint does not apply for builders
 * created with the {@link #LinearTransformBuilder()} constructor.</p>
 *
 * @param  sourceToTarget  a map of source positions to target positions.
 *         Source positions are assumed precise and target positions are assumed uncertain.
 * @throws IllegalArgumentException if this builder has been {@linkplain #LinearTransformBuilder(int...)
 *         created for a grid} but some source ordinates are not indices in that grid.
 * @throws MismatchedDimensionException if some positions do not have the expected number of dimensions.
 *
 * @since 0.8
 */
public void setControlPoints(final Map<? extends Position, ? extends Position> sourceToTarget) throws MismatchedDimensionException {
    ArgumentChecks.ensureNonNull("sourceToTarget", sourceToTarget);
    transform = null;
    correlation = null;
    sources = null;
    targets = null;
    numPoints = 0;
    int srcDim = 0;
    int tgtDim = 0;
    for (final Map.Entry<? extends Position, ? extends Position> entry : sourceToTarget.entrySet()) {
        final DirectPosition src = position(entry.getKey());
        if (src == null)
            continue;
        final DirectPosition tgt = position(entry.getValue());
        if (tgt == null)
            continue;
        /*
             * The first time that we get a non-null source and target coordinate, allocate the arrays.
             * The sources arrays are allocated only if the source coordiantes are randomly distributed.
             */
        if (targets == null) {
            tgtDim = tgt.getDimension();
            if (tgtDim <= 0) {
                throw new MismatchedDimensionException(mismatchedDimension("target", 2, tgtDim));
            }
            if (gridSize == null) {
                srcDim = src.getDimension();
                if (srcDim <= 0) {
                    throw new MismatchedDimensionException(mismatchedDimension("source", 2, srcDim));
                }
                final int capacity = sourceToTarget.size();
                sources = new double[srcDim][capacity];
                targets = new double[tgtDim][capacity];
            } else {
                srcDim = gridSize.length;
                allocate(tgtDim);
            }
        }
        /*
             * Verify that the source and target coordinates have the expected number of dimensions before to store
             * the coordinates. If the grid size is known, we do not need to store the source coordinates. Instead,
             * we compute its index in the fixed-size target arrays.
             */
        int d;
        if ((d = src.getDimension()) != srcDim)
            throw new MismatchedDimensionException(mismatchedDimension("source", srcDim, d));
        if ((d = tgt.getDimension()) != tgtDim)
            throw new MismatchedDimensionException(mismatchedDimension("target", tgtDim, d));
        int index;
        if (gridSize != null) {
            index = flatIndex(src);
        } else {
            index = numPoints;
            for (int i = 0; i < srcDim; i++) {
                sources[i][index] = src.getOrdinate(i);
            }
        }
        for (int i = 0; i < tgtDim; i++) {
            targets[i][index] = tgt.getOrdinate(i);
        }
        numPoints++;
    }
}
Also used : DirectPosition(org.opengis.geometry.DirectPosition) Map(java.util.Map) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException)

Example 4 with MismatchedDimensionException

use of org.opengis.geometry.MismatchedDimensionException in project sis by apache.

the class TransformCommand method transform.

/**
 * Transforms the given coordinates.
 */
private void transform(final List<double[]> points) throws TransformException {
    final int dimension = operation.getSourceCRS().getCoordinateSystem().getDimension();
    final MathTransform mt = operation.getMathTransform();
    final double[] result = new double[mt.getTargetDimensions()];
    final double[] domainCoordinate;
    final DirectPositionView positionInDomain;
    final ImmutableEnvelope domainOfValidity;
    final GeographicBoundingBox bbox;
    if (toDomainOfValidity != null && (bbox = CRS.getGeographicBoundingBox(operation)) != null) {
        domainOfValidity = new ImmutableEnvelope(bbox);
        domainCoordinate = new double[toDomainOfValidity.getTargetDimensions()];
        positionInDomain = new DirectPositionView.Double(domainCoordinate, 0, domainCoordinate.length);
    } else {
        domainOfValidity = null;
        domainCoordinate = null;
        positionInDomain = null;
    }
    for (final double[] coordinates : points) {
        if (coordinates.length != dimension) {
            throw new MismatchedDimensionException(Errors.format(Errors.Keys.MismatchedDimensionForCRS_3, operation.getSourceCRS().getName().getCode(), dimension, coordinates.length));
        }
        /*
             * At this point we got the coordinates and they have the expected number of dimensions.
             * Now perform the coordinate operation and print each ordinate values.  We will switch
             * to scientific notation if the coordinate is much larger than expected.
             */
        mt.transform(coordinates, 0, result, 0, 1);
        for (int i = 0; i < result.length; i++) {
            if (i != 0) {
                out.print(',');
            }
            final double value = result[i];
            final String s;
            if (Math.abs(value) >= thresholdForScientificNotation[i]) {
                s = Double.toString(value);
            } else {
                coordinateFormat.setMinimumFractionDigits(numFractionDigits[i]);
                coordinateFormat.setMaximumFractionDigits(numFractionDigits[i]);
                s = coordinateFormat.format(value);
            }
            out.print(CharSequences.spaces(ordinateWidth - s.length()));
            out.print(s);
        }
        /*
             * Append a warning after the transformed coordinate values if the source coordinate was outside
             * the domain of validity. A failure to perform a coordinate transformation is also considered as
             * being out of the domain of valididty.
             */
        if (domainOfValidity != null) {
            boolean inside;
            try {
                toDomainOfValidity.transform(coordinates, 0, domainCoordinate, 0, 1);
                inside = domainOfValidity.contains(positionInDomain);
            } catch (TransformException e) {
                inside = false;
                warning(e);
            }
            if (!inside) {
                out.print(",    ");
                printQuotedText(Errors.getResources(locale).getString(Errors.Keys.OutsideDomainOfValidity), 0, X364.FOREGROUND_RED);
            }
        }
        out.println();
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) TransformException(org.opengis.referencing.operation.TransformException) ImmutableEnvelope(org.apache.sis.geometry.ImmutableEnvelope) GeographicBoundingBox(org.opengis.metadata.extent.GeographicBoundingBox) DefaultGeographicBoundingBox(org.apache.sis.metadata.iso.extent.DefaultGeographicBoundingBox) InternationalString(org.opengis.util.InternationalString) MismatchedDimensionException(org.opengis.geometry.MismatchedDimensionException) DirectPositionView(org.apache.sis.internal.referencing.DirectPositionView)

Example 5 with MismatchedDimensionException

use of org.opengis.geometry.MismatchedDimensionException 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

MismatchedDimensionException (org.opengis.geometry.MismatchedDimensionException)29 TransformException (org.opengis.referencing.operation.TransformException)26 GeometryWrapper (org.apache.jena.geosparql.implementation.GeometryWrapper)19 FactoryException (org.opengis.util.FactoryException)19 ExprEvalException (org.apache.jena.sparql.expr.ExprEvalException)15 DatatypeFormatException (org.apache.jena.datatypes.DatatypeFormatException)10 Envelope (org.locationtech.jts.geom.Envelope)8 MathTransform (org.opengis.referencing.operation.MathTransform)6 FactoryException (org.opengis.referencing.FactoryException)4 ArrayList (java.util.ArrayList)3 Literal (org.apache.jena.rdf.model.Literal)3 Resource (org.apache.jena.rdf.model.Resource)3 Geometry (org.locationtech.jts.geom.Geometry)3 DirectPosition (org.opengis.geometry.DirectPosition)3 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)3 GeometryFinder (eu.esdihumboldt.hale.common.instance.geometry.GeometryFinder)2 CodeDefinition (eu.esdihumboldt.hale.common.instance.geometry.impl.CodeDefinition)2 DepthFirstInstanceTraverser (eu.esdihumboldt.hale.common.instance.helper.DepthFirstInstanceTraverser)2 InstanceTraverser (eu.esdihumboldt.hale.common.instance.helper.InstanceTraverser)2 GeometryProperty (eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty)2