Source Code Cross Referenced for ProjectiveTransform.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » operation » transform » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » GeoTools 2.4.1 » org.geotools.referencing.operation.transform 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *   
005:         *   (C) 2003-2006, Geotools Project Managment Committee (PMC)
006:         *   (C) 2001, Institut de Recherche pour le Développement
007:         *
008:         *    This library is free software; you can redistribute it and/or
009:         *    modify it under the terms of the GNU Lesser General Public
010:         *    License as published by the Free Software Foundation; either
011:         *    version 2.1 of the License, or (at your option) any later version.
012:         *
013:         *    This library is distributed in the hope that it will be useful,
014:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
015:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016:         *    Lesser General Public License for more details.
017:         *
018:         *    This package contains documentation from OpenGIS specifications.
019:         *    OpenGIS consortium's work is fully acknowledged here.
020:         */
021:        package org.geotools.referencing.operation.transform;
022:
023:        // J2SE dependencies and extensions
024:        import java.awt.geom.AffineTransform;
025:        import java.awt.geom.Point2D;
026:        import java.io.Serializable;
027:        import java.util.Arrays;
028:        import java.util.HashMap;
029:        import java.util.Map;
030:        import javax.vecmath.SingularMatrixException;
031:        import javax.units.NonSI;
032:
033:        // OpenGIS dependencies
034:        import org.opengis.parameter.ParameterDescriptor;
035:        import org.opengis.parameter.ParameterDescriptorGroup;
036:        import org.opengis.parameter.ParameterNotFoundException;
037:        import org.opengis.parameter.ParameterValueGroup;
038:        import org.opengis.referencing.operation.Conversion;
039:        import org.opengis.referencing.operation.MathTransform;
040:        import org.opengis.referencing.operation.Matrix;
041:        import org.opengis.referencing.operation.NoninvertibleTransformException;
042:        import org.opengis.referencing.operation.OperationMethod;
043:        import org.opengis.geometry.DirectPosition;
044:
045:        // Geotools dependencies
046:        import org.geotools.metadata.iso.citation.Citations;
047:        import org.geotools.parameter.MatrixParameterDescriptors;
048:        import org.geotools.parameter.MatrixParameters;
049:        import org.geotools.referencing.NamedIdentifier;
050:        import org.geotools.referencing.operation.LinearTransform;
051:        import org.geotools.referencing.operation.MathTransformProvider;
052:        import org.geotools.referencing.operation.matrix.MatrixFactory;
053:        import org.geotools.referencing.operation.matrix.GeneralMatrix;
054:        import org.geotools.referencing.operation.matrix.XMatrix;
055:        import org.geotools.resources.i18n.VocabularyKeys;
056:        import org.geotools.resources.i18n.Vocabulary;
057:        import org.geotools.resources.i18n.ErrorKeys;
058:        import org.geotools.resources.i18n.Errors;
059:
060:        /**
061:         * A usually affine, or otherwise a projective transform. A projective transform is capable of
062:         * mapping an arbitrary quadrilateral into another arbitrary quadrilateral, while preserving the
063:         * straightness of lines. In the special case where the transform is affine, the parallelism of
064:         * lines in the source is preserved in the output.
065:         * <p>
066:         * Such a coordinate transformation can be represented by a square {@linkplain GeneralMatrix matrix}
067:         * of an arbitrary size. Point coordinates must have a dimension equals to
068:         * <code>{@linkplain Matrix#getNumCol}-1</code>. For example, for square matrix of size 4&times;4,
069:         * coordinate points are three-dimensional. The transformed points <code>(x',y',z')</code> are
070:         * computed as below (note that this computation is similar to
071:         * {@link javax.media.jai.PerspectiveTransform} in <cite>Java Advanced Imaging</cite>):
072:         *
073:         * <blockquote><pre>
074:         * [ u ]     [ m<sub>00</sub>  m<sub>01</sub>  m<sub>02</sub>  m<sub>03</sub> ] [ x ]
075:         * [ v ]  =  [ m<sub>10</sub>  m<sub>11</sub>  m<sub>12</sub>  m<sub>13</sub> ] [ y ]
076:         * [ w ]     [ m<sub>20</sub>  m<sub>21</sub>  m<sub>22</sub>  m<sub>23</sub> ] [ z ]
077:         * [ t ]     [ m<sub>30</sub>  m<sub>31</sub>  m<sub>32</sub>  m<sub>33</sub> ] [ 1 ]
078:         *
079:         *   x' = u/t
080:         *   y' = v/t
081:         *   y' = w/t
082:         * </pre></blockquote>
083:         *
084:         * In the special case of an affine transform, the last row contains only zero
085:         * values except in the last column, which contains 1.
086:         *
087:         * @since 2.0
088:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/ProjectiveTransform.java $
089:         * @version $Id: ProjectiveTransform.java 24925 2007-03-27 20:12:08Z jgarnett $
090:         * @author Martin Desruisseaux
091:         *
092:         * @see javax.media.jai.PerspectiveTransform
093:         * @see java.awt.geom.AffineTransform
094:         * @see <A HREF="http://mathworld.wolfram.com/AffineTransformation.html">Affine transformation on MathWorld</A>
095:         */
096:        public class ProjectiveTransform extends AbstractMathTransform
097:                implements  LinearTransform, Serializable {
098:            /**
099:             * Serial number for interoperability with different versions.
100:             */
101:            private static final long serialVersionUID = -2104496465933824935L;
102:
103:            /**
104:             * The number of rows.
105:             */
106:            private final int numRow;
107:
108:            /**
109:             * The number of columns.
110:             */
111:            private final int numCol;
112:
113:            /**
114:             * Elements of the matrix. Column indice vary fastest.
115:             */
116:            private final double[] elt;
117:
118:            /**
119:             * The inverse transform. Will be created only when first needed.
120:             */
121:            private transient ProjectiveTransform inverse;
122:
123:            /**
124:             * Constructs a transform from the specified matrix.
125:             * The matrix should be affine, but it will not be verified.
126:             *
127:             * @param matrix The matrix.
128:             */
129:            protected ProjectiveTransform(final Matrix matrix) {
130:                numRow = matrix.getNumRow();
131:                numCol = matrix.getNumCol();
132:                elt = new double[numRow * numCol];
133:                int index = 0;
134:                for (int j = 0; j < numRow; j++) {
135:                    for (int i = 0; i < numCol; i++) {
136:                        elt[index++] = matrix.getElement(j, i);
137:                    }
138:                }
139:            }
140:
141:            /**
142:             * Creates a transform for the specified matrix.
143:             * The matrix should be affine, but it is not be verified.
144:             */
145:            public static LinearTransform create(final Matrix matrix) {
146:                final int dimension = matrix.getNumRow() - 1;
147:                if (dimension == matrix.getNumCol() - 1) {
148:                    if (matrix.isIdentity()) {
149:                        return IdentityTransform.create(dimension);
150:                    }
151:                    final GeneralMatrix m = toGMatrix(matrix);
152:                    if (m.isAffine()) {
153:                        switch (dimension) {
154:                        case 1:
155:                            return LinearTransform1D.create(m.getElement(0, 0),
156:                                    m.getElement(0, 1));
157:                        case 2:
158:                            return create(m.toAffineTransform2D());
159:                        }
160:                    }
161:                }
162:                return new ProjectiveTransform(matrix);
163:            }
164:
165:            /**
166:             * Creates a transform for the specified matrix as a Java2D object.
167:             * This method is provided for interoperability with
168:             * <A HREF="http://java.sun.com/products/java-media/2D/index.jsp">Java2D</A>.
169:             */
170:            public static LinearTransform create(final AffineTransform matrix) {
171:                if (matrix.isIdentity()) {
172:                    return IdentityTransform.create(2);
173:                }
174:                return new AffineTransform2D(matrix);
175:            }
176:
177:            /**
178:             * Creates a transform that apply a uniform scale along all axis.
179:             *
180:             * @param dimension The input and output dimensions.
181:             * @param scale The scale factor.
182:             *
183:             * @since 2.3
184:             */
185:            public static LinearTransform createScale(final int dimension,
186:                    final double scale) {
187:                if (scale == 1) {
188:                    return IdentityTransform.create(dimension);
189:                }
190:                final Matrix matrix = new GeneralMatrix(dimension + 1);
191:                for (int i = 0; i < dimension; i++) {
192:                    matrix.setElement(i, i, scale);
193:                }
194:                return create(matrix);
195:            }
196:
197:            /**
198:             * Creates a transform that apply the same translation along all axis.
199:             *
200:             * @param dimension The input and output dimensions.
201:             * @param offset The translation.
202:             *
203:             * @since 2.3
204:             */
205:            public static LinearTransform createTranslation(
206:                    final int dimension, final double offset) {
207:                if (offset == 0) {
208:                    return IdentityTransform.create(dimension);
209:                }
210:                final Matrix matrix = new GeneralMatrix(dimension + 1);
211:                for (int i = 0; i < dimension; i++) {
212:                    matrix.setElement(i, dimension, offset);
213:                }
214:                return create(matrix);
215:            }
216:
217:            /**
218:             * Creates a matrix that keep only a subset of the ordinate values.
219:             * The dimension of source coordinates is {@code sourceDim} and
220:             * the dimension of target coordinates is {@code toKeep.length}.
221:             *
222:             * @param  sourceDim the dimension of source coordinates.
223:             * @param  toKeep the indices of ordinate values to keep.
224:             * @return The matrix to give to the {@link #create(Matrix)}
225:             *         method in order to create the transform.
226:             * @throws IndexOutOfBoundsException if a value of {@code toKeep}
227:             *         is lower than 0 or not smaller than {@code sourceDim}.
228:             */
229:            public static Matrix createSelectMatrix(final int sourceDim,
230:                    final int[] toKeep) throws IndexOutOfBoundsException {
231:                final int targetDim = toKeep.length;
232:                final XMatrix matrix = MatrixFactory.create(targetDim + 1,
233:                        sourceDim + 1);
234:                matrix.setZero();
235:                for (int j = 0; j < targetDim; j++) {
236:                    matrix.setElement(j, toKeep[j], 1);
237:                }
238:                matrix.setElement(targetDim, sourceDim, 1);
239:                return matrix;
240:            }
241:
242:            /**
243:             * Returns the parameter descriptors for this math transform.
244:             */
245:            public ParameterDescriptorGroup getParameterDescriptors() {
246:                return ProviderAffine.PARAMETERS;
247:            }
248:
249:            /**
250:             * Returns the matrix elements as a group of parameters values. The number of parameters
251:             * depends on the matrix size. Only matrix elements different from their default value
252:             * will be included in this group.
253:             *
254:             * @param  matrix The matrix to returns as a group of parameters.
255:             * @return A copy of the parameter values for this math transform.
256:             */
257:            static ParameterValueGroup getParameterValues(final Matrix matrix) {
258:                final MatrixParameters values;
259:                values = (MatrixParameters) ProviderAffine.PARAMETERS
260:                        .createValue();
261:                values.setMatrix(matrix);
262:                return values;
263:            }
264:
265:            /**
266:             * Returns the matrix elements as a group of parameters values. The number of parameters
267:             * depends on the matrix size. Only matrix elements different from their default value
268:             * will be included in this group.
269:             *
270:             * @return A copy of the parameter values for this math transform.
271:             */
272:            public ParameterValueGroup getParameterValues() {
273:                return getParameterValues(getMatrix());
274:            }
275:
276:            /**
277:             * Transforms an array of floating point coordinates by this matrix. Point coordinates
278:             * must have a dimension equals to <code>{@link Matrix#getNumCol}-1</code>. For example,
279:             * for square matrix of size 4&times;4, coordinate points are three-dimensional and
280:             * stored in the arrays starting at the specified offset ({@code srcOff}) in the order
281:             * <code>[x<sub>0</sub>, y<sub>0</sub>, z<sub>0</sub>,
282:             *        x<sub>1</sub>, y<sub>1</sub>, z<sub>1</sub>...,
283:             *        x<sub>n</sub>, y<sub>n</sub>, z<sub>n</sub>]</code>.
284:             *
285:             * @param srcPts The array containing the source point coordinates.
286:             * @param srcOff The offset to the first point to be transformed in the source array.
287:             * @param dstPts The array into which the transformed point coordinates are returned.
288:             * @param dstOff The offset to the location of the first transformed point that is stored
289:             *               in the destination array. The source and destination array sections can
290:             *               be overlaps.
291:             * @param numPts The number of points to be transformed
292:             */
293:            public void transform(float[] srcPts, int srcOff,
294:                    final float[] dstPts, int dstOff, int numPts) {
295:                final int inputDimension = numCol - 1; // The last ordinate will be assumed equals to 1.
296:                final int outputDimension = numRow - 1;
297:                final double[] buffer = new double[numRow];
298:                if (srcPts == dstPts) {
299:                    // We are going to write in the source array. Checks if
300:                    // source and destination sections are going to clash.
301:                    final int upperSrc = srcOff + numPts * inputDimension;
302:                    if (upperSrc > dstOff) {
303:                        if (inputDimension >= outputDimension ? dstOff > srcOff
304:                                : dstOff + numPts * outputDimension > upperSrc) {
305:                            // If source overlaps destination, then the easiest workaround is
306:                            // to copy source data. This is not the most efficient however...
307:                            srcPts = new float[numPts * inputDimension];
308:                            System.arraycopy(dstPts, srcOff, srcPts, 0,
309:                                    srcPts.length);
310:                            srcOff = 0;
311:                        }
312:                    }
313:                }
314:                while (--numPts >= 0) {
315:                    int mix = 0;
316:                    for (int j = 0; j < numRow; j++) {
317:                        double sum = elt[mix + inputDimension];
318:                        for (int i = 0; i < inputDimension; i++) {
319:                            sum += srcPts[srcOff + i] * elt[mix++];
320:                        }
321:                        buffer[j] = sum;
322:                        mix++;
323:                    }
324:                    final double w = buffer[outputDimension];
325:                    for (int j = 0; j < outputDimension; j++) {
326:                        // 'w' is equals to 1 if the transform is affine.
327:                        dstPts[dstOff++] = (float) (buffer[j] / w);
328:                    }
329:                    srcOff += inputDimension;
330:                }
331:            }
332:
333:            /**
334:             * Transforms an array of floating point coordinates by this matrix. Point coordinates
335:             * must have a dimension equals to <code>{@link Matrix#getNumCol}-1</code>. For example,
336:             * for square matrix of size 4&times;4, coordinate points are three-dimensional and
337:             * stored in the arrays starting at the specified offset ({@code srcOff}) in the order
338:             * <code>[x<sub>0</sub>, y<sub>0</sub>, z<sub>0</sub>,
339:             *        x<sub>1</sub>, y<sub>1</sub>, z<sub>1</sub>...,
340:             *        x<sub>n</sub>, y<sub>n</sub>, z<sub>n</sub>]</code>.
341:             *
342:             * @param srcPts The array containing the source point coordinates.
343:             * @param srcOff The offset to the first point to be transformed in the source array.
344:             * @param dstPts The array into which the transformed point coordinates are returned.
345:             * @param dstOff The offset to the location of the first transformed point that is stored
346:             *               in the destination array. The source and destination array sections can
347:             *               be overlaps.
348:             * @param numPts The number of points to be transformed
349:             */
350:            public void transform(double[] srcPts, int srcOff,
351:                    final double[] dstPts, int dstOff, int numPts) {
352:                final int inputDimension = numCol - 1; // The last ordinate will be assumed equals to 1.
353:                final int outputDimension = numRow - 1;
354:                final double[] buffer = new double[numRow];
355:                if (srcPts == dstPts) {
356:                    // We are going to write in the source array. Checks if
357:                    // source and destination sections are going to clash.
358:                    final int upperSrc = srcOff + numPts * inputDimension;
359:                    if (upperSrc > dstOff) {
360:                        if (inputDimension >= outputDimension ? dstOff > srcOff
361:                                : dstOff + numPts * outputDimension > upperSrc) {
362:                            // If source overlaps destination, then the easiest workaround is
363:                            // to copy source data. This is not the most efficient however...
364:                            srcPts = new double[numPts * inputDimension];
365:                            System.arraycopy(dstPts, srcOff, srcPts, 0,
366:                                    srcPts.length);
367:                            srcOff = 0;
368:                        }
369:                    }
370:                }
371:                while (--numPts >= 0) {
372:                    int mix = 0;
373:                    for (int j = 0; j < numRow; j++) {
374:                        double sum = elt[mix + inputDimension];
375:                        for (int i = 0; i < inputDimension; i++) {
376:                            sum += srcPts[srcOff + i] * elt[mix++];
377:                        }
378:                        buffer[j] = sum;
379:                        mix++;
380:                    }
381:                    final double w = buffer[outputDimension];
382:                    for (int j = 0; j < outputDimension; j++) {
383:                        // 'w' is equals to 1 if the transform is affine.
384:                        dstPts[dstOff++] = buffer[j] / w;
385:                    }
386:                    srcOff += inputDimension;
387:                }
388:            }
389:
390:            /**
391:             * Gets the derivative of this transform at a point.
392:             * For a matrix transform, the derivative is the
393:             * same everywhere.
394:             */
395:            public Matrix derivative(final Point2D point) {
396:                return derivative((DirectPosition) null);
397:            }
398:
399:            /**
400:             * Gets the derivative of this transform at a point.
401:             * For a matrix transform, the derivative is the
402:             * same everywhere.
403:             */
404:            public Matrix derivative(final DirectPosition point) {
405:                final GeneralMatrix matrix = getGeneralMatrix();
406:                matrix.setSize(numRow - 1, numCol - 1);
407:                return matrix;
408:            }
409:
410:            /**
411:             * Returns a copy of the matrix.
412:             */
413:            public Matrix getMatrix() {
414:                return getGeneralMatrix();
415:            }
416:
417:            /**
418:             * Returns a copy of the matrix.
419:             */
420:            private GeneralMatrix getGeneralMatrix() {
421:                return new GeneralMatrix(numRow, numCol, elt);
422:            }
423:
424:            /**
425:             * Gets the dimension of input points.
426:             */
427:            public int getSourceDimensions() {
428:                return numCol - 1;
429:            }
430:
431:            /**
432:             * Gets the dimension of output points.
433:             */
434:            public int getTargetDimensions() {
435:                return numRow - 1;
436:            }
437:
438:            /**
439:             * Tests whether this transform does not move any points.
440:             */
441:            public boolean isIdentity() {
442:                if (numRow != numCol) {
443:                    return false;
444:                }
445:                int index = 0;
446:                for (int j = 0; j < numRow; j++) {
447:                    for (int i = 0; i < numCol; i++) {
448:                        if (elt[index++] != (i == j ? 1 : 0)) {
449:                            return false;
450:                        }
451:                    }
452:                }
453:                assert isIdentity(0);
454:                return true;
455:            }
456:
457:            /**
458:             * Tests whether this transform does not move any points by using the provided tolerance.
459:             * This method work in the same way than
460:             * {@link org.geotools.referencing.operation.matrix.XMatrix#isIdentity(double)}.
461:             *
462:             * @since 2.4
463:             */
464:            public boolean isIdentity(double tolerance) {
465:                tolerance = Math.abs(tolerance);
466:                if (numRow != numCol) {
467:                    return false;
468:                }
469:                int index = 0;
470:                for (int j = 0; j < numRow; j++) {
471:                    for (int i = 0; i < numCol; i++) {
472:                        double e = elt[index++];
473:                        if (i == j) {
474:                            e--;
475:                        }
476:                        // Uses '!' in order to catch NaN values.
477:                        if (!(Math.abs(e) <= tolerance)) {
478:                            return false;
479:                        }
480:                    }
481:                }
482:                return true;
483:            }
484:
485:            /**
486:             * Creates the inverse transform of this object.
487:             */
488:            public MathTransform inverse()
489:                    throws NoninvertibleTransformException {
490:                // No need to synchronize. This is not a big deal if the same object is created twice.
491:                if (inverse == null) {
492:                    if (isIdentity()) {
493:                        inverse = this ;
494:                    } else {
495:                        final XMatrix matrix = getGeneralMatrix();
496:                        try {
497:                            matrix.invert();
498:                        } catch (SingularMatrixException exception) {
499:                            throw new NoninvertibleTransformException(Errors
500:                                    .format(ErrorKeys.NONINVERTIBLE_TRANSFORM),
501:                                    exception);
502:                        }
503:                        inverse = new ProjectiveTransform(matrix);
504:                        inverse.inverse = this ;
505:                    }
506:                }
507:                return inverse;
508:            }
509:
510:            /**
511:             * Creates an inverse transform using the specified matrix.
512:             * To be overridden by {@link GeocentricAffineTransform}.
513:             */
514:            MathTransform createInverse(final Matrix matrix) {
515:                return new ProjectiveTransform(matrix);
516:            }
517:
518:            /**
519:             * Returns a hash value for this transform.
520:             * This value need not remain consistent between
521:             * different implementations of the same class.
522:             */
523:            public int hashCode() {
524:                long code = serialVersionUID;
525:                for (int i = elt.length; --i >= 0;) {
526:                    code = code * 37 + Double.doubleToLongBits(elt[i]);
527:                }
528:                return (int) (code >>> 32) ^ (int) code;
529:            }
530:
531:            /**
532:             * Compares the specified object with
533:             * this math transform for equality.
534:             */
535:            public boolean equals(final Object object) {
536:                if (object == this ) {
537:                    // Slight optimization
538:                    return true;
539:                }
540:                if (super .equals(object)) {
541:                    final ProjectiveTransform that = (ProjectiveTransform) object;
542:                    return this .numRow == that.numRow
543:                            && this .numCol == that.numCol
544:                            && Arrays.equals(this .elt, that.elt);
545:                }
546:                return false;
547:            }
548:
549:            /**
550:             * The provider for the "<cite>Affine general parametric transformation</cite>" (EPSG 9624).
551:             * The OGC's name is {@code "Affine"}. The default matrix size is
552:             * {@value org.geotools.parameter.MatrixParameterDescriptors#DEFAULT_MATRIX_SIZE}&times;{@value
553:             * org.geotools.parameter.MatrixParameterDescriptors#DEFAULT_MATRIX_SIZE}.
554:             * <p>
555:             * Note that affine transform is a special case of projective transform.
556:             *
557:             * @version $Id: ProjectiveTransform.java 24925 2007-03-27 20:12:08Z jgarnett $
558:             * @author Martin Desruisseaux
559:             */
560:            public static final class ProviderAffine extends
561:                    MathTransformProvider {
562:                /**
563:                 * Serial number for interoperability with different versions.
564:                 */
565:                private static final long serialVersionUID = 649555815622129472L;
566:
567:                /**
568:                 * The set of predefined providers.
569:                 */
570:                private static final ProviderAffine[] methods = new ProviderAffine[8];
571:
572:                /**
573:                 * The parameters group.
574:                 *
575:                 * @todo We should register EPSG parameter identifiers (A0, A1, A2, B0, B1, B2) as well.
576:                 */
577:                static final ParameterDescriptorGroup PARAMETERS;
578:                static {
579:                    final NamedIdentifier name = new NamedIdentifier(
580:                            Citations.OGC, "Affine");
581:                    final Map properties = new HashMap(4, 0.8f);
582:                    properties.put(NAME_KEY, name);
583:                    properties.put(IDENTIFIERS_KEY, name);
584:                    properties
585:                            .put(
586:                                    ALIAS_KEY,
587:                                    new NamedIdentifier[] {
588:                                            name,
589:                                            new NamedIdentifier(Citations.EPSG,
590:                                                    "Affine general parametric transformation"),
591:                                            new NamedIdentifier(Citations.EPSG,
592:                                                    "9624"),
593:                                            new NamedIdentifier(
594:                                                    Citations.GEOTOOLS,
595:                                                    Vocabulary
596:                                                            .formatInternational(VocabularyKeys.AFFINE_TRANSFORM)) });
597:                    PARAMETERS = new MatrixParameterDescriptors(properties);
598:                }
599:
600:                /**
601:                 * Creates a provider for affine transform with a default matrix size.
602:                 */
603:                public ProviderAffine() {
604:                    this (MatrixParameterDescriptors.DEFAULT_MATRIX_SIZE - 1,
605:                            MatrixParameterDescriptors.DEFAULT_MATRIX_SIZE - 1);
606:                    methods[MatrixParameterDescriptors.DEFAULT_MATRIX_SIZE - 2] = this ;
607:                }
608:
609:                /**
610:                 * Creates a provider for affine transform with the specified dimensions.
611:                 */
612:                private ProviderAffine(final int sourceDimensions,
613:                        final int targetDimensions) {
614:                    super (sourceDimensions, targetDimensions, PARAMETERS);
615:                }
616:
617:                /**
618:                 * Returns the operation type.
619:                 */
620:                public Class getOperationType() {
621:                    return Conversion.class;
622:                }
623:
624:                /**
625:                 * Creates a projective transform from the specified group of parameter values.
626:                 *
627:                 * @param  values The group of parameter values.
628:                 * @return The created math transform.
629:                 * @throws ParameterNotFoundException if a required parameter was not found.
630:                 */
631:                protected MathTransform createMathTransform(
632:                        final ParameterValueGroup values)
633:                        throws ParameterNotFoundException {
634:                    final MathTransform transform;
635:                    transform = create(((MatrixParameterDescriptors) getParameters())
636:                            .getMatrix(values));
637:                    return new Delegate(transform, getProvider(transform
638:                            .getSourceDimensions(), transform
639:                            .getTargetDimensions()));
640:                }
641:
642:                /**
643:                 * Returns the operation method for the specified source and target dimensions.
644:                 * This method provides different methods for different matrix sizes.
645:                 */
646:                public static ProviderAffine getProvider(
647:                        final int sourceDimensions, final int targetDimensions) {
648:                    if (sourceDimensions == targetDimensions) {
649:                        final int i = sourceDimensions - 1;
650:                        if (i >= 0 && i < methods.length) {
651:                            ProviderAffine method = methods[i];
652:                            if (method == null) {
653:                                methods[i] = method = new ProviderAffine(
654:                                        sourceDimensions, targetDimensions);
655:                            }
656:                            return method;
657:                        }
658:                    }
659:                    return new ProviderAffine(sourceDimensions,
660:                            targetDimensions);
661:                }
662:            }
663:
664:            /**
665:             * The provider for the "<cite>Longitude rotation</cite>" (EPSG 9601).
666:             *
667:             * @version $Id: ProjectiveTransform.java 24925 2007-03-27 20:12:08Z jgarnett $
668:             * @author Martin Desruisseaux
669:             */
670:            public static final class ProviderLongitudeRotation extends
671:                    MathTransformProvider {
672:                /**
673:                 * Serial number for interoperability with different versions.
674:                 */
675:                private static final long serialVersionUID = -2104496465933824935L;
676:
677:                /**
678:                 * The longitude offset.
679:                 */
680:                public static final ParameterDescriptor OFFSET = createDescriptor(
681:                        new NamedIdentifier[] { new NamedIdentifier(
682:                                Citations.EPSG, "Longitude offset") },
683:                        Double.NaN, -180, +180, NonSI.DEGREE_ANGLE);
684:
685:                /**
686:                 * The parameters group.
687:                 */
688:                static final ParameterDescriptorGroup PARAMETERS = createDescriptorGroup(
689:                        new NamedIdentifier[] {
690:                                new NamedIdentifier(Citations.EPSG,
691:                                        "Longitude rotation"),
692:                                new NamedIdentifier(Citations.EPSG, "9601") },
693:                        new ParameterDescriptor[] { OFFSET });
694:
695:                /**
696:                 * Constructs a provider with default parameters.
697:                 */
698:                public ProviderLongitudeRotation() {
699:                    super (2, 2, PARAMETERS);
700:                }
701:
702:                /**
703:                 * Returns the operation type.
704:                 */
705:                public Class getOperationType() {
706:                    return Conversion.class;
707:                }
708:
709:                /**
710:                 * Creates a transform from the specified group of parameter values.
711:                 *
712:                 * @param  values The group of parameter values.
713:                 * @return The created math transform.
714:                 * @throws ParameterNotFoundException if a required parameter was not found.
715:                 */
716:                protected MathTransform createMathTransform(
717:                        final ParameterValueGroup values)
718:                        throws ParameterNotFoundException {
719:                    final double offset = doubleValue(OFFSET, values);
720:                    return create(AffineTransform.getTranslateInstance(offset,
721:                            0));
722:                }
723:            }
724:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.