| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.sis.internal.referencing.provider; |
| |
| import javax.xml.bind.annotation.XmlTransient; |
| import org.opengis.parameter.ParameterDescriptorGroup; |
| import org.opengis.referencing.operation.OperationMethod; |
| import org.opengis.referencing.operation.SingleOperation; |
| import org.opengis.referencing.operation.Transformation; |
| |
| |
| /** |
| * Base class for providers that perform an operation on geographic or geocentric coordinates. |
| * In the geographic case, those operations can have two-dimensional and three-dimensional variants |
| * by adding or omitting the ellipsoidal height. Sometime those variants are explicitly declared |
| * in the EPSG database and are implemented in this package as separated operations. Sometime those |
| * variants are specific to Apache SIS and can be fetched only by a call to {@link #redimension(int, int)}. |
| * |
| * @author Martin Desruisseaux (Geomatys) |
| * @version 0.7 |
| * @since 0.7 |
| * @module |
| */ |
| @XmlTransient |
| abstract class GeodeticOperation extends AbstractProvider { |
| /** |
| * For cross-version compatibility. |
| */ |
| private static final long serialVersionUID = 5431035501162127059L; |
| |
| /** |
| * The providers for all combinations between 2D and 3D cases, or {@code null} if none. |
| * If non-null, then array length shall be 4. Indices are built with following rules: |
| * |
| * <ul> |
| * <li>Bit 1: dimension of source coordinates (0 for 2D, 1 for 3D).</li> |
| * <li>Bit 0: dimension of target coordinates (0 for 2D, 1 for 3D).</li> |
| * </ul> |
| * |
| * <strong>Do not modify this array after construction</strong>, since the same array is shared by many |
| * objects and there is no synchronization. |
| */ |
| final GeodeticOperation[] redimensioned; |
| |
| /** |
| * Constructs a math transform provider from a set of parameters. The provider name and |
| * {@linkplain #getIdentifiers() identifiers} will be the same than the parameter ones. |
| * This method expects an array either {@code null} or of length 4 with methods of the |
| * following dimensions: |
| * |
| * <ol> |
| * <li>2 → 2 dimensions in {@code redimensioned[0]}</li> |
| * <li>2 → 3 dimensions in {@code redimensioned[1]}</li> |
| * <li>3 → 2 dimensions in {@code redimensioned[2]}</li> |
| * <li>3 → 3 dimensions in {@code redimensioned[3]}</li> |
| * </ol> |
| * |
| * @param sourceDimensions number of dimensions in the source CRS of this operation method. |
| * @param targetDimensions number of dimensions in the target CRS of this operation method. |
| * @param parameters description of parameters expected by this operation. |
| * @param redimensioned providers for all combinations between 2D and 3D cases, or {@code null}. |
| */ |
| GeodeticOperation(final int sourceDimensions, |
| final int targetDimensions, |
| final ParameterDescriptorGroup parameters, |
| final GeodeticOperation[] redimensioned) |
| { |
| super(sourceDimensions, targetDimensions, parameters); |
| this.redimensioned = redimensioned; |
| } |
| |
| /** |
| * Returns the three-dimensional variant of this operation method, or {@code null} if none. |
| * This method needs to be overridden only if the three-dimensional variant is an instance |
| * of a different class than this instance. |
| * |
| * <p>This method is not needed on the JDK9 branch.</p> |
| */ |
| Class<? extends GeodeticOperation> variant3D() { |
| return null; |
| } |
| |
| /** |
| * Returns the elements of the given array at an index computed from the given dimensions. |
| * |
| * @param sourceDimensions the desired number of input dimensions. |
| * @param targetDimensions the desired number of output dimensions. |
| * @return the redimensioned operation method, or {@code null} if none. |
| */ |
| @Override |
| public final OperationMethod redimension(final int sourceDimensions, final int targetDimensions) { |
| if (redimensioned != null && (sourceDimensions & ~1) == 2 && (targetDimensions & ~1) == 2) { |
| final GeodeticOperation m = redimensioned[((sourceDimensions & 1) << 1) | (targetDimensions & 1)]; |
| if (m != null) { |
| assert (m.getSourceDimensions() == sourceDimensions) : sourceDimensions; |
| assert (m.getTargetDimensions() == targetDimensions) : targetDimensions; |
| return m; |
| } |
| } |
| return super.redimension(sourceDimensions, targetDimensions); |
| } |
| |
| /** |
| * Returns the interface implemented by most coordinate operations that extends this class. |
| * |
| * @return default to {@link Transformation}. |
| */ |
| @Override |
| public Class<? extends SingleOperation> getOperationType() { |
| return Transformation.class; |
| } |
| |
| /** |
| * The inverse of {@code GeodeticOperation} is usually the same operation with parameter signs inverted. |
| * |
| * @return {@code true} for most {@code GeodeticOperation} instances. |
| */ |
| @Override |
| public boolean isInvertible() { |
| return true; |
| } |
| } |