affinetransform.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 1,366 行 · 第 1/3 页
JAVA
1,366 行
}
/**
* Set this transform to the result of performing tx followed by the
* original version of this. This is less common than normal concatenation,
* but can still be used to chain transformations from one space to another.
* In matrix form:
* <pre>
* [ this ] = [ tx ] x [ this ]
* </pre>
*
* @param tx the transform to concatenate
* @throws NullPointerException if tx is null
* @see #concatenate(AffineTransform)
*/
public void preConcatenate(AffineTransform tx) {
double n00 = tx.m00 * m00 + tx.m01 * m10;
double n01 = tx.m00 * m01 + tx.m01 * m11;
double n02 = tx.m00 * m02 + tx.m01 * m12 + tx.m02;
double n10 = tx.m10 * m00 + tx.m11 * m10;
double n11 = tx.m10 * m01 + tx.m11 * m11;
double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12;
m00 = n00;
m01 = n01;
m02 = n02;
m10 = n10;
m11 = n11;
m12 = n12;
updateType();
}
/**
* Returns a transform, which if concatenated to this one, will result in
* the identity transform. This is useful for undoing transformations, but
* is only possible if the original transform has an inverse (ie. does not
* map multiple points to the same line or point). A transform exists only
* if getDeterminant() has a non-zero value.
*
* @return a new inverse transform
* @throws NoninvertibleTransformException if inversion is not possible
* @see #getDeterminant()
*/
public AffineTransform createInverse() throws NoninvertibleTransformException {
double det = getDeterminant();
if (det == 0)
throw new NoninvertibleTransformException("can't invert transform");
return new AffineTransform(m11 / det, -m10 / det, m01 / det, -m00 / det, -m02, -m12);
}
/**
* Perform this transformation on the given source point, and store the
* result in the destination (creating it if necessary). It is safe for
* src and dst to be the same.
*
* @param src the source point
* @param dst the destination, or null
* @return the transformation of src, in dst if it was non-null
* @throws NullPointerException if src is null
*/
public Point2D transform(Point2D src, Point2D dst) {
if (dst == null)
dst = new Point2D.Double();
double x = src.getX();
double y = src.getY();
double nx = m00 * x + m01 * y + m02;
double ny = m10 * x + m11 * y + m12;
dst.setLocation(nx, ny);
return dst;
}
/**
* Perform this transformation on an array of points, storing the results
* in another (possibly same) array. This will not create a destination
* array, but will create points for the null entries of the destination.
* The transformation is done sequentially. While having a single source
* and destination point be the same is safe, you should be aware that
* duplicate references to the same point in the source, and having the
* source overlap the destination, may result in your source points changing
* from a previous transform before it is their turn to be evaluated.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points (may have null entries)
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null, or src has null
* entries
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
* @throws ArrayStoreException if new points are incompatible with dst
*/
public void transform(Point2D[] src, int srcOff, Point2D[] dst, int dstOff, int num) {
while (--num >= 0)
dst[dstOff] = transform(src[srcOff++], dst[dstOff++]);
}
/**
* Perform this transformation on an array of points, in (x,y) pairs,
* storing the results in another (possibly same) array. This will not
* create a destination array. All sources are copied before the
* transformation, so that no result will overwrite a point that has not yet
* been evaluated.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
*/
public void transform(float[] srcPts, int srcOff, float[] dstPts, int dstOff, int num) {
if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) {
float[] f = new float[2 * num];
System.arraycopy(srcPts, srcOff, f, 0, 2 * num);
srcPts = f;
}
while (--num >= 0) {
float x = srcPts[srcOff++];
float y = srcPts[srcOff++];
dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
}
}
/**
* Perform this transformation on an array of points, in (x,y) pairs,
* storing the results in another (possibly same) array. This will not
* create a destination array. All sources are copied before the
* transformation, so that no result will overwrite a point that has not yet
* been evaluated.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
*/
public void transform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) {
if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) {
double[] d = new double[2 * num];
System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
srcPts = d;
}
while (--num >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = m00 * x + m01 * y + m02;
dstPts[dstOff++] = m10 * x + m11 * y + m12;
}
}
/**
* Perform this transformation on an array of points, in (x,y) pairs,
* storing the results in another array. This will not create a destination
* array.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
*/
public void transform(float[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) {
while (--num >= 0) {
float x = srcPts[srcOff++];
float y = srcPts[srcOff++];
dstPts[dstOff++] = m00 * x + m01 * y + m02;
dstPts[dstOff++] = m10 * x + m11 * y + m12;
}
}
/**
* Perform this transformation on an array of points, in (x,y) pairs,
* storing the results in another array. This will not create a destination
* array.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
*/
public void transform(double[] srcPts, int srcOff, float[] dstPts, int dstOff, int num) {
while (--num >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02);
dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12);
}
}
/**
* Perform the inverse of this transformation on the given source point,
* and store the result in the destination (creating it if necessary). It
* is safe for src and dst to be the same.
*
* @param src the source point
* @param dst the destination, or null
* @return the inverse transformation of src, in dst if it was non-null
* @throws NullPointerException if src is null
* @throws NoninvertibleTransformException if the inverse does not exist
* @see #getDeterminant()
*/
public Point2D inverseTransform(Point2D src, Point2D dst) throws NoninvertibleTransformException {
double det = getDeterminant();
if (det == 0)
throw new NoninvertibleTransformException("couldn't invert transform");
if (dst == null)
dst = new Point2D.Double();
double x = src.getX();
double y = src.getY();
double nx = (m11 * x + -m10 * y) / det - m02;
double ny = (m01 * x + -m00 * y) / det - m12;
dst.setLocation(nx, ny);
return dst;
}
/**
* Perform the inverse of this transformation on an array of points, in
* (x,y) pairs, storing the results in another (possibly same) array. This
* will not create a destination array. All sources are copied before the
* transformation, so that no result will overwrite a point that has not yet
* been evaluated.
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
* @throws NoninvertibleTransformException if the inverse does not exist
* @see #getDeterminant()
*/
public void inverseTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) throws NoninvertibleTransformException {
double det = getDeterminant();
if (det == 0)
throw new NoninvertibleTransformException("couldn't invert transform");
if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) {
double[] d = new double[2 * num];
System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
srcPts = d;
}
while (--num >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = (m11 * x + -m10 * y) / det - m02;
dstPts[dstOff++] = (m01 * x + -m00 * y) / det - m12;
}
}
/**
* Perform this transformation, less any translation, on the given source
* point, and store the result in the destination (creating it if
* necessary). It is safe for src and dst to be the same. The reduced
* transform is equivalent to:
* <pre>
* [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
* [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
* </pre>
*
* @param src the source point
* @param dst the destination, or null
* @return the delta transformation of src, in dst if it was non-null
* @throws NullPointerException if src is null
*/
public Point2D deltaTransform(Point2D src, Point2D dst) {
if (dst == null)
dst = new Point2D.Double();
double x = src.getX();
double y = src.getY();
double nx = m00 * x + m01 * y;
double ny = m10 * x + m11 * y;
dst.setLocation(nx, ny);
return dst;
}
/**
* Perform this transformation, less any translation, on an array of points,
* in (x,y) pairs, storing the results in another (possibly same) array.
* This will not create a destination array. All sources are copied before
* the transformation, so that no result will overwrite a point that has
* not yet been evaluated. The reduced transform is equivalent to:
* <pre>
* [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ]
* [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ]
* </pre>
*
* @param src the array of source points
* @param srcOff the starting offset into src
* @param dst the array of destination points
* @param dstOff the starting offset into dst
* @param num the number of points to transform
* @throws NullPointerException if src or dst is null
* @throws ArrayIndexOutOfBoundsException if array bounds are exceeded
*/
public void deltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff, int num) {
if (srcPts == dstPts && dstOff > srcOff && num > 1 && srcOff + 2 * num > dstOff) {
double[] d = new double[2 * num];
System.arraycopy(srcPts, srcOff, d, 0, 2 * num);
srcPts = d;
}
while (--num >= 0) {
double x = srcPts[srcOff++];
double y = srcPts[srcOff++];
dstPts[dstOff++] = m00 * x + m01 * y;
dstPts[dstOff++] = m10 * x + m11 * y;
}
}
/**
* Return a new Shape, based on the given one, where the path of the shape
* has been transformed by this transform. Notice that this uses GeneralPath,
* which only stores points in float precision.
*
* @param src the shape source to transform
* @return the shape, transformed by this
* @throws NullPointerException if src is null
* @see GeneralPath#transform(AffineTransform)
*/
public Shape createTransformedShape(Shape src) {
GeneralPath p = new GeneralPath(src);
p.transform(this);
return p;
}
/**
* Returns a string representation of the transform, in the format:
* <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], ["
* + m10 + ", " + m11 + ", " + m12 + "]]"</code>.
*
* @return the string representation
*/
public String toString() {
return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" + m10 + ", " + m11 + ", " + m12 + "]]";
}
/**
* Tests if this transformation is the identity:
* <pre>
* [ 1 0 0 ]
* [ 0 1 0 ]
* [ 0 0 1 ]
* </pre>
*
* @return true if this is the identity transform
*/
public boolean isIdentity() {
// Rather than rely on type, check explicitly.
return (m00 == 1 && m01 == 0 && m02 == 0 && m10 == 0 && m11 == 1 && m12 == 0);
}
/**
* Create a new transform of the same run-time type, with the same
* transforming properties as this one.
*
* @return the clone
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException e) {
throw (Error) new InternalError().initCause(e); // Impossible
}
}
/**
* Return the hashcode for this transformation. The formula is not
* documented, but appears to be the same as:
* <pre>
* long l = Double.doubleToLongBits(getScaleX());
* l = l * 31 + Double.doubleToLongBits(getShearY());
* l = l * 31 + Double.doubleToLongBits(getShearX());
* l = l * 31 + Double.doubleToLongBits(getScaleY());
* l = l * 31 + Double.doubleToLongBits(getTranslateX());
* l = l * 31 + Double.doubleToLongBits(getTranslateY());
* return (int) ((l >> 32) ^ l);
* </pre>
*
* @return the hashcode
*/
public int hashCode() {
long l = Double.doubleToLongBits(m00);
l = l * 31 + Double.doubleToLongBits(m10);
l = l * 31 + Double.doubleToLongBits(m01);
l = l * 31 + Double.doubleToLongBits(m11);
l = l * 31 + Double.doubleToLongBits(m02);
l = l * 31 + Double.doubleToLongBits(m12);
return (int) ((l >> 32) ^ l);
}
/**
* Compares two transforms for equality. This returns true if they have the
* same matrix values.
*
* @param o the transform to compare
* @return true if it is equal
*/
public boolean equals(Object obj) {
if (!(obj instanceof AffineTransform))
return false;
AffineTransform t = (AffineTransform) obj;
return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02 && m10 == t.m10 && m11 == t.m11 && m12 == t.m12);
}
/**
* Helper to decode the type from the matrix. This is not guaranteed
* to find the optimal type, but at least it will be valid.
*/
private void updateType() {
double det = getDeterminant();
if (det == 0) {
type = TYPE_GENERAL_TRANSFORM;
return;
}
// Scale (includes rotation by PI) or translation.
if (m01 == 0 && m10 == 0) {
if (m00 == m11)
type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE;
else
type = TYPE_GENERAL_SCALE;
if (m02 != 0 || m12 != 0)
type |= TYPE_TRANSLATION;
}
// Rotation.
else if (m00 == m11 && m01 == -m10) {
type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION;
if (det != 1)
type |= TYPE_UNIFORM_SCALE;
if (m02 != 0 || m12 != 0)
type |= TYPE_TRANSLATION;
} else
type = TYPE_GENERAL_TRANSFORM;
}
/**
* Reads a transform from an object stream.
*
* @param s the stream to read from
* @throws ClassNotFoundException if there is a problem deserializing
* @throws IOException if there is a problem deserializing
*/
private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
s.defaultReadObject();
updateType();
}
} // class AffineTransform
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?