001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2004-2013 Open Geospatial Consortium, Inc.
006     *    All Rights Reserved. http://www.opengeospatial.org/ogc/legal
007     *
008     *    Permission to use, copy, and modify this software and its documentation, with
009     *    or without modification, for any purpose and without fee or royalty is hereby
010     *    granted, provided that you include the following on ALL copies of the software
011     *    and documentation or portions thereof, including modifications, that you make:
012     *
013     *    1. The full text of this NOTICE in a location viewable to users of the
014     *       redistributed or derivative work.
015     *    2. Notice of any changes or modifications to the OGC files, including the
016     *       date changes were made.
017     *
018     *    THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE
019     *    NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
020     *    TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT
021     *    THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
022     *    PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
023     *
024     *    COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR
025     *    CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR DOCUMENTATION.
026     *
027     *    The name and trademarks of copyright holders may NOT be used in advertising or
028     *    publicity pertaining to the software without specific, written prior permission.
029     *    Title to copyright in this software and any associated documentation will at all
030     *    times remain with copyright holders.
031     */
032    package org.opengis.referencing.operation;
033    
034    import java.awt.geom.AffineTransform;
035    
036    import org.opengis.geometry.DirectPosition;
037    import org.opengis.geometry.MismatchedDimensionException;
038    import org.opengis.annotation.UML;
039    
040    import static org.opengis.annotation.Specification.*;
041    
042    
043    /**
044     * Transforms multi-dimensional coordinate points. This interface transforms coordinate
045     * value for a point given in the {@linkplain CoordinateOperation#getSourceCRS() source
046     * coordinate reference system} to coordinate value for the same point in the
047     * {@linkplain CoordinateOperation#getTargetCRS() target coordinate reference system}.
048     *
049     * <ul>
050     *   <li>In a {@linkplain Conversion conversion}, the transformation is accurate to within the
051     *   limitations of the computer making the calculations.</li>
052     *   <li>In a {@linkplain Transformation transformation}, where some of the operational parameters
053     *   are derived from observations, the transformation is accurate to within the limitations of
054     *   those observations.</li>
055     * </ul>
056     *
057     * If a client application wishes to query the source and target
058     * {@linkplain org.opengis.referencing.crs.CoordinateReferenceSystem coordinate reference systems}
059     * of an operation, then it should keep hold of the {@link CoordinateOperation} interface,
060     * and use the contained math transform object whenever it wishes to perform a transform.
061     *
062     * @author  Martin Desruisseaux (IRD)
063     * @version 3.0
064     * @since   1.0
065     *
066     * @see AffineTransform
067     * @see javax.media.jai.PerspectiveTransform
068     * @see javax.media.j3d.Transform3D
069     * @see MathTransformFactory
070     * @see CoordinateOperation#getMathTransform()
071     */
072    @UML(identifier="CT_MathTransform", specification=OGC_01009)
073    public interface MathTransform {
074        /**
075         * Gets the dimension of input points.
076         *
077         * @return The dimension of input points.
078         */
079        @UML(identifier="getDimSource", specification=OGC_01009)
080        int getSourceDimensions();
081    
082        /**
083         * Gets the dimension of output points.
084         *
085         * @return The dimension of output points.
086         */
087        @UML(identifier="getDimTarget", specification=OGC_01009)
088        int getTargetDimensions();
089    
090        /**
091         * Transforms the specified {@code ptSrc} and stores the result in
092         * {@code ptDst}. If {@code ptDst} is {@code null}, a new
093         * {@link DirectPosition} object is allocated and then the result of the
094         * transformation is stored in this object. In either case, {@code ptDst},
095         * which contains the transformed point, is returned for convenience.
096         * If {@code ptSrc} and {@code ptDst} are the same object,
097         * the input point is correctly overwritten with the transformed point.
098         *
099         * @param  ptSrc the specified coordinate point to be transformed.
100         * @param  ptDst the specified coordinate point that stores the result of transforming
101         *         {@code ptSrc}, or {@code null}.
102         * @return the coordinate point after transforming {@code ptSrc} and storing the result
103         *         in {@code ptDst}, or a newly created point if {@code ptDst} was null.
104         * @throws MismatchedDimensionException if {@code ptSrc} or
105         *         {@code ptDst} doesn't have the expected dimension.
106         * @throws TransformException if the point can't be transformed.
107         */
108        @UML(identifier="transform", specification=OGC_01009)
109        DirectPosition transform(DirectPosition ptSrc, DirectPosition ptDst)
110                throws MismatchedDimensionException, TransformException;
111    
112        /**
113         * Transforms a list of coordinate point ordinal values.
114         * This method is provided for efficiently transforming many points.
115         * The supplied array of ordinal values will contain packed ordinal
116         * values. For example, if the source dimension is 3, then the ordinals
117         * will be packed in this order:
118         *
119         * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
120         *  <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var> …).
121         *
122         * @param  srcPts the array containing the source point coordinates.
123         * @param  srcOff the offset to the first point to be transformed in the source array.
124         * @param  dstPts the array into which the transformed point coordinates are returned.
125         *                May be the same than {@code srcPts}.
126         * @param  dstOff the offset to the location of the first transformed point that is
127         *                stored in the destination array.
128         * @param  numPts the number of point objects to be transformed.
129         * @throws TransformException if a point can't be transformed. Some implementations will stop
130         *         at the first failure, wile some other implementations will fill the untransformable
131         *         points with {@linkplain Double#NaN NaN} values, continue and throw the exception
132         *         only at end. Implementations that fall in the later case should set the {@linkplain
133         *         TransformException#getLastCompletedTransform last completed transform} to {@code this}.
134         *
135         * @see AffineTransform#transform(double[], int, double[], int, int)
136         */
137        @UML(identifier="transformList", specification=OGC_01009)
138        void transform(double[] srcPts, int srcOff,
139                       double[] dstPts, int dstOff, int numPts) throws TransformException;
140    
141        /**
142         * Transforms a list of coordinate point ordinal values.
143         * This method is provided for efficiently transforming many points.
144         * The supplied array of ordinal values will contain packed ordinal
145         * values.  For example, if the source dimension is 3, then the ordinals
146         * will be packed in this order:
147         *
148         * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
149         *  <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var> …).
150         *
151         * @param  srcPts the array containing the source point coordinates.
152         * @param  srcOff the offset to the first point to be transformed in the source array.
153         * @param  dstPts the array into which the transformed point coordinates are returned.
154         *                May be the same than {@code srcPts}.
155         * @param  dstOff the offset to the location of the first transformed point that is
156         *                stored in the destination array.
157         * @param  numPts the number of point objects to be transformed.
158         * @throws TransformException if a point can't be transformed. Some implementations will stop
159         *         at the first failure, wile some other implementations will fill the untransformable
160         *         points with {@linkplain Double#NaN NaN} values, continue and throw the exception
161         *         only at end. Implementations that fall in the later case should set the {@linkplain
162         *         TransformException#getLastCompletedTransform last completed transform} to {@code this}.
163         *
164         * @see AffineTransform#transform(float[], int, float[], int, int)
165         */
166        void transform(float[] srcPts, int srcOff,
167                       float[] dstPts, int dstOff, int numPts) throws TransformException;
168    
169        /**
170         * Transforms a list of coordinate point ordinal values.
171         * This method is provided for efficiently transforming many points.
172         * The supplied array of ordinal values will contain packed ordinal
173         * values.  For example, if the source dimension is 3, then the ordinals
174         * will be packed in this order:
175         *
176         * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
177         *  <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var> …).
178         *
179         * @param  srcPts the array containing the source point coordinates.
180         * @param  srcOff the offset to the first point to be transformed in the source array.
181         * @param  dstPts the array into which the transformed point coordinates are returned.
182         * @param  dstOff the offset to the location of the first transformed point that is
183         *                stored in the destination array.
184         * @param  numPts the number of point objects to be transformed.
185         * @throws TransformException if a point can't be transformed. Some implementations will stop
186         *         at the first failure, wile some other implementations will fill the untransformable
187         *         points with {@linkplain Double#NaN NaN} values, continue and throw the exception
188         *         only at end. Implementations that fall in the later case should set the {@linkplain
189         *         TransformException#getLastCompletedTransform last completed transform} to {@code this}.
190         *
191         * @see AffineTransform#transform(float[], int, double[], int, int)
192         *
193         * @since 2.2
194         */
195        void transform(float [] srcPts, int srcOff,
196                       double[] dstPts, int dstOff, int numPts) throws TransformException;
197    
198        /**
199         * Transforms a list of coordinate point ordinal values.
200         * This method is provided for efficiently transforming many points.
201         * The supplied array of ordinal values will contain packed ordinal
202         * values.  For example, if the source dimension is 3, then the ordinals
203         * will be packed in this order:
204         *
205         * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
206         *  <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var> …).
207         *
208         * @param  srcPts the array containing the source point coordinates.
209         * @param  srcOff the offset to the first point to be transformed in the source array.
210         * @param  dstPts the array into which the transformed point coordinates are returned.
211         * @param  dstOff the offset to the location of the first transformed point that is
212         *                stored in the destination array.
213         * @param  numPts the number of point objects to be transformed.
214         * @throws TransformException if a point can't be transformed. Some implementations will stop
215         *         at the first failure, wile some other implementations will fill the untransformable
216         *         points with {@linkplain Double#NaN NaN} values, continue and throw the exception
217         *         only at end. Implementations that fall in the later case should set the {@linkplain
218         *         TransformException#getLastCompletedTransform last completed transform} to {@code this}.
219         *
220         * @see AffineTransform#transform(double[], int, float[], int, int)
221         *
222         * @since 2.2
223         */
224        void transform(double[] srcPts, int srcOff,
225                       float [] dstPts, int dstOff, int numPts) throws TransformException;
226    
227        /**
228         * Gets the derivative of this transform at a point. The derivative is the
229         * matrix of the non-translating portion of the approximate affine map at
230         * the point. The matrix will have dimensions corresponding to the source
231         * and target coordinate systems. If the input dimension is <var>M</var>,
232         * and the output dimension is <var>N</var>, then the matrix will have size
233         * <code>N×M</code>. The elements of the matrix
234         *
235         *              <code>{e<sub>n,m</sub> : n=0..(N-1)}</code>
236         *
237         * form a vector in the output space which is parallel to the displacement
238         * caused by a small change in the <var>m</var>'th ordinate in the input space.
239         *
240         * <p>For example, if the input dimension is 4 and the
241         * output dimension is 3, then a small displacement</p>
242         *
243         * <code>(x₀,&nbsp;x₁,&nbsp;x₂,&nbsp;x₃)</code>
244         *
245         * in the input space will result in a displacement
246         *
247         * <code>(y₀,&nbsp;y₁,&nbsp;y₂)</code>
248         *
249         * in the output space computed as below (<code>e<sub>n,m</sub></code>
250         * are the matrix elements):
251         *
252         * <pre>
253         *┌    ┐     ┌                    ┐ ┌    ┐
254         *│ y₀ │     │ e₀₀  e₀₁  e₀₂  e₀₃ │ │ x₀ │
255         *│ y₁ │  =  │ e₁₀  e₁₁  e₁₂  e₁₃ │ │ x₁ │
256         *│ y₂ │     │ e₂₀  e₂₁  e₂₂  e₂₃ │ │ x₂ │
257         *└    ┘     └                    ┘ │ x₃ │
258         *                                  └    ┘</pre>
259         *
260         * @param  point The coordinate point where to evaluate the derivative. Null
261         *         value is accepted only if the derivative is the same everywhere.
262         *         For example affine transform accept null value since they produces
263         *         identical derivative no matter the coordinate value. But most map
264         *         projection will requires a non-null value.
265         * @return The derivative at the specified point (never {@code null}).
266         *         This method never returns an internal object: changing the matrix
267         *         will not change the state of this math transform.
268         * @throws NullPointerException if the derivative dependents on coordinate
269         *         and {@code point} is {@code null}.
270         * @throws MismatchedDimensionException if {@code point} doesn't have
271         *         the expected dimension.
272         * @throws TransformException if the derivative can't be evaluated at the
273         *         specified point.
274         */
275        @UML(identifier="derivative", specification=OGC_01009)
276        Matrix derivative(final DirectPosition point)
277                throws MismatchedDimensionException, TransformException;
278    
279        /**
280         * Creates the inverse transform of this object. The target of the inverse transform
281         * is the source of the original. The source of the inverse transform is the target
282         * of the original. Using the original transform followed by the inverse's transform
283         * will result in an identity map on the source coordinate space, when allowances for
284         * error are made. This method may fail if the transform is not one to one. However,
285         * all cartographic projections should succeed.
286         *
287         * @return The inverse transform.
288         * @throws NoninvertibleTransformException if the transform can't be inverted.
289         *
290         * @see AffineTransform#createInverse()
291         */
292        @UML(identifier="inverse", specification=OGC_01009)
293        MathTransform inverse() throws NoninvertibleTransformException;
294    
295        /**
296         * Tests whether this transform does not move any points.
297         *
298         * @return {@code true} if this {@code MathTransform} is
299         *         an identity transform; {@code false} otherwise.
300         *
301         * @see AffineTransform#isIdentity()
302         */
303        @UML(identifier="isIdentity", specification=OGC_01009)
304        boolean isIdentity();
305    
306        /**
307         * Returns a <cite>Well Known Text</cite> (WKT) for this object. Well know text are
308         * <a href="../doc-files/WKT.html">defined in extended Backus Naur form</a>.
309         * This operation may fails if an object is too complex for the WKT format capability.
310         *
311         * @return The <cite>Well Known Text</cite> (WKT) for this object.
312         * @throws UnsupportedOperationException If this object can't be formatted as WKT.
313         *
314         * @see MathTransformFactory#createFromWKT(String)
315         */
316        @UML(identifier="getWKT", specification=OGC_01009)
317        String toWKT() throws UnsupportedOperationException;
318    }