Search in sources :

Example 6 with CompoundCRS

use of org.opengis.referencing.crs.CompoundCRS in project sis by apache.

the class MultiAuthoritiesFactoryTest method testCreateFromCombinedURIs.

/**
 * Implementation of {@link #testCreateFromCombinedURNs()} and {@link #testCreateFromCombinedHTTPs()}.
 */
private static void testCreateFromCombinedURIs(final MultiAuthoritiesFactory factory, final String heightOnWGS84) throws FactoryException {
    CompoundCRS crs = factory.createCompoundCRS(heightOnWGS84);
    assertArrayEquals("WGS 84 + MSL height", new SingleCRS[] { HardCodedCRS.WGS84_φλ, HardCodedCRS.GRAVITY_RELATED_HEIGHT }, crs.getComponents().toArray());
}
Also used : CompoundCRS(org.opengis.referencing.crs.CompoundCRS)

Example 7 with CompoundCRS

use of org.opengis.referencing.crs.CompoundCRS in project sis by apache.

the class Formatter method appendComplement.

/**
 * Appends the optional complementary attributes common to many {@link IdentifiedObject} subtypes.
 * Those attributes are {@code ANCHOR}, {@code SCOPE}, {@code AREA}, {@code BBOX}, {@code VERTICALEXTENT},
 * {@code TIMEEXTENT}, {@code ID} (previously known as {@code AUTHORITY}) and {@code REMARKS},
 * and have a special treatment: they are written by {@link #append(FormattableObject)}
 * after the {@code formatTo(Formatter)} method returned.
 *
 * <p>The {@code ID[<name>,<code>,…]} element is normally written only for the root element
 * (unless the convention is {@code INTERNAL}), but there is various exceptions to this rule.
 * If formatted, the {@code ID} element will be by default on the same line than the enclosing
 * element (e.g. {@code SPHEROID["Clarke 1866", …, ID["EPSG", 7008]]}). Other example:</p>
 *
 * {@preformat text
 *   PROJCS["NAD27 / Idaho Central",
 *     GEOGCS[...etc...],
 *     ...etc...
 *     ID["EPSG", 26769]]
 * }
 *
 * For non-internal conventions, all elements other than {@code ID[…]} are formatted
 * only for {@link CoordinateOperation} and root {@link ReferenceSystem} instances,
 * with an exception for remarks of {@code ReferenceSystem} embedded inside {@code CoordinateOperation}.
 * Those restrictions are our interpretation of the following ISO 19162 requirement:
 *
 * <blockquote>(…snip…) {@code <scope extent identifier remark>} is a collection of four optional attributes
 * which may be applied to a coordinate reference system, a coordinate operation or a boundCRS. (…snip…)
 * Identifier (…snip…) may also be utilised for components of these objects although this is not recommended
 * except for coordinate operation methods (including map projections) and parameters. (…snip…)
 * A {@code <remark>} can be included within the descriptions of source and target CRS embedded within
 * a coordinate transformation as well as within the coordinate transformation itself.</blockquote>
 */
@SuppressWarnings("null")
private void appendComplement(final IdentifiedObject object, final FormattableObject parent, final FormattableObject gp) {
    isComplement = true;
    // Whether to format ID[…] elements.
    final boolean showIDs;
    // Whether we shall limit to a single ID[…] element.
    final boolean filterID;
    // Whether to format any element other than ID[…] and Remarks[…].
    final boolean showOthers;
    // Whether to format Remarks[…].
    final boolean showRemarks;
    if (convention == Convention.INTERNAL) {
        showIDs = true;
        filterID = false;
        showOthers = true;
        showRemarks = true;
    } else {
        /*
             * Except for the special cases of OperationMethod and Parameters, ISO 19162 recommends to format the
             * ID only for the root element.  But Apache SIS adds an other exception to this rule by handling the
             * components of CompoundCRS as if they were root elements. The reason is that users often create their
             * own CompoundCRS from standard components, for example by adding a time axis to some standard CRS like
             * "WGS84". The resulting CompoundCRS usually have no identifier. Then the users often need to extract a
             * particular component of a CompoundCRS, most often the horizontal part, and will need its identifier
             * for example in a Web Map Service (WMS). Those ID are lost if we do not format them here.
             */
        if (parent == null || parent instanceof CompoundCRS) {
            showIDs = true;
        } else if (gp instanceof CoordinateOperation && !(parent instanceof IdentifiedObject)) {
            // "SourceCRS[…]" and "TargetCRS[…]" sub-elements in CoordinateOperation.
            showIDs = true;
        } else if (convention == Convention.WKT2_SIMPLIFIED) {
            showIDs = false;
        } else {
            showIDs = (object instanceof OperationMethod) || (object instanceof GeneralParameterDescriptor);
        }
        if (convention.majorVersion() == 1) {
            filterID = true;
            showOthers = false;
            showRemarks = false;
        } else {
            filterID = (parent != null);
            if (object instanceof CoordinateOperation) {
                showOthers = !(parent instanceof ConcatenatedOperation);
                showRemarks = showOthers;
            } else if (object instanceof ReferenceSystem) {
                showOthers = (parent == null);
                showRemarks = (parent == null) || (gp instanceof CoordinateOperation);
            } else {
                // Mandated by ISO 19162.
                showOthers = false;
                showRemarks = false;
            }
        }
    }
    if (showOthers) {
        appendForSubtypes(object);
    }
    if (showIDs) {
        Collection<ReferenceIdentifier> identifiers = object.getIdentifiers();
        if (identifiers != null) {
            // Paranoiac check
            if (filterID) {
                for (final ReferenceIdentifier id : identifiers) {
                    if (Citations.identifierMatches(authority, id.getAuthority())) {
                        identifiers = Collections.singleton(id);
                        break;
                    }
                }
            }
            for (ReferenceIdentifier id : identifiers) {
                if (!(id instanceof FormattableObject)) {
                    id = ImmutableIdentifier.castOrCopy(id);
                }
                append((FormattableObject) id);
                if (filterID)
                    break;
            }
        }
    }
    if (showRemarks) {
        appendOnNewLine(WKTKeywords.Remark, object.getRemarks(), ElementKind.REMARKS);
    }
    isComplement = false;
}
Also used : ReferenceIdentifier(org.opengis.referencing.ReferenceIdentifier) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) GeneralParameterDescriptor(org.opengis.parameter.GeneralParameterDescriptor) CoordinateOperation(org.opengis.referencing.operation.CoordinateOperation) ConcatenatedOperation(org.opengis.referencing.operation.ConcatenatedOperation) IdentifiedObject(org.opengis.referencing.IdentifiedObject) ReferenceSystem(org.opengis.referencing.ReferenceSystem) OperationMethod(org.opengis.referencing.operation.OperationMethod)

Example 8 with CompoundCRS

use of org.opengis.referencing.crs.CompoundCRS in project sis by apache.

the class CRS method getVerticalComponent.

/**
 * Returns the first vertical coordinate reference system found in the given CRS, or {@code null} if there is none.
 * If the given CRS is already an instance of {@code VerticalCRS}, then this method returns it as-is.
 * Otherwise if the given CRS is compound, then this method searches for the first vertical component
 * in the order of the {@linkplain #getSingleComponents(CoordinateReferenceSystem) single components list}.
 *
 * <div class="section">Height in a three-dimensional geographic CRS</div>
 * In ISO 19111 model, ellipsoidal heights are indissociable from geographic CRS because such heights
 * without their (<var>latitude</var>, <var>longitude</var>) locations make little sense. Consequently
 * a standard-conformant library should return {@code null} when asked for the {@code VerticalCRS}
 * component of a geographic CRS. This is what {@code getVerticalComponent(…)} does when the
 * {@code allowCreateEllipsoidal} argument is {@code false}.
 *
 * <p>However in some exceptional cases, handling ellipsoidal heights like any other kind of heights
 * may simplify the task. For example when computing <em>difference</em> between heights above the
 * same datum, the impact of ignoring locations may be smaller (but not necessarily canceled).
 * Orphan {@code VerticalCRS} may also be useful for information purpose like labeling a plot axis.
 * If the caller feels confident that ellipsoidal heights are safe for his task, he can set the
 * {@code allowCreateEllipsoidal} argument to {@code true}. In such case, this {@code getVerticalComponent(…)}
 * method will create a temporary {@code VerticalCRS} from the first three-dimensional {@code GeographicCRS}
 * <em>in last resort</em>, only if it can not find an existing {@code VerticalCRS} instance.
 * <strong>Note that this is not a valid CRS according ISO 19111</strong> — use with care.</p>
 *
 * @param  crs  the coordinate reference system, or {@code null}.
 * @param  allowCreateEllipsoidal {@code true} for allowing the creation of orphan CRS for ellipsoidal heights.
 *         The recommended value is {@code false}.
 * @return the first vertical CRS, or {@code null} if none.
 *
 * @see #compound(CoordinateReferenceSystem...)
 *
 * @category information
 */
public static VerticalCRS getVerticalComponent(final CoordinateReferenceSystem crs, final boolean allowCreateEllipsoidal) {
    if (crs instanceof VerticalCRS) {
        return (VerticalCRS) crs;
    }
    if (crs instanceof CompoundCRS) {
        final CompoundCRS cp = (CompoundCRS) crs;
        boolean a = false;
        do {
            // Executed at most twice.
            for (final CoordinateReferenceSystem c : cp.getComponents()) {
                final VerticalCRS candidate = getVerticalComponent(c, a);
                if (candidate != null) {
                    return candidate;
                }
            }
        } while ((a = !a) == allowCreateEllipsoidal);
    }
    if (allowCreateEllipsoidal && horizontalCode(crs) == 3) {
        final CoordinateSystem cs = crs.getCoordinateSystem();
        final int i = AxisDirections.indexOfColinear(cs, AxisDirection.UP);
        if (i >= 0) {
            final CoordinateSystemAxis axis = cs.getAxis(i);
            VerticalCRS c = CommonCRS.Vertical.ELLIPSOIDAL.crs();
            if (!c.getCoordinateSystem().getAxis(0).equals(axis)) {
                final Map<String, ?> properties = IdentifiedObjects.getProperties(c);
                c = new DefaultVerticalCRS(properties, c.getDatum(), new DefaultVerticalCS(properties, axis));
            }
            return c;
        }
    }
    return null;
}
Also used : DefaultVerticalCRS(org.apache.sis.referencing.crs.DefaultVerticalCRS) CoordinateSystem(org.opengis.referencing.cs.CoordinateSystem) DefaultVerticalCRS(org.apache.sis.referencing.crs.DefaultVerticalCRS) VerticalCRS(org.opengis.referencing.crs.VerticalCRS) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) DefaultCompoundCRS(org.apache.sis.referencing.crs.DefaultCompoundCRS) CoordinateSystemAxis(org.opengis.referencing.cs.CoordinateSystemAxis) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) DefaultVerticalCS(org.apache.sis.referencing.cs.DefaultVerticalCS)

Example 9 with CompoundCRS

use of org.opengis.referencing.crs.CompoundCRS 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 10 with CompoundCRS

use of org.opengis.referencing.crs.CompoundCRS in project sis by apache.

the class DefaultPassThroughOperation method getModifiedCoordinates.

/**
 * Returns the ordered sequence of indices in a source coordinate tuple of the coordinates
 * affected by this pass-through operation.
 *
 * @return zero-based indices of the modified source coordinates.
 *
 * @see PassThroughTransform#getModifiedCoordinates()
 */
@Override
public int[] getModifiedCoordinates() {
    final MathTransform transform = super.getMathTransform();
    if (transform instanceof PassThroughTransform) {
        return ((PassThroughTransform) transform).getModifiedCoordinates();
    } else {
        /*
             * Should not happen with objects created by public methods since the constructor created the transform
             * itself. However may happen with operations parsed from GML. As a fallback, search in the components
             * of CompoundCRS. This is not a universal fallback, but work for the most straightforward cases.
             */
        final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
        if (sourceCRS instanceof CompoundCRS) {
            int firstAffectedOrdinate = 0;
            final CoordinateReferenceSystem search = operation.getSourceCRS();
            for (final CoordinateReferenceSystem c : ((CompoundCRS) sourceCRS).getComponents()) {
                final int dim = ReferencingUtilities.getDimension(c);
                if (c == search) {
                    final int[] indices = new int[dim];
                    for (int i = 0; i < dim; i++) {
                        indices[i] = firstAffectedOrdinate + i;
                    }
                    return indices;
                }
                firstAffectedOrdinate += dim;
            }
        }
        throw new UnsupportedImplementationException(transform.getClass());
    }
}
Also used : MathTransform(org.opengis.referencing.operation.MathTransform) CompoundCRS(org.opengis.referencing.crs.CompoundCRS) CoordinateReferenceSystem(org.opengis.referencing.crs.CoordinateReferenceSystem) PassThroughTransform(org.apache.sis.referencing.operation.transform.PassThroughTransform) UnsupportedImplementationException(org.apache.sis.util.UnsupportedImplementationException)

Aggregations

CompoundCRS (org.opengis.referencing.crs.CompoundCRS)11 CoordinateOperation (org.opengis.referencing.operation.CoordinateOperation)6 DefaultCompoundCRS (org.apache.sis.referencing.crs.DefaultCompoundCRS)5 Test (org.junit.Test)5 DependsOnMethod (org.apache.sis.test.DependsOnMethod)4 CoordinateReferenceSystem (org.opengis.referencing.crs.CoordinateReferenceSystem)3 GeographicCRS (org.opengis.referencing.crs.GeographicCRS)3 VerticalCRS (org.opengis.referencing.crs.VerticalCRS)3 IdentifiedObject (org.opengis.referencing.IdentifiedObject)2 DerivedCRS (org.opengis.referencing.crs.DerivedCRS)2 CoordinateSystem (org.opengis.referencing.cs.CoordinateSystem)2 ConcatenatedOperation (org.opengis.referencing.operation.ConcatenatedOperation)2 HashMap (java.util.HashMap)1 DefaultDerivedCRS (org.apache.sis.referencing.crs.DefaultDerivedCRS)1 DefaultVerticalCRS (org.apache.sis.referencing.crs.DefaultVerticalCRS)1 DefaultVerticalCS (org.apache.sis.referencing.cs.DefaultVerticalCS)1 IdentifiedObjectFinder (org.apache.sis.referencing.factory.IdentifiedObjectFinder)1 NoSuchAuthorityFactoryException (org.apache.sis.referencing.factory.NoSuchAuthorityFactoryException)1 PassThroughTransform (org.apache.sis.referencing.operation.transform.PassThroughTransform)1 UnsupportedImplementationException (org.apache.sis.util.UnsupportedImplementationException)1