001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2004-2023 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.referencing.operation;
019
020import java.awt.Shape;
021import java.awt.geom.Point2D;
022import java.awt.geom.AffineTransform;
023
024
025/**
026 * Transforms two-dimensional coordinate points. {@link CoordinateOperation#getMathTransform()} may
027 * returns instance of this interface when source and destination coordinate systems are both two
028 * dimensional. {@code MathTransform2D} extends {@link MathTransform} by adding some methods for
029 * easier inter-operability with Java2D.
030 *
031 * @departure integration
032 *   This interface is not part of OGC specification. It has been added in GeoAPI for
033 *   close integration with the <cite>Java2D</cite> library. The API defined in this
034 *   interface matches the {@code java.awt.geom.AffineTransform} API.
035 *
036 * @author  Martin Desruisseaux (IRD, Geomatys)
037 * @version 3.1
038 * @since   1.0
039 */
040public interface MathTransform2D extends MathTransform {
041    /**
042     * Returns the number of dimensions of input points, which shall be 2.
043     *
044     * @return always 2.
045     */
046    @Override
047    default int getSourceDimensions() {
048        return 2;
049    }
050
051    /**
052     * Returns the number of dimensions of output points, which shall be 2.
053     *
054     * @return always 2.
055     */
056    @Override
057    default int getTargetDimensions() {
058        return 2;
059    }
060
061    /**
062     * Transforms the specified {@code ptSrc} and stores the result in {@code ptDst}.
063     * If {@code ptDst} is {@code null}, a new {@link Point2D} object is allocated
064     * and then the result of the transformation is stored in this object. In either case,
065     * {@code ptDst}, which contains the transformed point, is returned for convenience.
066     * If {@code ptSrc} and {@code ptDst} are the same object, the input point is
067     * correctly overwritten with the transformed point.
068     *
069     * @param  ptSrc  the coordinate point to be transformed.
070     * @param  ptDst  the coordinate point that stores the result of transforming {@code ptSrc},
071     *         or {@code null} if a new point shall be created.
072     * @return the coordinate point after transforming {@code ptSrc} and storing the result
073     *         in {@code ptDst} or in a new point if {@code ptDst} was null.
074     * @throws TransformException if the point cannot be transformed.
075     *
076     * @see AffineTransform#transform(Point2D, Point2D)
077     */
078    Point2D transform(Point2D ptSrc, Point2D ptDst) throws TransformException;
079
080    /**
081     * Transforms the specified shape. This method may replace straight lines by quadratic curves
082     * when applicable. It may also do the opposite (replace curves by straight lines). The returned
083     * shape doesn't need to have the same number of points than the original shape.
084     *
085     * @param  shape  the Shape to transform.
086     * @return the transformed shape. Some implementations may return
087     *         {@code shape} unmodified if this transform is identity.
088     * @throws TransformException if a transform failed.
089     *
090     * @see AffineTransform#createTransformedShape(Shape)
091     */
092    Shape createTransformedShape(Shape shape) throws TransformException;
093
094    /**
095     * Gets the derivative of this transform at a point. The derivative is the
096     * matrix of the non-translating portion of the approximate affine map at
097     * the point.
098     *
099     * @param  point  the coordinate point where to evaluate the derivative.
100     *         Null value is accepted only if the derivative is the same everywhere.
101     *         For example, affine transform accept null value since they produces identical derivative
102     *         no matter the coordinate value. But most map projection will requires a non-null value.
103     * @return the derivative at the specified point as a 2×2 matrix.
104     *         This method never returns an internal object:
105     *         changing the matrix will not change the state of this math transform.
106     * @throws NullPointerException if the derivative dependents on coordinate and {@code point} is {@code null}.
107     * @throws TransformException if the derivative cannot be evaluated at the specified point.
108     */
109    Matrix derivative(Point2D point) throws TransformException;
110
111    /**
112     * Returns the inverse transform of this object.
113     *
114     * @return the inverse transform.
115     * @throws NoninvertibleTransformException if the transform cannot be inverted.
116     *
117     * @see AffineTransform#createInverse()
118     */
119    @Override
120    default MathTransform2D inverse() throws NoninvertibleTransformException {
121        if (isIdentity()) {
122            return this;
123        }
124        throw new NoninvertibleTransformException();
125    }
126}