Source Code Cross Referenced for AffineTransformation.java in  » GIS » openjump » com » vividsolutions » jump » geom » 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 » openjump » com.vividsolutions.jump.geom 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.vividsolutions.jump.geom;
002:
003:        import com.vividsolutions.jts.geom.*;
004:        import com.vividsolutions.jump.I18N;
005:
006:        /**
007:         * This class represents a affine transformation on the 2D Cartesian plane. 
008:         * It can be used to transform a {@link Coordinate} or {@link Geometry}.
009:         * An affine transformation is a mapping of the 2D plane into itself
010:         * via a series of transformations of the following basic types:
011:         * <ul>
012:         * <li>reflection
013:         * <li>rotation
014:         * <li>scaling
015:         * <li>shearing
016:         * <li>translation
017:         * </ul>
018:         * In general, affine transformations preserve straightness and parallel lines,
019:         * but do not preserve distance or shape.
020:         * <p>
021:         * An affine transformation can be represented by a 3x3 
022:         * matrix in the following form:
023:         * <blockquote><pre>
024:         * T = | m00 m01 m02 |
025:         *     | m10 m11 m12 |
026:         *     |  0   0   1  |
027:         * </pre></blockquote>
028:         * A coordinate P = (x, y) can be transformed to a new coordinate P' = (x', y')
029:         * by representing it as a 3x1 matrix and using matrix multiplication to compute:
030:         * <blockquote><pre>
031:         * | x' |  = T x | x |
032:         * | y' |        | y |
033:         * | 1  |        | 1 |
034:         * </pre></blockquote>
035:         * Affine transformations can be composed using the {@link #compose} method.
036:         * Composition is not commutative.
037:         * Composition is computed via multiplication of the 
038:         * transformation matrices as follows:
039:         * <blockquote><pre>
040:         * A.compose(B) = T<sub>B</sub> x T<sub>A</sub>
041:         * </pre></blockquote>
042:         * This produces a transformation whose effect is that of A followed by B.
043:         * The methods {@link #reflect}, {@link #rotate}, {@link #scale}, {@link #shear}, and {@link #translate} 
044:         * have the effect of composing a transformation of that type with
045:         * the transformation they are applied to.  
046:         * 
047:         * @author Martin Davis
048:         *
049:         */
050:        public class AffineTransformation implements  Cloneable,
051:                CoordinateFilter {
052:
053:            /**
054:             * Creates a transformation for a reflection about the 
055:             * line (x0,y0) - (x1,y1).
056:             * 
057:             * @param x0 the x-ordinate of a point on the reflection line
058:             * @param y0 the y-ordinate of a point on the reflection line
059:             * @param x1 the x-ordinate of a another point on the reflection line
060:             * @param y1 the y-ordinate of a another point on the reflection line
061:             * @return a transformation for the reflection
062:             */
063:            public static AffineTransformation reflectionInstance(double x0,
064:                    double y0, double x1, double y1) {
065:                AffineTransformation trans = new AffineTransformation();
066:                trans.setToReflection(x0, y0, x1, y1);
067:                return trans;
068:            }
069:
070:            /**
071:             * Creates a transformation for a reflection about the 
072:             * line (0,0) - (x,y).
073:             * 
074:             * @param x the x-ordinate of a point on the reflection line
075:             * @param y the y-ordinate of a point on the reflection line
076:             * @return a transformation for the reflection
077:             */
078:            public static AffineTransformation reflectionInstance(double x,
079:                    double y) {
080:                AffineTransformation trans = new AffineTransformation();
081:                trans.setToReflection(x, y);
082:                return trans;
083:            }
084:
085:            /**
086:             * Creates a transformation for a rotation
087:             * about the origin 
088:             * by an angle <i>theta</i>.
089:             * Positive angles correspond to a rotation 
090:             * in the counter-clockwise direction.
091:             * 
092:             * @param theta the rotation angle, in radians
093:             * @return a transformation for the rotation
094:             */
095:            public static AffineTransformation rotationInstance(double theta) {
096:                return rotationInstance(Math.sin(theta), Math.cos(theta));
097:            }
098:
099:            /**
100:             * Creates a transformation for a rotation 
101:             * by an angle <i>theta</i>,
102:             * specified by the sine and cosine of the angle.
103:             * This allows providing exact values for sin(theta) and cos(theta)
104:             * for the common case of rotations of multiples of quarter-circles. 
105:             * 
106:             * @param sinTheta the sine of the rotation angle
107:             * @param cosTheta the cosine of the rotation angle
108:             * @return a transformation for the rotation
109:             */
110:            public static AffineTransformation rotationInstance(
111:                    double sinTheta, double cosTheta) {
112:                AffineTransformation trans = new AffineTransformation();
113:                trans.setToRotation(sinTheta, cosTheta);
114:                return trans;
115:            }
116:
117:            public static AffineTransformation scaleInstance(double xScale,
118:                    double yScale) {
119:                AffineTransformation trans = new AffineTransformation();
120:                trans.setToScale(xScale, yScale);
121:                return trans;
122:            }
123:
124:            public static AffineTransformation shearInstance(double xShear,
125:                    double yShear) {
126:                AffineTransformation trans = new AffineTransformation();
127:                trans.setToShear(xShear, yShear);
128:                return trans;
129:            }
130:
131:            public static AffineTransformation translationInstance(double x,
132:                    double y) {
133:                AffineTransformation trans = new AffineTransformation();
134:                trans.setToTranslation(x, y);
135:                return trans;
136:            }
137:
138:            // affine matrix entries
139:            // (bottom row is always [ 0 0 1 ])
140:            private double m00;
141:            private double m01;
142:            private double m02;
143:            private double m10;
144:            private double m11;
145:            private double m12;
146:
147:            /**
148:             * Constructs a new identity transformation
149:             *
150:             */
151:            public AffineTransformation() {
152:                setToIdentity();
153:            }
154:
155:            /**
156:             * Constructs a new transformation whose 
157:             * matrix has the specified values.
158:             * 
159:             * @param matrix an array containing the 6 values { m00, m01, m02, m10, m11, m12 }
160:             * @throws NullPointerException if matrix is null
161:             * @throws ArrayIndexOutOfBoundsException if matrix is too small 
162:             */
163:            public AffineTransformation(double[] matrix) {
164:                m00 = matrix[0];
165:                m01 = matrix[1];
166:                m02 = matrix[2];
167:                m10 = matrix[3];
168:                m11 = matrix[4];
169:                m12 = matrix[5];
170:            }
171:
172:            /**
173:             * Constructs a new transformation whose 
174:             * matrix has the specified values.
175:             * 
176:             * @param m00 the entry for the [0, 0] element in the transformation matrix 
177:             * @param m01 the entry for the [0, 1] element in the transformation matrix
178:             * @param m02 the entry for the [0, 2] element in the transformation matrix
179:             * @param m10 the entry for the [1, 0] element in the transformation matrix
180:             * @param m11 the entry for the [1, 1] element in the transformation matrix
181:             * @param m12 the entry for the [1, 2] element in the transformation matrix
182:             */
183:            public AffineTransformation(double m00, double m01, double m02,
184:                    double m10, double m11, double m12) {
185:                setTransformation(m00, m01, m02, m10, m11, m12);
186:            }
187:
188:            /**
189:             * Constructs a transformation which is
190:             * a copy of the given one.
191:             * 
192:             * @param trans the transformation to copy
193:             */
194:            public AffineTransformation(AffineTransformation trans) {
195:                setTransformation(trans);
196:            }
197:
198:            /**
199:             * Constructs a transformation
200:             * which maps the given source
201:             * points into the given destination points.
202:             * 
203:             * @param src0 source point 0
204:             * @param src1 source point 1
205:             * @param src2 source point 2
206:             * @param dest0 the mapped point for source point 0
207:             * @param dest1 the mapped point for source point 1
208:             * @param dest2 the mapped point for source point 2
209:             * 
210:             */
211:            public AffineTransformation(Coordinate src0, Coordinate src1,
212:                    Coordinate src2, Coordinate dest0, Coordinate dest1,
213:                    Coordinate dest2) {
214:            }
215:
216:            /**
217:             * Sets this transformation to be the identity transformation.
218:             * The identity transformation has the matrix:
219:             * <blockquote><pre>
220:             * | 1 0 0 |
221:             * | 0 1 0 |
222:             * | 0 0 1 |
223:             * </pre></blockquote>
224:             * @return this transformation, with an updated matrix
225:             */
226:            public AffineTransformation setToIdentity() {
227:                m00 = 1.0;
228:                m01 = 0.0;
229:                m02 = 0.0;
230:                m10 = 0.0;
231:                m11 = 1.0;
232:                m12 = 0.0;
233:                return this ;
234:            }
235:
236:            /**
237:             * Sets this transformation's matrix to have the given values.
238:             * 
239:             * @param m00 the entry for the [0, 0] element in the transformation matrix 
240:             * @param m01 the entry for the [0, 1] element in the transformation matrix
241:             * @param m02 the entry for the [0, 2] element in the transformation matrix
242:             * @param m10 the entry for the [1, 0] element in the transformation matrix
243:             * @param m11 the entry for the [1, 1] element in the transformation matrix
244:             * @param m12 the entry for the [1, 2] element in the transformation matrix
245:             * @return this transformation, with an updated matrix
246:             */
247:            public AffineTransformation setTransformation(double m00,
248:                    double m01, double m02, double m10, double m11, double m12) {
249:                this .m00 = m00;
250:                this .m01 = m01;
251:                this .m02 = m02;
252:                this .m10 = m10;
253:                this .m11 = m11;
254:                this .m12 = m12;
255:                return this ;
256:            }
257:
258:            /**
259:             * Sets this transformation to be a copy of the given one
260:             * 
261:             * @param trans a transformation to copy
262:             * @return this transformation, with an updated matrix
263:             */
264:            public AffineTransformation setTransformation(
265:                    AffineTransformation trans) {
266:                m00 = trans.m00;
267:                m01 = trans.m01;
268:                m02 = trans.m02;
269:                m10 = trans.m10;
270:                m11 = trans.m11;
271:                m12 = trans.m12;
272:                return this ;
273:            }
274:
275:            /**
276:             * Gets an array containing the entries
277:             * of the transformation matrix.
278:             * Only the 6 non-trivial entries are returned,
279:             * in the sequence:
280:             * <pre>
281:             * m00, m01, m02, m10, m11, m12
282:             * </pre>
283:             * 
284:             * @return an array of length 6
285:             */
286:            public double[] getMatrixEntries() {
287:                return new double[] { m00, m01, m02, m10, m11, m12 };
288:            }
289:
290:            /**
291:             * Computes the determinant of the transformation matrix. 
292:             * The determinant is computed as:
293:             * <blockquote><pre>
294:             * | m00 m01 m02 |
295:             * | m10 m11 m12 | = m00 * m11 - m01 * m10
296:             * |  0   0   1  |
297:             * </pre></blockquote>
298:             * If the determinant is zero, 
299:             * the transform is singular (not invertible), 
300:             * and operations which attempt to compute
301:             * an inverse will throw a <tt>NoninvertibleTransformException</tt>. 
302:
303:             * @return the determinant of the transformation
304:             * @see #getInverse()
305:             */
306:            public double getDeterminant() {
307:                return m00 * m11 - m01 * m10;
308:            }
309:
310:            /**
311:             * Computes the inverse of this transformation, if one
312:             * exists.
313:             * The inverse is the transformation which when 
314:             * composed with this one produces the identity 
315:             * transformation.
316:             * A transformation has an inverse if and only if it
317:             * is not singular (i.e. its
318:             * determinant is non-zero).
319:             * Geometrically, an transformation is non-invertible
320:             * if it maps the plane to a line or a point.
321:             * If no inverse exists this method
322:             * will throw a <tt>NoninvertibleTransformationException</tt>.
323:             * <p>
324:             * The matrix of the inverse is equal to the 
325:             * inverse of the matrix for the transformation.
326:             * It is computed as follows:
327:             * <blockquote><pre>  
328:             *                 1    
329:             * inverse(A)  =  ---   x  adjoint(A) 
330:             *                det 
331:             *
332:             *
333:             *             =   1       |  m11  -m01   m01*m12-m02*m11  |
334:             *                ---   x  | -m10   m00  -m00*m12+m10*m02  |
335:             *                det      |  0     0     m00*m11-m10*m01  |
336:             *
337:             *
338:             *
339:             *             = |  m11/det  -m01/det   m01*m12-m02*m11/det |
340:             *               | -m10/det   m00/det  -m00*m12+m10*m02/det |
341:             *               |   0           0          1               |
342:             *
343:             * </pre></blockquote>  
344:             *  
345:             * @return a new inverse transformation
346:             * @throws NoninvertibleTransformationException
347:             * @see #getDeterminant()
348:             */
349:            public AffineTransformation getInverse()
350:                    throws NoninvertibleTransformationException {
351:                double det = getDeterminant();
352:                if (det == 0)
353:                    throw new NoninvertibleTransformationException(
354:                            I18N
355:                                    .get("jump.geom.AffineTransformation.Transformation-is-non-invertible"));
356:
357:                double im00 = m11 / det;
358:                double im10 = -m10 / det;
359:                double im01 = -m01 / det;
360:                double im11 = m00 / det;
361:                double im02 = (m01 * m12 - m02 * m11) / det;
362:                double im12 = (-m00 * m12 + m10 * m02) / det;
363:
364:                return new AffineTransformation(im00, im01, im02, im10, im11,
365:                        im12);
366:            }
367:
368:            /**
369:             * Explicitly computes the math for a reflection.  May not work.
370:             * @param x0
371:             * @param y0
372:             * @param x1
373:             * @param y1
374:             * @return this transformation, with an updated matrix 
375:             */
376:            public AffineTransformation setToReflectionBasic(double x0,
377:                    double y0, double x1, double y1) {
378:                if (x0 == x1 && y0 == y1) {
379:                    throw new IllegalArgumentException(
380:                            I18N
381:                                    .get("jump.geom.AffineTransformation.Reflection-line-points-must-be-distinct"));
382:                }
383:                double dx = x1 - x0;
384:                double dy = y1 - y0;
385:                double d = Math.sqrt(dx * dx + dy * dy);
386:                double sin = dy / d;
387:                double cos = dx / d;
388:                double cs2 = 2 * sin * cos;
389:                double c2s2 = cos * cos - sin * sin;
390:                m00 = c2s2;
391:                m01 = cs2;
392:                m02 = 0.0;
393:                m10 = cs2;
394:                m11 = -c2s2;
395:                m12 = 0.0;
396:                return this ;
397:            }
398:
399:            public AffineTransformation setToReflection(double x0, double y0,
400:                    double x1, double y1) {
401:                if (x0 == x1 && y0 == y1) {
402:                    throw new IllegalArgumentException(
403:                            I18N
404:                                    .get("jump.geom.AffineTransformation.Reflection-line-points-must-be-distinct"));
405:                }
406:                // translate line vector to origin
407:                setToTranslation(-x0, -y0);
408:
409:                // rotate vector to positive x axis direction
410:                double dx = x1 - x0;
411:                double dy = y1 - y0;
412:                double d = Math.sqrt(dx * dx + dy * dy);
413:                double sin = dy / d;
414:                double cos = dx / d;
415:                rotate(-sin, cos);
416:                // reflect about the x axis
417:                scale(1, -1);
418:                // rotate back
419:                rotate(sin, cos);
420:                // translate back
421:                translate(x0, y0);
422:                return this ;
423:            }
424:
425:            /**
426:             * Sets this transformation to be a reflection 
427:             * about the line defined by vector (x,y).
428:             * The transformation for a reflection
429:             * is computed by:
430:             * <blockquote><pre>
431:             * d = sqrt(x<sup>2</sup> + y<sup>2</sup>)  
432:             * sin = x / d;
433:             * cos = x / d;
434:             * 
435:             * T<sub>ref</sub> = T<sub>rot(sin, cos)</sub> x T<sub>scale(1, -1)</sub> x T<sub>rot(-sin, cos)</sub  
436:             * </pre></blockquote> 
437:             * 
438:             * @param x the x-component of the reflection line vector
439:             * @param y the y-component of the reflection line vector
440:             * @return this transformation, with an updated matrix
441:             */
442:            public AffineTransformation setToReflection(double x, double y) {
443:                if (x == 0.0 && y == 0.0) {
444:                    throw new IllegalArgumentException(
445:                            I18N
446:                                    .get("jump.geom.AffineTransformation.Reflection-vector-must-be-non-zero"));
447:                }
448:                // rotate vector to positive x axis direction
449:                double d = Math.sqrt(x * x + y * y);
450:                double sin = y / d;
451:                double cos = x / d;
452:                rotate(-sin, cos);
453:                // reflect about the x-axis
454:                scale(1, -1);
455:                // rotate back
456:                rotate(sin, cos);
457:                return this ;
458:            }
459:
460:            /**
461:             * Sets this transformation to be a rotation.
462:             * A positive rotation angle corresponds 
463:             * to a counter-clockwise rotation.
464:             * The transformation matrix for a rotation
465:             * by an angle <tt>theta</tt>
466:             * has the value:
467:             * <blockquote><pre>  
468:             * |  cos(theta)  -sin(theta)   0 |
469:             * |  sin(theta)   cos(theta)   0 |
470:             * |           0            0   1 |
471:             * </pre></blockquote> 
472:             * 
473:             * @param theta the rotation angle, in radians
474:             * @return this transformation, with an updated matrix
475:             */
476:            private AffineTransformation setToRotation(double theta) {
477:                setToRotation(Math.sin(theta), Math.cos(theta));
478:                return this ;
479:            }
480:
481:            /**
482:             * Sets this transformation to be a rotation 
483:             * by specifying the sin and cos of the rotation angle directly.
484:             * The transformation matrix for the rotation
485:             * has the value:
486:             * <blockquote><pre>  
487:             * |  cosTheta  -sinTheta   0 |
488:             * |  sinTheta   cosTheta   0 |
489:             * |         0          0   1 |
490:             * </pre></blockquote> 
491:             * 
492:             * @param sinTheta the sine of the rotation angle
493:             * @param cosTheta the cosine of the rotation angle
494:             * @return this transformation, with an updated matrix
495:             */
496:            public AffineTransformation setToRotation(double sinTheta,
497:                    double cosTheta) {
498:                m00 = cosTheta;
499:                m01 = -sinTheta;
500:                m02 = 0.0;
501:                m10 = sinTheta;
502:                m11 = cosTheta;
503:                m12 = 0.0;
504:                return this ;
505:            }
506:
507:            /**
508:             * Sets this transformation to be a scaling.
509:             * The transformation matrix for a scale
510:             * has the value:
511:             * <blockquote><pre>  
512:             * |  xScale      0  dx |
513:             * |  1      yScale  dy |
514:             * |  0           0   1 |
515:             * </pre></blockquote> 
516:             * 
517:             * @param xScale the amount to scale x-ordinates by
518:             * @param yScale the amount to scale y-ordinates by
519:             * @return this transformation, with an updated matrix
520:             */
521:            public AffineTransformation setToScale(double xScale, double yScale) {
522:                m00 = xScale;
523:                m01 = 0.0;
524:                m02 = 0.0;
525:                m10 = 0.0;
526:                m11 = yScale;
527:                m12 = 0.0;
528:                return this ;
529:            }
530:
531:            /**
532:             * Sets this transformation to be a shear.
533:             * The transformation matrix for a shear 
534:             * has the value:
535:             * <blockquote><pre>  
536:             * |  1      xShear  0 |
537:             * |  yShear      1  0 |
538:             * |  0           0  1 |
539:             * </pre></blockquote> 
540:             * Note that a shear of (1, 1) is <i>not</i> 
541:             * equal to shear(1, 0) composed with shear(0, 1).
542:             * Instead, shear(1, 1) corresponds to a mapping onto the 
543:             * line x = y.
544:             * 
545:             * @param xShear the x component to shear by
546:             * @param yShear the y component to shear by
547:             * @return this transformation, with an updated matrix
548:             */
549:            public AffineTransformation setToShear(double xShear, double yShear) {
550:                m00 = 1.0;
551:                m01 = xShear;
552:                m02 = 0.0;
553:                m10 = yShear;
554:                m11 = 1.0;
555:                m12 = 0.0;
556:                return this ;
557:            }
558:
559:            /**
560:             * Sets this transformation to be a translation.
561:             * For a translation by the vector (x, y)
562:             * the transformation matrix has the value:
563:             * <blockquote><pre>  
564:             * |  1  0  dx |
565:             * |  1  0  dy |
566:             * |  0  0   1 |
567:             * </pre></blockquote> 
568:             * @param dx the x component to translate by
569:             * @param dy the y component to translate by
570:             * @return this transformation, with an updated matrix
571:             */
572:            public AffineTransformation setToTranslation(double dx, double dy) {
573:                m00 = 1.0;
574:                m01 = 0.0;
575:                m02 = dx;
576:                m10 = 0.0;
577:                m11 = 1.0;
578:                m12 = dy;
579:                return this ;
580:            }
581:
582:            /**
583:             * Updates the value of this transformation
584:             * to that of a reflection transformation composed 
585:             * with the current value.
586:             * 
587:             * @param x0 the x-ordinate of a point on the line to reflect around
588:             * @param y0 the y-ordinate of a point on the line to reflect around
589:             * @param x1 the x-ordinate of a point on the line to reflect around
590:             * @param y1 the y-ordinate of a point on the line to reflect around
591:             * @return this transformation, with an updated matrix
592:             */
593:            public AffineTransformation reflect(double x0, double y0,
594:                    double x1, double y1) {
595:                compose(reflectionInstance(x0, y0, x1, y1));
596:                return this ;
597:            }
598:
599:            /**
600:             * Updates the value of this transformation
601:             * to that of a reflection transformation composed 
602:             * with the current value.
603:             * 
604:             * @param x the x-ordinate of the line to reflect around
605:             * @param y the y-ordinate of the line to reflect around
606:             * @return this transformation, with an updated matrix
607:             */
608:            public AffineTransformation reflect(double x, double y) {
609:                compose(reflectionInstance(x, y));
610:                return this ;
611:            }
612:
613:            /**
614:             * Updates the value of this transformation
615:             * to that of a rotation transformation composed 
616:             * with the current value.
617:             * 
618:             * @param theta the angle to rotate by
619:             * @return this transformation, with an updated matrix
620:             */
621:            public AffineTransformation rotate(double theta) {
622:                compose(rotationInstance(theta));
623:                return this ;
624:            }
625:
626:            /**
627:             * Updates the value of this transformation
628:             * to that of a rotation transformation composed 
629:             * with the current value.
630:             * 
631:             * @param sinTheta the sine of the angle to rotate by
632:             * @param cosTheta the cosine of the angle to rotate by
633:             * @return this transformation, with an updated matrix
634:             */
635:            public AffineTransformation rotate(double sinTheta, double cosTheta) {
636:                compose(rotationInstance(sinTheta, cosTheta));
637:                return this ;
638:            }
639:
640:            /**
641:             * Updates the value of this transformation
642:             * to that of a scale transformation composed 
643:             * with the current value.
644:             * 
645:             * @param xScale the value to scale by in the x direction
646:             * @param yScale the value to scale by in the y direction
647:             * @return this transformation, with an updated matrix
648:             */
649:            public AffineTransformation scale(double xScale, double yScale) {
650:                compose(scaleInstance(xScale, yScale));
651:                return this ;
652:            }
653:
654:            /**
655:             * Updates the value of this transformation
656:             * to that of a shear transformation composed 
657:             * with the current value.
658:             * 
659:             * @param xShear the value to shear by in the x direction
660:             * @param yShear the value to shear by in the y direction
661:             * @return this transformation, with an updated matrix
662:             */
663:            public AffineTransformation shear(double xShear, double yShear) {
664:                compose(shearInstance(xShear, yShear));
665:                return this ;
666:            }
667:
668:            /**
669:             * Updates the value of this transformation
670:             * to that of a translation transformation composed 
671:             * with the current value.
672:             * 
673:             * @param x the value to translate by in the x direction
674:             * @param y the value to translate by in the y direction
675:             * @return this transformation, with an updated matrix
676:             */
677:            public AffineTransformation translate(double x, double y) {
678:                compose(translationInstance(x, y));
679:                return this ;
680:            }
681:
682:            /**
683:             * Composes the given {@link AffineTransformation} 
684:             * with this transformation.
685:             * This produces a transformation whose effect 
686:             * is equal to applying this transformation 
687:             * followed by the argument transformation.
688:             * Mathematically,
689:             * <blockquote><pre>
690:             * A.compose(B) = T<sub>B</sub> x T<sub>A</sub>
691:             * </pre></blockquote>
692:             * 
693:             * @param trans an affine transformation
694:             * @return this transformation, with an updated matrix
695:             */
696:            public AffineTransformation compose(AffineTransformation trans) {
697:                double mp00 = trans.m00 * m00 + trans.m01 * m10;
698:                double mp01 = trans.m00 * m01 + trans.m01 * m11;
699:                double mp02 = trans.m00 * m02 + trans.m01 * m12 + trans.m02;
700:                double mp10 = trans.m10 * m00 + trans.m11 * m10;
701:                double mp11 = trans.m10 * m01 + trans.m11 * m11;
702:                double mp12 = trans.m10 * m02 + trans.m11 * m12 + trans.m12;
703:                m00 = mp00;
704:                m01 = mp01;
705:                m02 = mp02;
706:                m10 = mp10;
707:                m11 = mp11;
708:                m12 = mp12;
709:                return this ;
710:            }
711:
712:            /**
713:             * Composes this transformation 
714:             * with the given {@link AffineTransformation}.
715:             * This produces a transformation whose effect 
716:             * is equal to applying the argument transformation 
717:             * followed by this transformation.
718:             * Mathematically,
719:             * <blockquote><pre>
720:             * A.composeBefore(B) = T<sub>A</sub> x T<sub>B</sub>
721:             * </pre></blockquote>
722:             * 
723:             * @param trans an affine transformation
724:             * @return this transformation, with an updated matrix
725:             */
726:            public AffineTransformation composeBefore(AffineTransformation trans) {
727:                double mp00 = m00 * trans.m00 + m01 * trans.m10;
728:                double mp01 = m00 * trans.m01 + m01 * trans.m11;
729:                double mp02 = m00 * trans.m02 + m01 * trans.m12 + m02;
730:                double mp10 = m10 * trans.m00 + m11 * trans.m10;
731:                double mp11 = m10 * trans.m01 + m11 * trans.m11;
732:                double mp12 = m10 * trans.m02 + m11 * trans.m12 + m12;
733:                m00 = mp00;
734:                m01 = mp01;
735:                m02 = mp02;
736:                m10 = mp10;
737:                m11 = mp11;
738:                m12 = mp12;
739:                return this ;
740:            }
741:
742:            public Coordinate transform(Coordinate src, Coordinate dest) {
743:                double xp = m00 * src.x + m01 * src.y + m02;
744:                double yp = m10 * src.x + m11 * src.y + m12;
745:                dest.x = xp;
746:                dest.y = yp;
747:                return dest;
748:            }
749:
750:            public CoordinateSequence transform(CoordinateSequence seq) {
751:                for (int i = 0; i < seq.size(); i++) {
752:                    double xp = m00 * seq.getOrdinate(i, 0) + m01
753:                            * seq.getOrdinate(i, 1) + m02;
754:                    double yp = m10 * seq.getOrdinate(i, 0) + m11
755:                            * seq.getOrdinate(i, 1) + m12;
756:                    seq.setOrdinate(i, 0, xp);
757:                    seq.setOrdinate(i, 1, yp);
758:                }
759:                return seq;
760:            }
761:
762:            public void filter(Coordinate pt) {
763:                double xp = m00 * pt.x + m01 * pt.y + m02;
764:                double yp = m10 * pt.x + m11 * pt.y + m12;
765:                pt.x = xp;
766:                pt.y = yp;
767:            }
768:
769:            /**
770:             * Tests if this transformation is the identity transformation.
771:             *
772:             * @return true if this is the identity transformation
773:             */
774:            public boolean isIdentity() {
775:                return (m00 == 1 && m01 == 0 && m02 == 0 && m10 == 0
776:                        && m11 == 1 && m12 == 0);
777:            }
778:
779:            /**
780:             * Tests if an object is an
781:             * <tt>AffineTransformation</tt>
782:             * and has the same matrix as 
783:             * this transformation.
784:             * 
785:             * @param obj an object to test
786:             * @return true if the given object is equal to this object
787:             */
788:            public boolean equals(Object obj) {
789:                if (obj instanceof  AffineTransformation)
790:                    return false;
791:                AffineTransformation trans = (AffineTransformation) obj;
792:                return m00 == trans.m00 && m01 == trans.m01 && m02 == trans.m02
793:                        && m10 == trans.m10 && m11 == trans.m11
794:                        && m12 == trans.m12;
795:            }
796:
797:            /**
798:             * Gets a text representation of this transformation.
799:             * The string is of the form:
800:             * <pre>
801:             * AffineTransformation[[m00, m01, m02], [m10, m11, m12]]
802:             * </pre>
803:             * 
804:             * @return a string representing this transformation
805:             * 
806:             */
807:            public String toString() {
808:                return "AffineTransformation[[" + m00 + ", " + m01 + ", " + m02
809:                        + "], [" + m10 + ", " + m11 + ", " + m12 + "]]";
810:            }
811:
812:            /**
813:             * Clones this transformation
814:             * 
815:             * @return a copy of this transformation
816:             */
817:            public Object clone() {
818:                return new AffineTransformation(this);
819:            }
820:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.