001    /*
002     *    GeoAPI - Java interfaces for OGC/ISO standards
003     *    http://www.geoapi.org
004     *
005     *    Copyright (C) 2004-2012 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.util.Set;
035    import org.opengis.util.Factory;
036    import org.opengis.util.FactoryException;
037    import org.opengis.util.NoSuchIdentifierException;
038    import org.opengis.referencing.cs.CoordinateSystem;
039    import org.opengis.referencing.datum.Ellipsoid;
040    import org.opengis.referencing.crs.*; // Contains some import for javadoc.
041    import org.opengis.parameter.*;       // Contains some import for javadoc.
042    import org.opengis.annotation.UML;
043    
044    import static org.opengis.annotation.Obligation.*;
045    import static org.opengis.annotation.Specification.*;
046    
047    
048    /**
049     * Low level factory for creating {@linkplain MathTransform math transforms}.
050     * Many high level GIS applications will never need to use this factory directly;
051     * they can use a {@linkplain CoordinateOperationFactory coordinate operation factory}
052     * instead. However, the {@code MathTransformFactory} interface can be used directly
053     * by applications that wish to transform other types of coordinates (e.g. color coordinates,
054     * or image pixel coordinates).
055     * <p>
056     * A {@linkplain MathTransform math transform} is an object that actually does
057     * the work of applying formulae to coordinate values. The math transform does
058     * not know or care how the coordinates relate to positions in the real world.
059     * This lack of semantics makes implementing {@code MathTransformFactory}
060     * significantly easier than it would be otherwise.
061     * <p>
062     * For example the affine transform applies a matrix to the coordinates
063     * without knowing how what it is doing relates to the real world. So if
064     * the matrix scales <var>Z</var> values by a factor of 1000, then it could
065     * be converting meters into millimeters, or it could be converting kilometers
066     * into meters.
067     * <p>
068     * Because {@linkplain MathTransform math transforms} have low semantic value
069     * (but high mathematical value), programmers who do not have much knowledge
070     * of how GIS applications use coordinate systems, or how those coordinate
071     * systems relate to the real world can implement {@code MathTransformFactory}.
072     * The low semantic content of {@linkplain MathTransform math transforms} also
073     * means that they will be useful in applications that have nothing to do with
074     * GIS coordinates. For example, a math transform could be used to map color
075     * coordinates between different color spaces, such as converting (red, green, blue)
076     * colors into (hue, light, saturation) colors.
077     * <p>
078     * Since a {@linkplain MathTransform math transform} does not know what its source
079     * and target coordinate systems mean, it is not necessary or desirable for a math
080     * transform object to keep information on its source and target coordinate systems.
081     *
082     * @author  Martin Desruisseaux (IRD)
083     * @version 3.0
084     * @since   1.0
085     *
086     * @see <A HREF="http://www.remotesensing.org/geotiff/proj_list/">Projection transform list on RemoteSensing.org</A>
087     */
088    @UML(identifier="CT_MathTransformFactory", specification=OGC_01009)
089    public interface MathTransformFactory extends Factory {
090        /**
091         * Returns a set of available methods for {@linkplain MathTransform math transforms}. For
092         * each element in this set, the {@linkplain OperationMethod#getName() operation method name}
093         * must be known to the {@link #getDefaultParameters(String)} method in this factory.
094         * The set of available methods is implementation dependent.
095         *
096         * @param  type <code>{@linkplain SingleOperation}.class</code> for fetching all operation methods,
097         *         or <code>{@linkplain Projection}.class</code> for fetching only map projection methods.
098         * @return All {@linkplain MathTransform math transform} methods available in this factory.
099         *
100         * @departure extension
101         *   This method is not part of the OGC specification. It has been added as a way to publish
102         *   the capabilities of a factory.
103         *
104         * @see #getDefaultParameters(String)
105         * @see #createParameterizedTransform(ParameterValueGroup)
106         * @see CoordinateOperationFactory#getOperationMethod(String)
107         */
108        Set<OperationMethod> getAvailableMethods(Class<? extends SingleOperation> type);
109    
110        /**
111         * Returns the operation method used for the latest call to
112         * {@link #createParameterizedTransform createParameterizedTransform},
113         * or {@code null} if not applicable.
114         * <p>
115         * Implementors should document how their implementation behave in a multi-threads environment.
116         * For example some implementations use {@linkplain java.lang.ThreadLocal thread local variables},
117         * while other can choose to returns {@code null} in all cases since this method is optional.
118         * <p>
119         * Note that this method may apply as well to convenience methods that delegate their work to
120         * {@code createParameterizedTransform}, like {@link #createBaseToDerived createBaseToDerived}.
121         *
122         * @return The last method used, or {@code null} if unknown of unsupported.
123         *
124         * @departure extension
125         *   This method is not part of the OGC specification. It has been added because this information
126         *   appears to be needed in practice. A more object-oriented approach would have been to
127         *   return a {<code>MathTransform</code>, <code>OperationMethod</code>} tuple in the
128         *   <code>createParameterizedTransform(&hellip)</code> method, but we wanted to keep the
129         *   later unchanged for historical reasons (it is inherited from OGC 01-009) and because
130         *   only a minority of use cases need the operation method.
131         *   <p>
132         *   Note that the existence of this method does not break thread-safety if the implementor
133         *   stores this information in a <code>ThreadLocal</code> variable.
134         *
135         * @since 2.1
136         */
137        OperationMethod getLastMethodUsed();
138    
139        /**
140         * Returns the default parameter values for a math transform using the given method.
141         * The {@code method} argument is the name of any operation method returned by
142         * <code>{@link #getAvailableMethods(Class) getAvailableMethods}({@linkplain CoordinateOperation}.class)</code>.
143         * A typical example is
144         * <code>"<A HREF="http://www.remotesensing.org/geotiff/proj_list/transverse_mercator.html">Transverse_Mercator</A>"</code>).
145         * <P>
146         * The {@linkplain ParameterDescriptorGroup#getName() parameter group name} shall be the
147         * method name, or an alias to be understood by <code>{@linkplain #createParameterizedTransform
148         * createParameterizedTransform}(parameters)</code>. This method creates new parameter instances
149         * at every call. Parameters are intended to be modified by the user before to be given to the
150         * above-cited {@code createParameterizedTransform} method.
151         *
152         * @param  method The case insensitive name of the method to search for.
153         * @return The default parameter values.
154         * @throws NoSuchIdentifierException if there is no transform registered for the specified method.
155         *
156         * @departure extension
157         *   This method is part of the GeoAPI mechanism for defining the math transform parameters
158         *   or deriving other transforms.
159         *
160         * @see #getAvailableMethods(Class)
161         * @see #createParameterizedTransform(ParameterValueGroup)
162         */
163        ParameterValueGroup getDefaultParameters(String method) throws NoSuchIdentifierException;
164    
165        /**
166         * Creates a {@linkplain #createParameterizedTransform parameterized transform} from a base CRS
167         * to a derived CS. This convenience method {@linkplain #createConcatenatedTransform concatenates}
168         * the parameterized transform with any other transform required for performing units changes and
169         * ordinates swapping, as described in the {@linkplain #createParameterizedTransform note on
170         * cartographic projections}.
171         * <p>
172         * In addition, implementations are encouraged to infer the {@code "semi_major"} and
173         * {@code "semi_minor"} parameter values from the {@linkplain Ellipsoid ellipsoid}, if
174         * they are not explicitly given.
175         *
176         * @param  baseCRS The source coordinate reference system.
177         * @param  parameters The parameter values for the transform.
178         * @param  derivedCS The target coordinate system.
179         * @return The parameterized transform.
180         * @throws NoSuchIdentifierException if there is no transform registered for the method.
181         * @throws FactoryException if the object creation failed. This exception is thrown
182         *         if some required parameter has not been supplied, or has illegal value.
183         *
184         * @departure extension
185         *   This method is part of the GeoAPI mechanism for defining the math transform parameters
186         *   or deriving other transforms.
187         *
188         * @since 2.1
189         */
190        MathTransform createBaseToDerived(CoordinateReferenceSystem baseCRS,
191                                          ParameterValueGroup       parameters,
192                                          CoordinateSystem          derivedCS)
193                throws NoSuchIdentifierException, FactoryException;
194    
195        /**
196         * Creates a transform from a group of parameters. The method name is inferred from
197         * the {@linkplain ParameterDescriptorGroup#getName() parameter group name}. Example:
198         *
199         * <blockquote><pre>
200         * ParameterValueGroup p = factory.getDefaultParameters("Transverse_Mercator");
201         * p.parameter("semi_major").setValue(6378137.000);
202         * p.parameter("semi_minor").setValue(6356752.314);
203         * MathTransform mt = factory.createParameterizedTransform(p);
204         * </pre></blockquote>
205         *
206         * <b>Note on cartographic projections:</b>
207         * <P>Cartographic projection transforms are used by {@linkplain ProjectedCRS projected coordinate reference systems}
208         * to map geographic coordinates (e.g. <var>longitude</var> and <var>latitude</var>) into (<var>x</var>,<var>y</var>)
209         * coordinates. These (<var>x</var>,<var>y</var>) coordinates can be imagined to lie on a plane, such as a paper map
210         * or a screen. All cartographic projection transforms created through this method will have the following properties:</P>
211         * <UL>
212         *   <LI>Converts from (<var>longitude</var>,<var>latitude</var>) coordinates to (<var>x</var>,<var>y</var>).</LI>
213         *   <LI>All angles are assumed to be degrees, and all distances are assumed to be meters.</LI>
214         *   <LI>The domain shall be a subset of {[-180,180)&times;(-90,90)}.</LI>
215         * </UL>
216         * <P>Although all cartographic projection transforms must have the properties listed above, many projected coordinate
217         * reference systems have different properties. For example, in Europe some projected CRSs use grads instead of degrees,
218         * and often the {@linkplain ProjectedCRS#getBaseCRS() base geographic CRS} is (<var>latitude</var>, <var>longitude</var>)
219         * instead of (<var>longitude</var>, <var>latitude</var>). This means that the cartographic projected transform is often
220         * used as a single step in a series of transforms, where the other steps change units and swap ordinates.</P>
221         *
222         * @param  parameters The parameter values.
223         * @return The parameterized transform.
224         * @throws NoSuchIdentifierException if there is no transform registered for the method.
225         * @throws FactoryException if the object creation failed. This exception is thrown
226         *         if some required parameter has not been supplied, or has illegal value.
227         *
228         * @see #getDefaultParameters(String)
229         * @see #getAvailableMethods(Class)
230         */
231        @UML(identifier="createParameterizedTransform", obligation=MANDATORY, specification=OGC_01009)
232        MathTransform createParameterizedTransform(ParameterValueGroup parameters)
233                throws NoSuchIdentifierException, FactoryException;
234    
235        /**
236         * Creates an affine transform from a matrix.
237         * If the transform's input dimension is {@code M}, and output dimension
238         * is {@code N}, then the matrix will have size {@code [N+1][M+1]}.
239         * The +1 in the matrix dimensions allows the matrix to do a shift, as well as
240         * a rotation. The {@code [M][j]} element of the matrix will be the <var>j</var>'th
241         * ordinate of the moved origin. The {@code [i][N]} element of the matrix
242         * will be 0 for <var>i</var> less than {@code M}, and 1 for <var>i</var>
243         * equals {@code M}.
244         *
245         * @param matrix The matrix used to define the affine transform.
246         * @return The affine transform.
247         * @throws FactoryException if the object creation failed.
248         */
249        @UML(identifier="createAffineTransform", obligation=MANDATORY, specification=OGC_01009)
250        MathTransform createAffineTransform(Matrix matrix) throws FactoryException;
251    
252        /**
253         * Creates a transform by concatenating two existing transforms.
254         * A concatenated transform acts in the same way as applying two
255         * transforms, one after the other.
256         *
257         * The dimension of the output space of the first transform must match
258         * the dimension of the input space in the second transform.
259         * If you wish to concatenate more than two transforms, then you can
260         * repeatedly use this method.
261         *
262         * @param  transform1 The first transform to apply to points.
263         * @param  transform2 The second transform to apply to points.
264         * @return The concatenated transform.
265         * @throws FactoryException if the object creation failed.
266         */
267        @UML(identifier="createConcatenatedTransform", obligation=MANDATORY, specification=OGC_01009)
268        MathTransform createConcatenatedTransform(MathTransform transform1,
269                                                  MathTransform transform2) throws FactoryException;
270    
271        /**
272         * Creates a transform which passes through a subset of ordinates to another transform.
273         * This allows transforms to operate on a subset of ordinates. For example giving
274         * (<var>latitude</var>, <var>longitude</var>, <var>height</var>) coordinates, a pass
275         * through transform can convert the height values from meters to feet without affecting
276         * the (<var>latitude</var>, <var>longitude</var>) values.
277         *
278         * @param  firstAffectedOrdinate The lowest index of the affected ordinates.
279         * @param  subTransform Transform to use for affected ordinates.
280         * @param  numTrailingOrdinates Number of trailing ordinates to pass through.
281         *         Affected ordinates will range from {@code firstAffectedOrdinate}
282         *         inclusive to {@code dimTarget-numTrailingOrdinates} exclusive.
283         * @return A pass through transform with the following dimensions:<br>
284         *         <pre>
285         * Source: firstAffectedOrdinate + subTransform.getDimSource() + numTrailingOrdinates
286         * Target: firstAffectedOrdinate + subTransform.getDimTarget() + numTrailingOrdinates</pre>
287         * @throws FactoryException if the object creation failed.
288         */
289        @UML(identifier="createPassThroughTransform", obligation=MANDATORY, specification=OGC_01009)
290        MathTransform createPassThroughTransform(int firstAffectedOrdinate,
291                                                 MathTransform subTransform,
292                                                 int numTrailingOrdinates) throws FactoryException;
293    
294        /**
295         * Creates a math transform object from a XML string.
296         *
297         * @param  xml Math transform encoded in XML format.
298         * @return The math transform (never {@code null}).
299         * @throws FactoryException if the object creation failed.
300         */
301        @UML(identifier="createFromXML", obligation=MANDATORY, specification=OGC_01009)
302        MathTransform createFromXML(String xml) throws FactoryException;
303    
304        /**
305         * Creates a math transform object from a string.
306         * The <A HREF="../doc-files/WKT.html">definition for WKT</A> is
307         * shown using Extended Backus Naur Form (EBNF).
308         *
309         * @param  wkt Math transform encoded in Well-Known Text format.
310         * @return The math transform (never {@code null}).
311         * @throws FactoryException if the Well-Known Text can't be parsed,
312         *         or if the math transform creation failed from some other reason.
313         *
314         * @see MathTransform#toWKT()
315         */
316        @UML(identifier="createFromWKT", obligation=MANDATORY, specification=OGC_01009)
317        MathTransform createFromWKT(String wkt) throws FactoryException;
318    }