AffineTransform
class represents a 2D affine transform
that performs a linear mapping from 2D coordinates to other 2D
coordinates that preserves the "straightness" and
"parallelness" of lines. Affine transformations can be constructed
using sequences of translations, scales, flips, rotations, and shears.
Such a coordinate transformation can be represented by a 3 row by
3 column matrix with an implied last row of [ 0 0 1 ]. This matrix
transforms source coordinates (x, y)
into
destination coordinates (x', y')
by considering
them to be a column vector and multiplying the coordinate vector
by the matrix according to the following process:
[ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ] [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ] [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ]
AffineTransform
representing the
Identity transformation.AffineTransform
that is a copy of
the specified AffineTransform
object.AffineTransform
from 6 floating point
values representing the 6 specifiable entries of the 3x3
transformation matrix.AffineTransform
from an array of
floating point values representing either the 4 non-translation
enries or the 6 specifiable entries of the 3x3 transformation
matrix. The values are retrieved from the array as
{ m00 m10 m01 m11 [m02 m12]}.AffineTransform
from 6 double
precision values representing the 6 specifiable entries of the 3x3
transformation matrix.AffineTransform
from an array of
double precision values representing either the 4 non-translation
entries or the 6 specifiable entries of the 3x3 transformation
matrix. The values are retrieved from the array as
{ m00 m10 m01 m11 [m02 m12]}.AffineTransform
object.AffineTransform
Tx
to
this AffineTransform
Cx in the most commonly useful
way to provide a new user space
that is mapped to the former user space by Tx
.
Cx is updated to perform the combined transformation.
Transforming a point p by the updated transform Cx' is
equivalent to first transforming p by Tx
and then
transforming the result by the original transform Cx like this:
Cx'(p) = Cx(Tx(p))
In matrix notation, if this transform Cx is
represented by the matrix [this] and Tx
is represented
by the matrix [Tx] then this method does the following:
[this] = [this] x [Tx]
AffineTransform
object representing the
inverse transformation.
The inverse transform Tx' of this transform Tx
maps coordinates transformed by Tx back
to their original coordinates.
In other words, Tx'(Tx(p)) = p = Tx(Tx'(p)).
If this transform maps all coordinates onto a point or a line
then it will not have an inverse, since coordinates that do
not lie on the destination point or line will not have an inverse
mapping.
The getDeterminant
method can be used to determine if this
transform has no inverse, in which case an exception will be
thrown if the createInverse
method is called.
Shape
after it has been transformed by
this transform.[ x' ] [ m00 m01 (m02) ] [ x ] [ m00x + m01y ] [ y' ] = [ m10 m11 (m12) ] [ y ] = [ m10x + m11y ] [ (1) ] [ (0) (0) ( 1 ) ] [ (1) ] [ (1) ]The two coordinate array sections can be exactly the same or can be overlapping sections of the same array without affecting the validity of the results. This method ensures that no source coordinates are overwritten by a previous operation before they can be transformed. The coordinates are stored in the arrays starting at the indicated offset in the order
[x0, y0, x1, y1, ..., xn, yn]
.ptSrc
and stores the result in ptDst
.
A relative distance vector is transformed without applying the
translation components of the affine transformation matrix
using the following equations:
[ x' ] [ m00 m01 (m02) ] [ x ] [ m00x + m01y ] [ y' ] = [ m10 m11 (m12) ] [ y ] = [ m10x + m11y ] [ (1) ] [ (0) (0) ( 1 ) ] [ (1) ] [ (1) ]If
ptDst
is null
, a new
Point2D
object is allocated and then the result of the
transform is stored in this object.
In either case, ptDst
, which contains the
transformed point, is returned for convenience.
If ptSrc
and ptDst
are the same object,
the input point is correctly overwritten with the transformed
point.true
if this AffineTransform
represents the same affine coordinate transform as the specified
argument.If the determinant is non-zero, then this transform is invertible and the various methods that depend on the inverse transform do not need to throw a NoninvertibleTransformException . If the determinant is zero then this transform can not be inverted since the transform maps all input coordinates onto a line or a point. If the determinant is near enough to zero then inverse transform operations might not carry enough precision to produce meaningful results.
If this transform represents a uniform scale, as indicated by
the getType
method then the determinant also
represents the square of the uniform scale factor by which all of
the points are expanded from or contracted towards the origin.
If this transform represents a non-uniform scale or more general
transform then the determinant is not likely to represent a
value useful for any purpose other than determining if inverse
transforms are possible.
Mathematically, the determinant is calculated using the formula:
| m00 m01 m02 | | m10 m11 m12 | = m00 * m11 - m01 * m10 | 0 0 1 |
[ cos(theta) -sin(theta) 0 ] [ sin(theta) cos(theta) 0 ] [ 0 0 1 ]Rotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
This operation is equivalent to the following sequence of calls:
AffineTransform Tx = new AffineTransform(); Tx.setToTranslation(x, y); // S3: final translation Tx.rotate(theta); // S2: rotate around anchor Tx.translate(-x, -y); // S1: translate anchor to originThe matrix representing the returned transform is:
[ cos(theta) -sin(theta) x-x*cos+y*sin ] [ sin(theta) cos(theta) y-x*sin-y*cos ] [ 0 0 1 ]Rotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
[ sx 0 0 ] [ 0 sy 0 ] [ 0 0 1 ]
[ 1 shx 0 ] [ shy 1 0 ] [ 0 0 1 ]
[ 1 0 tx ] [ 0 1 ty ] [ 0 0 1 ]
[x0, y0, x1, y1, ..., xn, yn]
.ptSrc
and stores the
result in ptDst
.
If ptDst
is null
, a new
Point2D
object is allocated and then the result of the
transform is stored in this object.
In either case, ptDst
, which contains the transformed
point, is returned for convenience.
If ptSrc
and ptDst
are the same
object, the input point is correctly overwritten with the
transformed point.true
if this AffineTransform
is
an identity transform.wait
methods.
The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.
This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:
synchronized
statement
that synchronizes on the object.
Class,
by executing a
synchronized static method of that class.
Only one thread at a time can own an object's monitor.
wait
methods.
The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
This method should only be called by a thread that is the owner
of this object's monitor. See the notify
method for a
description of the ways in which a thread can become the owner of
a monitor.
AffineTransform
Tx
to
this AffineTransform
Cx
in a less commonly used way such that Tx
modifies the
coordinate transformation relative to the absolute pixel
space rather than relative to the existing user space.
Cx is updated to perform the combined transformation.
Transforming a point p by the updated transform Cx' is
equivalent to first transforming p by the original transform
Cx and then transforming the result by
Tx
like this:
Cx'(p) = Tx(Cx(p))
In matrix notation, if this transform Cx
is represented by the matrix [this] and Tx
is
represented by the matrix [Tx] then this method does the
following:
[this] = [Tx] x [this]
AffineTransform
represented by the following matrix:
[ cos(theta) -sin(theta) 0 ] [ sin(theta) cos(theta) 0 ] [ 0 0 1 ]Rotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
This operation is equivalent to the following sequence of calls:
translate(x, y); // S3: final translation rotate(theta); // S2: rotate around anchor translate(-x, -y); // S1: translate anchor to originRotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
AffineTransform
represented by the following matrix:
[ sx 0 0 ] [ 0 sy 0 ] [ 0 0 1 ]
[ cos(theta) -sin(theta) 0 ] [ sin(theta) cos(theta) 0 ] [ 0 0 1 ]Rotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
This operation is equivalent to the following sequence of calls:
setToTranslation(x, y); // S3: final translation rotate(theta); // S2: rotate around anchor translate(-x, -y); // S1: translate anchor to originThe matrix representing this transform becomes:
[ cos(theta) -sin(theta) x-x*cos+y*sin ] [ sin(theta) cos(theta) y-x*sin-y*cos ] [ 0 0 1 ]Rotating with a positive angle theta rotates points on the positive x axis toward the positive y axis.
[ sx 0 0 ] [ 0 sy 0 ] [ 0 0 1 ]
[ 1 shx 0 ] [ shy 1 0 ] [ 0 0 1 ]
[ 1 0 tx ] [ 0 1 ty ] [ 0 0 1 ]
AffineTransform
object.AffineTransform
represented by the following matrix:
[ 1 shx 0 ] [ shy 1 0 ] [ 0 0 1 ]
String
that represents the value of this
Object
.[x0, y0, x1, y1, ..., xn, yn]
.[x0, y0, x1, y1, ..., xn, yn]
.[x0, y0, x1, y1, ..., xn, yn]
.[x0, y0, x1, y1, ..., xn, yn]
.ptDst
array is
null
, a new Point2D
object is allocated
and stored into that element before storing the results of the
transformation.
Note that this method does not take any precautions to
avoid problems caused by storing results into Point2D
objects that will be used as the source for calculations
further down the source array.
This method does guarantee that if a specified Point2D
object is both the source and destination for the same single point
transform operation then the results will not be stored until
the calculations are complete to avoid storing the results on
top of the operands.
If, however, the destination Point2D
object for one
operation is the same object as the source Point2D
object for another operation further down the source array then
the original coordinates in that point are overwritten before
they can be converted.
ptSrc
and stores the result
in ptDst
.
If ptDst
is null
, a new Point2D
object is allocated and then the result of the transformation is
stored in this object.
In either case, ptDst
, which contains the
transformed point, is returned for convenience.
If ptSrc
and ptDst
are the same
object, the input point is correctly overwritten with
the transformed point.AffineTransform
represented by the following matrix:
[ 1 0 tx ] [ 0 1 ty ] [ 0 0 1 ]
The current thread must own this object's monitor. The thread
releases ownership of this monitor and waits until another thread
notifies threads waiting on this object's monitor to wake up
either through a call to the notify
method or the
notifyAll
method. The thread then waits until it can
re-obtain ownership of the monitor and resumes execution.
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) { while (<condition does not hold>) obj.wait(); ... // Perform action appropriate to condition }This method should only be called by a thread that is the owner of this object's monitor. See the
notify
method for a
description of the ways in which a thread can become the owner of
a monitor.The current thread must own this object's monitor.
This method causes the current thread (call it T) to place itself in the wait set for this object and then to relinquish any and all synchronization claims on this object. Thread T becomes disabled for thread scheduling purposes and lies dormant until one of four things happens:
A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:
synchronized (obj) { while (<condition does not hold>) obj.wait(timeout); ... // Perform action appropriate to condition }(For more information on this topic, see Section 3.2.3 in Doug Lea's "Concurrent Programming in Java (Second Edition)" (Addison-Wesley, 2000), or Item 50 in Joshua Bloch's "Effective Java Programming Language Guide" (Addison-Wesley, 2001).
If the current thread is interrupted by another thread while it is waiting, then an InterruptedException is thrown. This exception is not thrown until the lock status of this object has been restored as described above.
Note that the wait method, as it places the current thread into the wait set for this object, unlocks only this object; any other objects on which the current thread may be synchronized remain locked while the thread waits.
This method should only be called by a thread that is the owner
of this object's monitor. See the notify
method for a
description of the ways in which a thread can become the owner of
a monitor.
This method is similar to the wait
method of one
argument, but it allows finer control over the amount of time to
wait for a notification before giving up. The amount of real time,
measured in nanoseconds, is given by:
1000000*timeout+nanos
In all other respects, this method does the same thing as the method of one argument. In particular, wait(0, 0) means the same thing as wait(0).
The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until either of the following two conditions has occurred:
notify
method
or the notifyAll
method.
timeout
milliseconds plus nanos
nanoseconds arguments, has
elapsed.
The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
synchronized (obj) { while (<condition does not hold>) obj.wait(timeout, nanos); ... // Perform action appropriate to condition }This method should only be called by a thread that is the owner of this object's monitor. See the
notify
method for a
description of the ways in which a thread can become the owner of
a monitor.