Search in sources :

Example 26 with CoordinateSystem

use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.

the class SubTypes method castOrCopy.

/**
 * Returns a SIS implementation for the given coordinate reference system.
 *
 * @see AbstractCRS#castOrCopy(CoordinateReferenceSystem)
 */
static AbstractCRS castOrCopy(final CoordinateReferenceSystem object) {
    if (object instanceof DerivedCRS) {
        return DefaultDerivedCRS.castOrCopy((DerivedCRS) object);
    }
    if (object instanceof ProjectedCRS) {
        return DefaultProjectedCRS.castOrCopy((ProjectedCRS) object);
    }
    if (object instanceof GeodeticCRS) {
        if (object instanceof GeographicCRS) {
            return DefaultGeographicCRS.castOrCopy((GeographicCRS) object);
        }
        if (object instanceof GeocentricCRS) {
            return DefaultGeocentricCRS.castOrCopy((GeocentricCRS) object);
        }
        /*
             * The GeographicCRS and GeocentricCRS types are not part of ISO 19111.
             * ISO uses a single type, GeodeticCRS, for both of them and infer the
             * geographic or geocentric type from the coordinate system. We do this
             * check here for instantiating the most appropriate SIS type, but only
             * if we need to create a new object anyway (see below for rational).
             */
        if (object instanceof DefaultGeodeticCRS) {
            /*
                 * Result of XML unmarshalling — keep as-is. We avoid creating a new object because it
                 * would break object identities specified in GML document by the xlink:href attribute.
                 * However we may revisit this policy in the future. See SC_CRS.setElement(AbstractCRS).
                 */
            return (DefaultGeodeticCRS) object;
        }
        final Map<String, ?> properties = IdentifiedObjects.getProperties(object);
        final GeodeticDatum datum = ((GeodeticCRS) object).getDatum();
        final CoordinateSystem cs = object.getCoordinateSystem();
        if (cs instanceof EllipsoidalCS) {
            return new DefaultGeographicCRS(properties, datum, (EllipsoidalCS) cs);
        }
        if (cs instanceof SphericalCS) {
            return new DefaultGeocentricCRS(properties, datum, (SphericalCS) cs);
        }
        if (cs instanceof CartesianCS) {
            return new DefaultGeocentricCRS(properties, datum, (CartesianCS) cs);
        }
    }
    if (object instanceof VerticalCRS) {
        return DefaultVerticalCRS.castOrCopy((VerticalCRS) object);
    }
    if (object instanceof TemporalCRS) {
        return DefaultTemporalCRS.castOrCopy((TemporalCRS) object);
    }
    if (object instanceof EngineeringCRS) {
        return DefaultEngineeringCRS.castOrCopy((EngineeringCRS) object);
    }
    if (object instanceof ImageCRS) {
        return DefaultImageCRS.castOrCopy((ImageCRS) object);
    }
    if (object instanceof CompoundCRS) {
        return DefaultCompoundCRS.castOrCopy((CompoundCRS) object);
    }
    /*
         * Intentionally check for AbstractCRS after the interfaces because user may have defined his own
         * subclass implementing the interface. If we were checking for AbstractCRS before the interfaces,
         * the returned instance could have been a user subclass without the JAXB annotations required
         * for XML marshalling.
         */
    if (object == null || object instanceof AbstractCRS) {
        return (AbstractCRS) object;
    }
    return new AbstractCRS(object);
}
Also used : CartesianCS(org.opengis.referencing.cs.CartesianCS) EngineeringCRS(org.opengis.referencing.crs.EngineeringCRS) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) DerivedCRS(org.opengis.referencing.crs.DerivedCRS) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) GeodeticDatum(org.opengis.referencing.datum.GeodeticDatum) GeodeticCRS(org.opengis.referencing.crs.GeodeticCRS) SphericalCS(org.opengis.referencing.cs.SphericalCS) TemporalCRS(org.opengis.referencing.crs.TemporalCRS) ProjectedCRS(org.opengis.referencing.crs.ProjectedCRS) ImageCRS(org.opengis.referencing.crs.ImageCRS) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) GeographicCRS(org.opengis.referencing.crs.GeographicCRS) GeocentricCRS(org.opengis.referencing.crs.GeocentricCRS)

Example 27 with CoordinateSystem

use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.

the class CoordinateSystems method swapAndScaleAxes.

/**
 * Returns an affine transform between two coordinate systems.
 * Only units and axes order (e.g. transforming from
 * ({@linkplain AxisDirection#NORTH North}, {@linkplain AxisDirection#WEST West}) to
 * ({@linkplain AxisDirection#EAST East}, {@linkplain AxisDirection#NORTH North})
 * are taken in account by this method.
 *
 * <div class="section">Conditions</div>
 * The two coordinate systems must implement the same GeoAPI coordinate system interface.
 * For example if {@code sourceCS} is a {@link org.opengis.referencing.cs.CartesianCS},
 * then {@code targetCS} must be a {@code CartesianCS} too.
 *
 * <div class="note"><b>Example:</b>
 * If coordinates in {@code sourceCS} are (<var>x</var>,<var>y</var>) tuples in metres
 * and coordinates in {@code targetCS} are (<var>-y</var>,<var>x</var>) tuples in centimetres,
 * then the transformation can be performed as below:
 *
 * {@preformat math
 *     ┌      ┐   ┌                ┐ ┌     ┐
 *     │-y(cm)│   │   0  -100    0 │ │ x(m)│
 *     │ x(cm)│ = │ 100     0    0 │ │ y(m)│
 *     │ 1    │   │   0     0    1 │ │ 1   │
 *     └      ┘   └                ┘ └     ┘
 * }
 * </div>
 *
 * @param  sourceCS  the source coordinate system.
 * @param  targetCS  the target coordinate system.
 * @return the conversion from {@code sourceCS} to {@code targetCS} as an affine transform.
 *         Only axis direction and units are taken in account.
 * @throws IllegalArgumentException if the CS are not of the same type, or axes do not match.
 * @throws IncommensurableException if the units are not compatible, or the conversion is non-linear.
 *
 * @see Matrices#createTransform(AxisDirection[], AxisDirection[])
 */
@SuppressWarnings("fallthrough")
public static Matrix swapAndScaleAxes(final CoordinateSystem sourceCS, final CoordinateSystem targetCS) throws IllegalArgumentException, IncommensurableException {
    ensureNonNull("sourceCS", sourceCS);
    ensureNonNull("targetCS", targetCS);
    if (!Classes.implementSameInterfaces(sourceCS.getClass(), targetCS.getClass(), CoordinateSystem.class)) {
        throw new IllegalArgumentException(Resources.format(Resources.Keys.IncompatibleCoordinateSystemTypes));
    }
    final AxisDirection[] srcAxes = getAxisDirections(sourceCS);
    final AxisDirection[] dstAxes = getAxisDirections(targetCS);
    final MatrixSIS matrix = Matrices.createTransform(srcAxes, dstAxes);
    assert Arrays.equals(srcAxes, dstAxes) == matrix.isIdentity() : matrix;
    /*
         * The previous code computed a matrix for swapping axes. Usually, this
         * matrix contains only 0 and 1 values with only one "1" value by row.
         * For example, the matrix operation for swapping x and y axes is:
         *          ┌ ┐   ┌         ┐ ┌ ┐
         *          │y│   │ 0  1  0 │ │x│
         *          │x│ = │ 1  0  0 │ │y│
         *          │1│   │ 0  0  1 │ │1│
         *          └ ┘   └         ┘ └ ┘
         * Now, take in account units conversions. Each matrix's element (j,i)
         * is multiplied by the conversion factor from sourceCS.getUnit(i) to
         * targetCS.getUnit(j). This is an element-by-element multiplication,
         * not a matrix multiplication. The last column is processed in a special
         * way, since it contains the offset values.
         */
    // == sourceCS.getDimension()
    final int sourceDim = matrix.getNumCol() - 1;
    // == targetCS.getDimension()
    final int targetDim = matrix.getNumRow() - 1;
    for (int j = 0; j < targetDim; j++) {
        final Unit<?> targetUnit = targetCS.getAxis(j).getUnit();
        for (int i = 0; i < sourceDim; i++) {
            if (matrix.getElement(j, i) == 0) {
                // (i.e. axes are orthogonal).
                continue;
            }
            final Unit<?> sourceUnit = sourceCS.getAxis(i).getUnit();
            if (Objects.equals(sourceUnit, targetUnit)) {
                // between source[i] and target[j].
                continue;
            }
            Number scale = 1;
            Number offset = 0;
            final Number[] coefficients = Units.coefficients(sourceUnit.getConverterToAny(targetUnit));
            switch(coefficients != null ? coefficients.length : -1) {
                // Fall through
                case 2:
                    scale = coefficients[1];
                // Fall through
                case 1:
                    offset = coefficients[0];
                case 0:
                    break;
                default:
                    throw new IncommensurableException(Resources.format(Resources.Keys.NonLinearUnitConversion_2, sourceUnit, targetUnit));
            }
            final DoubleDouble element = DoubleDouble.castOrCopy(matrix.getNumber(j, i));
            final DoubleDouble r = new DoubleDouble(element);
            r.multiply(scale);
            matrix.setNumber(j, i, r);
            r.setFrom(element);
            r.multiply(offset);
            r.add(matrix.getNumber(j, sourceDim));
            matrix.setNumber(j, sourceDim, r);
        }
    }
    return matrix;
}
Also used : IncommensurableException(javax.measure.IncommensurableException) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) AxisDirection(org.opengis.referencing.cs.AxisDirection) MatrixSIS(org.apache.sis.referencing.operation.matrix.MatrixSIS) DoubleDouble(org.apache.sis.internal.util.DoubleDouble)

Example 28 with CoordinateSystem

use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.

the class DefaultDerivedCRS method formatTo.

/**
 * Formats the inner part of the <cite>Well Known Text</cite> (WKT) representation of this CRS.
 *
 * @return {@code "Fitted_CS"} (WKT 1) or a type-dependent keyword (WKT 2).
 *
 * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#93">WKT 2 specification §15</a>
 */
@Override
protected String formatTo(final Formatter formatter) {
    // Gives to users a chance to override.
    final Conversion conversion = getConversionFromBase();
    if (conversion == null) {
        /*
             * Should never happen except temporarily at construction time, or if the user invoked the copy
             * constructor with an invalid Conversion, or if the user overrides the getConversionFromBase()
             * method. Delegates to the super-class method for avoiding a NullPointerException. That method
             * returns 'null', which will cause the WKT to be declared invalid.
             */
        return super.formatTo(formatter);
    }
    WKTUtilities.appendName(this, formatter, null);
    final Convention convention = formatter.getConvention();
    final boolean isWKT1 = (convention.majorVersion() == 1);
    /*
         * Both WKT 1 and WKT 2 format the base CRS. But WKT 1 formats the MathTransform before the base CRS,
         * while WKT 2 formats the conversion method and parameter values after the base CRS.
         */
    if (isWKT1) {
        MathTransform inverse = conversion.getMathTransform();
        try {
            inverse = inverse.inverse();
        } catch (NoninvertibleTransformException exception) {
            formatter.setInvalidWKT(this, exception);
            inverse = null;
        }
        formatter.newLine();
        formatter.append(inverse);
    }
    formatter.newLine();
    formatter.append(WKTUtilities.toFormattable(getBaseCRS()));
    if (isWKT1) {
        return WKTKeywords.Fitted_CS;
    } else {
        formatter.newLine();
        formatter.append(new // Format inside a "DefiningConversion" element.
        FormattableObject() {

            @Override
            protected String formatTo(final Formatter formatter) {
                WKTUtilities.appendName(conversion, formatter, null);
                formatter.newLine();
                formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod()));
                formatter.newLine();
                for (final GeneralParameterValue param : conversion.getParameterValues().values()) {
                    WKTUtilities.append(param, formatter);
                }
                return WKTKeywords.DerivingConversion;
            }
        });
        if (convention == Convention.INTERNAL || !isBaseCRS(formatter)) {
            final CoordinateSystem cs = getCoordinateSystem();
            formatCS(formatter, cs, ReferencingUtilities.getUnit(cs), isWKT1);
        }
        return keyword(formatter);
    }
}
Also used : NoninvertibleTransformException(org.opengis.referencing.operation.NoninvertibleTransformException) GeneralParameterValue(org.opengis.parameter.GeneralParameterValue) Convention(org.apache.sis.io.wkt.Convention) AxesConvention(org.apache.sis.referencing.cs.AxesConvention) MathTransform(org.opengis.referencing.operation.MathTransform) Formatter(org.apache.sis.io.wkt.Formatter) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CS_CoordinateSystem(org.apache.sis.internal.jaxb.referencing.CS_CoordinateSystem) Conversion(org.opengis.referencing.operation.Conversion) DefaultConversion(org.apache.sis.referencing.operation.DefaultConversion)

Example 29 with CoordinateSystem

use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.

the class ReferencingFunctions method getAxis.

/**
 * Returns the axis name and units for the specified dimension in a coordinate reference system or coordinate system.
 * This method returns a short axis name as used in Well Known Text (WKT) format, for example <cite>"Latitude"</cite>
 * instead of <cite>"Geodetic latitude"</cite>.
 *
 * @param  codeOrPath  the code allocated by an authority, or the path to a file.
 * @param  dimension   the dimension (1, 2, …).
 * @return the name of the requested axis.
 */
@Override
public String getAxis(final String codeOrPath, final int dimension) {
    final CacheKey<String> key = new CacheKey<>(String.class, codeOrPath, dimension, null);
    String name = key.peek();
    if (name == null) {
        final Cache.Handler<String> handler = key.lock();
        try {
            name = handler.peek();
            if (name == null) {
                final IdentifiedObject object;
                try {
                    object = getIdentifiedObject(codeOrPath, null);
                } catch (Exception exception) {
                    return getLocalizedMessage(exception);
                }
                CoordinateSystem cs = null;
                final CoordinateSystemAxis axis;
                if (object instanceof CoordinateSystemAxis) {
                    axis = (CoordinateSystemAxis) object;
                } else {
                    if (object instanceof CoordinateReferenceSystem) {
                        cs = ((CoordinateReferenceSystem) object).getCoordinateSystem();
                    } else if (object instanceof CoordinateSystem) {
                        cs = (CoordinateSystem) object;
                    } else {
                        final Class<?> actual;
                        if (object instanceof AbstractIdentifiedObject) {
                            actual = ((AbstractIdentifiedObject) object).getInterface();
                        } else {
                            actual = Classes.getClass(object);
                        }
                        return Errors.getResources(getJavaLocale()).getString(Errors.Keys.UnexpectedTypeForReference_3, codeOrPath, CoordinateReferenceSystem.class, actual);
                    }
                    if (dimension >= 1 && dimension <= cs.getDimension()) {
                        axis = cs.getAxis(dimension - 1);
                    } else {
                        return Errors.getResources(getJavaLocale()).getString(Errors.Keys.IndexOutOfBounds_1, dimension);
                    }
                }
                final String unit = axis.getUnit().toString();
                name = Transliterator.DEFAULT.toShortAxisName(cs, axis.getDirection(), axis.getName().getCode());
                if (unit != null && !unit.isEmpty()) {
                    name = name + " (" + unit + ')';
                }
            }
        } finally {
            handler.putAndUnlock(name);
        }
    }
    return name;
}
Also used : AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) InternationalString(org.opengis.util.InternationalString) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) DataStoreException(org.apache.sis.storage.DataStoreException) IllegalArgumentException(com.sun.star.lang.IllegalArgumentException) FactoryException(org.opengis.util.FactoryException) Cache(org.apache.sis.util.collection.Cache)

Example 30 with CoordinateSystem

use of org.opengis.referencing.cs.CoordinateSystem in project sis by apache.

the class CRSPair method label.

/**
 * Returns the name of the GeoAPI interface implemented by the specified object. In the GeographicCRS
 * or EllipsoidalCS cases, the trailing CRS or CS suffix is replaced by the number of dimensions
 * (e.g. "Geographic3D").
 */
static String label(final IdentifiedObject object) {
    if (object == null) {
        return null;
    }
    Class<? extends IdentifiedObject> type;
    if (object instanceof AbstractIdentifiedObject) {
        type = ((AbstractIdentifiedObject) object).getInterface();
    } else {
        type = Classes.getLeafInterfaces(object.getClass(), IdentifiedObject.class)[0];
    }
    String suffix, label = Classes.getShortName(type);
    if (label.endsWith((suffix = "CRS")) || label.endsWith(suffix = "CS")) {
        Object cs = object;
        if (object instanceof CoordinateReferenceSystem) {
            cs = ((CoordinateReferenceSystem) object).getCoordinateSystem();
        }
        if (cs instanceof EllipsoidalCS) {
            final StringBuilder sb = new StringBuilder(label);
            sb.setLength(label.length() - suffix.length());
            label = sb.append(((CoordinateSystem) cs).getDimension()).append('D').toString();
        }
    }
    String name = IdentifiedObjects.getName(object, null);
    if (name != null) {
        // Arbitrary length threshold.
        int i = 30;
        if (name.length() >= i) {
            while (i > 15) {
                // Arbitrary minimal length.
                final int c = name.codePointBefore(i);
                if (Character.isSpaceChar(c))
                    break;
                i -= Character.charCount(c);
            }
            name = CharSequences.trimWhitespaces(name, 0, i).toString() + '…';
        }
        label = label + "[“" + name + "”]";
    }
    return label;
}
Also used : AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) IdentifiedObject(org.opengis.referencing.IdentifiedObject) AbstractIdentifiedObject(org.apache.sis.referencing.AbstractIdentifiedObject) EllipsoidalCS(org.opengis.referencing.cs.EllipsoidalCS) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem)

Aggregations

CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)43 Test (org.junit.Test)16 CoordinateSystemAxis (org.opengis.referencing.cs.CoordinateSystemAxis)15 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)13 EllipsoidalCS (org.opengis.referencing.cs.EllipsoidalCS)9 DependsOnMethod (org.apache.sis.test.DependsOnMethod)7 FactoryException (org.opengis.util.FactoryException)7 AxisDirection (org.opengis.referencing.cs.AxisDirection)6 CartesianCS (org.opengis.referencing.cs.CartesianCS)6 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)5 Convention (org.apache.sis.io.wkt.Convention)4 GeodeticCRS (org.opengis.referencing.crs.GeodeticCRS)4 ProjectedCRS (org.opengis.referencing.crs.ProjectedCRS)4 TransformException (org.opengis.referencing.operation.TransformException)4 Unit (javax.measure.Unit)3 IdentifiedObject (org.opengis.referencing.IdentifiedObject)3 VerticalCRS (org.opengis.referencing.crs.VerticalCRS)3 GeodeticDatum (org.opengis.referencing.datum.GeodeticDatum)3 MathTransform (org.opengis.referencing.operation.MathTransform)3 NoninvertibleTransformException (org.opengis.referencing.operation.NoninvertibleTransformException)3