Source Code Cross Referenced for XAffineTransform.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » operation » matrix » 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.matrix 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2003-2006, Geotools Project Managment Committee (PMC)
005:         *    (C) 2001, Institut de Recherche pour le Développement
006:         *
007:         *    This library is free software; you can redistribute it and/or
008:         *    modify it under the terms of the GNU Lesser General Public
009:         *    License as published by the Free Software Foundation; either
010:         *    version 2.1 of the License, or (at your option) any later version.
011:         *
012:         *    This library is distributed in the hope that it will be useful,
013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         *    Lesser General Public License for more details.
016:         */
017:        package org.geotools.referencing.operation.matrix;
018:
019:        // J2SE dependencies
020:        import java.awt.geom.AffineTransform;
021:        import java.awt.geom.NoninvertibleTransformException;
022:        import java.awt.geom.Point2D;
023:        import java.awt.geom.Rectangle2D;
024:
025:        // Geotools dependencies
026:        import org.geotools.resources.XMath;
027:
028:        /**
029:         * Utility methods for affine transforms. This class provides two kind of services:
030:         *
031:         * <ul>
032:         *   <li><p>A set of public static methods working on any {@link AffineTransform}.</p></li>
033:         *   <li><p>An abstract base class that override all mutable {@link AffineTransform} methods
034:         *       in order to check for permission before changing the transform's state.
035:         *       If {@link #checkPermission} is defined to always throw an exception,
036:         *       then {@code XAffineTransform} is immutable.</p></li>
037:         * </ul>
038:         *
039:         * @since 2.3
040:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/operation/matrix/XAffineTransform.java $
041:         * @version $Id: XAffineTransform.java 26030 2007-06-26 14:55:47Z desruisseaux $
042:         * @author Martin Desruisseaux
043:         * @author Simone Giannecchini
044:         */
045:        public abstract class XAffineTransform extends AffineTransform {
046:            /**
047:             * Serial number for interoperability with different versions.
048:             */
049:            private static final long serialVersionUID = 5215291166450556451L;
050:
051:            /**
052:             * Tolerance value for floating point comparisons.
053:             *
054:             * @deprecated To be removed after we removed the deprecated {@link #round(AffineTransform)}
055:             *             method (replaced by {@link #round(AffineTransform,double)}).
056:             */
057:            public static final double EPS = 1E-6;
058:
059:            /**
060:             * Constructs a new {@code XAffineTransform} that is a
061:             * copy of the specified {@code AffineTransform} object.
062:             */
063:            protected XAffineTransform(final AffineTransform tr) {
064:                super (tr);
065:            }
066:
067:            /**
068:             * Check if the caller is allowed to change this {@code XAffineTransform} state.
069:             * If this method is defined to thrown an exception in all case, then this
070:             * {@code XAffineTransform} is immutable.
071:             */
072:            protected abstract void checkPermission();
073:
074:            /**
075:             * Check for {@linkplain #checkPermission permission} before translating this transform.
076:             */
077:            public void translate(double tx, double ty) {
078:                checkPermission();
079:                super .translate(tx, ty);
080:            }
081:
082:            /**
083:             * Check for {@linkplain #checkPermission permission} before rotating this transform.
084:             */
085:            public void rotate(double theta) {
086:                checkPermission();
087:                super .rotate(theta);
088:            }
089:
090:            /**
091:             * Check for {@linkplain #checkPermission permission} before rotating this transform.
092:             */
093:            public void rotate(double theta, double x, double y) {
094:                checkPermission();
095:                super .rotate(theta, x, y);
096:            }
097:
098:            /**
099:             * Check for {@linkplain #checkPermission permission} before scaling this transform.
100:             */
101:            public void scale(double sx, double sy) {
102:                checkPermission();
103:                super .scale(sx, sy);
104:            }
105:
106:            /**
107:             * Check for {@linkplain #checkPermission permission} before shearing this transform.
108:             */
109:            public void shear(double shx, double shy) {
110:                checkPermission();
111:                super .shear(shx, shy);
112:            }
113:
114:            /**
115:             * Check for {@linkplain #checkPermission permission} before setting this transform.
116:             */
117:            public void setToIdentity() {
118:                checkPermission();
119:                super .setToIdentity();
120:            }
121:
122:            /**
123:             * Check for {@linkplain #checkPermission permission} before setting this transform.
124:             */
125:            public void setToTranslation(double tx, double ty) {
126:                checkPermission();
127:                super .setToTranslation(tx, ty);
128:            }
129:
130:            /**
131:             * Check for {@linkplain #checkPermission permission} before setting this transform.
132:             */
133:            public void setToRotation(double theta) {
134:                checkPermission();
135:                super .setToRotation(theta);
136:            }
137:
138:            /**
139:             * Check for {@linkplain #checkPermission permission} before setting this transform.
140:             */
141:            public void setToRotation(double theta, double x, double y) {
142:                checkPermission();
143:                super .setToRotation(theta, x, y);
144:            }
145:
146:            /**
147:             * Check for {@linkplain #checkPermission permission} before setting this transform.
148:             */
149:            public void setToScale(double sx, double sy) {
150:                checkPermission();
151:                super .setToScale(sx, sy);
152:            }
153:
154:            /**
155:             * Check for {@linkplain #checkPermission permission} before setting this transform.
156:             */
157:            public void setToShear(double shx, double shy) {
158:                checkPermission();
159:                super .setToShear(shx, shy);
160:            }
161:
162:            /**
163:             * Check for {@linkplain #checkPermission permission} before setting this transform.
164:             */
165:            public void setTransform(AffineTransform Tx) {
166:                checkPermission();
167:                super .setTransform(Tx);
168:            }
169:
170:            /**
171:             * Check for {@linkplain #checkPermission permission} before setting this transform.
172:             */
173:            public void setTransform(double m00, double m10, double m01,
174:                    double m11, double m02, double m12) {
175:                checkPermission();
176:                super .setTransform(m00, m10, m01, m11, m02, m12);
177:            }
178:
179:            /**
180:             * Check for {@linkplain #checkPermission permission} before concatenating this transform.
181:             */
182:            public void concatenate(AffineTransform Tx) {
183:                checkPermission();
184:                super .concatenate(Tx);
185:            }
186:
187:            /**
188:             * Check for {@linkplain #checkPermission permission} before concatenating this transform.
189:             */
190:            public void preConcatenate(AffineTransform Tx) {
191:                checkPermission();
192:                super .preConcatenate(Tx);
193:            }
194:
195:            /**
196:             * Check whether or not this {@code XAffineTransform} is the identity by
197:             * using the provided {@code tolerance}.
198:             * 
199:             * @param tolerance The tolerance to use for this check.
200:             * @return {@code true} if the transform is identity, {@code false} otherwise.
201:             *
202:             * @since 2.3.1
203:             */
204:            public boolean isIdentity(double tolerance) {
205:                return isIdentity(this , tolerance);
206:            }
207:
208:            /**
209:             * Returns {@code true} if the specified affine transform is an identity transform up to the
210:             * specified tolerance. This method is equivalent to computing the difference between this
211:             * matrix and an identity matrix (as created by {@link AffineTransform#AffineTransform()
212:             * new AffineTransform()}) and returning {@code true} if and only if all differences are
213:             * smaller than or equal to {@code tolerance}.
214:             * <p>
215:             * This method is used for working around rounding error in affine transforms resulting
216:             * from a computation, as in the example below:
217:             *
218:             * <blockquote><pre>
219:             * [ 1.0000000000000000001  0.0                      0.0 ]
220:             * [ 0.0                    0.999999999999999999999  0.0 ]
221:             * [ 0.0                    0.0                      1.0 ]
222:             * </pre></blockquote>
223:             *   
224:             * @param tr The affine transform to be checked for identity.
225:             * @param tolerance The tolerance value to use when checking for identity.
226:             * return {@code true} if this tranformation is close enough to the
227:             *        identity, {@code false} otherwise.
228:             *
229:             * @since 2.3.1
230:             */
231:            public static boolean isIdentity(final AffineTransform tr,
232:                    double tolerance) {
233:                if (tr.isIdentity()) {
234:                    return true;
235:                }
236:                tolerance = Math.abs(tolerance);
237:                return Math.abs(tr.getScaleX() - 1) <= tolerance
238:                        && Math.abs(tr.getScaleY() - 1) <= tolerance
239:                        && Math.abs(tr.getShearX()) <= tolerance
240:                        && Math.abs(tr.getShearY()) <= tolerance
241:                        && Math.abs(tr.getTranslateX()) <= tolerance
242:                        && Math.abs(tr.getTranslateY()) <= tolerance;
243:            }
244:
245:            /**
246:             * Returns a rectangle which entirely contains the direct
247:             * transform of {@code bounds}. This operation is equivalent to:
248:             *
249:             * <blockquote><code>
250:             * {@linkplain #createTransformedShape createTransformedShape}(bounds).{@linkplain
251:             * Rectangle2D#getBounds2D() getBounds2D()}
252:             * </code></blockquote>
253:             *
254:             * @param transform Affine transform to use.
255:             * @param bounds    Rectangle to transform. This rectangle will not be modified.
256:             * @param dest      Rectangle in which to place the result.  If null, a new
257:             *                  rectangle will be created.
258:             *
259:             * @return The direct transform of the {@code bounds} rectangle.
260:             */
261:            public static Rectangle2D transform(
262:                    final AffineTransform transform, final Rectangle2D bounds,
263:                    final Rectangle2D dest) {
264:                double xmin = Double.POSITIVE_INFINITY;
265:                double ymin = Double.POSITIVE_INFINITY;
266:                double xmax = Double.NEGATIVE_INFINITY;
267:                double ymax = Double.NEGATIVE_INFINITY;
268:                final Point2D.Double point = new Point2D.Double();
269:                for (int i = 0; i < 4; i++) {
270:                    point.x = (i & 1) == 0 ? bounds.getMinX() : bounds
271:                            .getMaxX();
272:                    point.y = (i & 2) == 0 ? bounds.getMinY() : bounds
273:                            .getMaxY();
274:                    transform.transform(point, point);
275:                    if (point.x < xmin)
276:                        xmin = point.x;
277:                    if (point.x > xmax)
278:                        xmax = point.x;
279:                    if (point.y < ymin)
280:                        ymin = point.y;
281:                    if (point.y > ymax)
282:                        ymax = point.y;
283:                }
284:                if (dest != null) {
285:                    dest.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
286:                    return dest;
287:                }
288:                return new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax
289:                        - ymin);
290:            }
291:
292:            /**
293:             * Returns a rectangle which entirely contains the inverse
294:             * transform of {@code bounds}. This operation is equivalent to:
295:             *
296:             * <blockquote><code>
297:             * {@linkplain #createInverse() createInverse()}.{@linkplain
298:             * #createTransformedShape createTransformedShape}(bounds).{@linkplain
299:             * Rectangle2D#getBounds2D() getBounds2D()}
300:             * </code></blockquote>
301:             *
302:             * @param transform Affine transform to use.
303:             * @param bounds    Rectangle to transform. This rectangle will not be modified.
304:             * @param dest      Rectangle in which to place the result.  If null, a new
305:             *                  rectangle will be created.
306:             *
307:             * @return The inverse transform of the {@code bounds} rectangle.
308:             * @throws NoninvertibleTransformException if the affine transform can't be inverted.
309:             */
310:            public static Rectangle2D inverseTransform(
311:                    final AffineTransform transform, final Rectangle2D bounds,
312:                    final Rectangle2D dest)
313:                    throws NoninvertibleTransformException {
314:                double xmin = Double.POSITIVE_INFINITY;
315:                double ymin = Double.POSITIVE_INFINITY;
316:                double xmax = Double.NEGATIVE_INFINITY;
317:                double ymax = Double.NEGATIVE_INFINITY;
318:                final Point2D.Double point = new Point2D.Double();
319:                for (int i = 0; i < 4; i++) {
320:                    point.x = (i & 1) == 0 ? bounds.getMinX() : bounds
321:                            .getMaxX();
322:                    point.y = (i & 2) == 0 ? bounds.getMinY() : bounds
323:                            .getMaxY();
324:                    transform.inverseTransform(point, point);
325:                    if (point.x < xmin)
326:                        xmin = point.x;
327:                    if (point.x > xmax)
328:                        xmax = point.x;
329:                    if (point.y < ymin)
330:                        ymin = point.y;
331:                    if (point.y > ymax)
332:                        ymax = point.y;
333:                }
334:                if (dest != null) {
335:                    dest.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
336:                    return dest;
337:                }
338:                return new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax
339:                        - ymin);
340:            }
341:
342:            /**
343:             * Calculates the inverse affine transform of a point without without
344:             * applying the translation components.
345:             *
346:             * @param transform Affine transform to use.
347:             * @param source    Point to transform. This rectangle will not be modified.
348:             * @param dest      Point in which to place the result.  If {@code null}, a
349:             *                  new point will be created.
350:             *
351:             * @return The inverse transform of the {@code source} point.
352:             * @throws NoninvertibleTransformException if the affine transform can't be inverted.
353:             */
354:            public static Point2D inverseDeltaTransform(
355:                    final AffineTransform transform, final Point2D source,
356:                    final Point2D dest) throws NoninvertibleTransformException {
357:                final double m00 = transform.getScaleX();
358:                final double m11 = transform.getScaleY();
359:                final double m01 = transform.getShearX();
360:                final double m10 = transform.getShearY();
361:                final double det = m00 * m11 - m01 * m10;
362:                if (!(Math.abs(det) > Double.MIN_VALUE)) {
363:                    return transform.createInverse().deltaTransform(source,
364:                            dest);
365:                }
366:                final double x0 = source.getX();
367:                final double y0 = source.getY();
368:                final double x = (x0 * m11 - y0 * m01) / det;
369:                final double y = (y0 * m00 - x0 * m10) / det;
370:                if (dest != null) {
371:                    dest.setLocation(x, y);
372:                    return dest;
373:                }
374:                return new Point2D.Double(x, y);
375:            }
376:
377:            /**
378:             * Returns an estimation about whatever the specified transform swaps <var>x</var>
379:             * and <var>y</var> axis. This method assumes that the specified affine transform
380:             * is built from arbitrary translations, scales or rotations, but no shear. It
381:             * returns {@code +1} if the (<var>x</var>, <var>y</var>) axis order seems to be
382:             * preserved, {@code -1} if the transform seems to swap axis to the (<var>y</var>,
383:             * <var>x</var>) axis order, or {@code 0} if this method can not make a decision.
384:             */
385:            public static int getSwapXY(final AffineTransform tr) {
386:                final int flip = getFlip(tr);
387:                if (flip != 0) {
388:                    final double scaleX = getScaleX0(tr);
389:                    final double scaleY = getScaleY0(tr) * flip;
390:                    final double y = Math.abs(tr.getShearY() / scaleY
391:                            - tr.getShearX() / scaleX);
392:                    final double x = Math.abs(tr.getScaleY() / scaleY
393:                            + tr.getScaleX() / scaleX);
394:                    if (x > y)
395:                        return +1;
396:                    if (x < y)
397:                        return -1;
398:                    // At this point, we may have (x == y) or some NaN value.
399:                }
400:                return 0;
401:            }
402:
403:            /**
404:             * Returns an estimation of the rotation angle in radians. This method assumes that the
405:             * specified affine transform is built from arbitrary translations, scales or rotations,
406:             * but no shear. If a flip has been applied, then this method assumes that the flipped
407:             * axis is the <var>y</var> one in <cite>source CRS</cite> space. For a <cite>grid to
408:             * world CRS</cite> transform, this is the row number in grid coordinates.
409:             *
410:             * @param  tr The affine transform to inspect.
411:             * @return An estimation of the rotation angle in radians, or {@link Double#NaN NaN}
412:             *         if the angle can not be estimated.
413:             */
414:            public static double getRotation(final AffineTransform tr) {
415:                final int flip = getFlip(tr);
416:                if (flip != 0) {
417:                    final double scaleX = getScaleX0(tr);
418:                    final double scaleY = getScaleY0(tr) * flip;
419:                    return Math.atan2(tr.getShearY() / scaleY - tr.getShearX()
420:                            / scaleX, tr.getScaleY() / scaleY + tr.getScaleX()
421:                            / scaleX);
422:                }
423:                return Double.NaN;
424:            }
425:
426:            /**
427:             * Returns {@code -1} if one axis has been flipped, {@code +1} if no axis has been flipped,
428:             * or 0 if unknown. A flipped axis in an axis with direction reversed (typically the
429:             * <var>y</var> axis). This method assumes that the specified affine transform is built
430:             * from arbitrary translations, scales or rotations, but no shear. Note that it is not
431:             * possible to determine which of the <var>x</var> or <var>y</var> axis has been flipped.
432:             * <p>
433:             * This method can be used in order to set the sign of a scale according the flipping state.
434:             * The example below choose to apply the sign on the <var>y</var> scale, but this is an
435:             * arbitrary (while common) choice:
436:             *
437:             * <blockquote><code>
438:             * double scaleX0 = getScaleX0(transform);
439:             * double scaleY0 = getScaleY0(transform);
440:             * int    flip    = getFlip(transform);
441:             * if (flip != 0) {
442:             *     scaleY0 *= flip;
443:             *     // ... continue the process here.
444:             * }
445:             * </code></blockquote>
446:             *
447:             * This method is similar to the following code, except that this method
448:             * distinguish between "unflipped" and "unknow" states.
449:             *
450:             * <blockquote><code>
451:             * boolean flipped = (tr.{@linkplain #getType() getType()} & {@linkplain #TYPE_FLIP}) != 0;
452:             * </code></blockquote>
453:             */
454:            public static int getFlip(final AffineTransform tr) {
455:                final int scaleX = XMath.sgn(tr.getScaleX());
456:                final int scaleY = XMath.sgn(tr.getScaleY());
457:                final int shearX = XMath.sgn(tr.getShearX());
458:                final int shearY = XMath.sgn(tr.getShearY());
459:                if (scaleX == scaleY && shearX == -shearY)
460:                    return +1;
461:                if (scaleX == -scaleY && shearX == shearY)
462:                    return -1;
463:                return 0;
464:            }
465:
466:            /**
467:             * Returns the magnitude of scale factor <var>x</var> by cancelling the
468:             * effect of eventual flip and rotation. This factor is calculated by
469:             * <IMG src="{@docRoot}/org/geotools/display/canvas/doc-files/scaleX0.png">.
470:             */
471:            public static double getScaleX0(final AffineTransform tr) {
472:                return XMath.hypot(tr.getScaleX(), tr.getShearX());
473:            }
474:
475:            /**
476:             * Returns the magnitude of scale factor <var>y</var> by cancelling the
477:             * effect of eventual flip and rotation. This factor is calculated by
478:             * <IMG src="{@docRoot}/org/geotools/display/canvas/doc-files/scaleY0.png">.
479:             */
480:            public static double getScaleY0(final AffineTransform tr) {
481:                return XMath.hypot(tr.getScaleY(), tr.getShearY());
482:            }
483:
484:            /**
485:             * Returns a global scale factor for the specified affine transform.
486:             * This scale factor will combines {@link #getScaleX0} and {@link #getScaleY0}.
487:             * The way to compute such a "global" scale is somewhat arbitrary and may change
488:             * in a future version.
489:             */
490:            public static double getScale(final AffineTransform tr) {
491:                return 0.5 * (getScaleX0(tr) + getScaleY0(tr));
492:            }
493:
494:            /**
495:             * Returns an affine transform representing a zoom carried out around a
496:             * central point (<var>x</var>, <var>y</var>). The transforms will leave
497:             * the specified (<var>x</var>, <var>y</var>) coordinate unchanged.
498:             *
499:             * @param sx Scale along <var>x</var> axis.
500:             * @param sy Scale along <var>y</var> axis.
501:             * @param  x <var>x</var> coordinates of the central point.
502:             * @param  y <var>y</var> coordinates of the central point.
503:             * @return   Affine transform of a zoom which leaves the
504:             *          (<var>x</var>,<var>y</var>) coordinate unchanged.
505:             */
506:            public static AffineTransform getScaleInstance(final double sx,
507:                    final double sy, final double x, final double y) {
508:                return new AffineTransform(sx, 0, 0, sy, (1 - sx) * x, (1 - sy)
509:                        * y);
510:            }
511:
512:            /**
513:             * Checks whether the matrix coefficients are close to whole numbers.
514:             * If this is the case, these coefficients will be rounded up to the
515:             * nearest whole numbers. This rounding up is useful, for example, for
516:             * speeding up image displays.  Above all, it is efficient when we know that
517:             * a matrix has a chance of being close to the similarity matrix.
518:             * <p>
519:             * It is crucial to note that this method uses a default rounding threshold 
520:             * whose value is held by the field {@link #EPS} which is {@value #EPS}.
521:             *
522:             * @deprecated Use {@link #round(AffineTransform, double)} instead.
523:             */
524:            public static void round(final AffineTransform tr) {
525:                round(tr, EPS);
526:            }
527:
528:            /**
529:             * Checks whether the matrix coefficients are close to whole numbers.
530:             * If this is the case, these coefficients will be rounded up to the
531:             * nearest whole numbers. This rounding up is useful, for example, for
532:             * speeding up image displays.  Above all, it is efficient when we know that
533:             * a matrix has a chance of being close to the similarity matrix.
534:             *
535:             * @param tr The matrix to round. Rounding will be applied in place.
536:             * @param tolerance The maximal departure from integers in order to allow rounding.
537:             *        It is typically a small number like {@code 1E-6}.
538:             *
539:             * @since 2.3.1
540:             */
541:            public static void round(final AffineTransform tr,
542:                    final double tolerance) {
543:                double r;
544:                final double m00, m01, m10, m11;
545:                if (Math.abs((m00 = Math.rint(r = tr.getScaleX())) - r) <= tolerance
546:                        && Math.abs((m01 = Math.rint(r = tr.getShearX())) - r) <= tolerance
547:                        && Math.abs((m11 = Math.rint(r = tr.getScaleY())) - r) <= tolerance
548:                        && Math.abs((m10 = Math.rint(r = tr.getShearY())) - r) <= tolerance) {
549:                    if ((m00 != 0 || m01 != 0) && (m10 != 0 || m11 != 0)) {
550:                        double m02 = Math.rint(r = tr.getTranslateX());
551:                        if (!(Math.abs(m02 - r) <= tolerance))
552:                            m02 = r;
553:                        double m12 = Math.rint(r = tr.getTranslateY());
554:                        if (!(Math.abs(m12 - r) <= tolerance))
555:                            m12 = r;
556:                        tr.setTransform(m00, m10, m01, m11, m02, m12);
557:                    }
558:                }
559:            }
560:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.